diff --git a/framework/assets/js/app.js b/framework/assets/js/app.js index 2068458a..8734cefd 100755 --- a/framework/assets/js/app.js +++ b/framework/assets/js/app.js @@ -95,16 +95,6 @@ App.prototype.exitApp = function() { return PhoneGap.exec(null, null, "App", "exitApp", []); }; -/** - * Add entry to approved list of URLs (whitelist) that will be loaded into PhoneGap container instead of default browser. - * - * @param origin URL regular expression to allow - * @param subdomains T=include all subdomains under origin - */ -App.prototype.addWhiteListEntry = function(origin, subdomains) { - return PhoneGap.exec(null, null, "App", "addWhiteListEntry", [origin, subdomains]); -}; - PhoneGap.addConstructor(function() { navigator.app = new App(); }); diff --git a/framework/assets/js/filetransfer.js b/framework/assets/js/filetransfer.js index 690cfcd1..e3e0d996 100644 --- a/framework/assets/js/filetransfer.js +++ b/framework/assets/js/filetransfer.js @@ -83,6 +83,17 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro PhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, debug, chunkedMode]); }; +/** + * Downloads a file form a given URL and saves it to the specified directory. + * @param source {String} URL of the server to receive the file + * @param target {String} Full path of the file on the device + * @param successCallback (Function} Callback to be invoked when upload has completed + * @param errorCallback {Function} Callback to be invoked upon error + */ +FileTransfer.prototype.download = function(source, target, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'download', [source, target]); +}; + /** * Options to customize the HTTP request used to upload files. * @constructor diff --git a/framework/src/com/phonegap/App.java b/framework/src/com/phonegap/App.java index 62074345..bd56bc16 100755 --- a/framework/src/com/phonegap/App.java +++ b/framework/src/com/phonegap/App.java @@ -70,9 +70,6 @@ public class App extends Plugin { else if (action.equals("exitApp")) { this.exitApp(); } - else if (action.equals("addWhiteListEntry")) { - this.addWhiteListEntry(args.getString(0), args.optBoolean(1)); - } return new PluginResult(status, result); } catch (JSONException e) { return new PluginResult(PluginResult.Status.JSON_EXCEPTION); @@ -198,14 +195,4 @@ public class App extends Plugin { public void exitApp() { ((DroidGap)this.ctx).endActivity(); } - - /** - * Add entry to approved list of URLs (whitelist) - * - * @param origin URL regular expression to allow - * @param subdomains T=include all subdomains under origin - */ - public void addWhiteListEntry(String origin, boolean subdomains) { - ((DroidGap)this.ctx).addWhiteListEntry(origin, subdomains); - } } diff --git a/framework/src/com/phonegap/DroidGap.java b/framework/src/com/phonegap/DroidGap.java index 97c62b31..26a04f56 100755 --- a/framework/src/com/phonegap/DroidGap.java +++ b/framework/src/com/phonegap/DroidGap.java @@ -19,7 +19,6 @@ package com.phonegap; import java.util.HashMap; -import java.util.Map.Entry; import java.util.ArrayList; import java.util.Stack; import java.util.regex.Pattern; @@ -30,7 +29,6 @@ import java.io.IOException; import org.json.JSONArray; import org.json.JSONException; -import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; @@ -43,12 +41,10 @@ import android.content.res.Configuration; import android.content.res.XmlResourceParser; import android.graphics.Bitmap; import android.graphics.Color; -import android.graphics.Rect; import android.media.AudioManager; import android.net.Uri; import android.net.http.SslError; import android.os.Bundle; -import android.util.Log; import android.view.Display; import android.view.KeyEvent; import android.view.Menu; @@ -275,12 +271,10 @@ public class DroidGap extends PhonegapActivity { ViewGroup.LayoutParams.FILL_PARENT, 1.0F)); - WebViewReflect.checkCompatibility(); - this.appView.setWebChromeClient(new GapClient(DroidGap.this)); this.setWebViewClient(this.appView, new GapViewClient(this)); - this.appView.setInitialScale(100); + this.appView.setInitialScale(0); this.appView.setVerticalScrollBarEnabled(false); this.appView.requestFocusFromTouch(); @@ -299,10 +293,10 @@ public class DroidGap extends PhonegapActivity { settings.setDatabasePath(databasePath); // Enable DOM storage - WebViewReflect.setDomStorage(settings); + settings.setDomStorageEnabled(true); // Enable built-in geolocation - WebViewReflect.setGeolocationEnabled(settings, true); + settings.setGeolocationEnabled(true); // Add web view but make it invisible while loading URL this.appView.setVisibility(View.INVISIBLE); @@ -311,7 +305,6 @@ public class DroidGap extends PhonegapActivity { // Clear cancel flag this.cancelLoadUrl = false; - } /** @@ -1592,7 +1585,7 @@ public class DroidGap extends PhonegapActivity { // Load URL on UI thread me.runOnUiThread(new Runnable() { public void run() { - me.showWebPage(errorUrl, true, true, null); + me.showWebPage(errorUrl, false, true, null); } }); } @@ -1767,7 +1760,7 @@ public class DroidGap extends PhonegapActivity { * @param origin URL regular expression to allow * @param subdomains T=include all subdomains under origin */ - public void addWhiteListEntry(String origin, boolean subdomains) { + private void addWhiteListEntry(String origin, boolean subdomains) { try { // Unlimited access to network resources if(origin.compareTo("*") == 0) { diff --git a/framework/src/com/phonegap/FileTransfer.java b/framework/src/com/phonegap/FileTransfer.java index 8d014a22..8e0e1e03 100644 --- a/framework/src/com/phonegap/FileTransfer.java +++ b/framework/src/com/phonegap/FileTransfer.java @@ -20,8 +20,10 @@ package com.phonegap; import java.io.DataInputStream; import java.io.DataOutputStream; +import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; @@ -52,98 +54,100 @@ import com.phonegap.api.PluginResult; public class FileTransfer extends Plugin { - private static final String LOG_TAG = "FileUploader"; - private static final String LINE_START = "--"; - private static final String LINE_END = "\r\n"; - private static final String BOUNDRY = "*****"; + private static final String LOG_TAG = "FileUploader"; + private static final String LINE_START = "--"; + private static final String LINE_END = "\r\n"; + private static final String BOUNDRY = "*****"; - public static int FILE_NOT_FOUND_ERR = 1; + public static int FILE_NOT_FOUND_ERR = 1; public static int INVALID_URL_ERR = 2; public static int CONNECTION_ERR = 3; - + private SSLSocketFactory defaultSSLSocketFactory = null; private HostnameVerifier defaultHostnameVerifier = null; - /* (non-Javadoc) - * @see com.phonegap.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String) - */ - @Override - public PluginResult execute(String action, JSONArray args, String callbackId) { - String file = null; - String server = null; - try { - file = args.getString(0); - server = args.getString(1); - } - catch (JSONException e) { - Log.d(LOG_TAG, "Missing filename or server name"); - return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing filename or server name"); - } - - // Setup the options - String fileKey = null; - String fileName = null; - String mimeType = null; - - fileKey = getArgument(args, 2, "file"); - fileName = getArgument(args, 3, "image.jpg"); - mimeType = getArgument(args, 4, "image/jpeg"); + /* (non-Javadoc) + * @see com.phonegap.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String) + */ + @Override + public PluginResult execute(String action, JSONArray args, String callbackId) { + String source = null; + String target = null; + try { + source = args.getString(0); + target = args.getString(1); + } + catch (JSONException e) { + Log.d(LOG_TAG, "Missing source or target"); + return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing source or target"); + } - try { - JSONObject params = args.optJSONObject(5); - boolean trustEveryone = args.optBoolean(6); - boolean chunkedMode = args.getBoolean(7); + try { + if (action.equals("upload")) { + // Setup the options + String fileKey = null; + String fileName = null; + String mimeType = null; - if (action.equals("upload")) { - FileUploadResult r = upload(file, server, fileKey, fileName, mimeType, params, trustEveryone, chunkedMode); - Log.d(LOG_TAG, "****** About to return a result from upload"); - return new PluginResult(PluginResult.Status.OK, r.toJSONObject()); - } else { - return new PluginResult(PluginResult.Status.INVALID_ACTION); - } - } catch (FileNotFoundException e) { - Log.e(LOG_TAG, e.getMessage(), e); - JSONObject error = createFileUploadError(FILE_NOT_FOUND_ERR); + fileKey = getArgument(args, 2, "file"); + fileName = getArgument(args, 3, "image.jpg"); + mimeType = getArgument(args, 4, "image/jpeg"); + JSONObject params = args.optJSONObject(5); + boolean trustEveryone = args.optBoolean(6); + boolean chunkedMode = args.optBoolean(7); + FileUploadResult r = upload(source, target, fileKey, fileName, mimeType, params, trustEveryone, chunkedMode); + Log.d(LOG_TAG, "****** About to return a result from upload"); + return new PluginResult(PluginResult.Status.OK, r.toJSONObject()); + } else if (action.equals("download")) { + JSONObject r = download(source, target); + Log.d(LOG_TAG, "****** About to return a result from download"); + return new PluginResult(PluginResult.Status.OK, r, "window.localFileSystem._castEntry"); + } else { + return new PluginResult(PluginResult.Status.INVALID_ACTION); + } + } catch (FileNotFoundException e) { + Log.e(LOG_TAG, e.getMessage(), e); + JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target); return new PluginResult(PluginResult.Status.IO_EXCEPTION, error); } catch (IllegalArgumentException e) { - Log.e(LOG_TAG, e.getMessage(), e); - JSONObject error = createFileUploadError(INVALID_URL_ERR); + Log.e(LOG_TAG, e.getMessage(), e); + JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target); return new PluginResult(PluginResult.Status.IO_EXCEPTION, error); - } catch (SSLException e) { - Log.e(LOG_TAG, e.getMessage(), e); - Log.d(LOG_TAG, "Got my ssl exception!!!"); - JSONObject error = createFileUploadError(CONNECTION_ERR); + } catch (SSLException e) { + Log.e(LOG_TAG, e.getMessage(), e); + Log.d(LOG_TAG, "Got my ssl exception!!!"); + JSONObject error = createFileTransferError(CONNECTION_ERR, source, target); return new PluginResult(PluginResult.Status.IO_EXCEPTION, error); } catch (IOException e) { - Log.e(LOG_TAG, e.getMessage(), e); - JSONObject error = createFileUploadError(CONNECTION_ERR); + Log.e(LOG_TAG, e.getMessage(), e); + JSONObject error = createFileTransferError(CONNECTION_ERR, source, target); return new PluginResult(PluginResult.Status.IO_EXCEPTION, error); - } catch (JSONException e) { - Log.e(LOG_TAG, e.getMessage(), e); - return new PluginResult(PluginResult.Status.JSON_EXCEPTION); - } - } - - // always verify the host - don't check for certificate - final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() { - public boolean verify(String hostname, SSLSession session) { - return true; + } catch (JSONException e) { + Log.e(LOG_TAG, e.getMessage(), e); + return new PluginResult(PluginResult.Status.JSON_EXCEPTION); } - }; + } - /** - * This function will install a trust manager that will blindly trust all SSL - * certificates. The reason this code is being added is to enable developers - * to do development using self signed SSL certificates on their web server. - * - * The standard HttpsURLConnection class will throw an exception on self - * signed certificates if this code is not run. - */ - private void trustAllHosts() { + // always verify the host - don't check for certificate + final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() { + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + /** + * This function will install a trust manager that will blindly trust all SSL + * certificates. The reason this code is being added is to enable developers + * to do development using self signed SSL certificates on their web server. + * + * The standard HttpsURLConnection class will throw an exception on self + * signed certificates if this code is not run. + */ + private void trustAllHosts() { // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return new java.security.cert.X509Certificate[] {}; + return new java.security.cert.X509Certificate[] {}; } public void checkClientTrusted(X509Certificate[] chain, @@ -157,54 +161,56 @@ public class FileTransfer extends Plugin { // Install the all-trusting trust manager try { - // Backup the current SSL socket factory - defaultSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory(); - // Install our all trusting manager - SSLContext sc = SSLContext.getInstance("TLS"); + // Backup the current SSL socket factory + defaultSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory(); + // Install our all trusting manager + SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { Log.e(LOG_TAG, e.getMessage(), e); } - } + } - /** - * Create an error object based on the passed in errorCode - * @param errorCode the error - * @return JSONObject containing the error - */ - private JSONObject createFileUploadError(int errorCode) { - JSONObject error = null; - try { - error = new JSONObject(); - error.put("code", errorCode); - } catch (JSONException e) { - Log.e(LOG_TAG, e.getMessage(), e); - } - return error; - } - - /** - * Convenience method to read a parameter from the list of JSON args. - * @param args the args passed to the Plugin - * @param position the position to retrieve the arg from - * @param defaultString the default to be used if the arg does not exist - * @return String with the retrieved value - */ - private String getArgument(JSONArray args, int position, String defaultString) { - String arg = defaultString; - if(args.length() >= position) { - arg = args.optString(position); - if (arg == null || "null".equals(arg)) { - arg = defaultString; - } - } - return arg; - } - /** - * Uploads the specified file to the server URL provided using an HTTP - * multipart request. + * Create an error object based on the passed in errorCode + * @param errorCode the error + * @return JSONObject containing the error + */ + private JSONObject createFileTransferError(int errorCode, String source, String target) { + JSONObject error = null; + try { + error = new JSONObject(); + error.put("code", errorCode); + error.put("source", source); + error.put("target", target); + } catch (JSONException e) { + Log.e(LOG_TAG, e.getMessage(), e); + } + return error; + } + + /** + * Convenience method to read a parameter from the list of JSON args. + * @param args the args passed to the Plugin + * @param position the position to retrieve the arg from + * @param defaultString the default to be used if the arg does not exist + * @return String with the retrieved value + */ + private String getArgument(JSONArray args, int position, String defaultString) { + String arg = defaultString; + if(args.length() >= position) { + arg = args.optString(position); + if (arg == null || "null".equals(arg)) { + arg = defaultString; + } + } + return arg; + } + + /** + * Uploads the specified file to the server URL provided using an HTTP + * multipart request. * @param file Full path of the file on the file system * @param server URL of the server to receive the file * @param fileKey Name of file request parameter @@ -213,173 +219,221 @@ public class FileTransfer extends Plugin { * @param params key:value pairs of user-defined parameters * @return FileUploadResult containing result of upload request */ - public FileUploadResult upload(String file, String server, final String fileKey, final String fileName, - final String mimeType, JSONObject params, boolean trustEveryone, boolean chunkedMode) throws IOException, SSLException { - // Create return object - FileUploadResult result = new FileUploadResult(); - - // Get a input stream of the file on the phone - InputStream fileInputStream = getPathFromUri(file); + public FileUploadResult upload(String file, String server, final String fileKey, final String fileName, + final String mimeType, JSONObject params, boolean trustEveryone, boolean chunkedMode) throws IOException, SSLException { + // Create return object + FileUploadResult result = new FileUploadResult(); - HttpURLConnection conn = null; - DataOutputStream dos = null; + // Get a input stream of the file on the phone + InputStream fileInputStream = getPathFromUri(file); - int bytesRead, bytesAvailable, bufferSize; - long totalBytes; - byte[] buffer; - int maxBufferSize = 8096; + HttpURLConnection conn = null; + DataOutputStream dos = null; - //------------------ CLIENT REQUEST - // open a URL connection to the server - URL url = new URL(server); - - // Open a HTTP connection to the URL based on protocol + int bytesRead, bytesAvailable, bufferSize; + long totalBytes; + byte[] buffer; + int maxBufferSize = 8096; + + //------------------ CLIENT REQUEST + // open a URL connection to the server + URL url = new URL(server); + + // Open a HTTP connection to the URL based on protocol if (url.getProtocol().toLowerCase().equals("https")) { - // Using standard HTTPS connection. Will not allow self signed certificate - if (!trustEveryone) { - conn = (HttpsURLConnection) url.openConnection(); - } - // Use our HTTPS connection that blindly trusts everyone. - // This should only be used in debug environments - else { - // Setup the HTTPS connection class to trust everyone - trustAllHosts(); - HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); - // Save the current hostnameVerifier - defaultHostnameVerifier = https.getHostnameVerifier(); - // Setup the connection not to verify hostnames - https.setHostnameVerifier(DO_NOT_VERIFY); - conn = https; - } - } + // Using standard HTTPS connection. Will not allow self signed certificate + if (!trustEveryone) { + conn = (HttpsURLConnection) url.openConnection(); + } + // Use our HTTPS connection that blindly trusts everyone. + // This should only be used in debug environments + else { + // Setup the HTTPS connection class to trust everyone + trustAllHosts(); + HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); + // Save the current hostnameVerifier + defaultHostnameVerifier = https.getHostnameVerifier(); + // Setup the connection not to verify hostnames + https.setHostnameVerifier(DO_NOT_VERIFY); + conn = https; + } + } // Return a standard HTTP connection else { - conn = (HttpURLConnection) url.openConnection(); + conn = (HttpURLConnection) url.openConnection(); } - - // Allow Inputs - conn.setDoInput(true); - - // Allow Outputs - conn.setDoOutput(true); - - // Don't use a cached copy. - conn.setUseCaches(false); - - // Use a post method. - conn.setRequestMethod("POST"); - conn.setRequestProperty("Connection", "Keep-Alive"); - conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+BOUNDRY); - // Set the cookies on the response - String cookie = CookieManager.getInstance().getCookie(server); - if (cookie != null) { - conn.setRequestProperty("Cookie", cookie); - } - - // Should set this up as an option - if (chunkedMode) { - conn.setChunkedStreamingMode(maxBufferSize); - } - - dos = new DataOutputStream( conn.getOutputStream() ); + // Allow Inputs + conn.setDoInput(true); - // Send any extra parameters - try { - for (Iterator iter = params.keys(); iter.hasNext();) { - Object key = iter.next(); - dos.writeBytes(LINE_START + BOUNDRY + LINE_END); - dos.writeBytes("Content-Disposition: form-data; name=\"" + key.toString() + "\";"); - dos.writeBytes(LINE_END + LINE_END); - dos.write(params.getString(key.toString()).getBytes()); - dos.writeBytes(LINE_END); - } - } catch (JSONException e) { - Log.e(LOG_TAG, e.getMessage(), e); - } - - dos.writeBytes(LINE_START + BOUNDRY + LINE_END); - dos.writeBytes("Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"" + fileName +"\"" + LINE_END); - dos.writeBytes("Content-Type: " + mimeType + LINE_END); - dos.writeBytes(LINE_END); - - // create a buffer of maximum size - bytesAvailable = fileInputStream.available(); - bufferSize = Math.min(bytesAvailable, maxBufferSize); - buffer = new byte[bufferSize]; - - // read file and write it into form... - bytesRead = fileInputStream.read(buffer, 0, bufferSize); - totalBytes = 0; + // Allow Outputs + conn.setDoOutput(true); - while (bytesRead > 0) { - totalBytes += bytesRead; - result.setBytesSent(totalBytes); - dos.write(buffer, 0, bufferSize); - bytesAvailable = fileInputStream.available(); - bufferSize = Math.min(bytesAvailable, maxBufferSize); - bytesRead = fileInputStream.read(buffer, 0, bufferSize); - } + // Don't use a cached copy. + conn.setUseCaches(false); - // send multipart form data necesssary after file data... - dos.writeBytes(LINE_END); - dos.writeBytes(LINE_START + BOUNDRY + LINE_START + LINE_END); - - // close streams - fileInputStream.close(); - dos.flush(); - dos.close(); + // Use a post method. + conn.setRequestMethod("POST"); + conn.setRequestProperty("Connection", "Keep-Alive"); + conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+BOUNDRY); - //------------------ read the SERVER RESPONSE - StringBuffer responseString = new StringBuffer(""); - DataInputStream inStream; - try { - inStream = new DataInputStream ( conn.getInputStream() ); - } catch(FileNotFoundException e) { - throw new IOException("Received error from server"); - } - - String line; - while (( line = inStream.readLine()) != null) { - responseString.append(line); - } - Log.d(LOG_TAG, "got response from server"); - Log.d(LOG_TAG, responseString.toString()); + // Set the cookies on the response + String cookie = CookieManager.getInstance().getCookie(server); + if (cookie != null) { + conn.setRequestProperty("Cookie", cookie); + } - // send request and retrieve response + // Should set this up as an option + if (chunkedMode) { + conn.setChunkedStreamingMode(maxBufferSize); + } + + dos = new DataOutputStream( conn.getOutputStream() ); + + // Send any extra parameters + try { + for (Iterator iter = params.keys(); iter.hasNext();) { + Object key = iter.next(); + dos.writeBytes(LINE_START + BOUNDRY + LINE_END); + dos.writeBytes("Content-Disposition: form-data; name=\"" + key.toString() + "\";"); + dos.writeBytes(LINE_END + LINE_END); + dos.write(params.getString(key.toString()).getBytes()); + dos.writeBytes(LINE_END); + } + } catch (JSONException e) { + Log.e(LOG_TAG, e.getMessage(), e); + } + + dos.writeBytes(LINE_START + BOUNDRY + LINE_END); + dos.writeBytes("Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"" + fileName +"\"" + LINE_END); + dos.writeBytes("Content-Type: " + mimeType + LINE_END); + dos.writeBytes(LINE_END); + + // create a buffer of maximum size + bytesAvailable = fileInputStream.available(); + bufferSize = Math.min(bytesAvailable, maxBufferSize); + buffer = new byte[bufferSize]; + + // read file and write it into form... + bytesRead = fileInputStream.read(buffer, 0, bufferSize); + totalBytes = 0; + + while (bytesRead > 0) { + totalBytes += bytesRead; + result.setBytesSent(totalBytes); + dos.write(buffer, 0, bufferSize); + bytesAvailable = fileInputStream.available(); + bufferSize = Math.min(bytesAvailable, maxBufferSize); + bytesRead = fileInputStream.read(buffer, 0, bufferSize); + } + + // send multipart form data necesssary after file data... + dos.writeBytes(LINE_END); + dos.writeBytes(LINE_START + BOUNDRY + LINE_START + LINE_END); + + // close streams + fileInputStream.close(); + dos.flush(); + dos.close(); + + //------------------ read the SERVER RESPONSE + StringBuffer responseString = new StringBuffer(""); + DataInputStream inStream; + try { + inStream = new DataInputStream ( conn.getInputStream() ); + } catch(FileNotFoundException e) { + throw new IOException("Received error from server"); + } + + String line; + while (( line = inStream.readLine()) != null) { + responseString.append(line); + } + Log.d(LOG_TAG, "got response from server"); + Log.d(LOG_TAG, responseString.toString()); + + // send request and retrieve response result.setResponseCode(conn.getResponseCode()); result.setResponse(responseString.toString()); inStream.close(); conn.disconnect(); - + // Revert back to the proper verifier and socket factories if (trustEveryone && url.getProtocol().toLowerCase().equals("https")) { - ((HttpsURLConnection)conn).setHostnameVerifier(defaultHostnameVerifier); - HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSocketFactory); - } - - return result; - } + ((HttpsURLConnection)conn).setHostnameVerifier(defaultHostnameVerifier); + HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSocketFactory); + } - /** + return result; + } + + /** + * Downloads a file form a given URL and saves it to the specified directory. + * + * @param source URL of the server to receive the file + * @param target Full path of the file on the file system + * @return JSONObject the downloaded file + */ + public JSONObject download(String source, String target) throws IOException { + try { + File file = new File(target); + + // create needed directories + file.getParentFile().mkdirs(); + + // connect to server + URL url = new URL(source); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setDoOutput(true); + connection.connect(); + + Log.d(LOG_TAG, "Download file:" + url); + + InputStream inputStream = connection.getInputStream(); + byte[] buffer = new byte[1024]; + int bytesRead = 0; + + FileOutputStream outputStream = new FileOutputStream(file); + + // write bytes to file + while ( (bytesRead = inputStream.read(buffer)) > 0 ) { + outputStream.write(buffer,0, bytesRead); + } + + outputStream.close(); + + Log.d(LOG_TAG, "Saved file: " + target); + + // create FileEntry object + FileUtils fileUtil = new FileUtils(); + + return fileUtil.getEntry(file); + } catch (Exception e) { + Log.d(LOG_TAG, e.getMessage(), e); + throw new IOException("Error while downloading"); + } + } + + /** * Get an input stream based on file path or content:// uri - * + * * @param path * @return an input stream - * @throws FileNotFoundException + * @throws FileNotFoundException */ - private InputStream getPathFromUri(String path) throws FileNotFoundException { - if (path.startsWith("content:")) { - Uri uri = Uri.parse(path); - return ctx.getContentResolver().openInputStream(uri); - } - else if (path.startsWith("file://")) { - return new FileInputStream(path.substring(7)); - } - else { - return new FileInputStream(path); - } - } + private InputStream getPathFromUri(String path) throws FileNotFoundException { + if (path.startsWith("content:")) { + Uri uri = Uri.parse(path); + return ctx.getContentResolver().openInputStream(uri); + } + else if (path.startsWith("file://")) { + return new FileInputStream(path.substring(7)); + } + else { + return new FileInputStream(path); + } + } } diff --git a/framework/src/com/phonegap/FileUtils.java b/framework/src/com/phonegap/FileUtils.java index 33f847df..de20405c 100755 --- a/framework/src/com/phonegap/FileUtils.java +++ b/framework/src/com/phonegap/FileUtils.java @@ -50,214 +50,214 @@ import com.phonegap.file.TypeMismatchException; * Only files on the SD card can be accessed. */ public class FileUtils extends Plugin { - private static final String LOG_TAG = "FileUtils"; - private static final String _DATA = "_data"; // The column name where the file path is stored + private static final String LOG_TAG = "FileUtils"; + private static final String _DATA = "_data"; // The column name where the file path is stored - public static int NOT_FOUND_ERR = 1; - public static int SECURITY_ERR = 2; - public static int ABORT_ERR = 3; + public static int NOT_FOUND_ERR = 1; + public static int SECURITY_ERR = 2; + public static int ABORT_ERR = 3; - public static int NOT_READABLE_ERR = 4; - public static int ENCODING_ERR = 5; - public static int NO_MODIFICATION_ALLOWED_ERR = 6; - public static int INVALID_STATE_ERR = 7; - public static int SYNTAX_ERR = 8; - public static int INVALID_MODIFICATION_ERR = 9; + public static int NOT_READABLE_ERR = 4; + public static int ENCODING_ERR = 5; + public static int NO_MODIFICATION_ALLOWED_ERR = 6; + public static int INVALID_STATE_ERR = 7; + public static int SYNTAX_ERR = 8; + public static int INVALID_MODIFICATION_ERR = 9; public static int QUOTA_EXCEEDED_ERR = 10; public static int TYPE_MISMATCH_ERR = 11; public static int PATH_EXISTS_ERR = 12; - public static int TEMPORARY = 0; - public static int PERSISTENT = 1; - public static int RESOURCE = 2; - public static int APPLICATION = 3; - - FileReader f_in; - FileWriter f_out; - - /** - * Constructor. - */ - public FileUtils() { - } + public static int TEMPORARY = 0; + public static int PERSISTENT = 1; + public static int RESOURCE = 2; + public static int APPLICATION = 3; - /** - * 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. - * @return A PluginResult object with a status and message. - */ - public PluginResult execute(String action, JSONArray args, String callbackId) { - PluginResult.Status status = PluginResult.Status.OK; - String result = ""; - //System.out.println("FileUtils.execute("+action+")"); - - try { - try { - if (action.equals("testSaveLocationExists")) { - boolean b = DirectoryManager.testSaveLocationExists(); - return new PluginResult(status, b); - } - else if (action.equals("getFreeDiskSpace")) { - long l = DirectoryManager.getFreeDiskSpace(); - return new PluginResult(status, l); - } - else if (action.equals("testFileExists")) { - boolean b = DirectoryManager.testFileExists(args.getString(0)); - return new PluginResult(status, b); - } - else if (action.equals("testDirectoryExists")) { - boolean b = DirectoryManager.testFileExists(args.getString(0)); - return new PluginResult(status, b); - } - else if (action.equals("readAsText")) { - String s = this.readAsText(args.getString(0), args.getString(1)); - return new PluginResult(status, s); - } - else if (action.equals("readAsDataURL")) { - String s = this.readAsDataURL(args.getString(0)); - return new PluginResult(status, s); - } - else if (action.equals("write")) { - long fileSize = this.write(args.getString(0), args.getString(1), args.getInt(2)); - return new PluginResult(status, fileSize); - } - else if (action.equals("truncate")) { - long fileSize = this.truncateFile(args.getString(0), args.getLong(1)); - return new PluginResult(status, fileSize); - } - else if (action.equals("requestFileSystem")) { - long size = args.optLong(1); - if (size != 0) { - if (size > (DirectoryManager.getFreeDiskSpace()*1024)) { - JSONObject error = new JSONObject().put("code", FileUtils.QUOTA_EXCEEDED_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } - } - JSONObject obj = requestFileSystem(args.getInt(0)); - return new PluginResult(status, obj, "window.localFileSystem._castFS"); - } - else if (action.equals("resolveLocalFileSystemURI")) { - JSONObject obj = resolveLocalFileSystemURI(args.getString(0)); - return new PluginResult(status, obj, "window.localFileSystem._castEntry"); - } - else if (action.equals("getMetadata")) { - JSONObject obj = getMetadata(args.getString(0)); - return new PluginResult(status, obj, "window.localFileSystem._castDate"); - } - else if (action.equals("getFileMetadata")) { - JSONObject obj = getFileMetadata(args.getString(0)); - return new PluginResult(status, obj, "window.localFileSystem._castDate"); - } - else if (action.equals("getParent")) { - JSONObject obj = getParent(args.getString(0)); - return new PluginResult(status, obj, "window.localFileSystem._castEntry"); - } - else if (action.equals("getDirectory")) { - JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), true); - return new PluginResult(status, obj, "window.localFileSystem._castEntry"); - } - else if (action.equals("getFile")) { - JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), false); - return new PluginResult(status, obj, "window.localFileSystem._castEntry"); - } - else if (action.equals("remove")) { - boolean success; - - success = remove(args.getString(0)); - - if (success) { - notifyDelete(args.getString(0)); - return new PluginResult(status); - } else { - JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } - } - else if (action.equals("removeRecursively")) { - boolean success = removeRecursively(args.getString(0)); - if (success) { - return new PluginResult(status); - } else { - JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } - } - else if (action.equals("moveTo")) { - JSONObject entry = transferTo(args.getString(0), args.getJSONObject(1), args.optString(2), true); - return new PluginResult(status, entry, "window.localFileSystem._castEntry"); - } - else if (action.equals("copyTo")) { - JSONObject entry = transferTo(args.getString(0), args.getJSONObject(1), args.optString(2), false); - return new PluginResult(status, entry, "window.localFileSystem._castEntry"); - } - else if (action.equals("readEntries")) { - JSONArray entries = readEntries(args.getString(0)); - return new PluginResult(status, entries, "window.localFileSystem._castEntries"); - } - return new PluginResult(status, result); - } catch (FileNotFoundException e) { - JSONObject error = new JSONObject().put("code", FileUtils.NOT_FOUND_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } catch (FileExistsException e) { - JSONObject error = new JSONObject().put("code", FileUtils.PATH_EXISTS_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } catch (NoModificationAllowedException e) { - JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } catch (JSONException e) { - JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } catch (InvalidModificationException e) { - JSONObject error = new JSONObject().put("code", FileUtils.INVALID_MODIFICATION_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } catch (MalformedURLException e) { - JSONObject error = new JSONObject().put("code", FileUtils.ENCODING_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } catch (IOException e) { - JSONObject error = new JSONObject().put("code", FileUtils.INVALID_MODIFICATION_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } catch (EncodingException e) { - JSONObject error = new JSONObject().put("code", FileUtils.ENCODING_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } catch (TypeMismatchException e) { - JSONObject error = new JSONObject().put("code", FileUtils.TYPE_MISMATCH_ERR); - return new PluginResult(PluginResult.Status.ERROR, error); - } - } catch (JSONException e) { - e.printStackTrace(); - return new PluginResult(PluginResult.Status.JSON_EXCEPTION); - } - } - - /** - * Need to check to see if we need to clean up the content store - * - * @param filePath the path to check - */ - private void notifyDelete(String filePath) { - int result = this.ctx.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - MediaStore.Images.Media.DATA + " = ?", - new String[] {filePath}); - } + FileReader f_in; + FileWriter f_out; /** - * Allows the user to look up the Entry for a file or directory referred to by a local URI. - * - * @param url of the file/directory to look up - * @return a JSONObject representing a Entry from the filesystem - * @throws MalformedURLException if the url is not valid - * @throws FileNotFoundException if the file does not exist - * @throws IOException if the user can't read the file - * @throws JSONException - */ - private JSONObject resolveLocalFileSystemURI(String url) throws IOException, JSONException { + * Constructor. + */ + public FileUtils() { + } + + /** + * 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. + * @return A PluginResult object with a status and message. + */ + public PluginResult execute(String action, JSONArray args, String callbackId) { + PluginResult.Status status = PluginResult.Status.OK; + String result = ""; + //System.out.println("FileUtils.execute("+action+")"); + + try { + try { + if (action.equals("testSaveLocationExists")) { + boolean b = DirectoryManager.testSaveLocationExists(); + return new PluginResult(status, b); + } + else if (action.equals("getFreeDiskSpace")) { + long l = DirectoryManager.getFreeDiskSpace(); + return new PluginResult(status, l); + } + else if (action.equals("testFileExists")) { + boolean b = DirectoryManager.testFileExists(args.getString(0)); + return new PluginResult(status, b); + } + else if (action.equals("testDirectoryExists")) { + boolean b = DirectoryManager.testFileExists(args.getString(0)); + return new PluginResult(status, b); + } + else if (action.equals("readAsText")) { + String s = this.readAsText(args.getString(0), args.getString(1)); + return new PluginResult(status, s); + } + else if (action.equals("readAsDataURL")) { + String s = this.readAsDataURL(args.getString(0)); + return new PluginResult(status, s); + } + else if (action.equals("write")) { + long fileSize = this.write(args.getString(0), args.getString(1), args.getInt(2)); + return new PluginResult(status, fileSize); + } + else if (action.equals("truncate")) { + long fileSize = this.truncateFile(args.getString(0), args.getLong(1)); + return new PluginResult(status, fileSize); + } + else if (action.equals("requestFileSystem")) { + long size = args.optLong(1); + if (size != 0) { + if (size > (DirectoryManager.getFreeDiskSpace()*1024)) { + JSONObject error = new JSONObject().put("code", FileUtils.QUOTA_EXCEEDED_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } + } + JSONObject obj = requestFileSystem(args.getInt(0)); + return new PluginResult(status, obj, "window.localFileSystem._castFS"); + } + else if (action.equals("resolveLocalFileSystemURI")) { + JSONObject obj = resolveLocalFileSystemURI(args.getString(0)); + return new PluginResult(status, obj, "window.localFileSystem._castEntry"); + } + else if (action.equals("getMetadata")) { + JSONObject obj = getMetadata(args.getString(0)); + return new PluginResult(status, obj, "window.localFileSystem._castDate"); + } + else if (action.equals("getFileMetadata")) { + JSONObject obj = getFileMetadata(args.getString(0)); + return new PluginResult(status, obj, "window.localFileSystem._castDate"); + } + else if (action.equals("getParent")) { + JSONObject obj = getParent(args.getString(0)); + return new PluginResult(status, obj, "window.localFileSystem._castEntry"); + } + else if (action.equals("getDirectory")) { + JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), true); + return new PluginResult(status, obj, "window.localFileSystem._castEntry"); + } + else if (action.equals("getFile")) { + JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), false); + return new PluginResult(status, obj, "window.localFileSystem._castEntry"); + } + else if (action.equals("remove")) { + boolean success; + + success = remove(args.getString(0)); + + if (success) { + notifyDelete(args.getString(0)); + return new PluginResult(status); + } else { + JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } + } + else if (action.equals("removeRecursively")) { + boolean success = removeRecursively(args.getString(0)); + if (success) { + return new PluginResult(status); + } else { + JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } + } + else if (action.equals("moveTo")) { + JSONObject entry = transferTo(args.getString(0), args.getJSONObject(1), args.optString(2), true); + return new PluginResult(status, entry, "window.localFileSystem._castEntry"); + } + else if (action.equals("copyTo")) { + JSONObject entry = transferTo(args.getString(0), args.getJSONObject(1), args.optString(2), false); + return new PluginResult(status, entry, "window.localFileSystem._castEntry"); + } + else if (action.equals("readEntries")) { + JSONArray entries = readEntries(args.getString(0)); + return new PluginResult(status, entries, "window.localFileSystem._castEntries"); + } + return new PluginResult(status, result); + } catch (FileNotFoundException e) { + JSONObject error = new JSONObject().put("code", FileUtils.NOT_FOUND_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } catch (FileExistsException e) { + JSONObject error = new JSONObject().put("code", FileUtils.PATH_EXISTS_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } catch (NoModificationAllowedException e) { + JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } catch (JSONException e) { + JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } catch (InvalidModificationException e) { + JSONObject error = new JSONObject().put("code", FileUtils.INVALID_MODIFICATION_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } catch (MalformedURLException e) { + JSONObject error = new JSONObject().put("code", FileUtils.ENCODING_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } catch (IOException e) { + JSONObject error = new JSONObject().put("code", FileUtils.INVALID_MODIFICATION_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } catch (EncodingException e) { + JSONObject error = new JSONObject().put("code", FileUtils.ENCODING_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } catch (TypeMismatchException e) { + JSONObject error = new JSONObject().put("code", FileUtils.TYPE_MISMATCH_ERR); + return new PluginResult(PluginResult.Status.ERROR, error); + } + } catch (JSONException e) { + e.printStackTrace(); + return new PluginResult(PluginResult.Status.JSON_EXCEPTION); + } + } + + /** + * Need to check to see if we need to clean up the content store + * + * @param filePath the path to check + */ + private void notifyDelete(String filePath) { + int result = this.ctx.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + MediaStore.Images.Media.DATA + " = ?", + new String[] {filePath}); + } + + /** + * Allows the user to look up the Entry for a file or directory referred to by a local URI. + * + * @param url of the file/directory to look up + * @return a JSONObject representing a Entry from the filesystem + * @throws MalformedURLException if the url is not valid + * @throws FileNotFoundException if the file does not exist + * @throws IOException if the user can't read the file + * @throws JSONException + */ + private JSONObject resolveLocalFileSystemURI(String url) throws IOException, JSONException { String decoded = URLDecoder.decode(url, "UTF-8"); - + File fp = null; - + // Handle the special case where you get an Android content:// uri. if (decoded.startsWith("content:")) { Cursor cursor = this.ctx.managedQuery(Uri.parse(decoded), new String[] { MediaStore.Images.Media.DATA }, null, null, null); @@ -266,15 +266,15 @@ public class FileUtils extends Plugin { cursor.moveToFirst(); fp = new File(cursor.getString(column_index)); } else { - // Test to see if this is a valid URL first - @SuppressWarnings("unused") - URL testUrl = new URL(decoded); - - if (decoded.startsWith("file://")) { - fp = new File(decoded.substring(7, decoded.length())); - } else { - fp = new File(decoded); - } + // Test to see if this is a valid URL first + @SuppressWarnings("unused") + URL testUrl = new URL(decoded); + + if (decoded.startsWith("file://")) { + fp = new File(decoded.substring(7, decoded.length())); + } else { + fp = new File(decoded); + } } if (!fp.exists()) { @@ -283,614 +283,613 @@ public class FileUtils extends Plugin { if (!fp.canRead()) { throw new IOException(); } - return getEntry(fp); - } + return getEntry(fp); + } - /** - * Read the list of files from this directory. - * - * @param fileName the directory to read from - * @return a JSONArray containing JSONObjects that represent Entry objects. - * @throws FileNotFoundException if the directory is not found. - * @throws JSONException - */ - private JSONArray readEntries(String fileName) throws FileNotFoundException, JSONException { - File fp = new File(fileName); + /** + * Read the list of files from this directory. + * + * @param fileName the directory to read from + * @return a JSONArray containing JSONObjects that represent Entry objects. + * @throws FileNotFoundException if the directory is not found. + * @throws JSONException + */ + private JSONArray readEntries(String fileName) throws FileNotFoundException, JSONException { + File fp = new File(fileName); - if (!fp.exists()) { - // The directory we are listing doesn't exist so we should fail. - throw new FileNotFoundException(); - } + if (!fp.exists()) { + // The directory we are listing doesn't exist so we should fail. + throw new FileNotFoundException(); + } - JSONArray entries = new JSONArray(); - - if (fp.isDirectory()) { - File[] files = fp.listFiles(); - for (int i=0; i 0) { - throw new InvalidModificationException("directory is not empty"); - } - } - - // Try to rename the directory - if (!srcDir.renameTo(destinationDir)) { - // Trying to rename the directory failed. Possibly because we moved across file system on the device. - // Now we have to do things the hard way - // 1) Copy all the old files - // 2) delete the src directory - } - - return getEntry(destinationDir); - } + // Try to rename the file + if (!srcFile.renameTo(destFile)) { + // Trying to rename the file failed. Possibly because we moved across file system on the device. + // Now we have to do things the hard way + // 1) Copy all the old file + // 2) delete the src file + } - /** - * Deletes a directory and all of its contents, if any. In the event of an error - * [e.g. trying to delete a directory that contains a file that cannot be removed], - * some of the contents of the directory may be deleted. - * It is an error to attempt to delete the root directory of a filesystem. - * - * @param filePath the directory to be removed - * @return a boolean representing success of failure - * @throws FileExistsException - */ - private boolean removeRecursively(String filePath) throws FileExistsException { - File fp = new File(filePath); + return getEntry(destFile); + } - // You can't delete the root directory. - if (atRootDirectory(filePath)) { - return false; - } + /** + * Move a directory + * + * @param srcDir directory to be copied + * @param destinationDir destination to be copied to + * @return a DirectoryEntry object + * @throws JSONException + * @throws IOException + * @throws InvalidModificationException + */ + private JSONObject moveDirectory(File srcDir, File destinationDir) throws JSONException, InvalidModificationException { + // Renaming a file to an existing directory should fail + if (destinationDir.exists() && destinationDir.isFile()) { + throw new InvalidModificationException("Can't rename a file to a directory"); + } - return removeDirRecursively(fp); - } - - /** - * Loops through a directory deleting all the files. - * - * @param directory to be removed - * @return a boolean representing success of failure - * @throws FileExistsException - */ - private boolean removeDirRecursively(File directory) throws FileExistsException { - if (directory.isDirectory()) { - for (File file : directory.listFiles()) { - removeDirRecursively(file); - } - } + // Check to make sure we are not copying the directory into itself + if (isCopyOnItself(srcDir.getAbsolutePath(), destinationDir.getAbsolutePath())) { + throw new InvalidModificationException("Can't move itself into itself"); + } - if (!directory.delete()) { - throw new FileExistsException("could not delete: " + directory.getName()); - } else { - return true; - } - } + // If the destination directory already exists and is empty then delete it. This is according to spec. + if (destinationDir.exists()) { + if (destinationDir.list().length > 0) { + throw new InvalidModificationException("directory is not empty"); + } + } - /** - * Deletes a file or directory. It is an error to attempt to delete a directory that is not empty. - * It is an error to attempt to delete the root directory of a filesystem. - * - * @param filePath file or directory to be removed - * @return a boolean representing success of failure - * @throws NoModificationAllowedException - * @throws InvalidModificationException - */ - private boolean remove(String filePath) throws NoModificationAllowedException, InvalidModificationException { - File fp = new File(filePath); - - // You can't delete the root directory. - if (atRootDirectory(filePath)) { - throw new NoModificationAllowedException("You can't delete the root directory"); - } - - // You can't delete a directory that is not empty - if (fp.isDirectory() && fp.list().length > 0) { - throw new InvalidModificationException("You can't delete a directory that is not empty."); - } - - return fp.delete(); - } + // Try to rename the directory + if (!srcDir.renameTo(destinationDir)) { + // Trying to rename the directory failed. Possibly because we moved across file system on the device. + // Now we have to do things the hard way + // 1) Copy all the old files + // 2) delete the src directory + } - /** - * Creates or looks up a file. - * - * @param dirPath base directory - * @param fileName file/directory to lookup or create - * @param options specify whether to create or not - * @param directory if true look up directory, if false look up file - * @return a Entry object - * @throws FileExistsException - * @throws IOException - * @throws TypeMismatchException - * @throws EncodingException - * @throws JSONException - */ - private JSONObject getFile(String dirPath, String fileName, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException { - boolean create = false; - boolean exclusive = false; - if (options != null) { - create = options.optBoolean("create"); - if (create) { - exclusive = options.optBoolean("exclusive"); - } - } - - // Check for a ":" character in the file to line up with BB and iOS - if (fileName.contains(":")) { - throw new EncodingException("This file has a : in it's name"); - } - - File fp = createFileObject(dirPath, fileName); - - if (create) { - if (exclusive && fp.exists()) { - throw new FileExistsException("create/exclusive fails"); - } - if (directory) { - fp.mkdir(); - } else { - fp.createNewFile(); - } - if (!fp.exists()) { - throw new FileExistsException("create fails"); - } - } - else { - if (!fp.exists()) { - throw new FileNotFoundException("path does not exist"); - } - if (directory) { - if (fp.isFile()) { - throw new TypeMismatchException("path doesn't exist or is file"); - } - } else { - if (fp.isDirectory()) { - throw new TypeMismatchException("path doesn't exist or is directory"); - } - } - } + return getEntry(destinationDir); + } - // Return the directory - return getEntry(fp); - } + /** + * Deletes a directory and all of its contents, if any. In the event of an error + * [e.g. trying to delete a directory that contains a file that cannot be removed], + * some of the contents of the directory may be deleted. + * It is an error to attempt to delete the root directory of a filesystem. + * + * @param filePath the directory to be removed + * @return a boolean representing success of failure + * @throws FileExistsException + */ + private boolean removeRecursively(String filePath) throws FileExistsException { + File fp = new File(filePath); - /** - * If the path starts with a '/' just return that file object. If not construct the file - * object from the path passed in and the file name. - * - * @param dirPath root directory - * @param fileName new file name - * @return - */ - private File createFileObject(String dirPath, String fileName) { - File fp = null; - if (fileName.startsWith("/")) { - fp = new File(fileName); - } else { - fp = new File(dirPath + File.separator + fileName); - } - return fp; - } + // You can't delete the root directory. + if (atRootDirectory(filePath)) { + return false; + } - /** - * Look up the parent DirectoryEntry containing this Entry. - * If this Entry is the root of its filesystem, its parent is itself. - * - * @param filePath - * @return - * @throws JSONException - */ - private JSONObject getParent(String filePath) throws JSONException { - if (atRootDirectory(filePath)) { - return getEntry(filePath); - } - return getEntry(new File(filePath).getParent()); - } + return removeDirRecursively(fp); + } - /** - * Checks to see if we are at the root directory. Useful since we are - * not allow to delete this directory. - * - * @param filePath to directory - * @return true if we are at the root, false otherwise. - */ - private boolean atRootDirectory(String filePath) { - if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + ctx.getPackageName() + "/cache") || - filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath())) { - return true; - } - return false; - } + /** + * Loops through a directory deleting all the files. + * + * @param directory to be removed + * @return a boolean representing success of failure + * @throws FileExistsException + */ + private boolean removeDirRecursively(File directory) throws FileExistsException { + if (directory.isDirectory()) { + for (File file : directory.listFiles()) { + removeDirRecursively(file); + } + } - /** - * Look up metadata about this entry. - * - * @param filePath to entry - * @return a Metadata object - * @throws FileNotFoundException - * @throws JSONException - */ - private JSONObject getMetadata(String filePath) throws FileNotFoundException, JSONException { - File file = new File(filePath); - - if (!file.exists()) { - throw new FileNotFoundException("Failed to find file in getMetadata"); - } - - JSONObject metadata = new JSONObject(); - metadata.put("modificationTime", file.lastModified()); + if (!directory.delete()) { + throw new FileExistsException("could not delete: " + directory.getName()); + } else { + return true; + } + } - return metadata; - } + /** + * Deletes a file or directory. It is an error to attempt to delete a directory that is not empty. + * It is an error to attempt to delete the root directory of a filesystem. + * + * @param filePath file or directory to be removed + * @return a boolean representing success of failure + * @throws NoModificationAllowedException + * @throws InvalidModificationException + */ + private boolean remove(String filePath) throws NoModificationAllowedException, InvalidModificationException { + File fp = new File(filePath); - /** - * Returns a File that represents the current state of the file that this FileEntry represents. - * - * @param filePath to entry - * @return returns a JSONObject represent a W3C File object - * @throws FileNotFoundException - * @throws JSONException - */ - private JSONObject getFileMetadata(String filePath) throws FileNotFoundException, JSONException { - File file = new File(filePath); - - if (!file.exists()) { - throw new FileNotFoundException("File: " + filePath + " does not exist."); - } - - JSONObject metadata = new JSONObject(); - metadata.put("size", file.length()); - metadata.put("type", getMimeType(filePath)); - metadata.put("name", file.getName()); - metadata.put("fullPath", file.getAbsolutePath()); - metadata.put("lastModifiedDate", file.lastModified()); + // You can't delete the root directory. + if (atRootDirectory(filePath)) { + throw new NoModificationAllowedException("You can't delete the root directory"); + } - return metadata; - } + // You can't delete a directory that is not empty + if (fp.isDirectory() && fp.list().length > 0) { + throw new InvalidModificationException("You can't delete a directory that is not empty."); + } - /** - * Requests a filesystem in which to store application data. - * - * @param type of file system requested - * @return a JSONObject representing the file system - * @throws IOException - * @throws JSONException - */ - private JSONObject requestFileSystem(int type) throws IOException, JSONException { - JSONObject fs = new JSONObject(); - if (type == TEMPORARY) { - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - fs.put("name", "temporary"); - fs.put("root", getEntry(Environment.getExternalStorageDirectory().getAbsolutePath() + - "/Android/data/" + ctx.getPackageName() + "/cache/")); - - // Create the cache dir if it doesn't exist. - File fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + - "/Android/data/" + ctx.getPackageName() + "/cache/"); - fp.mkdirs(); - } else { - throw new IOException("SD Card not mounted"); - } - } - else if (type == PERSISTENT) { - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - fs.put("name", "persistent"); - fs.put("root", getEntry(Environment.getExternalStorageDirectory())); - } else { - throw new IOException("SD Card not mounted"); - } - } - else if (type == RESOURCE) { - fs.put("name", "resource"); - - } - else if (type == APPLICATION) { - fs.put("name", "application"); - - } - else { - throw new IOException("No filesystem of type requested"); - } + return fp.delete(); + } - return fs; - } + /** + * Creates or looks up a file. + * + * @param dirPath base directory + * @param fileName file/directory to lookup or create + * @param options specify whether to create or not + * @param directory if true look up directory, if false look up file + * @return a Entry object + * @throws FileExistsException + * @throws IOException + * @throws TypeMismatchException + * @throws EncodingException + * @throws JSONException + */ + private JSONObject getFile(String dirPath, String fileName, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException { + boolean create = false; + boolean exclusive = false; + if (options != null) { + create = options.optBoolean("create"); + if (create) { + exclusive = options.optBoolean("exclusive"); + } + } - /** - * Returns a JSON Object representing a directory on the device's file system - * - * @param path to the directory - * @return - * @throws JSONException - */ - private JSONObject getEntry(File file) throws JSONException { - JSONObject entry = new JSONObject(); + // Check for a ":" character in the file to line up with BB and iOS + if (fileName.contains(":")) { + throw new EncodingException("This file has a : in it's name"); + } - entry.put("isFile", file.isFile()); - entry.put("isDirectory", file.isDirectory()); - entry.put("name", file.getName()); - entry.put("fullPath", file.getAbsolutePath()); - // I can't add the next thing it as it would be an infinite loop - //entry.put("filesystem", null); + File fp = createFileObject(dirPath, fileName); - return entry; - } + if (create) { + if (exclusive && fp.exists()) { + throw new FileExistsException("create/exclusive fails"); + } + if (directory) { + fp.mkdir(); + } else { + fp.createNewFile(); + } + if (!fp.exists()) { + throw new FileExistsException("create fails"); + } + } + else { + if (!fp.exists()) { + throw new FileNotFoundException("path does not exist"); + } + if (directory) { + if (fp.isFile()) { + throw new TypeMismatchException("path doesn't exist or is file"); + } + } else { + if (fp.isDirectory()) { + throw new TypeMismatchException("path doesn't exist or is directory"); + } + } + } - /** - * Returns a JSON Object representing a directory on the device's file system - * - * @param path to the directory - * @return - * @throws JSONException - */ - private JSONObject getEntry(String path) throws JSONException { - return getEntry(new File(path)); - } + // Return the directory + return getEntry(fp); + } - /** - * Identifies if action to be executed returns a value and should be run synchronously. - * - * @param action The action to execute - * @return T=returns value - */ - public boolean isSynch(String action) { - if (action.equals("testSaveLocationExists")) { - return true; - } - else if (action.equals("getFreeDiskSpace")) { - return true; - } - else if (action.equals("testFileExists")) { - return true; - } - else if (action.equals("testDirectoryExists")) { - return true; - } - return false; - } + /** + * If the path starts with a '/' just return that file object. If not construct the file + * object from the path passed in and the file name. + * + * @param dirPath root directory + * @param fileName new file name + * @return + */ + private File createFileObject(String dirPath, String fileName) { + File fp = null; + if (fileName.startsWith("/")) { + fp = new File(fileName); + } else { + fp = new File(dirPath + File.separator + fileName); + } + return fp; + } + + /** + * Look up the parent DirectoryEntry containing this Entry. + * If this Entry is the root of its filesystem, its parent is itself. + * + * @param filePath + * @return + * @throws JSONException + */ + private JSONObject getParent(String filePath) throws JSONException { + if (atRootDirectory(filePath)) { + return getEntry(filePath); + } + return getEntry(new File(filePath).getParent()); + } + + /** + * Checks to see if we are at the root directory. Useful since we are + * not allow to delete this directory. + * + * @param filePath to directory + * @return true if we are at the root, false otherwise. + */ + private boolean atRootDirectory(String filePath) { + if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + ctx.getPackageName() + "/cache") || + filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath())) { + return true; + } + return false; + } + + /** + * Look up metadata about this entry. + * + * @param filePath to entry + * @return a Metadata object + * @throws FileNotFoundException + * @throws JSONException + */ + private JSONObject getMetadata(String filePath) throws FileNotFoundException, JSONException { + File file = new File(filePath); + + if (!file.exists()) { + throw new FileNotFoundException("Failed to find file in getMetadata"); + } + + JSONObject metadata = new JSONObject(); + metadata.put("modificationTime", file.lastModified()); + + return metadata; + } + + /** + * Returns a File that represents the current state of the file that this FileEntry represents. + * + * @param filePath to entry + * @return returns a JSONObject represent a W3C File object + * @throws FileNotFoundException + * @throws JSONException + */ + private JSONObject getFileMetadata(String filePath) throws FileNotFoundException, JSONException { + File file = new File(filePath); + + if (!file.exists()) { + throw new FileNotFoundException("File: " + filePath + " does not exist."); + } + + JSONObject metadata = new JSONObject(); + metadata.put("size", file.length()); + metadata.put("type", getMimeType(filePath)); + metadata.put("name", file.getName()); + metadata.put("fullPath", file.getAbsolutePath()); + metadata.put("lastModifiedDate", file.lastModified()); + + return metadata; + } + + /** + * Requests a filesystem in which to store application data. + * + * @param type of file system requested + * @return a JSONObject representing the file system + * @throws IOException + * @throws JSONException + */ + private JSONObject requestFileSystem(int type) throws IOException, JSONException { + JSONObject fs = new JSONObject(); + if (type == TEMPORARY) { + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + fs.put("name", "temporary"); + fs.put("root", getEntry(Environment.getExternalStorageDirectory().getAbsolutePath() + + "/Android/data/" + ctx.getPackageName() + "/cache/")); + + // Create the cache dir if it doesn't exist. + File fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + + "/Android/data/" + ctx.getPackageName() + "/cache/"); + fp.mkdirs(); + } else { + throw new IOException("SD Card not mounted"); + } + } + else if (type == PERSISTENT) { + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + fs.put("name", "persistent"); + fs.put("root", getEntry(Environment.getExternalStorageDirectory())); + } else { + throw new IOException("SD Card not mounted"); + } + } + else if (type == RESOURCE) { + fs.put("name", "resource"); + + } + else if (type == APPLICATION) { + fs.put("name", "application"); + + } + else { + throw new IOException("No filesystem of type requested"); + } + + return fs; + } + + /** + * Returns a JSON Object representing a directory on the device's file system + * + * @param path to the directory + * @return + * @throws JSONException + */ + public JSONObject getEntry(File file) throws JSONException { + JSONObject entry = new JSONObject(); + + entry.put("isFile", file.isFile()); + entry.put("isDirectory", file.isDirectory()); + entry.put("name", file.getName()); + entry.put("fullPath", file.getAbsolutePath()); + // I can't add the next thing it as it would be an infinite loop + //entry.put("filesystem", null); + + return entry; + } + + /** + * Returns a JSON Object representing a directory on the device's file system + * + * @param path to the directory + * @return + * @throws JSONException + */ + private JSONObject getEntry(String path) throws JSONException { + return getEntry(new File(path)); + } + + /** + * Identifies if action to be executed returns a value and should be run synchronously. + * + * @param action The action to execute + * @return T=returns value + */ + public boolean isSynch(String action) { + if (action.equals("testSaveLocationExists")) { + return true; + } + else if (action.equals("getFreeDiskSpace")) { + return true; + } + else if (action.equals("testFileExists")) { + return true; + } + else if (action.equals("testDirectoryExists")) { + return true; + } + return false; + } //-------------------------------------------------------------------------- // LOCAL METHODS //-------------------------------------------------------------------------- - + /** * Read content of text file. - * + * * @param filename The name of the file. * @param encoding The encoding to return contents as. Typical value is UTF-8. * (see http://www.iana.org/assignments/character-sets) @@ -898,125 +897,125 @@ public class FileUtils extends Plugin { * @throws FileNotFoundException, IOException */ public String readAsText(String filename, String encoding) throws FileNotFoundException, IOException { - byte[] bytes = new byte[1000]; - BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - int numRead = 0; - while ((numRead = bis.read(bytes, 0, 1000)) >= 0) { - bos.write(bytes, 0, numRead); - } + byte[] bytes = new byte[1000]; + BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int numRead = 0; + while ((numRead = bis.read(bytes, 0, 1000)) >= 0) { + bos.write(bytes, 0, numRead); + } return new String(bos.toByteArray(), encoding); } - + /** * Read content of text file and return as base64 encoded data url. - * + * * @param filename The name of the file. * @return Contents of file = data:;base64, * @throws FileNotFoundException, IOException */ public String readAsDataURL(String filename) throws FileNotFoundException, IOException { - byte[] bytes = new byte[1000]; - BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - int numRead = 0; - while ((numRead = bis.read(bytes, 0, 1000)) >= 0) { - bos.write(bytes, 0, numRead); - } - - // Determine content type from file name - String contentType = null; - if (filename.startsWith("content:")) { - Uri fileUri = Uri.parse(filename); - contentType = this.ctx.getContentResolver().getType(fileUri); - } - else { - contentType = getMimeType(filename); - } + byte[] bytes = new byte[1000]; + BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int numRead = 0; + while ((numRead = bis.read(bytes, 0, 1000)) >= 0) { + bos.write(bytes, 0, numRead); + } - byte[] base64 = Base64.encodeBase64(bos.toByteArray()); - String data = "data:" + contentType + ";base64," + new String(base64); - return data; + // Determine content type from file name + String contentType = null; + if (filename.startsWith("content:")) { + Uri fileUri = Uri.parse(filename); + contentType = this.ctx.getContentResolver().getType(fileUri); + } + else { + contentType = getMimeType(filename); + } + + byte[] base64 = Base64.encodeBase64(bos.toByteArray()); + String data = "data:" + contentType + ";base64," + new String(base64); + return data; } /** * Looks up the mime type of a given file name. - * + * * @param filename * @return a mime type */ - public static String getMimeType(String filename) { - MimeTypeMap map = MimeTypeMap.getSingleton(); - return map.getMimeTypeFromExtension(map.getFileExtensionFromUrl(filename)); - } - + public static String getMimeType(String filename) { + MimeTypeMap map = MimeTypeMap.getSingleton(); + return map.getMimeTypeFromExtension(map.getFileExtensionFromUrl(filename)); + } + /** * Write contents of file. - * + * * @param filename The name of the file. * @param data The contents of the file. - * @param offset The position to begin writing the file. + * @param offset The position to begin writing the file. * @throws FileNotFoundException, IOException */ /**/ public long write(String filename, String data, int offset) throws FileNotFoundException, IOException { - boolean append = false; - if (offset > 0) { - this.truncateFile(filename, offset); - append = true; - } - - byte [] rawData = data.getBytes(); - ByteArrayInputStream in = new ByteArrayInputStream(rawData); - FileOutputStream out = new FileOutputStream(filename, append); - byte buff[] = new byte[rawData.length]; - in.read(buff, 0, buff.length); - out.write(buff, 0, rawData.length); - out.flush(); - out.close(); - - return data.length(); + boolean append = false; + if (offset > 0) { + this.truncateFile(filename, offset); + append = true; + } + + byte [] rawData = data.getBytes(); + ByteArrayInputStream in = new ByteArrayInputStream(rawData); + FileOutputStream out = new FileOutputStream(filename, append); + byte buff[] = new byte[rawData.length]; + in.read(buff, 0, buff.length); + out.write(buff, 0, rawData.length); + out.flush(); + out.close(); + + return data.length(); } - + /** * Truncate the file to size - * + * * @param filename * @param size - * @throws FileNotFoundException, IOException + * @throws FileNotFoundException, IOException */ private long truncateFile(String filename, long size) throws FileNotFoundException, IOException { - RandomAccessFile raf = new RandomAccessFile(filename, "rw"); + RandomAccessFile raf = new RandomAccessFile(filename, "rw"); - if (raf.length() >= size) { - FileChannel channel = raf.getChannel(); - channel.truncate(size); - return size; - } - - return raf.length(); + if (raf.length() >= size) { + FileChannel channel = raf.getChannel(); + channel.truncate(size); + return size; + } + + return raf.length(); } - + /** * Get an input stream based on file path or content:// uri - * + * * @param path * @return an input stream - * @throws FileNotFoundException + * @throws FileNotFoundException */ - private InputStream getPathFromUri(String path) throws FileNotFoundException { - if (path.startsWith("content")) { - Uri uri = Uri.parse(path); - return ctx.getContentResolver().openInputStream(uri); - } - else { - return new FileInputStream(path); - } - } - + private InputStream getPathFromUri(String path) throws FileNotFoundException { + if (path.startsWith("content")) { + Uri uri = Uri.parse(path); + return ctx.getContentResolver().openInputStream(uri); + } + else { + return new FileInputStream(path); + } + } + /** * Queries the media store to find out what the file path is for the Uri we supply - * + * * @param contentUri the Uri of the audio/image/video * @param ctx the current applicaiton context * @return the full path to the file diff --git a/framework/src/com/phonegap/WebViewReflect.java b/framework/src/com/phonegap/WebViewReflect.java deleted file mode 100644 index 22f57d3f..00000000 --- a/framework/src/com/phonegap/WebViewReflect.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - 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. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package com.phonegap; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import android.webkit.WebSettings; - -public class WebViewReflect { - private static Method mWebSettings_setDatabaseEnabled; - private static Method mWebSettings_setDatabasePath; - private static Method mWebSettings_setDomStorageEnabled; - private static Method mWebSettings_setGeolocationEnabled; - - static - { - checkCompatibility(); - } - - private static void setDatabaseEnabled(boolean e) throws IOException { - try - { - mWebSettings_setDatabaseEnabled.invoke(e); - } - catch (InvocationTargetException ite) { - /* unpack original exception when possible */ - Throwable cause = ite.getCause(); - if (cause instanceof IOException) { - throw (IOException) cause; - } else if (cause instanceof RuntimeException) { - throw (RuntimeException) cause; - } else if (cause instanceof Error) { - throw (Error) cause; - } else { - /* unexpected checked exception; wrap and re-throw */ - throw new RuntimeException(ite); - } - } catch (IllegalAccessException ie) { - System.err.println("unexpected " + ie); - } - } - - - public static void checkCompatibility() { - try { - mWebSettings_setDatabaseEnabled = WebSettings.class.getMethod( - "setDatabaseEnabled", new Class[] { boolean.class } ); - mWebSettings_setDatabasePath = WebSettings.class.getMethod( - "setDatabasePath", new Class[] { String.class }); - mWebSettings_setDomStorageEnabled = WebSettings.class.getMethod( - "setDomStorageEnabled", new Class[] { boolean.class }); - mWebSettings_setGeolocationEnabled = WebSettings.class.getMethod( - "setGeolocationEnabled", new Class[] { boolean.class }); - /* success, this is a newer device */ - } catch (NoSuchMethodException nsme) { - /* failure, must be older device */ - } - } - - public static void setStorage(WebSettings setting, boolean enable, String path) { - if (mWebSettings_setDatabaseEnabled != null) { - /* feature is supported */ - try { - mWebSettings_setDatabaseEnabled.invoke(setting, enable); - mWebSettings_setDatabasePath.invoke(setting, path); - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InvocationTargetException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } else { - /* feature not supported, do something else */ - } - } - public static void setGeolocationEnabled(WebSettings setting, boolean enable) { - if (mWebSettings_setGeolocationEnabled != null) { - /* feature is supported */ - try { - mWebSettings_setGeolocationEnabled.invoke(setting, enable); - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InvocationTargetException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } else { - /* feature not supported, do something else */ - System.out.println("Native Geolocation not supported - we're ok"); - } - } - public static void setDomStorage(WebSettings setting) - { - if(mWebSettings_setDomStorageEnabled != null) - { - /* feature is supported */ - try { - mWebSettings_setDomStorageEnabled.invoke(setting, true); - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InvocationTargetException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } else { - /* feature not supported, do something else */ - } - - } -}