You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ma...@apache.org on 2012/06/06 16:46:50 UTC
[4/7] Changing all tabs to spaces
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6d1e0356/framework/src/org/apache/cordova/CallbackServer.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CallbackServer.java b/framework/src/org/apache/cordova/CallbackServer.java
index 6b6ce70..a34ef3c 100755
--- a/framework/src/org/apache/cordova/CallbackServer.java
+++ b/framework/src/org/apache/cordova/CallbackServer.java
@@ -25,337 +25,334 @@ import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
-import java.net.URLEncoder;
import java.util.LinkedList;
-import android.util.Log;
-
/**
* This class provides a way for Java to run JavaScript in the web page that has loaded Cordova.
* The CallbackServer class implements an XHR server and a polling server with a list of JavaScript
* statements that are to be executed on the web page.
- *
+ *
* The process flow for XHR is:
- * 1. JavaScript makes an async XHR call.
- * 2. The server holds the connection open until data is available.
- * 3. The server writes the data to the client and closes the connection.
- * 4. The server immediately starts listening for the next XHR call.
+ * 1. JavaScript makes an async XHR call.
+ * 2. The server holds the connection open until data is available.
+ * 3. The server writes the data to the client and closes the connection.
+ * 4. The server immediately starts listening for the next XHR call.
* 5. The client receives this XHR response, processes it.
* 6. The client sends a new async XHR request.
*
* The CallbackServer class requires the following permission in Android manifest file
* <uses-permission android:name="android.permission.INTERNET" />
- *
+ *
* If the device has a proxy set, then XHR cannot be used, so polling must be used instead.
- * This can be determined by the client by calling CallbackServer.usePolling().
- *
+ * This can be determined by the client by calling CallbackServer.usePolling().
+ *
* The process flow for polling is:
* 1. The client calls CallbackServer.getJavascript() to retrieve next statement.
* 2. If statement available, then client processes it.
- * 3. The client repeats #1 in loop.
+ * 3. The client repeats #1 in loop.
*/
public class CallbackServer implements Runnable {
-
- private static final String LOG_TAG = "CallbackServer";
-
- /**
- * The list of JavaScript statements to be sent to JavaScript.
- */
- private LinkedList<String> javascript;
-
- /**
- * The port to listen on.
- */
- private int port;
-
- /**
- * The server thread.
- */
- private Thread serverThread;
-
- /**
- * Indicates the server is running.
- */
- private boolean active;
-
- /**
- * Indicates that the JavaScript statements list is empty
- */
- private boolean empty;
-
- /**
- * Indicates that polling should be used instead of XHR.
- */
- private boolean usePolling = true;
-
- /**
- * Security token to prevent other apps from accessing this callback server via XHR
- */
- private String token;
-
- /**
- * Constructor.
- */
- public CallbackServer() {
- //System.out.println("CallbackServer()");
- this.active = false;
- this.empty = true;
- this.port = 0;
- this.javascript = new LinkedList<String>();
- }
-
- /**
- * Init callback server and start XHR if running local app.
- *
- * If Cordova app is loaded from file://, then we can use XHR
- * otherwise we have to use polling due to cross-domain security restrictions.
- *
- * @param url The URL of the Cordova app being loaded
- */
- public void init(String url) {
- //System.out.println("CallbackServer.start("+url+")");
- this.active = false;
- this.empty = true;
- this.port = 0;
- this.javascript = new LinkedList<String>();
-
- // Determine if XHR or polling is to be used
- if ((url != null) && !url.startsWith("file://")) {
- this.usePolling = true;
- this.stopServer();
- }
- else if (android.net.Proxy.getDefaultHost() != null) {
- this.usePolling = true;
- this.stopServer();
- }
- else {
- this.usePolling = false;
- this.startServer();
- }
- }
-
+
+ private static final String LOG_TAG = "CallbackServer";
+
+ /**
+ * The list of JavaScript statements to be sent to JavaScript.
+ */
+ private LinkedList<String> javascript;
+
+ /**
+ * The port to listen on.
+ */
+ private int port;
+
+ /**
+ * The server thread.
+ */
+ private Thread serverThread;
+
+ /**
+ * Indicates the server is running.
+ */
+ private boolean active;
+
+ /**
+ * Indicates that the JavaScript statements list is empty
+ */
+ private boolean empty;
+
+ /**
+ * Indicates that polling should be used instead of XHR.
+ */
+ private boolean usePolling = true;
+
+ /**
+ * Security token to prevent other apps from accessing this callback server via XHR
+ */
+ private String token;
+
+ /**
+ * Constructor.
+ */
+ public CallbackServer() {
+ //System.out.println("CallbackServer()");
+ this.active = false;
+ this.empty = true;
+ this.port = 0;
+ this.javascript = new LinkedList<String>();
+ }
+
+ /**
+ * Init callback server and start XHR if running local app.
+ *
+ * If Cordova app is loaded from file://, then we can use XHR
+ * otherwise we have to use polling due to cross-domain security restrictions.
+ *
+ * @param url The URL of the Cordova app being loaded
+ */
+ public void init(String url) {
+ //System.out.println("CallbackServer.start("+url+")");
+ this.active = false;
+ this.empty = true;
+ this.port = 0;
+ this.javascript = new LinkedList<String>();
+
+ // Determine if XHR or polling is to be used
+ if ((url != null) && !url.startsWith("file://")) {
+ this.usePolling = true;
+ this.stopServer();
+ }
+ else if (android.net.Proxy.getDefaultHost() != null) {
+ this.usePolling = true;
+ this.stopServer();
+ }
+ else {
+ this.usePolling = false;
+ this.startServer();
+ }
+ }
+
/**
* Re-init when loading a new HTML page into webview.
- *
+ *
* @param url The URL of the Cordova app being loaded
*/
- public void reinit(String url) {
- this.stopServer();
- this.init(url);
- }
-
- /**
- * Return if polling is being used instead of XHR.
- *
- * @return
- */
- public boolean usePolling() {
- return this.usePolling;
- }
-
- /**
- * Get the port that this server is running on.
- *
- * @return
- */
- public int getPort() {
- return this.port;
- }
-
- /**
- * Get the security token that this server requires when calling getJavascript().
- *
- * @return
- */
- public String getToken() {
- return this.token;
- }
-
- /**
- * Start the server on a new thread.
- */
- public void startServer() {
- //System.out.println("CallbackServer.startServer()");
- this.active = false;
-
- // Start server on new thread
- this.serverThread = new Thread(this);
- this.serverThread.start();
- }
-
- /**
- * Restart the server on a new thread.
- */
- public void restartServer() {
-
- // Stop server
- this.stopServer();
-
- // Start server again
- this.startServer();
- }
-
- /**
- * Start running the server.
- * This is called automatically when the server thread is started.
- */
- public void run() {
-
- // Start server
- try {
- this.active = true;
- String request;
- ServerSocket waitSocket = new ServerSocket(0);
- this.port = waitSocket.getLocalPort();
- //System.out.println("CallbackServer -- using port " +this.port);
- this.token = java.util.UUID.randomUUID().toString();
- //System.out.println("CallbackServer -- using token "+this.token);
-
- while (this.active) {
- //System.out.println("CallbackServer: Waiting for data on socket");
- Socket connection = waitSocket.accept();
- BufferedReader xhrReader = new BufferedReader(new InputStreamReader(connection.getInputStream()),40);
- DataOutputStream output = new DataOutputStream(connection.getOutputStream());
- request = xhrReader.readLine();
- String response = "";
- //System.out.println("CallbackServerRequest="+request);
- if (this.active && (request != null)) {
- if (request.contains("GET")) {
-
- // Get requested file
- String[] requestParts = request.split(" ");
-
- // Must have security token
- if ((requestParts.length == 3) && (requestParts[1].substring(1).equals(this.token))) {
- //System.out.println("CallbackServer -- Processing GET request");
-
- // Wait until there is some data to send, or send empty data every 10 sec
- // to prevent XHR timeout on the client
- synchronized (this) {
- while (this.empty) {
- try {
- this.wait(10000); // prevent timeout from happening
- //System.out.println("CallbackServer>>> break <<<");
- break;
- }
- catch (Exception e) { }
- }
- }
-
- // If server is still running
- if (this.active) {
-
- // If no data, then send 404 back to client before it times out
- if (this.empty) {
- //System.out.println("CallbackServer -- sending data 0");
- response = "HTTP/1.1 404 NO DATA\r\n\r\n "; // need to send content otherwise some Android devices fail, so send space
- }
- else {
- //System.out.println("CallbackServer -- sending item");
- response = "HTTP/1.1 200 OK\r\n\r\n";
- String js = this.getJavascript();
- if (js != null) {
- response += encode(js, "UTF-8");
- }
- }
- }
- else {
- response = "HTTP/1.1 503 Service Unavailable\r\n\r\n ";
- }
- }
- else {
- response = "HTTP/1.1 403 Forbidden\r\n\r\n ";
- }
- }
- else {
- response = "HTTP/1.1 400 Bad Request\r\n\r\n ";
- }
- //System.out.println("CallbackServer: response="+response);
- //System.out.println("CallbackServer: closing output");
- output.writeBytes(response);
- output.flush();
- }
- output.close();
- xhrReader.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- this.active = false;
- //System.out.println("CallbackServer.startServer() - EXIT");
- }
-
- /**
- * Stop server.
- * This stops the thread that the server is running on.
- */
- public void stopServer() {
- //System.out.println("CallbackServer.stopServer()");
- if (this.active) {
- this.active = false;
-
- // Break out of server wait
- synchronized (this) {
- this.notify();
- }
- }
- }
+ public void reinit(String url) {
+ this.stopServer();
+ this.init(url);
+ }
+
+ /**
+ * Return if polling is being used instead of XHR.
+ *
+ * @return
+ */
+ public boolean usePolling() {
+ return this.usePolling;
+ }
+
+ /**
+ * Get the port that this server is running on.
+ *
+ * @return
+ */
+ public int getPort() {
+ return this.port;
+ }
+
+ /**
+ * Get the security token that this server requires when calling getJavascript().
+ *
+ * @return
+ */
+ public String getToken() {
+ return this.token;
+ }
+
+ /**
+ * Start the server on a new thread.
+ */
+ public void startServer() {
+ //System.out.println("CallbackServer.startServer()");
+ this.active = false;
+
+ // Start server on new thread
+ this.serverThread = new Thread(this);
+ this.serverThread.start();
+ }
+
+ /**
+ * Restart the server on a new thread.
+ */
+ public void restartServer() {
+
+ // Stop server
+ this.stopServer();
+
+ // Start server again
+ this.startServer();
+ }
+
+ /**
+ * Start running the server.
+ * This is called automatically when the server thread is started.
+ */
+ public void run() {
+
+ // Start server
+ try {
+ this.active = true;
+ String request;
+ ServerSocket waitSocket = new ServerSocket(0);
+ this.port = waitSocket.getLocalPort();
+ //System.out.println("CallbackServer -- using port " +this.port);
+ this.token = java.util.UUID.randomUUID().toString();
+ //System.out.println("CallbackServer -- using token "+this.token);
+
+ while (this.active) {
+ //System.out.println("CallbackServer: Waiting for data on socket");
+ Socket connection = waitSocket.accept();
+ BufferedReader xhrReader = new BufferedReader(new InputStreamReader(connection.getInputStream()),40);
+ DataOutputStream output = new DataOutputStream(connection.getOutputStream());
+ request = xhrReader.readLine();
+ String response = "";
+ //System.out.println("CallbackServerRequest="+request);
+ if (this.active && (request != null)) {
+ if (request.contains("GET")) {
+
+ // Get requested file
+ String[] requestParts = request.split(" ");
+
+ // Must have security token
+ if ((requestParts.length == 3) && (requestParts[1].substring(1).equals(this.token))) {
+ //System.out.println("CallbackServer -- Processing GET request");
+
+ // Wait until there is some data to send, or send empty data every 10 sec
+ // to prevent XHR timeout on the client
+ synchronized (this) {
+ while (this.empty) {
+ try {
+ this.wait(10000); // prevent timeout from happening
+ //System.out.println("CallbackServer>>> break <<<");
+ break;
+ }
+ catch (Exception e) { }
+ }
+ }
+
+ // If server is still running
+ if (this.active) {
+
+ // If no data, then send 404 back to client before it times out
+ if (this.empty) {
+ //System.out.println("CallbackServer -- sending data 0");
+ response = "HTTP/1.1 404 NO DATA\r\n\r\n "; // need to send content otherwise some Android devices fail, so send space
+ }
+ else {
+ //System.out.println("CallbackServer -- sending item");
+ response = "HTTP/1.1 200 OK\r\n\r\n";
+ String js = this.getJavascript();
+ if (js != null) {
+ response += encode(js, "UTF-8");
+ }
+ }
+ }
+ else {
+ response = "HTTP/1.1 503 Service Unavailable\r\n\r\n ";
+ }
+ }
+ else {
+ response = "HTTP/1.1 403 Forbidden\r\n\r\n ";
+ }
+ }
+ else {
+ response = "HTTP/1.1 400 Bad Request\r\n\r\n ";
+ }
+ //System.out.println("CallbackServer: response="+response);
+ //System.out.println("CallbackServer: closing output");
+ output.writeBytes(response);
+ output.flush();
+ }
+ output.close();
+ xhrReader.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ this.active = false;
+ //System.out.println("CallbackServer.startServer() - EXIT");
+ }
+
+ /**
+ * Stop server.
+ * This stops the thread that the server is running on.
+ */
+ public void stopServer() {
+ //System.out.println("CallbackServer.stopServer()");
+ if (this.active) {
+ this.active = false;
+
+ // Break out of server wait
+ synchronized (this) {
+ this.notify();
+ }
+ }
+ }
/**
* Destroy
*/
public void destroy() {
- this.stopServer();
+ this.stopServer();
+ }
+
+ /**
+ * Get the number of JavaScript statements.
+ *
+ * @return int
+ */
+ public int getSize() {
+ synchronized(this) {
+ int size = this.javascript.size();
+ return size;
+ }
+ }
+
+ /**
+ * Get the next JavaScript statement and remove from list.
+ *
+ * @return String
+ */
+ public String getJavascript() {
+ synchronized(this) {
+ if (this.javascript.size() == 0) {
+ return null;
+ }
+ String statement = this.javascript.remove(0);
+ if (this.javascript.size() == 0) {
+ this.empty = true;
+ }
+ return statement;
+ }
+ }
+
+ /**
+ * Add a JavaScript statement to the list.
+ *
+ * @param statement
+ */
+ public void sendJavascript(String statement) {
+ synchronized (this) {
+ this.javascript.add(statement);
+ this.empty = false;
+ this.notify();
+ }
}
- /**
- * Get the number of JavaScript statements.
- *
- * @return int
- */
- public int getSize() {
- synchronized(this) {
- int size = this.javascript.size();
- return size;
- }
- }
-
- /**
- * Get the next JavaScript statement and remove from list.
- *
- * @return String
- */
- public String getJavascript() {
- synchronized(this) {
- if (this.javascript.size() == 0) {
- return null;
- }
- String statement = this.javascript.remove(0);
- if (this.javascript.size() == 0) {
- this.empty = true;
- }
- return statement;
- }
- }
-
- /**
- * Add a JavaScript statement to the list.
- *
- * @param statement
- */
- public void sendJavascript(String statement) {
- synchronized (this) {
- this.javascript.add(statement);
- this.empty = false;
- this.notify();
- }
- }
-
- /* The Following code has been modified from original implementation of URLEncoder */
-
- /* start */
-
- /*
+ /* The Following code has been modified from original implementation of URLEncoder */
+
+ /* start */
+
+ /*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
@@ -371,24 +368,24 @@ public class CallbackServer implements Runnable {
* See the License for the specific language governing permissions and
* limitations under the License.
*/
- static final String digits = "0123456789ABCDEF";
+ static final String digits = "0123456789ABCDEF";
/**
- * This will encode the return value to JavaScript. We revert the encoding for
- * common characters that don't require encoding to reduce the size of the string
+ * This will encode the return value to JavaScript. We revert the encoding for
+ * common characters that don't require encoding to reduce the size of the string
* being passed to JavaScript.
- *
+ *
* @param s to be encoded
* @param enc encoding type
* @return encoded string
*/
- public static String encode(String s, String enc) throws UnsupportedEncodingException {
+ public static String encode(String s, String enc) throws UnsupportedEncodingException {
if (s == null || enc == null) {
throw new NullPointerException();
}
// check for UnsupportedEncodingException
"".getBytes(enc);
-
+
// Guess a bit bigger for encoded form
StringBuilder buf = new StringBuilder(s.length() + 16);
int start = -1;
@@ -426,6 +423,6 @@ public class CallbackServer implements Runnable {
buf.append(digits.charAt(bytes[j] & 0xf));
}
}
-
+
/* end */
}
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6d1e0356/framework/src/org/apache/cordova/CameraLauncher.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java
index e6fe153..cba7e49 100755
--- a/framework/src/org/apache/cordova/CameraLauncher.java
+++ b/framework/src/org/apache/cordova/CameraLauncher.java
@@ -44,40 +44,40 @@ import android.provider.MediaStore;
/**
* This class launches the camera view, allows the user to take a picture, closes the camera view,
- * and returns the captured image. When the camera view is closed, the screen displayed before
+ * and returns the captured image. When the camera view is closed, the screen displayed before
* the camera view was shown is redisplayed.
*/
public class CameraLauncher extends Plugin {
private static final int DATA_URL = 0; // Return base64 encoded string
private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android)
-
+
private static final int PHOTOLIBRARY = 0; // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
private static final int CAMERA = 1; // Take picture from camera
private static final int SAVEDPHOTOALBUM = 2; // Choose image from picture library (same as PHOTOLIBRARY for Android)
-
+
private static final int PICTURE = 0; // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType
private static final int VIDEO = 1; // allow selection of video only, ONLY RETURNS URL
private static final int ALLMEDIA = 2; // allow selection from all media types
-
+
private static final int JPEG = 0; // Take a picture of type JPEG
private static final int PNG = 1; // Take a picture of type PNG
private static final String GET_PICTURE = "Get Picture";
private static final String GET_VIDEO = "Get Video";
private static final String GET_All = "Get All";
-
+
private static final String LOG_TAG = "CameraLauncher";
-
+
private int mQuality; // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
private int targetWidth; // desired width of the image
private int targetHeight; // desired height of the image
- private Uri imageUri; // Uri of captured image
+ private Uri imageUri; // Uri of captured image
private int encodingType; // Type of encoding to use
private int mediaType; // What type of media to retrieve
-
+
public String callbackId;
private int numPics;
-
+
/**
* Constructor.
*/
@@ -86,7 +86,7 @@ public class CameraLauncher extends Plugin {
/**
* Executes the request and returns PluginResult.
- *
+ *
* @param action The action to execute.
* @param args JSONArry of arguments for the plugin.
* @param callbackId The callback id used when calling back into JavaScript.
@@ -94,9 +94,9 @@ public class CameraLauncher extends Plugin {
*/
public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.OK;
- String result = "";
+ String result = "";
this.callbackId = callbackId;
-
+
try {
if (action.equals("takePicture")) {
int srcType = CAMERA;
@@ -114,7 +114,7 @@ public class CameraLauncher extends Plugin {
this.targetHeight = args.getInt(4);
this.encodingType = args.getInt(5);
this.mediaType = args.getInt(6);
-
+
if (srcType == CAMERA) {
this.takePicture(destType, encodingType);
}
@@ -131,32 +131,32 @@ public class CameraLauncher extends Plugin {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
-
+
//--------------------------------------------------------------------------
// LOCAL METHODS
//--------------------------------------------------------------------------
-
+
/**
* Take a picture with the camera.
* When an image is captured or the camera view is cancelled, the result is returned
* in CordovaActivity.onActivityResult, which forwards the result to this.onActivityResult.
- *
+ *
* The image can either be returned as a base64 string or a URI that points to the file.
* To display base64 string in an img tag, set the source to:
* img.src="data:image/jpeg;base64,"+result;
* or to display URI in an img tag
* img.src=result;
- *
+ *
* @param quality Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
- * @param returnType Set the type of image to return.
+ * @param returnType Set the type of image to return.
*/
public void takePicture(int returnType, int encodingType) {
// Save the number of images currently on disk for later
this.numPics = queryImgDB().getCount();
-
+
// Display camera
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
-
+
// Specify file so that large image is captured and returned
// TODO: What if there isn't any external storage?
File photo = createCaptureFile(encodingType);
@@ -168,7 +168,7 @@ public class CameraLauncher extends Plugin {
/**
* Create a file in the applications temporary directory based upon the supplied encoding.
- *
+ *
* @param encodingType of the image to be taken
* @return a File object pointing to the temporary picture
*/
@@ -177,7 +177,7 @@ public class CameraLauncher extends Plugin {
if (encodingType == JPEG) {
photo = new File(DirectoryManager.getTempDirectoryPath(ctx.getContext()), "Pic.jpg");
} else if (encodingType == PNG) {
- photo = new File(DirectoryManager.getTempDirectoryPath(ctx.getContext()), "Pic.png");
+ photo = new File(DirectoryManager.getTempDirectoryPath(ctx.getContext()), "Pic.png");
} else {
throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
}
@@ -186,29 +186,29 @@ public class CameraLauncher extends Plugin {
/**
* Get image from photo library.
- *
+ *
* @param quality Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
* @param srcType The album to get image from.
- * @param returnType Set the type of image to return.
+ * @param returnType Set the type of image to return.
*/
// TODO: Images selected from SDCARD don't display correctly, but from CAMERA ALBUM do!
public void getImage(int srcType, int returnType) {
Intent intent = new Intent();
String title = GET_PICTURE;
if (this.mediaType == PICTURE) {
- intent.setType("image/*");
+ intent.setType("image/*");
}
else if (this.mediaType == VIDEO) {
- intent.setType("video/*");
+ intent.setType("video/*");
title = GET_VIDEO;
}
else if (this.mediaType == ALLMEDIA) {
- // I wanted to make the type 'image/*, video/*' but this does not work on all versions
+ // I wanted to make the type 'image/*, video/*' but this does not work on all versions
// of android so I had to go with the wildcard search.
- intent.setType("*/*");
+ intent.setType("*/*");
title = GET_All;
}
-
+
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
this.ctx.startActivityForResult((Plugin) this, Intent.createChooser(intent,
@@ -217,9 +217,9 @@ public class CameraLauncher extends Plugin {
/**
* Scales the bitmap according to the requested size.
- *
+ *
* @param bitmap The bitmap to scale.
- * @return Bitmap A new Bitmap object of the same bitmap after scaling.
+ * @return Bitmap A new Bitmap object of the same bitmap after scaling.
*/
public Bitmap scaleBitmap(Bitmap bitmap) {
int newWidth = this.targetWidth;
@@ -255,27 +255,27 @@ public class CameraLauncher extends Plugin {
newWidth = (newHeight * origWidth) / origHeight;
}
}
-
+
Bitmap retval = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
bitmap.recycle();
return retval;
}
-
+
/**
- * Called when the camera view exits.
- *
- * @param requestCode The request code originally supplied to startActivityForResult(),
+ * Called when the camera view exits.
+ *
+ * @param requestCode The request code originally supplied to startActivityForResult(),
* allowing you to identify who this result came from.
* @param resultCode The integer result code returned by the child activity through its setResult().
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
*/
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
-
+
// Get src and dest types from request code
int srcType = (requestCode/16) - 1;
int destType = (requestCode % 16) - 1;
int rotate = 0;
-
+
// Create an ExifHelper to save the exif data that is lost during compression
ExifHelper exif = new ExifHelper();
try {
@@ -303,7 +303,7 @@ public class CameraLauncher extends Plugin {
}
bitmap = scaleBitmap(bitmap);
-
+
// If sending base64 image back
if (destType == DATA_URL) {
this.processPicture(bitmap);
@@ -324,7 +324,7 @@ public class CameraLauncher extends Plugin {
try {
uri = this.ctx.getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException ex) {
- LOG.d(LOG_TAG, "Can't write to internal media storage.");
+ LOG.d(LOG_TAG, "Can't write to internal media storage.");
this.failPicture("Error capturing image - no media storage found.");
return;
}
@@ -334,7 +334,7 @@ public class CameraLauncher extends Plugin {
OutputStream os = this.ctx.getContentResolver().openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
os.close();
-
+
// Restore exif data to file
if (this.encodingType == JPEG) {
exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
@@ -347,12 +347,12 @@ public class CameraLauncher extends Plugin {
bitmap.recycle();
bitmap = null;
System.gc();
-
+
checkForDuplicateImage(FILE_URI);
} catch (IOException e) {
e.printStackTrace();
this.failPicture("Error capturing image.");
- }
+ }
}
// If cancelled
@@ -365,17 +365,17 @@ public class CameraLauncher extends Plugin {
this.failPicture("Did not complete!");
}
}
-
+
// If retrieving photo from library
else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) {
if (resultCode == Activity.RESULT_OK) {
Uri uri = intent.getData();
android.content.ContentResolver resolver = this.ctx.getContentResolver();
-
- // If you ask for video or all media type you will automatically get back a file URI
+
+ // If you ask for video or all media type you will automatically get back a file URI
// and there will be no attempt to resize any returned data
if (this.mediaType != PICTURE) {
- this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
+ this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
}
else {
// If sending base64 image back
@@ -383,8 +383,8 @@ public class CameraLauncher extends Plugin {
try {
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
String[] cols = { MediaStore.Images.Media.ORIENTATION };
- Cursor cursor = this.ctx.getContentResolver().query(intent.getData(),
- cols,
+ Cursor cursor = this.ctx.getContentResolver().query(intent.getData(),
+ cols,
null, null, null);
if (cursor != null) {
cursor.moveToPosition(0);
@@ -406,7 +406,7 @@ public class CameraLauncher extends Plugin {
this.failPicture("Error retrieving image.");
}
}
-
+
// If sending filename back
else if (destType == FILE_URI) {
// Do we need to scale the returned file
@@ -414,12 +414,12 @@ public class CameraLauncher extends Plugin {
try {
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
bitmap = scaleBitmap(bitmap);
-
+
String fileName = DirectoryManager.getTempDirectoryPath(ctx.getContext()) + "/resize.jpg";
- OutputStream os = new FileOutputStream(fileName);
+ OutputStream os = new FileOutputStream(fileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
os.close();
-
+
// Restore exif data to file
if (this.encodingType == JPEG) {
exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
@@ -428,8 +428,8 @@ public class CameraLauncher extends Plugin {
bitmap.recycle();
bitmap = null;
-
- // The resized image is cached by the app in order to get around this and not have to delete you
+
+ // The resized image is cached by the app in order to get around this and not have to delete you
// application cache I'm adding the current system time to the end of the file url.
this.success(new PluginResult(PluginResult.Status.OK, ("file://" + fileName + "?" + System.currentTimeMillis())), this.callbackId);
System.gc();
@@ -439,23 +439,23 @@ public class CameraLauncher extends Plugin {
}
}
else {
- this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
+ this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
}
}
}
}
else if (resultCode == Activity.RESULT_CANCELED) {
- this.failPicture("Selection cancelled.");
+ this.failPicture("Selection cancelled.");
}
else {
- this.failPicture("Selection did not complete!");
+ this.failPicture("Selection did not complete!");
}
}
}
/**
* Creates a cursor that can be used to determine how many images we have.
- *
+ *
* @return a cursor
*/
private Cursor queryImgDB() {
@@ -466,27 +466,27 @@ public class CameraLauncher extends Plugin {
null,
null);
}
-
+
/**
* Used to find out if we are in a situation where the Camera Intent adds to images
- * to the content store. If we are using a FILE_URI and the number of images in the DB
+ * to the content store. If we are using a FILE_URI and the number of images in the DB
* increases by 2 we have a duplicate, when using a DATA_URL the number is 1.
- *
+ *
* @param type FILE_URI or DATA_URL
*/
private void checkForDuplicateImage(int type) {
int diff = 1;
Cursor cursor = queryImgDB();
int currentNumOfImages = cursor.getCount();
-
+
if (type == FILE_URI) {
diff = 2;
}
-
+
// delete the duplicate file if the difference is 2 for file URI or 1 for Data URL
if ((currentNumOfImages - numPics) == diff) {
cursor.moveToLast();
- int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1;
+ int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1;
Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id);
this.ctx.getContentResolver().delete(uri, null, null);
}
@@ -497,7 +497,7 @@ public class CameraLauncher extends Plugin {
*
* @param bitmap
*/
- public void processPicture(Bitmap bitmap) {
+ public void processPicture(Bitmap bitmap) {
ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
try {
if (bitmap.compress(CompressFormat.JPEG, mQuality, jpeg_data)) {
@@ -508,17 +508,17 @@ public class CameraLauncher extends Plugin {
js_out = null;
output = null;
code = null;
- }
+ }
}
catch(Exception e) {
this.failPicture("Error compressing image.");
- }
+ }
jpeg_data = null;
}
-
+
/**
* Send error message to JavaScript.
- *
+ *
* @param err
*/
public void failPicture(String err) {
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6d1e0356/framework/src/org/apache/cordova/Capture.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/Capture.java b/framework/src/org/apache/cordova/Capture.java
index 1eb0b90..adf7059 100644
--- a/framework/src/org/apache/cordova/Capture.java
+++ b/framework/src/org/apache/cordova/Capture.java
@@ -45,23 +45,23 @@ public class Capture extends Plugin {
private static final String VIDEO_MP4 = "video/mp4";
private static final String AUDIO_3GPP = "audio/3gpp";
private static final String IMAGE_JPEG = "image/jpeg";
-
+
private static final int CAPTURE_AUDIO = 0; // Constant for capture audio
private static final int CAPTURE_IMAGE = 1; // Constant for capture image
private static final int CAPTURE_VIDEO = 2; // Constant for capture video
private static final String LOG_TAG = "Capture";
-
+
private static final int CAPTURE_INTERNAL_ERR = 0;
private static final int CAPTURE_APPLICATION_BUSY = 1;
private static final int CAPTURE_INVALID_ARGUMENT = 2;
private static final int CAPTURE_NO_MEDIA_FILES = 3;
private static final int CAPTURE_NOT_SUPPORTED = 20;
-
+
private String callbackId; // The ID of the callback to be invoked with our result
private long limit; // the number of pics/vids/clips to take
private double duration; // optional duration parameter for video recording
private JSONArray results; // The array of results to be returned to the user
- private Uri imageUri; // Uri of captured image
+ private Uri imageUri; // Uri of captured image
@Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
@@ -69,7 +69,7 @@ public class Capture extends Plugin {
this.limit = 1;
this.duration = 0.0f;
this.results = new JSONArray();
-
+
JSONObject options = args.optJSONObject(0);
if (options != null) {
limit = options.optLong("limit", 1);
@@ -91,9 +91,9 @@ public class Capture extends Plugin {
this.captureImage();
}
else if (action.equals("captureVideo")) {
- this.captureVideo(duration);
+ this.captureVideo(duration);
}
-
+
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
r.setKeepCallback(true);
return r;
@@ -101,7 +101,7 @@ public class Capture extends Plugin {
/**
* Provides the media data file data depending on it's mime type
- *
+ *
* @param filePath path to the file
* @param mimeType of the file
* @return a MediaFileData object
@@ -122,7 +122,7 @@ public class Capture extends Plugin {
mimeType = FileUtils.getMimeType(filePath);
}
Log.d(LOG_TAG, "Mime type = " + mimeType);
-
+
if (mimeType.equals(IMAGE_JPEG) || filePath.endsWith(".jpg")) {
obj = getImageData(filePath, obj);
}
@@ -141,7 +141,7 @@ public class Capture extends Plugin {
/**
* Get the Image specific attributes
- *
+ *
* @param filePath path to the file
* @param obj represents the Media File Data
* @return a JSONObject that represents the Media File Data
@@ -157,7 +157,7 @@ public class Capture extends Plugin {
/**
* Get the Image specific attributes
- *
+ *
* @param filePath path to the file
* @param obj represents the Media File Data
* @param video if true get video attributes as well
@@ -177,7 +177,7 @@ public class Capture extends Plugin {
}
catch (IOException e) {
Log.d(LOG_TAG, "Error: loading video file");
- }
+ }
return obj;
}
@@ -211,18 +211,18 @@ public class Capture extends Plugin {
Intent intent = new Intent(android.provider.MediaStore.ACTION_VIDEO_CAPTURE);
// Introduced in API 8
//intent.putExtra(android.provider.MediaStore.EXTRA_DURATION_LIMIT, duration);
-
+
this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_VIDEO);
}
-
+
/**
- * Called when the video view exits.
- *
- * @param requestCode The request code originally supplied to startActivityForResult(),
+ * Called when the video view exits.
+ *
+ * @param requestCode The request code originally supplied to startActivityForResult(),
* allowing you to identify who this result came from.
* @param resultCode The integer result code returned by the child activity through its setResult().
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
- * @throws JSONException
+ * @throws JSONException
*/
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
@@ -252,7 +252,7 @@ public class Capture extends Plugin {
ExifHelper exif = new ExifHelper();
exif.createInFile(DirectoryManager.getTempDirectoryPath(ctx.getContext()) + "/Capture.jpg");
exif.readExifData();
-
+
// Read in bitmap of captured image
Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getContentResolver(), imageUri);
@@ -268,7 +268,7 @@ public class Capture extends Plugin {
try {
uri = this.ctx.getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException ex) {
- LOG.d(LOG_TAG, "Can't write to internal media storage.");
+ LOG.d(LOG_TAG, "Can't write to internal media storage.");
this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image - no media storage found."));
return;
}
@@ -282,14 +282,14 @@ public class Capture extends Plugin {
bitmap.recycle();
bitmap = null;
System.gc();
-
+
// Restore exif data to file
exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
exif.writeExifData();
-
+
// Add image to results
results.put(createMediaFile(uri));
-
+
if (results.length() >= limit) {
// Send Uri back to JavaScript for viewing image
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
@@ -320,7 +320,7 @@ public class Capture extends Plugin {
else if (resultCode == Activity.RESULT_CANCELED) {
// If we have partial results send them back to the user
if (results.length() > 0) {
- this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
+ this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
}
// user canceled the action
else {
@@ -331,7 +331,7 @@ public class Capture extends Plugin {
else {
// If we have partial results send them back to the user
if (results.length() > 0) {
- this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
+ this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
}
// something bad happened
else {
@@ -342,43 +342,43 @@ public class Capture extends Plugin {
/**
* Creates a JSONObject that represents a File from the Uri
- *
+ *
* @param data the Uri of the audio/image/video
* @return a JSONObject that represents a File
- * @throws IOException
+ * @throws IOException
*/
private JSONObject createMediaFile(Uri data){
File fp = new File(FileUtils.getRealPathFromURI(data, this.ctx));
JSONObject obj = new JSONObject();
- try {
+ try {
// File properties
obj.put("name", fp.getName());
obj.put("fullPath", "file://" + fp.getAbsolutePath());
-
- // Because of an issue with MimeTypeMap.getMimeTypeFromExtension() all .3gpp files
- // are reported as video/3gpp. I'm doing this hacky check of the URI to see if it
+
+ // Because of an issue with MimeTypeMap.getMimeTypeFromExtension() all .3gpp files
+ // are reported as video/3gpp. I'm doing this hacky check of the URI to see if it
// is stored in the audio or video content store.
if (fp.getAbsoluteFile().toString().endsWith(".3gp") || fp.getAbsoluteFile().toString().endsWith(".3gpp")) {
if (data.toString().contains("/audio/")) {
- obj.put("type", AUDIO_3GPP);
+ obj.put("type", AUDIO_3GPP);
} else {
- obj.put("type", VIDEO_3GPP);
- }
+ obj.put("type", VIDEO_3GPP);
+ }
} else {
- obj.put("type", FileUtils.getMimeType(fp.getAbsolutePath()));
+ obj.put("type", FileUtils.getMimeType(fp.getAbsolutePath()));
}
-
+
obj.put("lastModifiedDate", fp.lastModified());
obj.put("size", fp.length());
} catch (JSONException e) {
// this will never happen
e.printStackTrace();
}
-
+
return obj;
}
-
+
private JSONObject createErrorObject(int code, String message) {
JSONObject obj = new JSONObject();
try {
@@ -392,7 +392,7 @@ public class Capture extends Plugin {
/**
* Send error message to JavaScript.
- *
+ *
* @param err
*/
public void fail(JSONObject err) {
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6d1e0356/framework/src/org/apache/cordova/CompassListener.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CompassListener.java b/framework/src/org/apache/cordova/CompassListener.java
index 01d431a..8615157 100755
--- a/framework/src/org/apache/cordova/CompassListener.java
+++ b/framework/src/org/apache/cordova/CompassListener.java
@@ -43,18 +43,18 @@ public class CompassListener extends Plugin implements SensorEventListener {
public static int STARTING = 1;
public static int RUNNING = 2;
public static int ERROR_FAILED_TO_START = 3;
-
+
public long TIMEOUT = 30000; // Timeout in msec to shut off listener
-
+
int status; // status of listener
float heading; // most recent heading value
long timeStamp; // time of most recent value
long lastAccessTime; // time the value was last retrieved
int accuracy; // accuracy of the sensor
-
+
private SensorManager sensorManager;// Sensor manager
Sensor mSensor; // Compass sensor returned by sensor manager
-
+
/**
* Constructor.
*/
@@ -67,7 +67,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
/**
* Sets the context of the Command. This can then be used to do things like
* get file paths associated with the Activity.
- *
+ *
* @param ctx The context of the main Activity.
*/
public void setContext(CordovaInterface ctx) {
@@ -77,7 +77,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
/**
* Executes the request and returns PluginResult.
- *
+ *
* @param action The action to execute.
* @param args JSONArry of arguments for the plugin.
* @param callbackId The callback id used when calling back into JavaScript.
@@ -85,8 +85,8 @@ public class CompassListener extends Plugin implements SensorEventListener {
*/
public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.OK;
- String result = "";
-
+ String result = "";
+
try {
if (action.equals("start")) {
this.start();
@@ -116,7 +116,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
}
}
if (timeout == 0) {
- return new PluginResult(PluginResult.Status.IO_EXCEPTION, CompassListener.ERROR_FAILED_TO_START);
+ return new PluginResult(PluginResult.Status.IO_EXCEPTION, CompassListener.ERROR_FAILED_TO_START);
}
}
return new PluginResult(status, getCompassHeading());
@@ -140,7 +140,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
/**
* Identifies if action to be executed returns a value and should be run synchronously.
- *
+ *
* @param action The action to execute
* @return T=returns value
*/
@@ -159,7 +159,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
}
return false;
}
-
+
/**
* Called when listener is to be shut down and object is being destroyed.
*/
@@ -173,11 +173,11 @@ public class CompassListener extends Plugin implements SensorEventListener {
/**
* Start listening for compass sensor.
- *
+ *
* @return status of listener
*/
public int start() {
-
+
// If already starting or running, then just return
if ((this.status == CompassListener.RUNNING) || (this.status == CompassListener.STARTING)) {
return this.status;
@@ -198,10 +198,10 @@ public class CompassListener extends Plugin implements SensorEventListener {
else {
this.setStatus(CompassListener.ERROR_FAILED_TO_START);
}
-
+
return this.status;
}
-
+
/**
* Stop listening to compass sensor.
*/
@@ -211,15 +211,15 @@ public class CompassListener extends Plugin implements SensorEventListener {
}
this.setStatus(CompassListener.STOPPED);
}
-
-
+
+
public void onAccuracyChanged(Sensor sensor, int accuracy) {
- // TODO Auto-generated method stub
+ // TODO Auto-generated method stub
}
/**
* Sensor listener event.
- *
+ *
* @param SensorEvent event
*/
public void onSensorChanged(SensorEvent event) {
@@ -237,38 +237,38 @@ public class CompassListener extends Plugin implements SensorEventListener {
this.stop();
}
}
-
+
/**
* Get status of compass sensor.
- *
+ *
* @return status
*/
public int getStatus() {
return this.status;
}
-
+
/**
* Get the most recent compass heading.
- *
+ *
* @return heading
*/
public float getHeading() {
this.lastAccessTime = System.currentTimeMillis();
return this.heading;
}
-
+
/**
* Set the timeout to turn off compass sensor if getHeading() hasn't been called.
- *
+ *
* @param timeout Timeout in msec.
*/
public void setTimeout(long timeout) {
this.TIMEOUT = timeout;
}
-
+
/**
* Get the timeout to turn off compass sensor if getHeading() hasn't been called.
- *
+ *
* @return timeout in msec
*/
public long getTimeout() {
@@ -285,23 +285,23 @@ public class CompassListener extends Plugin implements SensorEventListener {
/**
* Create the CompassHeading JSON object to be returned to JavaScript
- *
+ *
* @return a compass heading
*/
private JSONObject getCompassHeading() {
JSONObject obj = new JSONObject();
-
+
try {
obj.put("magneticHeading", this.getHeading());
obj.put("trueHeading", this.getHeading());
- // Since the magnetic and true heading are always the same our and accuracy
+ // Since the magnetic and true heading are always the same our and accuracy
// is defined as the difference between true and magnetic always return zero
obj.put("headingAccuracy", 0);
obj.put("timestamp", this.timeStamp);
} catch (JSONException e) {
// Should never happen
}
-
+
return obj;
}
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6d1e0356/framework/src/org/apache/cordova/ContactAccessor.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/ContactAccessor.java b/framework/src/org/apache/cordova/ContactAccessor.java
index d2bf66c..b8ac636 100644
--- a/framework/src/org/apache/cordova/ContactAccessor.java
+++ b/framework/src/org/apache/cordova/ContactAccessor.java
@@ -34,15 +34,15 @@ import org.json.JSONObject;
* Eclair or higher, we want to use {@link ContactAccessorSdk5}.
*/
public abstract class ContactAccessor {
-
+
protected final String LOG_TAG = "ContactsAccessor";
protected Context mApp;
protected WebView mView;
-
+
/**
- * Check to see if the data associated with the key is required to
+ * Check to see if the data associated with the key is required to
* be populated in the Contact object.
- * @param key
+ * @param key
* @param map created by running buildPopulationSet.
* @return true if the key data is required
*/
@@ -50,7 +50,7 @@ public abstract class ContactAccessor {
Boolean retVal = map.get(key);
return (retVal == null) ? false : retVal.booleanValue();
}
-
+
/**
* Create a hash map of what data needs to be populated in the Contact object
* @param fields the list of fields to populate
@@ -58,7 +58,7 @@ public abstract class ContactAccessor {
*/
protected HashMap<String,Boolean> buildPopulationSet(JSONArray fields) {
HashMap<String,Boolean> map = new HashMap<String,Boolean>();
-
+
String key;
try {
if (fields.length() == 1 && fields.getString(0).equals("*")) {
@@ -75,7 +75,7 @@ public abstract class ContactAccessor {
map.put("urls", true);
map.put("photos", true);
map.put("categories", true);
- }
+ }
else {
for (int i=0; i<fields.length(); i++) {
key = fields.getString(i);
@@ -127,12 +127,12 @@ public abstract class ContactAccessor {
}
return map;
}
-
+
/**
- * Convenience method to get a string from a JSON object. Saves a
+ * Convenience method to get a string from a JSON object. Saves a
* lot of try/catch writing.
* If the property is not found in the object null will be returned.
- *
+ *
* @param obj contact object to search
* @param property to be looked up
* @return The value of the property
@@ -150,7 +150,7 @@ public abstract class ContactAccessor {
}
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get = " + e.getMessage());
- }
+ }
return value;
}
@@ -167,7 +167,7 @@ public abstract class ContactAccessor {
/**
* Handles searching through SDK-specific contacts API.
- * @throws JSONException
+ * @throws JSONException
*/
public abstract JSONObject getContactById(String id) throws JSONException;
@@ -175,9 +175,9 @@ public abstract class ContactAccessor {
* Handles removing a contact from the database.
*/
public abstract boolean remove(String id);
-
+
/**
- * A class that represents the where clause to be used in the database query
+ * A class that represents the where clause to be used in the database query
*/
class WhereOptions {
private String where;