You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2013/05/24 01:41:51 UTC

[30/38] updated android, ios, bb libraries to 2.8.x branch. fixed a few assertions with project changes. removed blackberry support until create script can be finalized.

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java b/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
index c1ca15c..784c34c 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
@@ -64,6 +64,8 @@ import android.os.Build;
 import android.util.Log;
 import android.webkit.CookieManager;
 
+import com.squareup.okhttp.OkHttpClient;
+
 public class FileTransfer extends CordovaPlugin {
 
     private static final String LOG_TAG = "FileTransfer";
@@ -79,6 +81,8 @@ public class FileTransfer extends CordovaPlugin {
     private static HashMap<String, RequestContext> activeRequests = new HashMap<String, RequestContext>();
     private static final int MAX_BUFFER_SIZE = 16 * 1024;
 
+    private static OkHttpClient httpClient = new OkHttpClient();
+
     private static final class RequestContext {
         String source;
         String target;
@@ -174,39 +178,6 @@ public class FileTransfer extends CordovaPlugin {
         }
     }
 
-    /**
-     * Works around a bug on Android 2.3.
-     * http://code.google.com/p/android/issues/detail?id=14562
-     */
-    private static final class DoneHandlerInputStream extends TrackingHTTPInputStream {
-        private boolean done;
-        
-        public DoneHandlerInputStream(InputStream stream) {
-            super(stream);
-        }
-        
-        @Override
-        public int read() throws IOException {
-            int result = done ? -1 : super.read();
-            done = (result == -1);
-            return result;
-        }
-
-        @Override
-        public int read(byte[] buffer) throws IOException {
-            int result = done ? -1 : super.read(buffer);
-            done = (result == -1);
-            return result;
-        }
-
-        @Override
-        public int read(byte[] bytes, int offset, int count) throws IOException {
-            int result = done ? -1 : super.read(bytes, offset, count);
-            done = (result == -1);
-            return result;
-        }
-    }
-    
     @Override
     public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
         if (action.equals("upload") || action.equals("download")) {
@@ -327,13 +298,13 @@ public class FileTransfer extends CordovaPlugin {
                     if (useHttps) {
                         // Using standard HTTPS connection. Will not allow self signed certificate
                         if (!trustEveryone) {
-                            conn = (HttpsURLConnection) url.openConnection();
+                            conn = (HttpsURLConnection) httpClient.open(url);
                         }
                         // 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
-                            HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
+                            HttpsURLConnection https = (HttpsURLConnection) httpClient.open(url);
                             oldSocketFactory  = trustAllHosts(https);
                             // Save the current hostnameVerifier
                             oldHostnameVerifier = https.getHostnameVerifier();
@@ -344,7 +315,7 @@ public class FileTransfer extends CordovaPlugin {
                     }
                     // Return a standard HTTP connection
                     else {
-                        conn = (HttpURLConnection) url.openConnection();
+                        conn = httpClient.open(url);
                     }
 
                     // Allow Inputs
@@ -561,9 +532,6 @@ public class FileTransfer extends CordovaPlugin {
     }
 
     private static TrackingInputStream getInputStream(URLConnection conn) throws IOException {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
-            return new DoneHandlerInputStream(conn.getInputStream());
-        }
         String encoding = conn.getContentEncoding();
         if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
         	return new TrackingGZIPInputStream(new ExposedGZIPInputStream(conn.getInputStream()));
@@ -681,7 +649,7 @@ public class FileTransfer extends CordovaPlugin {
      */
     private static String getArgument(JSONArray args, int position, String defaultString) {
         String arg = defaultString;
-        if (args.length() >= position) {
+        if (args.length() > position) {
             arg = args.optString(position);
             if (arg == null || "null".equals(arg)) {
                 arg = defaultString;
@@ -749,13 +717,13 @@ public class FileTransfer extends CordovaPlugin {
                     if (useHttps) {
                         // Using standard HTTPS connection. Will not allow self signed certificate
                         if (!trustEveryone) {
-                            connection = (HttpsURLConnection) url.openConnection();
+                            connection = (HttpsURLConnection) httpClient.open(url);
                         }
                         // 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
-                            HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
+                            HttpsURLConnection https = (HttpsURLConnection) httpClient.open(url);
                             oldSocketFactory = trustAllHosts(https);
                             // Save the current hostnameVerifier
                             oldHostnameVerifier = https.getHostnameVerifier();
@@ -766,7 +734,8 @@ public class FileTransfer extends CordovaPlugin {
                     }
                     // Return a standard HTTP connection
                     else {
-                          connection = url.openConnection();
+                          connection = httpClient.open(url);
+
                     }
     
                     if (connection instanceof HttpURLConnection) {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/framework/src/org/apache/cordova/FileUtils.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/FileUtils.java b/lib/cordova-android/framework/src/org/apache/cordova/FileUtils.java
index 2135be9..e62fc4a 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/FileUtils.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/FileUtils.java
@@ -18,8 +18,6 @@
  */
 package org.apache.cordova;
 
-import android.database.Cursor;
-import android.net.Uri;
 import android.os.Environment;
 import android.provider.MediaStore;
 import android.util.Log;
@@ -27,6 +25,7 @@ import android.util.Log;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.cordova.api.CallbackContext;
 import org.apache.cordova.api.CordovaPlugin;
+import org.apache.cordova.api.DataResource;
 import org.apache.cordova.api.PluginResult;
 import org.apache.cordova.file.EncodingException;
 import org.apache.cordova.file.FileExistsException;
@@ -46,8 +45,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.RandomAccessFile;
 import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLDecoder;
 import java.nio.channels.FileChannel;
 
 /**
@@ -234,7 +231,7 @@ public class FileUtils extends CordovaPlugin {
      * @param filePath the path to check
      */
     private void notifyDelete(String filePath) {
-        String newFilePath = FileHelper.getRealPath(filePath, cordova);
+        String newFilePath = DataResource.initiateNewDataRequestForUri(filePath, webView.pluginManager, cordova, "FileUtils.notifyDelete").getRealFile().getPath();
         try {
             this.cordova.getActivity().getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                     MediaStore.Images.Media.DATA + " = ?",
@@ -256,37 +253,10 @@ public class FileUtils extends CordovaPlugin {
      * @throws IOException if the user can't read the file
      * @throws JSONException
      */
-    @SuppressWarnings("deprecation")
     private JSONObject resolveLocalFileSystemURI(String url) throws IOException, JSONException {
-        String decoded = URLDecoder.decode(url, "UTF-8");
+        File fp = DataResource.initiateNewDataRequestForUri(url, webView.pluginManager, cordova, "FileUtils.resolveLocalFileSystemURI").getRealFile();
 
-        File fp = null;
-
-        // Handle the special case where you get an Android content:// uri.
-        if (decoded.startsWith("content:")) {
-            Cursor cursor = this.cordova.getActivity().managedQuery(Uri.parse(decoded), new String[] { MediaStore.Images.Media.DATA }, null, null, null);
-            // Note: MediaStore.Images/Audio/Video.Media.DATA is always "_data"
-            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
-            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://")) {
-                int questionMark = decoded.indexOf("?");
-                if (questionMark < 0) {
-                    fp = new File(decoded.substring(7, decoded.length()));
-                } else {
-                    fp = new File(decoded.substring(7, questionMark));
-                }
-            } else {
-                fp = new File(decoded);
-            }
-        }
-
-        if (!fp.exists()) {
+        if (fp == null || !fp.exists()) {
             throw new FileNotFoundException();
         }
         if (!fp.canRead()) {
@@ -304,9 +274,9 @@ public class FileUtils extends CordovaPlugin {
      * @throws JSONException
      */
     private JSONArray readEntries(String fileName) throws FileNotFoundException, JSONException {
-        File fp = createFileObject(fileName);
+        File fp = DataResource.initiateNewDataRequestForUri(fileName, webView.pluginManager, cordova, "FileUtils.readEntries").getRealFile();
 
-        if (!fp.exists()) {
+        if (fp == null || !fp.exists()) {
             // The directory we are listing doesn't exist so we should fail.
             throw new FileNotFoundException();
         }
@@ -341,8 +311,10 @@ public class FileUtils extends CordovaPlugin {
      * @throws FileExistsException
      */
     private JSONObject transferTo(String fileName, String newParent, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
-        String newFileName = FileHelper.getRealPath(fileName, cordova);
-        newParent = FileHelper.getRealPath(newParent, cordova);
+        DataResource dataResourceFrom = DataResource.initiateNewDataRequestForUri(fileName, webView.pluginManager, cordova, "FileUtils.transferTo");
+        String newFileName = dataResourceFrom.getRealFile().getPath();
+        DataResource dataResourceTo = DataResource.initiateNewDataRequestForUri(newParent, webView.pluginManager, cordova, "FileUtils.transferTo");
+        newParent = dataResourceTo.getRealFile().getPath();
 
         // Check for invalid file name
         if (newName != null && newName.contains(":")) {
@@ -613,7 +585,7 @@ public class FileUtils extends CordovaPlugin {
      * @throws FileExistsException
      */
     private boolean removeRecursively(String filePath) throws FileExistsException {
-        File fp = createFileObject(filePath);
+        File fp = DataResource.initiateNewDataRequestForUri(filePath, webView.pluginManager, cordova, "FileUtils.readEntries").getRealFile();
 
         // You can't delete the root directory.
         if (atRootDirectory(filePath)) {
@@ -654,7 +626,7 @@ public class FileUtils extends CordovaPlugin {
      * @throws InvalidModificationException
      */
     private boolean remove(String filePath) throws NoModificationAllowedException, InvalidModificationException {
-        File fp = createFileObject(filePath);
+        File fp = DataResource.initiateNewDataRequestForUri(filePath, webView.pluginManager, cordova, "FileUtils.readEntries").getRealFile();
 
         // You can't delete the root directory.
         if (atRootDirectory(filePath)) {
@@ -698,7 +670,8 @@ public class FileUtils extends CordovaPlugin {
             throw new EncodingException("This file has a : in it's name");
         }
 
-        File fp = createFileObject(dirPath, fileName);
+        String filePath = getFullFilePath(dirPath, fileName);
+        File fp = DataResource.initiateNewDataRequestForUri(filePath, webView.pluginManager, cordova, "FileUtils.getFile").getRealFile();
 
         if (create) {
             if (exclusive && fp.exists()) {
@@ -740,15 +713,14 @@ public class FileUtils extends CordovaPlugin {
      * @param fileName new file name
      * @return
      */
-    private File createFileObject(String dirPath, String fileName) {
-        File fp = null;
+    private String getFullFilePath(String dirPath, String fileName) {
         if (fileName.startsWith("/")) {
-            fp = new File(fileName);
+            return fileName;
         } else {
-            dirPath = FileHelper.getRealPath(dirPath, cordova);
-            fp = new File(dirPath + File.separator + fileName);
+            DataResource dataResource = DataResource.initiateNewDataRequestForUri(dirPath, webView.pluginManager, cordova, "FileUtils.getFullFilePath");
+            dirPath = dataResource.getRealFile().getPath();
+            return dirPath + File.separator + fileName;
         }
-        return fp;
     }
 
     /**
@@ -760,12 +732,13 @@ public class FileUtils extends CordovaPlugin {
      * @throws JSONException
      */
     private JSONObject getParent(String filePath) throws JSONException {
-        filePath = FileHelper.getRealPath(filePath, cordova);
+        DataResource dataResource = DataResource.initiateNewDataRequestForUri(filePath, webView.pluginManager, cordova, "FileUtils.getParent");
+        filePath = dataResource.getRealFile().getPath();
 
         if (atRootDirectory(filePath)) {
             return getEntry(filePath);
         }
-        return getEntry(new File(filePath).getParent());
+        return getEntry(dataResource.getRealFile().getParent());
     }
 
     /**
@@ -776,7 +749,7 @@ public class FileUtils extends CordovaPlugin {
      * @return true if we are at the root, false otherwise.
      */
     private boolean atRootDirectory(String filePath) {
-        filePath = FileHelper.getRealPath(filePath, cordova);
+        filePath = DataResource.initiateNewDataRequestForUri(filePath, webView.pluginManager, cordova, "FileUtils.atRootDirectory").getRealFile().getPath();
 
         if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + cordova.getActivity().getPackageName() + "/cache") ||
                 filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath()) ||
@@ -787,19 +760,6 @@ public class FileUtils extends CordovaPlugin {
     }
 
     /**
-     * Create a File object from the passed in path
-     *
-     * @param filePath
-     * @return
-     */
-    private File createFileObject(String filePath) {
-        filePath = FileHelper.getRealPath(filePath, cordova);
-
-        File file = new File(filePath);
-        return file;
-    }
-
-    /**
      * Look up metadata about this entry.
      *
      * @param filePath to entry
@@ -807,9 +767,9 @@ public class FileUtils extends CordovaPlugin {
      * @throws FileNotFoundException
      */
     private long getMetadata(String filePath) throws FileNotFoundException {
-        File file = createFileObject(filePath);
+        File file = DataResource.initiateNewDataRequestForUri(filePath, webView.pluginManager, cordova, "FileUtils.getMetadata").getRealFile();
 
-        if (!file.exists()) {
+        if (file == null || !file.exists()) {
             throw new FileNotFoundException("Failed to find file in getMetadata");
         }
 
@@ -825,15 +785,16 @@ public class FileUtils extends CordovaPlugin {
      * @throws JSONException
      */
     private JSONObject getFileMetadata(String filePath) throws FileNotFoundException, JSONException {
-        File file = createFileObject(filePath);
+        DataResource dataResource = DataResource.initiateNewDataRequestForUri(filePath, webView.pluginManager, cordova, "FileUtils.getMetadata");
+        File file = dataResource.getRealFile();
 
-        if (!file.exists()) {
+        if (file == null || !file.exists()) {
             throw new FileNotFoundException("File: " + filePath + " does not exist.");
         }
 
         JSONObject metadata = new JSONObject();
         metadata.put("size", file.length());
-        metadata.put("type", FileHelper.getMimeType(filePath, cordova));
+        metadata.put("type", dataResource.getMimeType());
         metadata.put("name", file.getName());
         metadata.put("fullPath", filePath);
         metadata.put("lastModifiedDate", file.lastModified());
@@ -935,7 +896,8 @@ public class FileUtils extends CordovaPlugin {
         this.cordova.getThreadPool().execute(new Runnable() {
             public void run() {
                 try {
-                    byte[] bytes = readAsBinaryHelper(filename, start, end);
+                    DataResource dataResource = DataResource.initiateNewDataRequestForUri(filename, webView.pluginManager, cordova, "FileUtils.readFileAs");
+                    byte[] bytes = readAsBinaryHelper(dataResource.getInputStream(), start, end);
                     
                     PluginResult result;
                     switch (resultType) {
@@ -949,7 +911,7 @@ public class FileUtils extends CordovaPlugin {
                             result = new PluginResult(PluginResult.Status.OK, bytes, true);
                             break;
                         default: // Base64.
-                            String contentType = FileHelper.getMimeType(filename, cordova);
+                            String contentType = dataResource.getMimeType();
                             byte[] base64 = Base64.encodeBase64(bytes);
                             String s = "data:" + contentType + ";base64," + new String(base64, "US-ASCII");
                             result = new PluginResult(PluginResult.Status.OK, s);
@@ -976,10 +938,9 @@ public class FileUtils extends CordovaPlugin {
      * @return                  Contents of the file as a byte[].
      * @throws IOException
      */
-    private byte[] readAsBinaryHelper(String filename, int start, int end) throws IOException {
+    private byte[] readAsBinaryHelper(InputStream inputStream, int start, int end) throws IOException {
         int numBytesToRead = end - start;
         byte[] bytes = new byte[numBytesToRead];
-        InputStream inputStream = FileHelper.getInputStreamFromUriString(filename, cordova);
         int numBytesRead = 0;
 
         if (start > 0) {
@@ -1008,7 +969,8 @@ public class FileUtils extends CordovaPlugin {
             throw new NoModificationAllowedException("Couldn't write to file given its content URI");
         }
 
-        filename = FileHelper.getRealPath(filename, cordova);
+        DataResource dataResource = DataResource.initiateNewDataRequestForUri(filename, webView.pluginManager, cordova, "FileUtils.write");
+        filename = dataResource.getRealFile().getPath();
 
         boolean append = false;
         if (offset > 0) {
@@ -1037,13 +999,16 @@ public class FileUtils extends CordovaPlugin {
      * @throws NoModificationAllowedException
      */
     private long truncateFile(String filename, long size) throws FileNotFoundException, IOException, NoModificationAllowedException {
-        if (filename.startsWith("content://")) {
-            throw new NoModificationAllowedException("Couldn't truncate file given its content URI");
+        DataResource dataResource = DataResource.initiateNewDataRequestForUri(filename, webView.pluginManager, cordova, "FileUtils.truncateFile");
+        if(!dataResource.isWritable()) {
+            throw new NoModificationAllowedException("Couldn't truncate file as it is not writable");
+        }
+        File file = dataResource.getRealFile();
+        if(file == null) {
+            throw new FileNotFoundException("Couldn't get the file");
         }
 
-        filename = FileHelper.getRealPath(filename, cordova);
-
-        RandomAccessFile raf = new RandomAccessFile(filename, "rw");
+        RandomAccessFile raf = new RandomAccessFile(file, "rw");
         try {
             if (raf.length() >= size) {
                 FileChannel channel = raf.getChannel();

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java b/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
index 847972e..14c7603 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
@@ -22,6 +22,8 @@ import java.io.IOException;
 import java.io.InputStream;
 
 import org.apache.cordova.api.CordovaInterface;
+import org.apache.cordova.api.DataResource;
+import org.apache.cordova.api.DataResourceContext;
 import org.apache.cordova.api.LOG;
 
 import android.annotation.TargetApi;
@@ -43,41 +45,27 @@ public class IceCreamCordovaWebViewClient extends CordovaWebViewClient {
 
     @Override
     public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
+        // We need to support the new DataResource intercepts without breaking the shouldInterceptRequest mechanism.
+        DataResource dataResource = DataResource.initiateNewDataRequestForUri(url, this.appView.pluginManager, cordova,
+                "WebViewClient.shouldInterceptRequest");
+        url = dataResource.getUri().toString();
+
+        // This mechanism is no longer needed due to the dataResource mechanism. It would be awesome to just get rid of it.
         //Check if plugins intercept the request
         WebResourceResponse ret = super.shouldInterceptRequest(view, url);
-        if(ret == null && (url.contains("?") || url.contains("#") || needsIceCreamSpaceInAssetUrlFix(url))){
-            ret = generateWebResourceResponse(url);
-        }
-        return ret;
-    }
-
-    private WebResourceResponse generateWebResourceResponse(String url) {
-        if (url.startsWith("file:///android_asset/")) {
-            String mimetype = FileHelper.getMimeType(url, cordova);
 
+        if(ret == null) {
             try {
-                InputStream stream = FileHelper.getInputStreamFromUriString(url, cordova);
-                WebResourceResponse response = new WebResourceResponse(mimetype, "UTF-8", stream);
-                return response;
-            } catch (IOException e) {
-                LOG.e("generateWebResourceResponse", e.getMessage(), e);
+                InputStream is;
+                String mimeType;
+                if((is = dataResource.getInputStream()) != null && (mimeType = dataResource.getMimeType()) != null) {
+                    // If we don't know how to open this file, let the browser continue loading
+                    ret = new WebResourceResponse(mimeType, "UTF-8", is);
+                }
+            } catch(IOException e) {
+                LOG.e("IceCreamCordovaWebViewClient", "Error occurred while loading a file.", e);
             }
         }
-        return null;
-    }
-    
-    private static boolean needsIceCreamSpaceInAssetUrlFix(String url) {
-        if (!url.contains("%20")){
-            return false;
-        }
-
-        switch(android.os.Build.VERSION.SDK_INT){
-            case android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH:
-            case android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1:
-                return true;
-            default:
-                return false;
-        }
+        return ret;
     }
-    
 }

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java b/lib/cordova-android/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java
index 280269b..52712ac 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java
@@ -35,13 +35,13 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
     private int oldWidth = 0; // Need to save old width for orientation change
     private int screenWidth = 0;
     private int screenHeight = 0;
-    private DroidGap app = null;
+    private CordovaActivity app = null;
 
     public LinearLayoutSoftKeyboardDetect(Context context, int width, int height) {
         super(context);
         screenWidth = width;
         screenHeight = height;
-        app = (DroidGap) context;
+        app = (CordovaActivity) context;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/framework/src/org/apache/cordova/Notification.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/Notification.java b/lib/cordova-android/framework/src/org/apache/cordova/Notification.java
index 9d96062..cf2e95f 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/Notification.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/Notification.java
@@ -74,7 +74,7 @@ public class Notification extends CordovaPlugin {
             return true;
         }
         else if (action.equals("prompt")) {
-            this.prompt(args.getString(0), args.getString(1), args.getJSONArray(2), callbackContext);
+            this.prompt(args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), callbackContext);
             return true;
         }
         else if (action.equals("activityStart")) {
@@ -208,41 +208,40 @@ public class Notification extends CordovaPlugin {
                 // First button
                 if (buttonLabels.length() > 0) {
                     try {
-						dlg.setNegativeButton(buttonLabels.getString(0),
-						        new AlertDialog.OnClickListener() {
-						            public void onClick(DialogInterface dialog, int which) {
-						                dialog.dismiss();
-						                callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 1));
-						            }
-						        });
-					} catch (JSONException e) { }
+                        dlg.setNegativeButton(buttonLabels.getString(0),
+                            new AlertDialog.OnClickListener() {
+                                public void onClick(DialogInterface dialog, int which) {
+                                    dialog.dismiss();
+                                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 1));
+                                }
+                            });
+                    } catch (JSONException e) { }
                 }
 
                 // Second button
                 if (buttonLabels.length() > 1) {
                     try {
-						dlg.setNeutralButton(buttonLabels.getString(1),
-						        new AlertDialog.OnClickListener() {
-						            public void onClick(DialogInterface dialog, int which) {
-						                dialog.dismiss();
-						                callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 2));
-						            }
-						        });
-					} catch (JSONException e) { }
+                        dlg.setNeutralButton(buttonLabels.getString(1),
+                            new AlertDialog.OnClickListener() {
+                                public void onClick(DialogInterface dialog, int which) {
+                                    dialog.dismiss();
+                                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 2));
+                                }
+                            });
+                    } catch (JSONException e) { }
                 }
 
                 // Third button
                 if (buttonLabels.length() > 2) {
                     try {
-						dlg.setPositiveButton(buttonLabels.getString(2),
-						        new AlertDialog.OnClickListener() {
-						            public void onClick(DialogInterface dialog, int which) {
-						                dialog.dismiss();
-						                callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 3));
-						            }
-						        }
-						        );
-					} catch (JSONException e) { }
+                        dlg.setPositiveButton(buttonLabels.getString(2),
+                            new AlertDialog.OnClickListener() {
+                                public void onClick(DialogInterface dialog, int which) {
+                                  dialog.dismiss();
+                                  callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 3));
+                                }
+                            });
+                    } catch (JSONException e) { }
                 }
                 dlg.setOnCancelListener(new AlertDialog.OnCancelListener() {
                     public void onCancel(DialogInterface dialog)
@@ -271,11 +270,12 @@ public class Notification extends CordovaPlugin {
      * @param buttonLabels      A comma separated list of button labels (Up to 3 buttons)
      * @param callbackContext   The callback context.
      */
-    public synchronized void prompt(final String message, final String title, final JSONArray buttonLabels, final CallbackContext callbackContext) {
+    public synchronized void prompt(final String message, final String title, final JSONArray buttonLabels, final String defaultText, final CallbackContext callbackContext) {
     	
         final CordovaInterface cordova = this.cordova;
         final EditText promptInput =  new EditText(cordova.getActivity());
-
+        promptInput.setHint(defaultText);
+       
         Runnable runnable = new Runnable() {
             public void run() {
                 AlertDialog.Builder dlg = new AlertDialog.Builder(cordova.getActivity());
@@ -290,73 +290,72 @@ public class Notification extends CordovaPlugin {
                 // First button
                 if (buttonLabels.length() > 0) {
                     try {
-						dlg.setNegativeButton(buttonLabels.getString(0),
-						        new AlertDialog.OnClickListener() {
-						            public void onClick(DialogInterface dialog, int which) {
-						                dialog.dismiss();
-						                try {
-											result.put("buttonIndex",1);
-							                result.put("input1", promptInput.getText());
-										} catch (JSONException e) { e.printStackTrace(); }
-						                callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
-						            }
-						        });
-					} catch (JSONException e) { }
+                        dlg.setNegativeButton(buttonLabels.getString(0),
+                            new AlertDialog.OnClickListener() {
+                                public void onClick(DialogInterface dialog, int which) {
+                                    dialog.dismiss();
+                                    try {
+                                        result.put("buttonIndex",1);
+                                        result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText());											
+                                    } catch (JSONException e) { e.printStackTrace(); }
+                                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
+                                }
+                            });
+                    } catch (JSONException e) { }
                 }
 
                 // Second button
                 if (buttonLabels.length() > 1) {
                     try {
-						dlg.setNeutralButton(buttonLabels.getString(1),
-						        new AlertDialog.OnClickListener() {
-						            public void onClick(DialogInterface dialog, int which) {
-						                dialog.dismiss();
-						                try {
-											result.put("buttonIndex",2);
-							                result.put("input1", promptInput.getText());
-										} catch (JSONException e) { e.printStackTrace(); }
-						                callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
-						            }
-						        });
-					} catch (JSONException e) { }
+                        dlg.setNeutralButton(buttonLabels.getString(1),
+                            new AlertDialog.OnClickListener() {
+                                public void onClick(DialogInterface dialog, int which) {
+                                    dialog.dismiss();
+                                    try {
+                                        result.put("buttonIndex",2);
+                                        result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText());
+                                    } catch (JSONException e) { e.printStackTrace(); }
+                                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
+                                }
+                            });
+                    } catch (JSONException e) { }
                 }
 
                 // Third button
                 if (buttonLabels.length() > 2) {
                     try {
-						dlg.setPositiveButton(buttonLabels.getString(2),
-						        new AlertDialog.OnClickListener() {
-						            public void onClick(DialogInterface dialog, int which) {
-						                dialog.dismiss();
-						                try {
-											result.put("buttonIndex",3);
-							                result.put("input1", promptInput.getText());
-										} catch (JSONException e) { e.printStackTrace(); }
-						                callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
-						            }
-						        }
-						        );
-					} catch (JSONException e) { }
+                        dlg.setPositiveButton(buttonLabels.getString(2),
+                            new AlertDialog.OnClickListener() {
+                                public void onClick(DialogInterface dialog, int which) {
+                                    dialog.dismiss();
+                                    try {
+                                        result.put("buttonIndex",3);
+                                        result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText());
+                                    } catch (JSONException e) { e.printStackTrace(); }
+                                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
+                                }
+                            });
+                    } catch (JSONException e) { }
                 }
                 dlg.setOnCancelListener(new AlertDialog.OnCancelListener() {
-                    public void onCancel(DialogInterface dialog)
-                    {
+                    public void onCancel(DialogInterface dialog){
                         dialog.dismiss();
-		                try {
-							result.put("buttonIndex",0);
-			                result.put("input1", promptInput.getText());
-						} catch (JSONException e) { e.printStackTrace(); }
-		                callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
+                        try {
+                            result.put("buttonIndex",0);
+                            result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText());
+                        } catch (JSONException e) { e.printStackTrace(); }
+                        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
                     }
                 });
 
                 dlg.create();
                 dlg.show();
-                
+
             };
         };
         this.cordova.getActivity().runOnUiThread(runnable);
     }
+
     /**
      * Show the spinner.
      *
@@ -446,5 +445,4 @@ public class Notification extends CordovaPlugin {
             this.progressDialog = null;
         }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/framework/src/org/apache/cordova/StandAlone.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/StandAlone.java b/lib/cordova-android/framework/src/org/apache/cordova/StandAlone.java
deleted file mode 100644
index a199dda..0000000
--- a/lib/cordova-android/framework/src/org/apache/cordova/StandAlone.java
+++ /dev/null
@@ -1,32 +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 org.apache.cordova;
-
-import android.os.Bundle;
-
-public class StandAlone extends DroidGap {
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        super.loadUrl("file:///android_asset/www/index.html");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/framework/src/org/apache/cordova/api/CordovaPlugin.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/api/CordovaPlugin.java b/lib/cordova-android/framework/src/org/apache/cordova/api/CordovaPlugin.java
index 2b225e6..866677c 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/api/CordovaPlugin.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/api/CordovaPlugin.java
@@ -176,6 +176,20 @@ public class CordovaPlugin {
     }
 
     /**
+     * All plugins can now choose if they want to modify any uri requests. This includes all webview requests, opening of files, content uri's etc.
+     * This mechanism allows several plugins to modify the same request
+     * @param requestSource The source of the incoming request
+     *
+     * @param dataResource          The resource to be loaded.
+     * @param dataResourceContext   Context associated with the resource load
+     * @return                      Return a new DataResource if the plugin wants to assist in loading the request or null if it doesn't.
+     */
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+    public DataResource handleDataResourceRequest(DataResource dataResource, DataResourceContext dataResourceContext) {
+        return null;
+    }
+
+    /**
      * Called when the WebView does a top-level navigation or refreshes.
      *
      * Plugins should stop any long-running processes and clean up internal state.

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/framework/src/org/apache/cordova/api/DataResource.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/api/DataResource.java b/lib/cordova-android/framework/src/org/apache/cordova/api/DataResource.java
new file mode 100644
index 0000000..3e6ead8
--- /dev/null
+++ b/lib/cordova-android/framework/src/org/apache/cordova/api/DataResource.java
@@ -0,0 +1,141 @@
+package org.apache.cordova.api;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.cordova.FileHelper;
+
+import android.net.Uri;
+
+/*
+ * All requests to access files, browser network requests etc have to go through this class.
+ */
+public class DataResource {
+    private CordovaInterface cordova;
+
+    // Uri of the request. Always required.
+    private Uri uri;
+    // Remaining fields may or may not be null
+    private InputStream is;
+    private OutputStream os;
+    private String mimeType;
+    private Boolean writable;
+    private File realFile;
+    private boolean retryIsLoad = true;
+    private boolean retryOsLoad = true;
+    private boolean retryMimeTypeLoad = true;
+    private boolean retryWritableLoad = true;
+    private boolean retryRealFileLoad = true;
+
+    public DataResource(CordovaInterface cordova, Uri uri) {
+        this.cordova = cordova;
+        this.uri = uri;
+    }
+    public DataResource(CordovaInterface cordova, Uri uri, InputStream is,
+            OutputStream os, String mimeType, boolean writable, File realFile) {
+        this(cordova, uri);
+        this.is = is;
+        this.mimeType = mimeType;
+        this.writable = Boolean.valueOf(writable);
+        this.realFile = realFile;
+    }
+    public Uri getUri() {
+        // Uri is always provided
+        return uri;
+    }
+    public InputStream getInputStream() throws IOException {
+        if(is == null && retryIsLoad) {
+            try {
+                is = FileHelper.getInputStreamFromUriString(uri.toString(), cordova);
+            } finally {
+                // We failed loading once, don't try loading anymore
+                if(is == null) {
+                    retryIsLoad = false;
+                }
+            }
+        }
+        return is;
+    }
+    public OutputStream getOutputStream() throws FileNotFoundException {
+        if(os == null && retryOsLoad) {
+            try {
+                os = FileHelper.getOutputStreamFromUriString(uri.toString(), cordova);
+            } finally {
+                // We failed loading once, don't try loading anymore
+                if(os == null) {
+                    retryOsLoad = false;
+                }
+            }
+        }
+        return os;
+    }
+    public String getMimeType() {
+        if(mimeType == null && retryMimeTypeLoad) {
+            try {
+                mimeType = FileHelper.getMimeType(uri.toString(), cordova);
+            } finally {
+                // We failed loading once, don't try loading anymore
+                if(mimeType == null) {
+                    retryMimeTypeLoad = false;
+                }
+            }
+        }
+        return mimeType;
+    }
+    public boolean isWritable() {
+        if(writable == null && retryWritableLoad) {
+            try {
+                writable = FileHelper.isUriWritable(uri.toString());
+            } finally {
+                // We failed loading once, don't try loading anymore
+                if(writable == null) {
+                    retryWritableLoad = false;
+                }
+            }
+        }
+        // default to false
+        return writable != null && writable.booleanValue();
+    }
+    public File getRealFile() {
+        if(realFile == null && retryRealFileLoad) {
+            try {
+                String realPath = FileHelper.getRealPath(uri, cordova);
+                if(realPath != null) {
+                    realFile = new File(realPath);
+                }
+            } finally {
+                // We failed loading once, don't try loading anymore
+                if(realFile == null) {
+                    retryRealFileLoad = false;
+                }
+            }
+        }
+        return realFile;
+    }
+
+    // static instantiation methods
+    public static DataResource initiateNewDataRequestForUri(String uriString, PluginManager pluginManager, CordovaInterface cordova, String requestSourceTag){
+        // if no protocol is specified, assume its file:
+        uriString = FileHelper.insertFileProtocol(uriString);
+        return initiateNewDataRequestForUri(Uri.parse(uriString), pluginManager, cordova, requestSourceTag);
+    }
+    public static DataResource initiateNewDataRequestForUri(Uri uri, PluginManager pluginManager, CordovaInterface cordova, String requestSourceTag){
+        return initiateNewDataRequestForUri(uri, pluginManager, cordova, new DataResourceContext(requestSourceTag));
+    }
+    public static DataResource initiateNewDataRequestForUri(String uriString, PluginManager pluginManager, CordovaInterface cordova, DataResourceContext dataResourceContext){
+     // if no protocol is specified, assume its file:
+        uriString = FileHelper.insertFileProtocol(uriString);
+        return initiateNewDataRequestForUri(Uri.parse(uriString), pluginManager, cordova, dataResourceContext);
+    }
+    public static DataResource initiateNewDataRequestForUri(Uri uri, PluginManager pluginManager, CordovaInterface cordova, DataResourceContext dataResourceContext){
+        DataResource dataResource = new DataResource(cordova, uri);
+        if (pluginManager != null) {
+            // get the resource as returned by plugins
+            dataResource = pluginManager.handleDataResourceRequestWithPlugins(dataResource, dataResourceContext);
+        }
+        return dataResource;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/framework/src/org/apache/cordova/api/DataResourceContext.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/api/DataResourceContext.java b/lib/cordova-android/framework/src/org/apache/cordova/api/DataResourceContext.java
new file mode 100644
index 0000000..310586b
--- /dev/null
+++ b/lib/cordova-android/framework/src/org/apache/cordova/api/DataResourceContext.java
@@ -0,0 +1,31 @@
+package org.apache.cordova.api;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+/*
+ * Some context information associated with a DataRequest.
+ */
+public class DataResourceContext {
+    // A random id that is unique for a particular request.
+    private int requestId;
+    // A tag associated with the source of this dataResourceContext
+    private String source;
+    // If needed, any data associated with core plugins can be a part of the context object
+    // If needed, any data associated with non core plugins  should store data in a Map so as to not clutter the context object
+    private Map<String, Object> dataMap;
+    public DataResourceContext(String source) {
+        this.requestId = new Random().nextInt();
+        this.source = source;
+        this.dataMap = new HashMap<String, Object>();
+    }
+    public int getRequestId() {
+        return requestId;
+    }
+    public String getSource() {
+        return source;
+    }
+    public Map<String, Object> getDataMap() {
+        return dataMap;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/framework/src/org/apache/cordova/api/PluginManager.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/api/PluginManager.java b/lib/cordova-android/framework/src/org/apache/cordova/api/PluginManager.java
index 774b21c..e0ceabf 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/api/PluginManager.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/api/PluginManager.java
@@ -54,6 +54,7 @@ public class PluginManager {
     // Map URL schemes like foo: to plugins that want to handle those schemes
     // This would allow how all URLs are handled to be offloaded to a plugin
     protected HashMap<String, String> urlMap = new HashMap<String, String>();
+    private int MAX_REPITIONS = 1000;
 
     /**
      * Constructor.
@@ -109,7 +110,6 @@ public class PluginManager {
         int eventType = -1;
         String service = "", pluginClass = "", paramType = "";
         boolean onload = false;
-        PluginEntry entry = null;
         boolean insideFeature = false;
         while (eventType != XmlResourceParser.END_DOCUMENT) {
             if (eventType == XmlResourceParser.START_TAG) {
@@ -118,45 +118,37 @@ public class PluginManager {
                 if (strNode.equals("plugin")) {
                     service = xml.getAttributeValue(null, "name");
                     pluginClass = xml.getAttributeValue(null, "value");
-                    // System.out.println("Plugin: "+name+" => "+value);
+                    Log.d(TAG, "<plugin> tags are deprecated, please use <features> instead. <plugin> will no longer work as of Cordova 3.0");
                     onload = "true".equals(xml.getAttributeValue(null, "onload"));
-                    entry = new PluginEntry(service, pluginClass, onload);
-                    this.addService(entry);
                 }
                 //What is this?
                 else if (strNode.equals("url-filter")) {
                     this.urlMap.put(xml.getAttributeValue(null, "value"), service);
                 }
                 else if (strNode.equals("feature")) {
-                    insideFeature = true;
-                    //Check for supported feature sets (Accelerometer, Geolocation, etc)
+                    //Check for supported feature sets  aka. plugins (Accelerometer, Geolocation, etc)
                     //Set the bit for reading params
-                    String uri = xml.getAttributeValue(null,"name");
+                    insideFeature = true;
+                    service = xml.getAttributeValue(null, "name");
                 }
-                else if(strNode.equals("param")) {
-                    if(insideFeature)
-                    {
-                        paramType = xml.getAttributeValue(null, "name");
-                        if(paramType.equals("service"))
-                            service = xml.getAttributeValue(null, "value");
-                        else if(paramType.equals("package"))
-                            pluginClass = xml.getAttributeValue(null, "value");
-                        if(service.length() > 0  && pluginClass.length() > 0)
-                        {
-                            onload = "true".equals(xml.getAttributeValue(null, "onload"));
-                            entry = new PluginEntry(service, pluginClass, onload);
-                            this.addService(entry);
-                            service = "";
-                            pluginClass = "";
-                        }
-                    }
+                else if (insideFeature && strNode.equals("param")) {
+                    paramType = xml.getAttributeValue(null, "name");
+                    if (paramType.equals("service")) // check if it is using the older service param
+                        service = xml.getAttributeValue(null, "value");
+                    else if (paramType.equals("package") || paramType.equals("android-package"))
+                        pluginClass = xml.getAttributeValue(null,"value");
+                    else if (paramType.equals("onload"))
+                        onload = "true".equals(xml.getAttributeValue(null, "value"));
                 }
             }
             else if (eventType == XmlResourceParser.END_TAG)
             {
                 String strNode = xml.getName();
-                if(strNode.equals("feature"))
+                if (strNode.equals("feature") || strNode.equals("plugin"))
                 {
+                    PluginEntry entry = new PluginEntry(service, pluginClass, onload);
+                    this.addService(entry);
+
                     //Empty the strings to prevent plugin loading bugs
                     service = "";
                     pluginClass = "";
@@ -409,4 +401,32 @@ public class PluginManager {
         LOG.e(TAG, "https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-android.git;a=blob;f=framework/res/xml/plugins.xml");
         LOG.e(TAG, "=====================================================================================");
     }
+
+    /**
+     * Called when the any resource is going to be loaded - either from the webview, files or any other resource
+     *
+     *
+     * @param dataResource          The resource request to be loaded.
+     * @param dataResourceContext   The context of the dataResource request
+     * @return                      Return the resource request that will be loaded. The returned request may be modified or unchanged.
+     */
+    public DataResource handleDataResourceRequestWithPlugins(DataResource dataResource, DataResourceContext dataResourceContext){
+        int repetitions = 0;
+        boolean requestModified = true;
+        while(requestModified && repetitions < MAX_REPITIONS) {
+            requestModified = false;
+            repetitions ++;
+            for (PluginEntry entry : this.entries.values()) {
+                if (entry.plugin != null) {
+                    DataResource ret = entry.plugin.handleDataResourceRequest(dataResource, dataResourceContext);
+                    if(ret != null) {
+                        dataResource = ret;
+                        requestModified = true;
+                        break;
+                    }
+                }
+            }
+        }
+        return dataResource;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/test/proguard.cfg
----------------------------------------------------------------------
diff --git a/lib/cordova-android/test/proguard.cfg b/lib/cordova-android/test/proguard.cfg
deleted file mode 100644
index b1cdf17..0000000
--- a/lib/cordova-android/test/proguard.cfg
+++ /dev/null
@@ -1,40 +0,0 @@
--optimizationpasses 5
--dontusemixedcaseclassnames
--dontskipnonpubliclibraryclasses
--dontpreverify
--verbose
--optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-
--keep public class * extends android.app.Activity
--keep public class * extends android.app.Application
--keep public class * extends android.app.Service
--keep public class * extends android.content.BroadcastReceiver
--keep public class * extends android.content.ContentProvider
--keep public class * extends android.app.backup.BackupAgentHelper
--keep public class * extends android.preference.Preference
--keep public class com.android.vending.licensing.ILicensingService
-
--keepclasseswithmembernames class * {
-    native <methods>;
-}
-
--keepclasseswithmembers class * {
-    public <init>(android.content.Context, android.util.AttributeSet);
-}
-
--keepclasseswithmembers class * {
-    public <init>(android.content.Context, android.util.AttributeSet, int);
-}
-
--keepclassmembers class * extends android.app.Activity {
-   public void *(android.view.View);
-}
-
--keepclassmembers enum * {
-    public static **[] values();
-    public static ** valueOf(java.lang.String);
-}
-
--keep class * implements android.os.Parcelable {
-  public static final android.os.Parcelable$Creator *;
-}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-android/test/res/xml/config.xml
----------------------------------------------------------------------
diff --git a/lib/cordova-android/test/res/xml/config.xml b/lib/cordova-android/test/res/xml/config.xml
index 675aeb5..d3ea4d8 100644
--- a/lib/cordova-android/test/res/xml/config.xml
+++ b/lib/cordova-android/test/res/xml/config.xml
@@ -1,57 +1,86 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-       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.
--->
-<cordova>
-    <!--
-    access elements control the Android whitelist.
-    Domains are assumed blocked unless set otherwise
-     -->
-
-    <access origin="http://127.0.0.1*"/> <!-- allow local pages -->
-
-    <!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
-    <!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
-    <access origin=".*"/>
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns     = "http://www.w3.org/ns/widgets"
+        id        = "io.cordova.helloCordova"
+        version   = "2.0.0">
+    <name>Hello Cordova</name>
+
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+
+    <author href="http://cordova.io" email="callback-dev@incubator.apache.org">
+        Apache Cordova Team
+    </author>
+
+    <access origin="*"/>
+ 
+
+    <!-- <content src="http://mysite.com/myapp.html" /> for external pages -->
+    <content src="index.html" />
 
     <log level="DEBUG"/>
+
+    <!-- Preferences for Android -->
     <preference name="useBrowserHistory" value="true" />
-<plugins>
-    <plugin name="App" value="org.apache.cordova.App"/>
-    <plugin name="Activity" value="org.apache.cordova.test.ActivityPlugin"/>
-    <plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
-    <plugin name="Device" value="org.apache.cordova.Device"/>
-    <plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
-    <plugin name="Compass" value="org.apache.cordova.CompassListener"/>
-    <plugin name="Media" value="org.apache.cordova.AudioHandler"/>
-    <plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
-    <plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
-    <plugin name="File" value="org.apache.cordova.FileUtils"/>
-    <plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
-    <plugin name="Notification" value="org.apache.cordova.Notification"/>
-    <plugin name="Storage" value="org.apache.cordova.Storage"/>
-    <plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
-    <plugin name="Capture" value="org.apache.cordova.Capture"/>
-    <plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
-    <plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
-    <plugin name="Echo" value="org.apache.cordova.Echo" />
-    <plugin name="Globalization" value="org.apache.cordova.Globalization"/>
-    <plugin name="InAppBrowser" value="org.apache.cordova.InAppBrowser"/>
-</plugins>
-</cordova>
+    <preference name="exit-on-suspend" value="false" />
+
+    <feature name="App">
+      <param name="android-package" value="org.apache.cordova.App"/>
+    </feature>
+    <feature name="Geolocation">
+      <param name="android-package" value="org.apache.cordova.GeoBroker"/>
+    </feature>
+    <feature name="Device">
+      <param name="android-package" value="org.apache.cordova.Device"/>
+    </feature>
+    <feature name="Accelerometer">
+      <param name="android-package" value="org.apache.cordova.AccelListener"/>
+    </feature>
+    <feature name="Compass">
+      <param name="android-package" value="org.apache.cordova.CompassListener"/>
+    </feature>
+    <feature name="Media">
+      <param name="android-package" value="org.apache.cordova.AudioHandler"/>
+    </feature>
+    <feature name="Camera">
+      <param name="android-package" value="org.apache.cordova.CameraLauncher"/>
+    </feature>
+    <feature name="Contacts">
+      <param name="android-package" value="org.apache.cordova.ContactManager"/>
+    </feature>
+    <feature name="File">
+      <param name="android-package" value="org.apache.cordova.FileUtils"/>
+    </feature>
+    <feature name="NetworkStatus">
+      <param name="android-package" value="org.apache.cordova.NetworkManager"/>
+    </feature>
+    <feature name="Notification">
+      <param name="android-package" value="org.apache.cordova.Notification"/>
+    </feature>
+    <feature name="Storage">
+      <param name="android-package" value="org.apache.cordova.Storage"/>
+    </feature>
+    <feature name="FileTransfer">
+      <param name="android-package" value="org.apache.cordova.FileTransfer"/>
+    </feature>
+    <feature name="Capture">
+      <param name="android-package" value="org.apache.cordova.Capture"/>
+    </feature>
+    <feature name="Battery">
+      <param name="android-package" value="org.apache.cordova.BatteryListener"/>
+    </feature>
+    <feature name="SplashScreen">
+      <param name="android-package" value="org.apache.cordova.SplashScreen"/>
+    </feature>
+    <feature name="Echo">
+      <param name="android-package" value="org.apache.cordova.Echo"/>
+    </feature>
+    <feature name="Globalization">
+      <param name="android-package" value="org.apache.cordova.Globalization"/>
+    </feature>
+    <feature name="InAppBrowser">
+      <param name="android-package" value="org.apache.cordova.InAppBrowser"/>
+    </feature>
+         
+</widget>
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/.jshint
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/.jshint b/lib/cordova-blackberry/.jshint
new file mode 100644
index 0000000..9f5611b
--- /dev/null
+++ b/lib/cordova-blackberry/.jshint
@@ -0,0 +1,3 @@
+{
+    "es5" : true
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/.jshintignore
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/.jshintignore b/lib/cordova-blackberry/.jshintignore
new file mode 100644
index 0000000..6bb2b92
--- /dev/null
+++ b/lib/cordova-blackberry/.jshintignore
@@ -0,0 +1 @@
+bin/test/cordova/unit/params-bad.json

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/.npmignore
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/.npmignore b/lib/cordova-blackberry/.npmignore
new file mode 100644
index 0000000..db4145c
--- /dev/null
+++ b/lib/cordova-blackberry/.npmignore
@@ -0,0 +1,2 @@
+.gitignore
+.gitkeep

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/Jakefile
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/Jakefile b/lib/cordova-blackberry/Jakefile
new file mode 100644
index 0000000..81b2f6f
--- /dev/null
+++ b/lib/cordova-blackberry/Jakefile
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF
+ * or more contributor license agreements.  See th
+ * distributed with this work for additional infor
+ * regarding copyright ownership.  The ASF license
+ * to you under the Apache License, Version 2.0 (t
+ * "License"); you may not use this file except in
+ * with the License.  You may obtain a copy of the
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to
+ * software distributed under the License is distr
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ * KIND, either express or implied.  See the Licen
+ * specific language governing permissions and lim
+ * under the License.
+ */
+
+var DESC_NEW_LINE = "\n\t\t      #";
+
+var util         = require('util'),
+    fs           = require('fs'),
+    childProcess = require('child_process'),
+    path         = require("path"),
+    rexp_minified = new RegExp("\\.min\\.js$"),
+    rexp_src = new RegExp('\\.js$');
+
+// HELPERS
+// Iterates over a directory
+function forEachFile(root, cbFile, cbDone) {
+    var count = 0;
+
+    function scan(name) {
+        ++count;
+
+        fs.stat(name, function (err, stats) {
+            if (err) cbFile(err);
+
+            if (stats.isDirectory()) {
+                fs.readdir(name, function (err, files) {
+                    if (err) cbFile(err);
+
+                    files.forEach(function (file) {
+                        scan(path.join(name, file));
+                    });
+                    done();
+                });
+            } else if (stats.isFile()) {
+                cbFile(null, name, stats, done);
+            } else {
+                done();
+            }
+        });
+    }
+
+    function done() {
+        --count;
+        if (count === 0 && cbDone) cbDone();
+    }
+
+    scan(root);
+}
+
+desc("runs test");
+task('default', ['hint','test'], function () {});
+
+desc("run all tests in node - jake test [path]");
+task('test', [], function () {
+    require('./scripts/test')(null, process.argv.length >= 4 ? process.argv[3] : null);
+});
+
+desc('check sources with JSHint');
+task('hint', ['complainwhitespace'], function () {
+    var knownWarnings = [
+        "Redefinition of 'FileReader'",
+        "Redefinition of 'require'",
+        "Read only",
+        "Redefinition of 'console'"
+    ];
+    var filterKnownWarnings = function(el, index, array) {
+        var wut = true;
+        // filter out the known warnings listed out above
+        knownWarnings.forEach(function(e) {
+            wut = wut && (el.indexOf(e) == -1);
+        });
+        wut = wut && (!el.match(/\d+ errors/));
+        return wut;
+    };
+
+    childProcess.exec("jshint framework/lib bin/lib bin/test bin/templates/project/cordova bin/templates/project/project.json --config .jshint --extra-ext .json",function(err,stdout,stderr) {
+        var exs = stdout.split('\n');
+        console.log(exs.filter(filterKnownWarnings).join('\n'));
+        complete();
+    });
+}, true);
+
+var complainedAboutWhitespace = false
+
+desc('complain about what fixwhitespace would fix');
+task('complainwhitespace', function() {
+    processWhiteSpace(function(file, newSource) {
+        if (!complainedAboutWhitespace) {
+            console.log("files with whitespace issues: (to fix: `jake fixwhitespace`)")
+            complainedAboutWhitespace = true
+        }
+
+        console.log("   " + file)
+    })
+}, true);
+
+desc('converts tabs to four spaces, eliminates trailing white space, converts newlines to proper form - enforcing style guide ftw!');
+task('fixwhitespace', function() {
+    processWhiteSpace(function(file, newSource) {
+        if (!complainedAboutWhitespace) {
+            console.log("fixed whitespace issues in:")
+            complainedAboutWhitespace = true
+        }
+
+        fs.writeFileSync(file, newSource, 'utf8');
+        console.log("   " + file)
+    })
+}, true);
+
+function processWhiteSpace(processor) {
+    forEachFile('framework', function(err, file, stats, cbDone) {
+        //if (err) throw err;
+        if (rexp_minified.test(file) || !rexp_src.test(file)) {
+            cbDone();
+        } else {
+            var origsrc = src = fs.readFileSync(file, 'utf8');
+
+            // tabs -> four spaces
+            if (src.indexOf('\t') >= 0) {
+                src = src.split('\t').join('    ');
+            }
+
+            // eliminate trailing white space
+            src = src.replace(/ +\n/g, '\n');
+
+            if (origsrc !== src) {
+                // write it out yo
+                processor(file, src);
+            }
+            cbDone();
+        }
+    }, complete);
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/README.md
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/README.md b/lib/cordova-blackberry/README.md
index e2f9896..a19b87a 100644
--- a/lib/cordova-blackberry/README.md
+++ b/lib/cordova-blackberry/README.md
@@ -1,183 +1,96 @@
-Cordova BlackBerry WebWorks
-============================
+# Apache Cordova for BlackBerry 10
 
-[Cordova framework](http://incubator.apache.org/cordova/) for __BlackBerry Tablet OS, Smartphones and BlackBerry 10 devices__. The framework is implemented using the [BlackBerry WebWorks SDK](http://us.blackberry.com/developers/tablet/webworks.jsp).
+Apache Cordova is an application development platform which allows mobile applications to be written with web technology: HTML, CSS and JavaScript. Access to device APIs is provided by native plugins.
 
-Directory Structure
--------------------
+This implementation for BlackBerry 10 packages web assets into a BAR file which may be deployed to devices and simulators.
 
-    framework/ ... BlackBerry WebWorks JavaScript Extension (Cordova native code)
-    javascript/ .. Cordova JavaScript (concatenated, non-minified)
-    bin/ ......... Scripts for project creation
+## Pre-requisites
 
-Introduction
-------------
+Install the latest BlackBerry 10 NDK:
 
-BlackBerry WebWorks is a framework for developing web-based applications for BlackBerry SmartPhones (BlackBerry OS 5.0 and higher) and the TabletOS.  Creating a web application is one of the easiest ways to have an application that runs on both platforms.
+[https://developer.blackberry.com/native/download/](https://developer.blackberry.com/native/download)
 
-The WebWorks framework allows developers to create applications using web content and resources (HTML/CSS/JavaScript) that are able to access device features through the [BlackBerry WebWorks API](http://www.blackberry.com/developers/docs/widgetapi/).  In addition, the framework allows developers to create their own WebWorks JavaScript Extensions to expose additional device capabilities through JavaScript APIs.  These extensions are written using either the BlackBerry Java API for SmartPhones, or Adobe AIR for the Tablet OS.
+Setup environment variables:
+- [Linux/Mac] `source [BBNDK directory]/bbndk-env.sh`
+- [Windows] `[BBNDK directory]\bbndk-env.bat`
 
-The cordova-blackberry-webworks platform allows web developers to develop applications targeting BlackBerry 5.0 and higher devices using the common [Cordova API](http://docs.cordova.io).  When possible, Cordova makes use of the WebWorks JavaScript API; however, most Cordova features are implemented in the native Java or AIR environment as a WebWorks JavaScript Extension.
+Install code signing keys:
 
+[https://developer.blackberry.com/html5/documentation/signing_setup_bb10_apps_2008396_11.html](https://developer.blackberry.com/html5/documentation/signing_setup_bb10_apps_2008396_11.html)
 
-Getting Started
-===============
+Install node.js:
 
-Several guides are available on the [Cordova Documentation site](http://docs.cordova.io/) (Getting Started Guides - on the left side near the bottom) to help you get started developing for the cordova-blackberry-webworks platform.  This guide will help you install and configure the BlackBerry WebWorks development environment, and the cordova-blackberry-webworks platform.  It will also step you through the process of creating a Cordova project.
+[http://nodejs.org/](http://nodejs.org/)
 
-[Getting Started with Cordova BlackBerry WebWorks](http://docs.cordova.io/guide_getting-started_blackberry_index.md.html)
+## Getting Started
 
-This guide is for advanced developers who wish to develop their own cordova-blackberry-webworks plugin.
+Create a new project:
 
-[How To Create a Cordova Plugin for Cordova BlackBerry WebWorks](http://docs.cordova.io/guide_plugin-development_blackberry_index.md.html)
+`bin/create <path to project>`
 
+## Managing Targets
 
-Installing the cordova-blackberry-webworks Framework
-=====================================================
+A target is a device or simulator which will run the app.
 
-Cloning the cordova-blackberry-webworks repository always provides you with the latest (EDGE) version of the Cordova code.  To clone the repository, do the following:
+This command will add a new target: 
 
-    $ cd C:\some\path\
-    $ git clone git://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks.git
+`<path to project>/cordova/target add <name> <ip> <device | simulator> [-p | --password <password>] [--pin <devicepin>]`
 
-Cordova BlackBerry Developer Tools
----
+To remove a target:
 
-The Cordova developer tooling is split between general tooling and project level tooling. If you are on Windows, please run the equivalent .bat files instead of the shell scripts :)
+`<path to project>/cordova/target remove <name>`
 
-### General Commands
+To set a target as default:
 
-    ./bin/create [path appname packagename] ............ creates a sample app with the specified application name, to the specified path
+`<path to project>/cordova/target default <name>`
 
-Please note that once you `create` a Cordova BlackBerry project, you
-will need to edit the `project.properties` file that resides inside your
-generated application directory to set up your environment properly. You
-will need to specify things like the location of the BlackBerry Widget
-Packager(s), device and signing key passwords, simulator executables,
-and device IPs (if applicable).
+## Building
 
-The ./bin/create command is also required to be called in order to automatically download 
-the bin/template/project/lib/ant-contrib.jar file. Please be aware that without running
-this command first, your project will not have this important file! Once that ant-contrib.jar
-file is downloaded, there is no need to update that file or download again.
+`<path to project>/cordova/build`
 
-#### Running the Example Project
+A project can be built in debug or release mode.
 
-Create the example project and build it to the first device:
+To run an application in debug mode, a debug token must first be installed on the device. The build script will automatically attempt to generate a token and install it. This requires code signing keys to be installed on the development machine. Debug mode will also enable WebInspector. A prompt will appear with the URL to access WebInspector from a remote machine.
 
-    ./bin/create
-    cd example
-    ./cordova/run blackberry
+If building in release mode, a unique buildId must be provided, either via command line or by setting it in config.xml.
 
-#### Creating a new Cordova BlackBerry Project
+Here is the build script syntax:
 
-    ./bin/create ~/Desktop/myapp MyAppName MyAppPackageName
+`build command [<target>] [-k | --keystorepass] [-b | --buildId <number>] [-p | --params <json>] [-ll | --loglevel <level>]`
 
-### Project Commands
+Commands:
 
-These commands live in a generated Cordova BlackBerry project. As per
-the note above, please make sure you edit the `project.properties` file
-inside your application directory appropriately otherwise these commands
-will not work!
+    release [options] 
+        Build in release mode. This will sign the resulting bar.
+    
+    debug [options] 
+        Build in debug mode.
 
-    ./cordova/run ............................ install to a connected device or simulator
-    ./cordova/build .......................... build project, but do not deploy to simulator or device
+  Options:
 
+    -h, --help                       output usage information
+    -k, --keystorepass <password>    Signing key password
+    -b, --buildId <num>              Specifies the build number for signing (typically incremented from previous signing).
+    -p, --params <params JSON file>  Specifies additional parameters to pass to downstream tools.
+    -ll, --loglevel <loglevel>       set the logging level (error, warn, verbose)`
 
-(Legacy) Creating a New Cordova Project
--------------------------------
+## Deploying
 
-The (legacy) Cordova ant build scripts enable you to create multiple, independent Cordova projects.
+To deploy the project to a target, use the run command:
 
-(Note: The Cordova build script requires Apache ANT 1.8 or higher. Also, these scripts won't work without
-the bin/template/project/lib/ant-contrib.jar file so please run the ./bin/create command to automatically
-download that file or manually download it and place it in the bin/template/lib/ directory.
+`<path to project>/cordova/run <target>`
 
-The build script packages the Cordova source code and resources into each project you create.  This allows you to easily distribute the project to other BlackBerry WebWorks developers.  To create a Cordova project:
+## Plugin Management
 
-    $ cd cordova-blackberry-webworks
-    $ ant help
+To add a plugin from a local path, you will first need to run fetch:
 
-    $ ant create -Dproject.path="C:\development\my_new_project"
+`<path to project>/cordova/plugin fetch <path to plugin>`
 
-    $ cd C:\development\my_new_project
-    $ ant help
+Now the plugin can be installed by name:
 
-For each project, you need to tell ANT where you installed the BlackBerry WebWorks SDK, which packages and compiles your code into a deployable application.  You can specify the location of the BlackBerry WebWorks Packager (BBWP) by editing __project.properties__ in the project directory.
+`<path to project>/cordova/plugin install <name>`
 
-    [edit project.properties]
+Plugins hosted remotely can be installed by name without using fetch. To see a list of available remote plugins use:
 
-Building and Deploying a Project
---------------------------------
+`<path to project>/cordova/plugin list`
 
-The Cordova build scripts automate common tasks, such as compiling your project, and deploying it to simulators or devices.  To see what options are available, use:
-
-    $ cd C:\development\my_new_project
-    $ ant help
-
-Every command is in the form `ant TARGET COMMAND [options]`, where
-target is either `blackberry`, `playbook` or `qnx`.
-
-To build your project into a deployable application (.cod/.jad) file:
-
-    $ ant TARGET build
-
-To build your project and load it in a BlackBerry simulator:
-
-    $ ant TARGET load-simulator
-
-To build your project and load it onto a USB-attached device:
-
-    $ ant TARGET load-device
-
-Updating the Cordova Framework
--------------------------------
-
-As you develop your application, there may be updates made to the Cordova source code.  To incorporate Cordova changes into your project, use the build script as follows:
-
-    $ cd cordova-blackberry-webworks
-    $ git pull origin master
-
-    $ ant update -Dproject.path="C:\development\my_new_project"
-
-Customizing Cordova
---------------------
-
-By default, Cordova gives access to all the core Cordova APIs as detailed at docs.cordova.io.
-If you want to remove some of those APIs you can do so by editing the plugins.xml document in your 
-application root. You need to edit the plugins.xml file to add third-party plugins to your application 
-as well.
-
-Creating a Distribution
------------------------
-
-### Update Version
-
-    $ ant version -Dvalue="1.0.0"
-
-    $ git diff
-    $ git commit -am "Update to version 1.0.0"
-    $ git tag 1.0.0
-
-### Create distribution
-
-    $ ant dist
-
-Troubleshooting
-===============
-
-__Q: I uploaded my application to the BlackBerry device, but it will not open or run.__
-
-__A:__ Try hard resetting the device by pressing and hold ALT + CAPS LOCK + DEL. You must press and hold each key in sequence and not all at once.  Some devices require _either_ the right or left CAPS LOCK key to be pressed.  Some devices also require this combination to be pressed twice.
-
-__Q: My simulator screen is not refreshing and I see blocks on a clicked position.__
-
-__A:__ Windows 7 and the simulator's graphics acceleration do not mix. On the simulator, set View -> Graphics Acceleration to Off.
-
-__Q: When I use the Cordova [Camera.getPicture API](http://docs.cordova.io/cordova_camera_camera.md.html#camera.getPicture) on my device, the camera never returns to my application.  Why does this happen?__
-
-__A:__ Cordova uses a JavaScript Extension to invoke the native camera application so the user can take a picture.  When the picture is taken, Cordova will close the native camera application by emulating a key injection (pressing the back/escape button).  On a physical device, users will have to set permissions to allow the application to simulate key injections.  Setting application permissions is device-specific.  On a Storm2 (9550), for example, select the BlackBerry button from the Home screen to get to All Applications screen, then Options > Applications > Your Application.  Then select Edit Default Permissions > Interactions > Input Simulation and set it to 'Allow'.  Save your changes.
-
-__Q: None of the Cordova APIs are working, why is that?__
-
-__A:__ You probably need to update your plugins.xml file in the root of your application.

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/VERSION
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/VERSION b/lib/cordova-blackberry/VERSION
index 24ba9a3..38f8e88 100644
--- a/lib/cordova-blackberry/VERSION
+++ b/lib/cordova-blackberry/VERSION
@@ -1 +1 @@
-2.7.0
+dev

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/bin/check_reqs
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/bin/check_reqs b/lib/cordova-blackberry/bin/check_reqs
new file mode 100755
index 0000000..9a8e9ee
--- /dev/null
+++ b/lib/cordova-blackberry/bin/check_reqs
@@ -0,0 +1,28 @@
+#!/usr/bin/env node
+
+/**
+ * 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.
+ */
+
+var qnxHost = process.env.QNX_HOST;
+
+if (typeof qnxHost !== "undefined" && typeof process.env.QNX_TARGET !== "undefined" && process.env.PATH.indexOf(qnxHost) !== -1) {
+    process.exit(0);
+} else {
+    process.exit(-1);
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/bin/check_reqs.bat
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/bin/check_reqs.bat b/lib/cordova-blackberry/bin/check_reqs.bat
new file mode 100755
index 0000000..ed05fac
--- /dev/null
+++ b/lib/cordova-blackberry/bin/check_reqs.bat
@@ -0,0 +1,21 @@
+@ECHO OFF
+goto comment
+       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.
+:comment
+
+@node.exe %~dp0\check_reqs %*

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/bin/create
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/bin/create b/lib/cordova-blackberry/bin/create
index ca84dc8..87ce4c3 100755
--- a/lib/cordova-blackberry/bin/create
+++ b/lib/cordova-blackberry/bin/create
@@ -17,92 +17,9 @@
 #       under the License.
 #
 # create a cordova/blackberry project
-# 
+#
 # USAGE
 #   ./create [path package appname]
 #
-set -e
-
-if [ -n "$1" ] && [ "$1" == "-h" ]
-then
-  echo "Usage: $0 <path_to_new_project> <package_name> <project_name>"
-  echo "    <path_to_new_project>: Path to your new Cordova iOS project"
-  echo "    <package_name>: Package name, following reverse-domain style convention (ignored on BlackBerry platforms)"
-  echo "    <project_name>: Project name"
-  echo 'After you have created your application, make sure to customize the project.properties file inside your app directory with your environment specifics!'
-  exit 0;
-fi
-
-
-BUILD_PATH="$( cd "$( dirname "$0" )/.." && pwd )"
-VERSION=$(cat "$BUILD_PATH/VERSION")
-
-PROJECT_PATH="${1:-"./example"}"
-PACKAGE=${2:-"org.apache.cordova.example"}
-NAME=${3:-"cordovaExample"}
-
-# clobber any existing example
-if [ -d "$PROJECT_PATH" ]
-then
-    echo "Project already exists! Delete and recreate"
-    exit 1
-fi
-
-# cleanup after exit and/or on error
-function on_exit {
-    echo "Cleaning up ..."
-    [ -d "$BUILD_PATH/build" ] && rm -rf "$BUILD_PATH/build"
-    echo "Remember to update the project.properties file inside your application directory!"
-}
-
-function on_error {
-    echo "An error occured. Deleting project..."
-    [ -d "$PROJECT_PATH" ] && rm -rf "$PROJECT_PATH"
-}
-
-function replace {
-    local pattern=$1
-    local filename=$2
-    # Mac OS X requires -i argument
-    if [[ "$OSTYPE" =~ "darwin" ]]
-    then
-        /usr/bin/sed -i '' -e $pattern "$filename"
-    elif [[ "$OSTYPE" =~ "linux" ]]
-    then
-        /bin/sed -i -e $pattern "$filename"
-    fi
-}
-
-# we do not want the script to silently fail
-trap on_error ERR
-trap on_exit EXIT
-
-ANT="$(which ant)"
-
-MANIFEST_PATH="$PROJECT_PATH/www/config.xml"
-
-# compile cordova.js and cordova.jar if in source, ignore if in distribution
-if [ ! -e "$BUILD_PATH/www/ext/cordova-$VERSION.jar" ] && [ -d "$BUILD_PATH/framework" ]
-then
-    if [ ! -e "$BUILD_PATH"/bin/templates/project/lib/ant-contrib/ant-contrib-1.0b3.jar ]; then
-        echo "Downloading ant-contrib"
-        # Use curl to get the jar
-        curl -OL http://central.maven.org/maven2/ant-contrib/ant-contrib/1.0b3/ant-contrib-1.0b3.jar &> /dev/null
-        mkdir -p "$BUILD_PATH"/bin/templates/project/lib/ant-contrib
-        mv ant-contrib-1.0b3.jar "$BUILD_PATH"/bin/templates/project/lib/ant-contrib
-    fi
-    
-	echo "Creating BlackBerry project..."
-	("$ANT" create -Dproject.path="$PROJECT_PATH" -f "$BUILD_PATH/build.xml" &> /dev/null)
-    # interpolate the activity and package into config.xml
-    echo "Updating config.xml ..."
-    replace "s/__NAME__/${NAME}/g" "$MANIFEST_PATH"
-    replace "s/__PACKAGE__/${PACKAGE}/g" "$MANIFEST_PATH"
-else
-	# copy project template if in distribution
-	echo "Copying assets and resources ..."
-	cp -r "$BUILD_PATH/sample/." "$PROJECT_PATH"
-    echo "Updating config.xml ..."
-    replace "s/cordovaExample/${NAME}/g" "$MANIFEST_PATH"
-    replace "s/org.apache.cordova.example/${PACKAGE}/g" "$MANIFEST_PATH"
-fi
+#!/bin/sh
+node $( dirname "$0" )"/create.js" "$@"