You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by js...@apache.org on 2014/07/07 23:43:54 UTC

[48/51] [partial] CB-7087 Retire blackberry10/ directory

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/localize.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/localize.js b/bin/templates/project/cordova/lib/localize.js
new file mode 100755
index 0000000..a6fe900
--- /dev/null
+++ b/bin/templates/project/cordova/lib/localize.js
@@ -0,0 +1,204 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed 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 Localize = require("localize"),
+    loc = new Localize({
+        "EXCEPTION_NATIVEPACKAGER": {
+            "en": "Native Packager exception occurred"
+        },
+        "EXCEPTION_WIDGET_ARCHIVE_NOT_FOUND": {
+            "en": "Failed to find WebWorks archive: $[1]"
+        },
+        "EXCEPTION_MISSING_SIGNING_KEY_FILE": {
+            "en": "Cannot sign application - failed to find signing key file: $[1]"
+        },
+        "WARNING_MISSING_SIGNING_KEY_FILE": {
+            "en": "Build ID set in config.xml [version], but signing key file was not found: $[1]"
+        },
+        "EXCEPTION_MISSING_SIGNING_PASSWORD": {
+            "en": "Cannot sign application - No signing password provided [-g]"
+        },
+        "WARNING_SIGNING_PASSWORD_EXPECTED": {
+            "en": "Build ID set in config.xml [version], but no signing password was provided [-g]. Bar will be unsigned"
+        },
+        "EXCEPTION_DEBUG_TOKEN_NOT_FOUND": {
+            "en": "Failed to find debug token. If you have an existing debug token, please copy it to $[1]. To generate a new debug token, execute the 'run' command."
+        },
+        "EXCEPTION_DEBUG_TOKEN_WRONG_FILE_EXTENSION": {
+            "en": "Specified debug token not a .bar extension"
+        },
+        "PROGRESS_SESSION_CONFIGXML": {
+            "en": "Parsing config.xml"
+        },
+        "PROGRESS_FILE_POPULATING_SOURCE": {
+            "en": "Populating application source"
+        },
+        "PROGRESS_GEN_OUTPUT": {
+            "en": "Generating output files"
+        },
+        "PROGRESS_PACKAGING": {
+            "en": "Packaging the BAR file"
+        },
+        "PROGRESS_COMPLETE": {
+            "en": "BAR packaging complete"
+        },
+        "EXCEPTION_PARSING_XML": {
+            "en": "An error has occurred parsing the config.xml. Please ensure that it is syntactically correct"
+        },
+        "EXCEPTION_INVALID_VERSION": {
+            "en": "Please enter a valid application version"
+        },
+        "EXCEPTION_INVALID_NAME": {
+            "en": "Please enter a valid application name"
+        },
+        "EXCEPTION_INVALID_AUTHOR": {
+            "en": "Please enter an author for the application"
+        },
+        "EXCEPTION_INVALID_ID": {
+            "en": "Please enter an application id"
+        },
+        "EXCEPTION_INVALID_FEATURE_ID": {
+            "en": "Invalid <feature> element - failed to find the id attribute"
+        },
+        "EXCEPTION_BUFFER_ERROR": {
+            "en": "ERROR in bufferToString(): Buffer length must be even"
+        },
+        "EXCEPTION_FEATURE_DEFINED_WITH_WILDCARD_ACCESS_URI_OR_ORIGIN": {
+            "en": "Invalid config.xml - no <feature> tags are allowed for this <access> element"
+        },
+        "EXCEPTION_INVALID_ACCESS_URI_NO_PROTOCOL": {
+            "en": "Invalid URI attribute in the access element - protocol required($[1])"
+        },
+        "WARNING_URI_AND_ORIGIN_FOUND_IN_CONFIG": {
+            "en": "Invalid config.xml - <access> tags should have one of 'uri' or 'origin' attributes. 'origin' attribute will be ignored"
+        },
+        "EXCEPTION_INVALID_ACCESS_URI_NO_URN": {
+            "en": "Failed to parse the URI attribute in the access element($[1])"
+        },
+        "EXCEPTION_CMDLINE_ARG_INVALID": {
+            "en": "Invalid command line argument \"$[1]\""
+        },
+        "EXCEPTION_INVOKE_TARGET_INVALID_ID": {
+            "en": "Each rim:invoke-target element must specify a valid id attribute"
+        },
+        "EXCEPTION_INVOKE_TARGET_INVALID_TYPE": {
+            "en": "rim:invoke-target element must be specified and cannot be empty"
+        },
+        "EXCEPTION_INVOKE_TARGET_ACTION_INVALID": {
+            "en": "Each filter element must specify at least one valid action"
+        },
+        "EXCEPTION_INVOKE_TARGET_MIME_TYPE_INVALID": {
+            "en": "Each filter element must specify at least one valid mime-type"
+        },
+        "EXCEPTION_INVOKE_TARGET_FILTER_PROPERTY_INVALID": {
+            "en": "At least one property element in an invoke filter is invalid"
+        },
+        "EXCEPTION_INVALID_ICON_SRC": {
+            "en": "Icon src cannot be empty"
+        },
+        "EXCEPTION_INVALID_SPLASH_SRC": {
+            "en": "Splash src cannot be empty"
+        },
+        "EXCEPTION_INVALID_ICON_SRC_LOCALES": {
+            "en": "Icon src should not point to files under \"locales\" folder, bbwp will perform folder-based localization"
+        },
+        "EXCEPTION_INVALID_SPLASH_SRC_LOCALES": {
+            "en": "Splash src should not point to files under \"locales\" folder, bbwp will perform folder-based localization"
+        },
+        "EXCEPTION_EXTENSION_CIRCULAR_DEPENDENCY": {
+            "en": "Circular dependency detected for extension: \"$[1]\""
+        },
+        "EXCEPTION_EXTENSION_NOT_FOUND": {
+            "en": "Extension \"$[1]\" not found in \"ext\" folder"
+        },
+        "EXCEPTION_PARAMS_FILE_ERROR": {
+            "en": "An error has occurred parsing \"$[1]\""
+        },
+        "EXCEPTION_PARAMS_FILE_NOT_FOUND": {
+            "en": "\"$[1]\" does not exist"
+        },
+        "EXCEPTION_MISSING_TOOLS": {
+            "en": "BBNDK tools could not be found. Please ensure you have installed the BlackBerry Native SDK [http://developer.blackberry.com/native/] and have the PATH configured via bbndk-env script."
+        },
+        "EXCEPTION_INVALID_ORIENTATION_MODE": {
+            "en": "\"$[1]\" is not a valid orientation mode"
+        },
+        "EXCEPTION_EMPTY_ORIENTATION_MODE": {
+            "en": "blackberry.app.orientation parameter \"mode\" missing"
+        },
+        "EXCEPTION_BGCOLOR_INVALID" : {
+            "en": "Background color \"$[1]\" is not a valid number"
+        },
+        "EXCEPTION_CONFIG_NOT_FOUND" : {
+            "en": "No config.xml file was found at the root of the .zip file"
+        },
+        "EXCEPTION_CORDOVA_JS_IN_LIB_DIR" : {
+            "en": "$[1] cordova.js files found in lib"
+        },
+        "WARN_CORDOVA_JS_PACKAGED" : {
+            "en": "cordova.js is now packaged as local:///chrome/cordova.js"
+        },
+        "WARN_WEBPLATFORM_JS_PACKAGED" : {
+            "en": "webplatform.js has been packaged as an alternative to the on device version"
+        },
+        "WARN_WEBPLATFORM_I18N_PACKAGED" : {
+            "en": "i18n.js has been packaged as an alternative to the on device version"
+        },
+        "EXCEPTION_INVALID_ARCHIVE_PATH" : {
+            "en": "An archive or directory does not exist at the path specified: \"$[1]\""
+        },
+        "EXCEPTION_APPDESC_NOT_FOUND" : {
+            "en": "The bar descriptor file does not exist at the path specified: \"$[1]\""
+        },
+        "WARNING_ORIENTATION_DEPRECATED": {
+            "en": "blackberry.app.orientation has been deprecated, please use blackberry.app instead"
+        },
+        "WARNING_WEBSECURITY_DISABLED": {
+            "en": "You have disabled all web security in this WebWorks application"
+        },
+        "PROGRESS_DEBUG_TOKEN_IS_VALID": {
+            "en": "The existing debug token is valid"
+        },
+        "WARN_TARGET_NOT_EXIST": {
+            "en": "The target \"$[1]\" does not exist"
+        },
+        "WARN_IP_NOT_DEFINED": {
+            "en": "IP is not defined in target \"$[1]\""
+        },
+        "WARN_PASSWORD_NOT_DEFINED": {
+            "en": "Password is not defined in target \"$[1]\""
+        },
+        "PROGRESS_DEPLOYING_DEBUG_TOKEN": {
+            "en": "Deploying debug token to target \"$[1]\""
+        },
+        "WARN_NO_DEVICE_PIN_FOUND": {
+            "en": "No device PIN found, will omit debug token generation"
+        },
+        "WARN_NO_SIGNING_PASSWORD_PROVIDED": {
+            "en": "No signing password provided, debug token cannot be generated. Please enter a value for 'keystorepass' in $[1]/.cordova/blackberry10.json or use --keystorepass via command-line."
+        },
+        "PROGRESS_GENERATING_DEBUG_TOKEN": {
+            "en": "Generating debug token"
+        },
+        "WARN_RUN_DEVICE_OVERRIDES_EMULATOR": {
+            "en": "Skipping emulator detection and detecting device. Please provide only 1 of --target, --device, and --emulator"
+        }
+
+    }, "", ""); // TODO maybe a bug in localize, must set default locale to "" in order get it to work
+
+loc.setLocale("en");
+
+module.exports = loc;

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/log
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/log b/bin/templates/project/cordova/lib/log
new file mode 100755
index 0000000..84e76c6
--- /dev/null
+++ b/bin/templates/project/cordova/lib/log
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+<<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
+set -e
+NOTIMPLEMENTED_VALUE=1
+
+echo 'BlackBerry10: logging not supported at this time.'
+exit $NOTIMPLEMENTED_VALUE

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/log.bat
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/log.bat b/bin/templates/project/cordova/lib/log.bat
new file mode 100644
index 0000000..ef5f6d9
--- /dev/null
+++ b/bin/templates/project/cordova/lib/log.bat
@@ -0,0 +1,21 @@
+:: 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.
+
+@ECHO OFF
+
+ECHO echo 'BlackBerry10: logging not supported at this time.'
+EXIT /B 1

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/logger.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/logger.js b/bin/templates/project/cordova/lib/logger.js
new file mode 100644
index 0000000..f751a57
--- /dev/null
+++ b/bin/templates/project/cordova/lib/logger.js
@@ -0,0 +1,40 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed 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 level = 'verbose';
+
+module.exports = {
+    level: function (value) {
+        level = value;
+    },
+    info: function (msg) {
+        if (level === 'verbose') {
+            console.log("[INFO]    " + msg.replace(/info: /i, ""));
+        }
+    },
+    error: function (msg) {
+        console.error("[ERROR]   " + msg.replace(/error: /i, ""));
+    },
+    warn: function (msg) {
+        if (level !== 'error') {
+            console.log("[WARN]    " + msg.replace(/warning: /i, ""));
+        }
+    },
+    log: function (msg) {
+        if (level === "verbose") {
+            console.log("[INFO]    " + msg.replace(/info: /i, ""));
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/native-packager.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/native-packager.js b/bin/templates/project/cordova/lib/native-packager.js
new file mode 100644
index 0000000..9f53779
--- /dev/null
+++ b/bin/templates/project/cordova/lib/native-packager.js
@@ -0,0 +1,293 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed 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.
+ */
+/*jshint sub:true*/
+var childProcess = require("child_process"),
+    fs = require("fs"),
+    path = require("path"),
+    util = require("util"),
+    utils = require("./utils"),
+    data2xml = require("../third_party/data2xml/data2xml"),
+    wrench = require("wrench"),
+    conf = require("./conf"),
+    logger = require("./logger"),
+    localize = require("./localize"),
+    pkgrUtils = require("./packager-utils"),
+    i18nMgr = require("./i18n-manager"),
+    et = require("elementtree"),
+    xmlHelper = require("./xml-helpers"),
+    NL = pkgrUtils.isWindows() ? "\r\n" : "\n";
+
+function generateTabletXMLFile(session, config) {
+    var files = wrench.readdirSyncRecursive(session.sourceDir),
+        xmlData,
+        xmlDoc,
+        xmlObject = {
+            id : config.id,
+            versionNumber : config.version,
+            author : config.author,
+            asset : [{
+                _attr : { entry : 'true', type : 'qnx/elf' },
+                _value : 'wwe'
+            }],
+            entryPointType : {
+                _value : "Qnx/WebKit"
+            },
+            cascadesTheme : {
+                _value : config.theme
+            },
+            initialWindow : {
+                systemChrome : 'none',
+                transparent : 'true',
+                autoOrients : 'true'
+            },
+            env : [{
+                _attr : { value : '2.0.0', var : 'WEBWORKS_VERSION'}
+            }],
+            permission : [{
+                _attr : { system : 'true'},
+                _value : 'run_native'
+            }, {
+                // hardcoded access_internet to ensure user has internet (whitelist takes care of security)
+                _attr : { system : 'false'},
+                _value : 'access_internet'
+            }]
+        };
+
+    // If appdesc is specified, use it as the bar descriptor
+    if (session.appdesc) {
+        pkgrUtils.copyFile(session.appdesc, session.sourceDir);
+        return;
+    }
+
+    //Enable slog2 output if debugging
+    if (session.debug) {
+        xmlObject.env.push({
+            _attr : { value : 'slog2', 'var' : 'CONSOLE_MODE' }
+        });
+    }
+
+    //Write user specified permissions
+    if (config.permissions) {
+        config.permissions.forEach(function (permission) {
+            var permissionAttr,
+                permissionValue;
+
+            if (typeof permission === "string") {
+                //Permission with no attributes
+                permissionValue = permission;
+            } else if (permission["@"] && permission["#"]) {
+                //Permission with attributes
+                permissionAttr = permission["@"];
+                permissionValue = permission["#"];
+            }
+
+            if (permissionValue) {
+                xmlObject.permission.push({
+                    _attr : permissionAttr,
+                    _value : permissionValue
+                });
+            }
+        });
+    }
+
+    i18nMgr.generateLocalizedText(session, config, xmlObject, "name");
+
+    if (config.description) {
+        i18nMgr.generateLocalizedText(session, config, xmlObject, "description");
+    }
+
+    i18nMgr.generateLocalizedMetadata(session, config, xmlObject, "icon");
+    i18nMgr.generateLocalizedMetadata(session, config, xmlObject, "rim:splash");
+
+    if (config["invoke-target"]) {
+        xmlObject["invoke-target"] = [];
+
+        config["invoke-target"].forEach(function (invokeTarget) {
+
+            var xmlInvokeTarget = {
+                "_attr" : { id : invokeTarget["@"]["id"] },
+                "entry-point" : config.name,
+                "type" : invokeTarget["type"]
+            };
+
+            if (invokeTarget["require-source-permissions"]) {
+                xmlInvokeTarget["require-source-permissions"] = {
+                    _value : invokeTarget["require-source-permissions"]
+                };
+            }
+
+            if (invokeTarget.filter) {
+                xmlInvokeTarget.filter = [];
+                invokeTarget.filter.forEach(function (filter) {
+                    var xmlFilter = {
+                        "action" : filter.action,
+                        "mime-type": filter["mime-type"]
+                    };
+
+                    if (filter.property) {
+                        xmlFilter.property = [];
+                        filter.property.forEach(function (property) {
+                            xmlFilter.property.push({
+                                "_attr": { var : property["@"]["var"], value : property["@"].value }
+                            });
+                        });
+                    }
+
+                    xmlInvokeTarget.filter.push(xmlFilter);
+                });
+            }
+
+            xmlObject["invoke-target"].push(xmlInvokeTarget);
+
+        });
+    }
+
+    //buildId
+    if (config.buildId) {
+        xmlObject.buildId = config.buildId;
+    }
+
+    if (files) {
+        files.forEach(function (file) {
+            file = path.resolve(session.sourceDir, file);
+
+            if (file.indexOf(conf.BAR_DESCRIPTOR) < 0 && !fs.statSync(file).isDirectory()) {
+                file = file.replace(/\\/g, "/");
+                file = file.split("src/")[1];
+
+                if (path.extname(file) === ".so") {
+                    xmlObject.asset.push({
+                        _attr : { type : 'qnx/elf' },
+                        _value : file
+                    });
+                } else {
+                    xmlObject.asset.push({
+                        _value : file
+                    });
+                }
+            }
+        });
+    }
+
+    //Add orientation mode
+    if (config.orientation) {
+        xmlObject.initialWindow.aspectRatio = config.orientation;
+    }
+
+    //Add auto orientation
+    xmlObject.initialWindow.autoOrients = config.autoOrientation;
+
+    xmlData = data2xml('qnx', xmlObject);
+
+    //Inject any config-file modifications for bar-descriptor.xml
+    if (config.configFileInjections && Array.isArray(config.configFileInjections)) {
+        xmlDoc = new et.ElementTree(et.XML(xmlData));
+        config.configFileInjections.forEach(function (config_file) {
+            if (config_file.attrib["parent"] && config_file.attrib["target"]  && config_file.attrib["target"] === "bar-descriptor.xml") {
+                xmlHelper.graftXML(xmlDoc, config_file._children, config_file.attrib["parent"]);
+            }
+        });
+        xmlData = xmlDoc.write({indent: 4});
+    }
+
+    pkgrUtils.writeFile(session.sourceDir, conf.BAR_DESCRIPTOR, xmlData);
+}
+
+function generateOptionsFile(session, target, config) {
+    var srcFiles = wrench.readdirSyncRecursive(session.sourceDir),
+        isSigning = session.isSigningRequired(config),
+        optionsStr = "-package" + NL,
+        params = session.getParams("blackberry-nativepackager");
+
+    //if -d was provided and we are not signing [-g], set debugToken and devMode
+    if (session.debug && !isSigning) {
+        if (fs.existsSync(conf.DEBUG_TOKEN)) {
+            optionsStr += "-debugToken" + NL;
+            optionsStr += conf.DEBUG_TOKEN + NL;
+        } else {
+            logger.warn(localize.translate("EXCEPTION_DEBUG_TOKEN_NOT_FOUND", path.join(pkgrUtils.homedir(), '.cordova', 'blackberry10debugtoken.bar')));
+        }
+        optionsStr += "-devMode" + NL;
+    }
+
+    if (target === "device" && isSigning && config.buildId) {
+        optionsStr += "-buildId" + NL;
+        optionsStr += config.buildId + NL;
+    }
+
+    if (params) {
+        Object.getOwnPropertyNames(params).forEach(function (p) {
+            optionsStr += p + NL;
+
+            if (params[p]) {
+                optionsStr += params[p] + NL;
+            }
+        });
+    }
+
+    optionsStr += path.resolve(util.format(session.barPath, target)) + NL;
+
+    //to support splash screens/icons for multiple resolutions/devices
+    optionsStr += "-barVersion" + NL;
+    optionsStr += "1.5" + NL;
+
+    optionsStr += "-C" + NL;
+    optionsStr += session.sourceDir + NL;
+    optionsStr += conf.BAR_DESCRIPTOR + NL;
+
+    srcFiles.forEach(function (file) {
+        file = path.resolve(session.sourceDir, file);
+
+        if (file.indexOf(conf.BAR_DESCRIPTOR) < 0 && !fs.statSync(file).isDirectory()) {
+            optionsStr += file + NL;
+        }
+    });
+
+    fs.writeFileSync(path.normalize(session.sourceDir + "/../options"), optionsStr);
+}
+
+function execNativePackager(session, callback) {
+    var script = path.join(process.env.CORDOVA_BBTOOLS, "blackberry-nativepackager"),
+        cwd = session.sourceDir,
+        nativePkgr;
+
+    if (pkgrUtils.isWindows()) {
+        script += ".bat";
+    }
+
+    nativePkgr = childProcess.spawn(script, ["@../options"], {
+        "cwd": cwd,
+        "env": process.env
+    });
+
+    nativePkgr.stdout.on("data", pkgrUtils.handleProcessOutput);
+
+    nativePkgr.stderr.on("data", pkgrUtils.handleProcessOutput);
+
+    nativePkgr.on("exit", function (code) {
+        if (callback && typeof callback === "function") {
+            callback(code);
+        }
+    });
+}
+
+module.exports = {
+    exec: function (session, target, config, callback) {
+        generateOptionsFile(session, target, config);
+        generateTabletXMLFile(session, config);
+        execNativePackager(session, callback);
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/packager-utils.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/packager-utils.js b/bin/templates/project/cordova/lib/packager-utils.js
new file mode 100644
index 0000000..95fe955
--- /dev/null
+++ b/bin/templates/project/cordova/lib/packager-utils.js
@@ -0,0 +1,198 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed 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.
+ */
+
+/* globals Buffer */
+
+var fs = require('fs'),
+    path = require('path'),
+    wrench = require('wrench'),
+    localize = require("./localize"),
+    logger = require("./logger"),
+    os = require('os'),
+    _self;
+
+function swapBytes(buffer) {
+    var l = buffer.length,
+        i,
+        a;
+
+    if (l % 2 === 0x01) {
+        throw localize.translate("EXCEPTION_BUFFER_ERROR");
+    }
+
+    for (i = 0; i < l; i += 2) {
+        a = buffer[i];
+        buffer[i] = buffer[i + 1];
+        buffer[i + 1] = a;
+    }
+
+    return buffer;
+}
+
+_self = {
+    writeFile: function (fileLocation, fileName, fileData) {
+        //If directory does not exist, create it.
+        if (!fs.existsSync(fileLocation)) {
+            wrench.mkdirSyncRecursive(fileLocation, "0755");
+        }
+
+        fs.writeFileSync(path.join(fileLocation, fileName), fileData);
+    },
+
+    copyFile: function (srcFile, destDir, baseDir) {
+        var filename = path.basename(srcFile),
+            fileBuffer = fs.readFileSync(srcFile),
+            fileLocation;
+
+        //if a base directory was provided, determine
+        //folder structure from the relative path of the base folder
+        if (baseDir && srcFile.indexOf(baseDir) === 0) {
+            fileLocation = srcFile.replace(baseDir, destDir);
+            wrench.mkdirSyncRecursive(path.dirname(fileLocation), "0755");
+            fs.writeFileSync(fileLocation, fileBuffer);
+        } else {
+            fs.writeFileSync(path.join(destDir, filename), fileBuffer);
+        }
+    },
+
+    listFiles: function (directory, filter) {
+        var files = wrench.readdirSyncRecursive(directory),
+            filteredFiles = [];
+
+        files.forEach(function (file) {
+            //On mac wrench.readdirSyncRecursive does not return absolute paths, so resolve one.
+            file = path.resolve(directory, file);
+
+            if (filter(file)) {
+                filteredFiles.push(file);
+            }
+        });
+
+        return filteredFiles;
+    },
+
+    isWindows: function () {
+        return os.type().toLowerCase().indexOf("windows") >= 0;
+    },
+
+    isArray: function (obj) {
+        return obj.constructor.toString().indexOf("Array") !== -1;
+    },
+
+    isEmpty : function (obj) {
+        for (var prop in obj) {
+            if (obj.hasOwnProperty(prop))
+                return false;
+        }
+        return true;
+    },
+
+    toBoolean: function (myString, defaultVal) {
+        // if defaultVal is not passed, default value is undefined
+        return myString === "true" ? true : myString === "false" ? false : defaultVal;
+    },
+
+    homedir: function () {
+        if (_self.isWindows()) {
+            return process.env.USERPROFILE;
+        } 
+        return process.env.HOME;
+    },
+
+    parseUri : function (str) {
+        var i, uri = {},
+            key = [ "source", "scheme", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor" ],
+            matcher = /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(str);
+
+        for (i = key.length - 1; i >= 0; i--) {
+            uri[key[i]] = matcher[i] || "";
+        }
+
+        return uri;
+    },
+
+    // uri - output from parseUri
+    isAbsoluteURI : function (uri) {
+        if (uri && uri.source) {
+            return uri.relative !== uri.source;
+        }
+
+        return false;
+    },
+
+    isLocalURI : function (uri) {
+        return uri && uri.scheme && uri.scheme.toLowerCase() === "local";
+    },
+
+    // Convert node.js Buffer data (encoded) to String
+    bufferToString : function (data) {
+        var s = "";
+        if (Buffer.isBuffer(data)) {
+            if (data.length >= 2 && data[0] === 0xFF && data[1] === 0xFE) {
+                s = data.toString("ucs2", 2);
+            } else if (data.length >= 2 && data[0] === 0xFE && data[1] === 0xFF) {
+                swapBytes(data);
+                s = data.toString("ucs2", 2);
+            } else if (data.length >= 3 && data[0] === 0xEF && data[1] === 0xBB && data[2] === 0xBF) {
+                s = data.toString("utf8", 3);
+            } else {
+                s = data.toString("utf8");
+            }
+        }
+
+        return s;
+    },
+
+    // Wrap object property in an Array if the property is defined and it is not an Array
+    wrapPropertyInArray : function (obj, property) {
+        if (obj && obj[property] && !(obj[property] instanceof Array)) {
+            obj[property] = [ obj[property] ];
+        }
+    },
+
+    loadModule: function (path) {
+        return require(path);
+    },
+
+    handleProcessOutput: function (data) {
+        var msg = data.toString().replace(/[\n\r]/g, '');
+
+        if (msg) {
+            if (msg.indexOf("[ERROR] ") >= 0) {
+                logger.error(msg.substring(8).trim());
+            } else if (msg.indexOf("[WARN] ") >= 0) {
+                logger.warn(msg.substring(7).trim());
+            } else if (msg.indexOf("[INFO] ") >= 0) {
+                logger.info(msg.substring(8).trim());
+            } else if (msg.indexOf("[BUILD] ") >= 0) {
+                logger.info(msg.substring(8).trim());
+            } else {
+                logger.info(msg);
+            }
+        }
+    },
+
+    escapeStringForShell: function (str) {
+        if (require('os').type().toLowerCase().indexOf("windows") >= 0) {
+            return "\"" + str + "\"";
+        } else {
+            return str.replace(/(["\s'$`\\])/g, '\\$1');
+        }
+    }
+
+};
+
+module.exports = _self;

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/packager-validator.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/packager-validator.js b/bin/templates/project/cordova/lib/packager-validator.js
new file mode 100644
index 0000000..985e137
--- /dev/null
+++ b/bin/templates/project/cordova/lib/packager-validator.js
@@ -0,0 +1,108 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed 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 check = require('validator').check,
+    sanitize = require('validator').sanitize,
+    localize = require("./localize"),
+    logger = require("./logger"),
+    path = require("path"),
+    fs = require("fs"),
+    packagerUtils = require("./packager-utils"),
+    signingUtils = require("./signing-utils"),
+    CORDOVA_JS_REGEX = /(cordova-.+js)|cordova\.js/,
+    _self;
+
+//NOTE this class is unfinished and is a work in progress
+
+_self = {
+    //TODO create one global validate method that will validate
+    //both the session and configObj?
+    validateSession: function (session, widgetConfig) {
+        //The string checks below is to get around a really weird issue in commander
+        //where sometimes unspecified arguments come in as a function...
+        var keysFound = session.keystore,
+            keysDefault = session.keystore === signingUtils.getDefaultPath("author.p12"),
+            cskFound = session.keystoreCsk,//barsigner.csk
+            dbFound = session.keystoreDb,//barsigner.db
+            bbidFound = session.keystoreBBID,
+            keysPassword = session.storepass && typeof session.storepass === "string",
+            commandLinebuildId = session.buildId && typeof session.buildId === "string",//--buildId
+            buildId = widgetConfig.buildId && typeof widgetConfig.buildId === "string",//Finalized Build ID
+
+            //Constants
+            AUTHOR_P12 = "author.p12",
+            BARSIGNER_CSK = "barsigner.csk",
+            BARSIGNER_DB = "barsigner.db",
+            BARSIGNER_BBID = "bbidtoken.csk",
+
+            //Logging function
+            signingFileWarn = function (file) {
+                logger.warn(localize.translate("WARNING_MISSING_SIGNING_KEY_FILE", file));
+            },
+            signingFileError = function (file) {
+                throw localize.translate("EXCEPTION_MISSING_SIGNING_KEY_FILE", file);
+            };
+
+        //If -g <password> or --buildId is set, but signing key files are missing, throw an error
+        if (keysPassword || commandLinebuildId) {
+            if (!keysFound) {
+                signingFileError(AUTHOR_P12);
+            } else if (keysDefault && !cskFound && !bbidFound) {
+                //Only warn about BBID since the old tokens are deprecated
+                signingFileError(BARSIGNER_BBID);
+            } else if (keysDefault && cskFound && !dbFound) {
+                signingFileError(BARSIGNER_DB);
+            }
+
+        //If a buildId exists in config, but no keys were found, throw a warning
+        } else if (buildId) {
+            if (!keysFound) {
+                signingFileWarn(AUTHOR_P12);
+            } else if (keysDefault && !cskFound && !bbidFound) {
+                //Only warn about BBID since the old tokens are deprecated
+                signingFileWarn(BARSIGNER_BBID);
+            } else if (keysDefault && cskFound && !dbFound) {
+                signingFileWarn(BARSIGNER_DB);
+            }
+        }
+
+        if (commandLinebuildId && !keysPassword) {
+            //if --buildId was provided with NO password, throw error
+            throw localize.translate("EXCEPTION_MISSING_SIGNING_PASSWORD");
+        }
+
+        //if --appdesc was provided, but the file is not existing, throw an error
+        if (session.appdesc && !fs.existsSync(session.appdesc)) {
+            throw localize.translate("EXCEPTION_APPDESC_NOT_FOUND", session.appdesc);
+        }
+    },
+
+    //Validation for configObj, iterates through whitelisted features in configObj to remove any non-existing APIs
+    validateConfig: function (session, configObj) {
+        var cordovaJsFiles;
+        //if packageCordovaJs was set, test for existing cordova.js files
+        if (configObj.packageCordovaJs) {
+            cordovaJsFiles = packagerUtils.listFiles(session.sourceDir, function (file) {
+                return CORDOVA_JS_REGEX.test(file);
+            });
+            if (cordovaJsFiles.length > 0) {
+                logger.warn(localize.translate("WARN_CORDOVA_JS_PACKAGED"));
+            }
+        }
+
+    }
+};
+
+module.exports = _self;

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/packager.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/packager.js b/bin/templates/project/cordova/lib/packager.js
new file mode 100644
index 0000000..e8ac24c
--- /dev/null
+++ b/bin/templates/project/cordova/lib/packager.js
@@ -0,0 +1,77 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed 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 path = require("path"),
+    wrench = require("wrench"),
+    cmdline = require("./cmdline"),
+    logger = require("./logger"),
+    fileManager = require("./file-manager"),
+    localize = require("./localize"),
+    configParser = require("./config-parser"),
+    packagerUtils = require("./packager-utils"),
+    packagerValidator = require("./packager-validator"),
+    barBuilder = require("./bar-builder"),
+    session;
+
+module.exports = {
+    start: function (callback) {
+        try {
+            cmdline.parse(process.argv);
+            session = require("./session").initialize(cmdline.commander);
+
+            //prepare files for webworks archiving
+            logger.log(localize.translate("PROGRESS_FILE_POPULATING_SOURCE"));
+            fileManager.prepareOutputFiles(session);
+
+            //parse config.xml
+            logger.log(localize.translate("PROGRESS_SESSION_CONFIGXML"));
+            configParser.parse(path.join(session.sourceDir, "config.xml"), session, function (configObj) {
+                //validate session Object
+                packagerValidator.validateSession(session, configObj);
+                //validage configuration object
+                packagerValidator.validateConfig(session, configObj);
+
+                //generate user.js
+                logger.log(localize.translate("PROGRESS_GEN_OUTPUT"));
+                //Adding debuEnabled property to user.js. Framework will enable/disable WebInspector based on that variable.
+                configObj.debugEnabled = session.debug;
+
+                barBuilder.build(session, configObj, function (code) {
+                    fileManager.cleanSource(session);
+
+                    if (code === 0) {
+                        logger.log(localize.translate("PROGRESS_COMPLETE"));
+                    }
+
+                    if (callback && typeof callback === "function") {
+                        callback(code);
+                    }
+                });
+            });
+        } catch (e) {
+            try {
+                fileManager.cleanSource(session);
+            } catch (ex) {
+            } finally {
+                logger.error(e);
+                if (callback && typeof callback === "function") {
+                    callback(e);
+                }
+            }
+
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/params.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/params.js b/bin/templates/project/cordova/lib/params.js
new file mode 100644
index 0000000..955302f
--- /dev/null
+++ b/bin/templates/project/cordova/lib/params.js
@@ -0,0 +1,56 @@
+/*
+ *  Copyright 2014 BlackBerry Limited.
+ *
+ * Licensed 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 path = require("path"),
+    fs = require("fs"),
+    utils = require("./utils"),
+    localize = require("./localize");
+
+function getParams(toolName, cmdline) {
+    var properties = utils.getProperties(),
+        params = properties[toolName],
+        paramsPath,
+        cmdParams;
+
+    if (cmdline && cmdline.params) {
+        if (!cmdParams) {
+            paramsPath = path.resolve(cmdline.params);
+
+            if (fs.existsSync(paramsPath)) {
+                try {
+                    cmdParams = require(paramsPath);
+                } catch (e) {
+                    throw localize.translate("EXCEPTION_PARAMS_FILE_ERROR", paramsPath);
+                }
+            } else {
+                throw localize.translate("EXCEPTION_PARAMS_FILE_NOT_FOUND", paramsPath);
+            }
+        }
+    }
+
+    if (cmdParams && cmdParams[toolName]) {
+        if (params) {
+            params = utils.mixin(cmdParams[toolName], params);
+        } else {
+            params = cmdParams[toolName];
+        }
+    }
+
+    return params;
+}
+
+
+module.exports = getParams;

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/run-utils.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/run-utils.js b/bin/templates/project/cordova/lib/run-utils.js
new file mode 100644
index 0000000..fb7fefd
--- /dev/null
+++ b/bin/templates/project/cordova/lib/run-utils.js
@@ -0,0 +1,298 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed 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 fs = require("fs"),
+    path = require("path"),
+    utils = require("./utils"),
+    targetUtils = require("./target-utils.js"),
+    localize = require("./localize"),
+    pkgrUtils = require("./packager-utils"),
+    debugTokenHelper = require("./debugtoken-helper"),
+    xml2js = require('xml2js'),
+    logger = require("./logger"),
+    async = require("async"),
+    session = require("./session"),
+    properties = utils.getProperties(),
+    workingdir = path.normalize(__dirname + "/.."),
+    _self;
+
+//Options looking for are: (Device | Emulator, query, devicepass). Calls back with:  (error || options object, target object)
+function getTargetName(options, done) {
+    var ipFinder = options.emulator ? targetUtils.findConnectedSimulator : targetUtils.findConnectedDevice,
+        targetType = options.emulator ? "emulator" : "device";
+
+    if (options.target) {
+        done(null, options, options.target);
+    } else {
+        
+        if (options.device && options.emulator) {
+            localize.translate("WARN_RUN_DEVICE_OVERRIDES_EMULATOR");
+        }
+
+        async.series(
+        {
+            ip: function (done) {
+                ipFinder(function (ip) {
+                    done(ip ? null : "No connected BlackBerry 10 " + targetType + " found", ip);
+                });
+            },
+            devicePass: function (done) {
+                if (!options.devicepass && options.devicepass !== "") {
+                    if (options.query) {
+                        utils.prompt({description: getPasswordPrompt(targetType), hidden: true}, done);
+                    } else {
+                        done("");
+                    }
+                } else {
+                    done(null, options.devicepass);
+                }
+            }
+        },
+        function (err, results) {
+            if (err) {
+                done(err);
+            } else {
+                options.devicepass = results.devicePass;
+                _self.checkDeviceInfo(options, results.ip, targetType, results.devicePass, done);
+            }
+        });
+    }
+}
+
+//Options looking for are: (query, devicepass). Calls back with:  (error || target object)
+function validateTarget(options, targetName, allDone) {
+    var deployTarget,
+        err,
+        runTasks = [];
+
+    if (!targetName) {
+        err = "No target exists, to add that target please run: target add <name> <ip> [-t | --type <device | simulator>] [-p <password>] [--pin <devicepin>]";
+    } else if (!properties.targets[targetName]) {
+        err = "The target \"" + targetName + "\" does not exist, to add that target please run: target add " + targetName + " <ip> [-t | --type <device | simulator>] [-p <password>] [--pin <devicepin>]";
+    } else {
+        deployTarget = utils.clone(properties.targets[targetName]);
+        deployTarget.name = targetName;
+
+        if (!deployTarget.ip) {
+            if (options.query) {
+                runTasks.push(function (done) {
+                    utils.prompt({description: "Please enter the IP address for target " + deployTarget.name + ": "}, function (e, ip) {
+                        deployTarget.ip = ip;
+                        done(e);
+                    });
+                });
+            } else {
+                err = "IP is not defined in target \"" + deployTarget.name + "\"";
+            }
+        }
+
+        if (err === undefined && !deployTarget.password && deployTarget.password !== "") {
+            if (options.devicepass || options.devicepass === "") {
+                deployTarget.password = options.devicepass;
+            } else {
+                if (options.query) {
+                    runTasks.push(function (done) {
+                        utils.prompt({description: getPasswordPrompt(deployTarget.type), hidden: true}, function (e, devicePass) {
+                            deployTarget.password = devicePass;
+                            done(e);
+                        });
+                    });
+                } else if (!options.emulator) {
+                    err = "No device password provided. You can omit --no-query, use --devicepass, or enter a value for 'password' to the target " + deployTarget.name + " defined at " + utils.getPropertiesFilePath();
+                }
+            }
+        }
+
+        if (!deployTarget.pin) {
+            runTasks.push(function (done) {
+                targetUtils.getDeviceInfo(deployTarget.ip, deployTarget.password, function (err, result) {
+                    deployTarget.pin = result.pin;
+                    done(err);
+                });
+            });
+        }
+    }
+
+    async.series(runTasks, function (e) {
+        var finalErr = err || e;
+        if (!finalErr && deployTarget) {
+            logger.info("Target " + deployTarget.name + " selected");
+        }
+        allDone(err || e, options, deployTarget);
+    });
+}
+//Options looking for are: (keystorepass, query). Calls back with:  (error || target object)
+function handleDebugToken(options, deployTarget, allDone) {
+    options.keystorepass = session.getKeyStorePass(options);
+
+    // deploy debug token for device debug builds only
+    if (deployTarget.pin && !options.emulator && options.build && !options.release) {
+        async.waterfall(
+            [
+                debugTokenHelper.checkDebugToken.bind(this, deployTarget.pin),
+                function (done) {
+                    //If no keystorepass is provided debugTokenHelper will throw an error.
+                    if (!options.keystorepass && options.query) {
+                        utils.prompt({description: "Please enter your keystore password: ", hidden: true}, function (err, result) {
+                            options.keystorepass = result;
+                            done(null, result);
+                        });
+                    } else {
+                        done(null, options.keystorepass);
+                    }
+                },
+                debugTokenHelper.createToken.bind(this, properties, "all")
+            ],
+            function (err, results) {
+                // If the error is true, then the debug token is valid and creation was skipped.
+                if (err === true) {
+                    logger.info(localize.translate("PROGRESS_DEBUG_TOKEN_IS_VALID"));
+                    //Clear the error so it is still deployed
+                    err = null;
+                }
+
+                if (!err) {
+                    debugTokenHelper.deployToken(deployTarget.name, deployTarget.ip, deployTarget.password, function (code) {
+                        allDone(code, deployTarget);
+                    });
+                } else {
+                    allDone(null, deployTarget);
+                }
+            }
+        );
+    } else {
+        allDone(null, deployTarget);
+    }
+}
+
+function generateDeployOptions(options, deployTarget) {
+    var deployOptions = [],
+        barPath = pkgrUtils.escapeStringForShell(
+            path.normalize(__dirname + "/../../build/" +
+                (deployTarget.type === "device" ? "device" : "simulator") +
+                "/" + utils.genBarName() + ".bar"));
+
+    deployOptions.push("-device");
+    deployOptions.push(deployTarget.ip);
+
+    if (deployTarget.password) {
+        deployOptions.push("-password");
+        deployOptions.push(deployTarget.password);
+    }
+
+    deployOptions.push("-package");
+    deployOptions.push(barPath);
+    deployOptions.push("-uninstallApp");
+    deployOptions.push("-installApp");
+
+    if (options.launch) {
+        deployOptions.push("-launchApp");
+    }
+
+    return deployOptions;
+}
+
+function execNativeDeploy(deployOptions, callback) {
+    var script = path.normalize(path.join(process.env.CORDOVA_BBTOOLS, "blackberry-deploy"));
+
+    utils.exec(script, deployOptions, {
+        "cwd": workingdir,
+        "env": process.env
+    }, callback);
+}
+
+function getPasswordPrompt(targetType) {
+    var prompt = "Please enter your " + targetType + " password";
+    if (targetType === "emulator") {
+        prompt += " (For no password press ENTER)";
+    }
+    prompt += ": ";
+    return prompt;
+}
+
+_self = {
+    //options looking for are: (query, devicepass, password, target, (device || emulator)) Function returns (error || deployTarget)
+    getValidatedTarget : function (options, callback) {
+        async.waterfall(
+            [
+                getTargetName.bind(this, options),
+                validateTarget,
+                handleDebugToken
+            ], callback
+        );
+    },
+
+    //Function returns (error || null)
+    install : function (options, deployTarget, allDone) {
+        var script = path.join(process.env.CORDOVA_BBTOOLS, "blackberry-deploy"),
+            args = [
+                "-device",
+                deployTarget.ip
+            ],
+            projectRootDir = path.normalize(path.join(__dirname, "..")),
+            installedAppsOutput,
+            runTasks = [];
+
+        if (deployTarget.password) {
+            args.push("-password", deployTarget.password);
+        }
+        runTasks = [
+            function uninstallInstallLaunchApp(result, done) {
+                var deployOptions = generateDeployOptions(options, deployTarget);
+                execNativeDeploy(deployOptions, done);
+            }
+        ];
+
+        async.waterfall(runTasks,
+            function (err, results) {
+                allDone(null, deployTarget);
+            }
+        );
+    },
+
+    //Function returns (error || deployTarget)
+    checkBuild : function (deployTarget, allDone) {
+        var barPath = path.normalize(__dirname + "/../../build/" +
+                (deployTarget.type === "device" ? "device" : "simulator") +
+                "/" + utils.genBarName() + ".bar");
+        if (fs.existsSync(barPath)) {
+            allDone(null, deployTarget);
+        } else {
+            allDone("No build file exists, please run: build [--debug | --release] [--keystorepass <password>] [--buildId <number>] [--params <json>] [--loglevel <level>] [--web-inspector] [--no-signing]");
+        }
+    },
+
+    //No options needed within function Function returns (error || options, targetName)
+    checkDeviceInfo : function (options, ip, deviceType, devicePass, done) {
+        var props = utils.getProperties(),
+            targetName;
+
+        targetUtils.getDeviceInfo(ip, devicePass, function (err, device) {
+            if (!err) {
+                targetName = device.name.replace(/ /g, "-") + "-" + device.pin;
+                props.targets[targetName] = {
+                    ip: ip,
+                    pin: device.pin,
+                    type: deviceType
+                };
+                utils.writeToPropertiesFile(props);
+            }
+            done(err, options, targetName);
+        });
+    }
+};
+
+module.exports = _self;

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/run.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/run.js b/bin/templates/project/cordova/lib/run.js
new file mode 100755
index 0000000..15ff7eb
--- /dev/null
+++ b/bin/templates/project/cordova/lib/run.js
@@ -0,0 +1,78 @@
+#!/usr/bin/env node
+
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed 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 path = require("path"),
+    os = require("os"),
+    utils = require("./utils"),
+    options = require('commander'),
+    runUtils = require("./run-utils"),
+    async = require("async");
+
+function install(deployTarget, done) {
+    var buildCmd = utils.isWindows() ? "build" : "./build",
+        buildArgs = options.keystorepass ? ["-k", options.keystorepass] : [],
+        projectRootDir = path.normalize(path.join(__dirname, "..")),
+        installTasks = [];
+
+    if (options.build) {
+        if (options.release) {
+            buildArgs.push("--release");
+        }
+        installTasks.push(utils.exec.bind(this, buildCmd, buildArgs, {"cwd": projectRootDir}));
+    }
+
+    installTasks.push(runUtils.install.bind(this, options, deployTarget));
+
+    async.series(installTasks, done);
+}
+
+options
+    .usage('[--device] [--emulator] [--target=<id>] [--release] [--no-query] [-k | --keystorepass] [--devicepass] [--no-launch] [--no-uninstall] [--no-build]')
+    .option('-k, --keystorepass <password>', 'the password of signing key; needed for creating debug token')
+    .option('--device', 'run on connected device')
+    .option('--emulator', 'run on BB10 simulator')
+    .option('--devicepass <password>', 'device password')
+    .option('--target <id>', 'specifies the target to run the application')
+    .option('--release', 'build in release mode')
+    .option('--no-query', 'fail if no password is provided and one is needed')
+    .option('--no-launch', 'do not launch the application on device')
+    .option('--no-build', 'deploy the pre-built bar file and skip building')
+    .on('--help', function () {
+        console.log('  Examples:');
+        console.log('');
+        console.log("  Deploying to a predefined target");
+        console.log('    $ run --target=Z10');
+        console.log("  Deploying to a connected device");
+        console.log('    $ run --device --devicepass devicePassword --keystorepass keystorePassword');
+        console.log('');
+    });
+
+process.argv.forEach(function (argument, index, args) {
+    if (argument.match(/^--target=/)) {
+        args.splice(index, 1, "--target", argument.substr("--target=".length));
+    }
+});
+
+options.parse(process.argv);
+
+utils.waterfall(
+    [
+        runUtils.getValidatedTarget.bind(this, options),
+        install
+    ]
+);

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/session.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/session.js b/bin/templates/project/cordova/lib/session.js
new file mode 100644
index 0000000..3dd8763
--- /dev/null
+++ b/bin/templates/project/cordova/lib/session.js
@@ -0,0 +1,125 @@
+/*
+ *  Copyright 2014 BlackBerry Limited.
+ *
+ * Licensed 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 path = require("path"),
+    fs = require("fs"),
+    wrench = require("wrench"),
+    utils = require("./utils"),
+    logger = require("./logger"),
+    signingUtils = require("./signing-utils"),
+    barConf = require("./bar-conf"),
+    localize = require("./localize"),
+    getParams = require("./params");
+
+
+module.exports = {
+    getKeyStorePass: function (cmdline) {
+        var properties = utils.getProperties(),
+            params = getParams("blackberry-signer", cmdline) || {},
+            keystorepass;
+
+        //Check commandline first, then properties, then params
+        //Packager expects value provided as password
+        //Cordova scripts expects value provided as keystorepass
+        //String checks are to get around issue where commander sometimes passed in a function
+        if (cmdline.password && typeof cmdline.password === "string") {
+            keystorepass = cmdline.password;
+        } else if (cmdline.keystorepass && typeof cmdline.keystorepass === "string") {
+            keystorepass = cmdline.keystorepass;
+        } else if (properties.keystorepass) {
+            keystorepass = properties.keystorepass;
+        } else if (params["-storepass"]) {
+            keystorepass = params["-storepass"];
+        }
+
+        return keystorepass;
+    },
+    initialize: function (cmdline) {
+        var sourceDir,
+            signingPassword = module.exports.getKeyStorePass(cmdline),
+            outputDir = cmdline.output,
+            archivePath = path.resolve(cmdline.args[0] ? cmdline.args[0] : "../../www"),
+            archiveName = utils.genBarName(),
+            appdesc,
+            buildId = cmdline.buildId,
+            signerParams = getParams("blackberry-signer", cmdline) || {},
+            keystore = signerParams["-keystore"],
+            bbidtoken = signerParams["-bbidtoken"];
+
+        //If -o option was not provided, default output location is the same as .zip
+        outputDir = outputDir || path.dirname(archivePath);
+
+        if (cmdline.appdesc && "string" === typeof cmdline.appdesc) {
+            appdesc = path.resolve(cmdline.appdesc);
+        }
+
+        //If -s [dir] is provided
+        if (cmdline.source && "string" === typeof cmdline.source) {
+            sourceDir = cmdline.source + "/src";
+        } else {
+            sourceDir = outputDir + "/src";
+        }
+
+        if (!fs.existsSync(sourceDir)) {
+            wrench.mkdirSyncRecursive(sourceDir, "0755");
+        }
+
+        logger.level(cmdline.loglevel || 'verbose');
+
+        //If signer params exist, check whether the files are there
+        //This is to be consistent with the default files
+        if (keystore && !fs.existsSync(keystore)) {
+            keystore = false;
+        }
+        if (bbidtoken && !fs.existsSync(bbidtoken)) {
+            bbidtoken = false;
+        }
+
+        return {
+            "conf": require("./conf"),
+            "keepSource": !!cmdline.source,
+            "sourceDir": path.resolve(sourceDir),
+            "sourcePaths": {
+                "ROOT": path.resolve(sourceDir),
+                "CHROME": path.normalize(path.resolve(sourceDir) + barConf.CHROME),
+                "LIB": path.normalize(path.resolve(sourceDir) + barConf.LIB),
+                "EXT": path.normalize(path.resolve(sourceDir) + barConf.EXT),
+                "UI": path.normalize(path.resolve(sourceDir) + barConf.UI),
+                "PLUGINS": path.normalize(path.resolve(sourceDir) + barConf.PLUGINS),
+                "JNEXT_PLUGINS": path.normalize(path.resolve(sourceDir) + barConf.JNEXT_PLUGINS)
+            },
+            "outputDir": path.resolve(outputDir),
+            "archivePath": archivePath,
+            "archiveName": archiveName,
+            "barPath": outputDir + "/%s/" + archiveName + ".bar",
+            "debug": !!cmdline.debug,
+            "keystore": keystore || signingUtils.getKeyStorePath(),
+            "keystoreCsk": signingUtils.getCskPath(),
+            "keystoreDb": signingUtils.getDbPath(),
+            "keystoreBBID": bbidtoken || signingUtils.getKeyStorePathBBID(),
+            "storepass": signingPassword,
+            "buildId": buildId,
+            "appdesc" : appdesc,
+            getParams: function (toolName) {
+                return getParams(toolName, cmdline);
+            },
+            isSigningRequired: function (config) {
+                return (keystore || signingUtils.getKeyStorePath()) && signingPassword;
+            },
+            "targets": ["simulator", "device"]
+        };
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/signing-helper.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/signing-helper.js b/bin/templates/project/cordova/lib/signing-helper.js
new file mode 100644
index 0000000..3ede0b6
--- /dev/null
+++ b/bin/templates/project/cordova/lib/signing-helper.js
@@ -0,0 +1,89 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed 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 path = require('path'),
+    fs = require("fs"),
+    os = require('os'),
+    childProcess = require("child_process"),
+    util = require("util"),
+    utils = require("./utils"),
+    conf = require("./conf"),
+    pkgrUtils = require("./packager-utils"),
+    signingUtils = require("./signing-utils"),
+    logger = require("./logger"),
+    _self;
+
+function execSigner(session, target, callback) {
+    var script = path.join(process.env.CORDOVA_BBTOOLS, "blackberry-signer"),
+        signer,
+        params = session.getParams("blackberry-signer"),
+        args = [];
+
+    if (params) {
+        Object.getOwnPropertyNames(params).forEach(function (p) {
+            args.push(p);
+
+            if (params[p]) {
+                args.push(params[p]);
+            }
+        });
+    }
+
+    //Only specify default args if they aren't specified by the user
+    if (args.indexOf("-keystore") === -1) {
+        args.push("-keystore");
+        args.push(session.keystore);
+    }
+    if (args.indexOf("-storepass") === -1) {
+        args.push("-storepass");
+        args.push(session.storepass);
+    }
+
+    //Validate arguments
+
+
+    args.push(path.resolve(util.format(session.barPath, target)));
+
+    utils.exec(script, args, {
+        "env": process.env
+    }, callback);
+}
+
+_self = {
+    execSigner: execSigner,
+
+    warn: function () {
+        if (!signingUtils.getKeyStorePath()) {
+            logger.warn(
+                "Cannot sign applications. Author.p12 file cannot be found at default location: " +
+                signingUtils.getDefaultPath("author.p12")
+            );
+        }
+
+        if (!signingUtils.getKeyStorePathBBID()) {
+
+            if (signingUtils.getCskPath() && signingUtils.getDbPath()) {
+                logger.warn("Using legacy signing keys");
+            } else {
+                logger.warn(
+                    "Cannot sign applications. bbidtoken.csk file cannot be found at default location: " +
+                    signingUtils.getDefaultPath("bbidtoken.csk")
+                );
+            }
+        }
+    }
+};
+
+module.exports = _self;

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/signing-utils.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/signing-utils.js b/bin/templates/project/cordova/lib/signing-utils.js
new file mode 100644
index 0000000..2f3b398
--- /dev/null
+++ b/bin/templates/project/cordova/lib/signing-utils.js
@@ -0,0 +1,79 @@
+/*
+ * Licensed 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 fs = require('fs'),
+    path = require('path'),
+    os = require('os'),
+    childProcess = require('child_process'),
+    AUTHOR_P12 = "author.p12",
+    BBIDTOKEN = "bbidtoken.csk",
+    CSK = "barsigner.csk",
+    DB = "barsigner.db",
+    _self;
+
+function getDefaultPath(file) {
+    // The default location where signing key files are stored will vary based on the OS:
+    // Windows XP: %USERPROFILE%\Local Settings\Application Data\Research In Motion
+    // Windows Vista and Windows 7: %USERPROFILE%\AppData\Local\Research In Motion
+    // Mac OS: ~/Library/Research In Motion
+    // UNIX or Linux: ~/.rim
+    var p = "";
+    if (os.type().toLowerCase().indexOf("windows") >= 0) {
+        p = process.env.LOCALAPPDATA === undefined ?
+            /* ...-XP */
+            process.env.USERPROFILE + "\\Local Settings\\Application Data" :
+            /* Vista+ */
+            process.env.LOCALAPPDATA;
+        p += "\\Research In Motion\\";
+    } else if (os.type().toLowerCase().indexOf("darwin") >= 0) {
+        // Try Mac OS location
+        p = process.env.HOME + "/Library/Research In Motion/";
+    } else if (os.type().toLowerCase().indexOf("linux") >= 0) {
+        // Try Linux location
+        p = process.env.HOME + "/.rim/";
+    }
+
+    return p + file;
+
+}
+
+function getDefaultPathIfExists(file) {
+    var p = getDefaultPath(file);
+    if (fs.existsSync(p)) {
+        return p;
+    }
+}
+
+_self = {
+    getDefaultPath: getDefaultPath,
+
+    getKeyStorePath : function () {
+        // Todo: decide where to put sigtool.p12 which is generated and used in WebWorks SDK for Tablet OS
+        return getDefaultPathIfExists(AUTHOR_P12);
+    },
+
+    getKeyStorePathBBID: function () {
+        return getDefaultPathIfExists(BBIDTOKEN);
+    },
+
+    getCskPath : function () {
+        return getDefaultPathIfExists(CSK);
+    },
+
+    getDbPath : function () {
+        return getDefaultPathIfExists(DB);
+    }
+};
+
+module.exports = _self;

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/start-emulator
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/start-emulator b/bin/templates/project/cordova/lib/start-emulator
new file mode 100755
index 0000000..1ad590b
--- /dev/null
+++ b/bin/templates/project/cordova/lib/start-emulator
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+<<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
+# support for this script on BB10 is dependent on vmware tools being on the path, or in the default install directory
+# Valid values for "--target": path to 'vmwarevm' file
+
+VMWARE_DEFAULT_PATH=/Applications/VMware\ Fusion.app/Contents/Library
+VMWARE_TOOL=vmrun
+OS_NAME=`uname`
+ERROR_VALUE=2
+NOTIMPLEMENTED_VALUE=1
+
+if [ "$1" = "" -o ! -e "$1" ]
+then
+    echo "BlackBerry10: must provide path to valid vmwarevm image"
+    exit $ERROR_VALUE
+fi
+
+if [ "$OS_NAME" = "Darwin" ]; then
+    if [ "`which vmrun`" = "" ]; then
+        echo "BlackBerry10: VMware Fusion 'vmrun' tool not found on path, trying default install path"
+        runpath=$VMWARE_DEFAULT_PATH/$VMWARE_TOOL
+    else
+        runpath=`which vmrun`
+    fi
+    
+    if [ -x "$runpath" ]; then
+        echo $runpath start $1
+        `$"$runpath" start "$1" > /dev/null`
+
+        exit 0 
+    else
+        echo "BlackBerry10: could not find VMware Fusion 'vmrun' tool"
+        exit $ERROR_VALUE
+    fi
+else
+    echo "BlackBerry10: currently only supports installing to emulator on OS X"
+    exit $NOTIMPLEMENTED_VALUE 
+fi

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/start-emulator.bat
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/start-emulator.bat b/bin/templates/project/cordova/lib/start-emulator.bat
new file mode 100644
index 0000000..714d6b4
--- /dev/null
+++ b/bin/templates/project/cordova/lib/start-emulator.bat
@@ -0,0 +1,22 @@
+:: 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.
+
+@ECHO OFF
+set NOTIMPLEMENTED_VALUE=1
+
+ECHO echo 'BlackBerry10: Not able to start emulator images on windows command-line at this time.'
+EXIT /B %NOTIMPLEMENTED_VALUE%

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/a6733a83/bin/templates/project/cordova/lib/target-utils.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/cordova/lib/target-utils.js b/bin/templates/project/cordova/lib/target-utils.js
new file mode 100755
index 0000000..bb3b34d
--- /dev/null
+++ b/bin/templates/project/cordova/lib/target-utils.js
@@ -0,0 +1,282 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed 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 _self,
+    os = require("os"),
+    fs = require('fs'),
+    path = require('path'),
+    bb10_utils = require('./utils'),
+    blackberryProperties = bb10_utils.getProperties();
+
+
+//fix older blackberry10.json files 
+//these may include 'simulator' type rather than 'emulator'
+function replaceSimulator(targets) {
+    var replace = false,
+        t;
+    for (t in targets) {
+        if (targets.hasOwnProperty(t) && targets[t].type === "simulator") {
+            targets[t].type = "emulator";
+            replace = true;
+        }
+    }
+    if (replace) {
+        blackberryProperties.targets = targets;
+        bb10_utils.writeToPropertiesFile(blackberryProperties);
+    }
+}
+
+_self = {
+    getTargetList : function (type, pruneDisconnected, callback) {
+        var targList = [],
+            count = 0,
+            targets = blackberryProperties.targets,
+            addItem = function (t) {
+                targets[t].name = t;
+                targList.push(targets[t]);
+            },
+            complete = function () {
+                if (count === Object.keys(targets).length) {
+                    callback(targList);
+                }
+            },
+            checkConnection = function (name) {
+                _self.checkConnection(targets[name].ip, type, function (connected) {
+                    count++;
+                    if (connected) {
+                        addItem(name);
+                    }
+                    complete();
+                });
+            },
+            t;
+
+        if (targets) {
+            replaceSimulator(targets);
+            for (t in targets) {
+                if (targets.hasOwnProperty(t) && targets[t].type === type) {
+                    if (pruneDisconnected) {
+                        checkConnection(t);
+                    }
+                    else {
+                        addItem(t);
+                        count++;
+                    }
+                } else {
+                    count++;
+                }
+            }
+        }
+        complete();
+    },
+
+    getDeviceInfo: function (ip, password, callback) {
+        var cmd = path.join(process.env.CORDOVA_BBTOOLS, 'blackberry-deploy'),
+            args = [
+                '-listDeviceInfo',
+                ip
+            ],
+            options = {
+                _customOptions: { silent: true }
+            };
+
+        if (password) {
+            args.push('-password');
+            args.push(password);
+        }
+
+        bb10_utils.exec(cmd, args, options, function (error, stdout, stderr) {
+            var err = error,
+                result = {},
+                name = /modelname::(.*?)(\r?)\n/.exec(stdout),
+                pin = /devicepin::0x(.*?)(\r?)\n/.exec(stdout);
+            if (name && name.length > 0) {
+                result.name = name[1];
+            }
+            if (pin && pin.length > 0) {
+                result.pin = pin[1];
+            }
+
+            if (!result.name) {
+                if (stdout.indexOf("Error:") !== -1) {
+                    err = stdout.slice(stdout.indexOf("Error:") + 6);
+                } else if (stdout === "" && stderr.indexOf("Error:") === 0) {
+                    err = stderr.slice(7);
+                } else {
+                    err = "Unable to authenticate with BlackBerry 10 device/emulator at " + ip + ".";
+                }
+            }
+
+            callback(err, result);
+        });
+    },
+
+    findConnectedDevice: function (callback) {
+        var defaultIp = '169.254.0.1',
+            count = 0,
+            i;
+        _self.discoverUsb(function (result) {
+            if (!result || result.length === 0) {
+                result = [defaultIp];
+            }
+            for (i = 0; i < result.length; i++) {
+                /* jshint ignore:start */
+                _self.checkConnection(result[i], 'device', function (connection, ip) {
+                    if (connection)  {
+                        callback(ip);
+                        return;
+                    } else if (++count === result.length) {
+                        callback();
+                    }
+                });
+                /* jshint ignore:end */
+            }
+        });
+    },
+
+    discoverUsb: function (callback) {
+        var IPV4_TYPE = "IPv4",
+            IP_SPLIT_REGEXP = /(169\.254\.\d{1,3}\.)(\d{1,3})/,
+            networkInterfaces = os.networkInterfaces(),
+            result,
+            matches = [],
+            ni,
+            i;
+
+        for (ni in networkInterfaces) {
+            if (networkInterfaces.hasOwnProperty(ni)) {
+                for (i = 0; i < networkInterfaces[ni].length; i++) {
+                    if (networkInterfaces[ni][i].family === IPV4_TYPE) {
+                        result = IP_SPLIT_REGEXP.exec(networkInterfaces[ni][i].address);
+                        if (result && result[1] && result[2]) {
+                            matches.push(result[1] + (result[2] - 1));
+                        }
+                    }
+                }
+
+            }
+        }
+        callback(matches);
+    },
+
+    findConnectedSimulator: function (callback) {
+        var pathVmDhcpLeases,
+            pathUserProfile,
+            pathAllUserProfile,
+            vmDhcpLeasesFiles,
+            DHCP_LEASES_REGEX = /VMware\\vmnetdhcp.leases$/,
+            targets = blackberryProperties.targets,
+            ipsToTest = [],
+            dhcpIPs = [],
+            t;
+
+        // Firstly, check targets in the properties file
+        if (targets) {
+            for (t in targets) {
+                if (targets.hasOwnProperty(t) && targets[t].type === "emulator" && targets[t].ip) {
+                    ipsToTest.push(targets[t].ip);
+                }
+            }
+        }
+
+        // Secondly, check VMware dhcp.leases file
+        if (bb10_utils.isWindows()) {
+            pathUserProfile = process.env.USERPROFILE;
+            pathAllUserProfile = pathUserProfile.substr(0, pathUserProfile.lastIndexOf("\\") + 1) + "All Users";
+            vmDhcpLeasesFiles = bb10_utils.readdirSyncRecursive(pathAllUserProfile).filter(function (file) {
+                return DHCP_LEASES_REGEX.test(file);
+            });
+            pathVmDhcpLeases = vmDhcpLeasesFiles[0];
+        } else if (bb10_utils.isOSX()) {
+            pathVmDhcpLeases = "/private/var/db/vmware/vmnet-dhcpd-vmnet8.leases";
+        } else {
+            pathVmDhcpLeases = "/var/db/vmware/vmnet-dhcpd-vmnet8.leases";
+        }
+
+        fs.readFile(pathVmDhcpLeases, 'utf8', function (err, data) {
+            if (!err) {
+                // Find all lines that start with "lease xxx.xxx.xxx.xxx "
+                dhcpIPs = data.match(/lease \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} /g) || [];
+                dhcpIPs = dhcpIPs.map(function (result) {
+                    return result.substr(6, result.indexOf(' ', 7) - 6);
+                });
+            }
+
+            ipsToTest = ipsToTest.concat(dhcpIPs);
+            // Remove duplicated ip
+            ipsToTest = ipsToTest.filter(function (item, index, arr) {
+                return arr.indexOf(item) === index;
+            });
+
+            _self.checkConnectionRecursive(ipsToTest, 0, callback);
+        });
+    },
+
+    checkConnectionRecursive: function (ips, index, callback) {
+        var ip;
+
+        if (!ips || index === ips.length) {
+            callback();
+            return;
+        }
+
+        console.log("Searching for connected BlackBerry 10 Simulator (" + (index + 1) + "/" + ips.length + ")...");
+        ip = ips[index];
+        _self.checkConnection(ip, "emulator", function (connection) {
+            if (connection) {
+                callback(ip);
+            } else {
+                _self.checkConnectionRecursive(ips, index + 1, callback);
+            }
+        });
+    },
+
+    checkConnection: function (ip, type, callback) {
+        var script = path.join(process.env.CORDOVA_BBTOOLS, 'blackberry-deploy'),
+            args = [
+                '-test',
+                ip
+            ],
+            options = {
+                _customOptions: { silent: true }
+            };
+
+        bb10_utils.exec(script, args, options, function (error, stdout, stderr) {
+            // error code 3 corresponds to connected device with password
+            // null or "Error: null" in stderr corresponds to connected simulator or device without password
+            var connected =
+                    error === null ||
+                    (error && error.code === 3) ||
+                    stderr.length === 0 ||
+                    stderr.indexOf('Error: null') >= 0 ||
+                    stderr.indexOf('Error: Authentication failed') >= 0;
+            callback(connected, ip);
+        });
+    },
+
+    listTargets : function (type, pruneDisconnected) {
+        _self.getTargetList(type, pruneDisconnected, function (targets) {
+            for (var t in targets) {
+                if (targets.hasOwnProperty(t)) {
+                    console.log(targets[t].name + ' ip: ' + targets[t].ip);
+                }
+            }
+        });
+    }
+
+};
+
+module.exports = _self;