You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by de...@apache.org on 2012/02/08 21:14:02 UTC

[12/19] CB-226 Rename to Cordova.

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/05319d3c/framework/ext/src/org/apache/cordova/geolocation/GeolocationStatus.java
----------------------------------------------------------------------
diff --git a/framework/ext/src/org/apache/cordova/geolocation/GeolocationStatus.java b/framework/ext/src/org/apache/cordova/geolocation/GeolocationStatus.java
new file mode 100644
index 0000000..4c70a10
--- /dev/null
+++ b/framework/ext/src/org/apache/cordova/geolocation/GeolocationStatus.java
@@ -0,0 +1,36 @@
+/*
+ * 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.geolocation;
+
+import org.apache.cordova.api.PluginResult;
+
+public class GeolocationStatus extends PluginResult.Status {
+
+	protected GeolocationStatus(int status, String message) {
+		super(status, message);
+	}
+
+	public static final GeolocationStatus GPS_NOT_AVAILABLE = new GeolocationStatus(101, "GPS not available");
+	public static final GeolocationStatus GPS_OUT_OF_SERVICE = new GeolocationStatus(102, "GPS out of service");
+	public static final GeolocationStatus GPS_TEMPORARILY_UNAVAILABLE = new GeolocationStatus(103, "GPS temporarily unavailable");
+	public static final GeolocationStatus GPS_TIMEOUT = new GeolocationStatus(104, "GPS location acquisition timed out");
+	public static final GeolocationStatus GPS_INTERUPTED_EXCEPTION = new GeolocationStatus(105, "GPS location acquisition interrupted");
+	public static final GeolocationStatus GPS_INVALID_LOCATION = new GeolocationStatus(106, "GPS returned an invalid location");
+	public static final GeolocationStatus GPS_JSON_EXCEPTION = new GeolocationStatus(107, "An illegal argument was passed to the location listener");
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/05319d3c/framework/ext/src/org/apache/cordova/geolocation/Position.java
----------------------------------------------------------------------
diff --git a/framework/ext/src/org/apache/cordova/geolocation/Position.java b/framework/ext/src/org/apache/cordova/geolocation/Position.java
new file mode 100644
index 0000000..6ce490e
--- /dev/null
+++ b/framework/ext/src/org/apache/cordova/geolocation/Position.java
@@ -0,0 +1,133 @@
+/*
+ * 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.geolocation;
+
+import javax.microedition.location.Location;
+
+import org.apache.cordova.json4j.JSONException;
+import org.apache.cordova.json4j.JSONObject;
+
+/**
+ * Stores geo location variables.
+ */
+public class Position {
+
+	private double _lat = 0;
+    private double _lng = 0;
+	private float altitude = 0;
+	private float accuracy = 0;
+	private float alt_accuracy = 0;
+    private float heading = 0;
+	private float velocity = 0;
+	private long timestamp = 0;
+
+	public Position(double lat, double lng, float altitude, float accuracy, float alt_accuracy,
+			float heading, float speed, long timestamp) {
+		this._lat = lat;
+		this._lng = lng;
+		this.altitude = altitude;
+		this.accuracy = accuracy;
+		this.alt_accuracy = alt_accuracy;
+		this.heading = heading;
+		this.velocity = speed;
+		this.timestamp = timestamp;
+	}
+
+	public static Position fromLocation(Location location) {
+		double latitude = location.getQualifiedCoordinates().getLatitude();
+        double longitude = location.getQualifiedCoordinates().getLongitude();
+        float altitude = location.getQualifiedCoordinates().getAltitude();
+        float accuracy = location.getQualifiedCoordinates().getHorizontalAccuracy();
+        float alt_accuracy = location.getQualifiedCoordinates().getVerticalAccuracy();
+        float heading = location.getCourse();
+        float speed = location.getSpeed();
+        long time = location.getTimestamp();
+
+		return new Position(latitude, longitude, altitude, accuracy, alt_accuracy, heading, speed, time);
+	}
+
+    public double getLatitude() {
+		return _lat;
+	}
+
+	public void setLatitude(double _lat) {
+		this._lat = _lat;
+	}
+
+	public double getLongitude() {
+		return _lng;
+	}
+
+	public void setLongitude(double _lng) {
+		this._lng = _lng;
+	}
+
+	public float getAltitude() {
+		return altitude;
+	}
+
+	public void setAltitude(float altitude) {
+		this.altitude = altitude;
+	}
+
+	public float getAccuracy() {
+		return accuracy;
+	}
+
+	public void setAccuracy(float accuracy) {
+		this.accuracy = accuracy;
+	}
+
+	public float getAltitudeAccuracy() {
+		return alt_accuracy;
+	}
+
+	public void setAltitudeAccuracy(float alt_accuracy) {
+		this.alt_accuracy = alt_accuracy;
+	}
+
+	public float getHeading() {
+		return heading;
+	}
+
+	public void setHeading(float heading) {
+		this.heading = heading;
+	}
+
+	public float getVelocity() {
+		return velocity;
+	}
+
+	public void setVelocity(float velocity) {
+		this.velocity = velocity;
+	}
+
+	public long getTimestamp() {
+		return timestamp;
+	}
+
+	public void setTimestamp(long timestamp) {
+		this.timestamp = timestamp;
+	}
+
+	public JSONObject toJSONObject() throws JSONException {
+		return new JSONObject("{latitude:" + String.valueOf(_lat) + ", longitude:" + String.valueOf(_lng) + ", altitude:" + altitude + ", accuracy:" + accuracy + ", heading:" + heading + ", speed:" + velocity + ", alt_accuracy:" + alt_accuracy + ", timestamp:" + timestamp + "}");
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/05319d3c/framework/ext/src/org/apache/cordova/geolocation/PositionOptions.java
----------------------------------------------------------------------
diff --git a/framework/ext/src/org/apache/cordova/geolocation/PositionOptions.java b/framework/ext/src/org/apache/cordova/geolocation/PositionOptions.java
new file mode 100644
index 0000000..85d5853
--- /dev/null
+++ b/framework/ext/src/org/apache/cordova/geolocation/PositionOptions.java
@@ -0,0 +1,42 @@
+/*
+ * 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.geolocation;
+
+import org.apache.cordova.json4j.JSONArray;
+import org.apache.cordova.json4j.JSONException;
+
+public class PositionOptions {
+	private static final int START_ARG_MAX_AGE = 1;
+	private static final int START_ARG_TIMEOUT = 2;
+	private static final int START_ARG_HIGH_ACCURACY = 3;
+
+	public int maxAge;
+	public int timeout;
+	public boolean enableHighAccuracy;
+
+	public static PositionOptions fromJSONArray(JSONArray args) throws NumberFormatException, JSONException {
+		PositionOptions po = new PositionOptions();
+
+		po.maxAge = Integer.parseInt(args.getString(START_ARG_MAX_AGE));
+		po.timeout = Integer.parseInt(args.getString(START_ARG_TIMEOUT));
+		po.enableHighAccuracy = args.getBoolean(START_ARG_HIGH_ACCURACY);
+
+		return po;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/05319d3c/framework/ext/src/org/apache/cordova/http/FileTransfer.java
----------------------------------------------------------------------
diff --git a/framework/ext/src/org/apache/cordova/http/FileTransfer.java b/framework/ext/src/org/apache/cordova/http/FileTransfer.java
new file mode 100644
index 0000000..d4c8362
--- /dev/null
+++ b/framework/ext/src/org/apache/cordova/http/FileTransfer.java
@@ -0,0 +1,376 @@
+/*
+ * 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.http;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.microedition.io.Connector;
+import javax.microedition.io.HttpConnection;
+import javax.microedition.io.file.FileConnection;
+
+import org.apache.cordova.api.Plugin;
+import org.apache.cordova.api.PluginResult;
+import org.apache.cordova.file.Entry;
+import org.apache.cordova.json4j.JSONArray;
+import org.apache.cordova.json4j.JSONException;
+import org.apache.cordova.json4j.JSONObject;
+import org.apache.cordova.util.Logger;
+
+import net.rim.device.api.io.FileNotFoundException;
+import net.rim.device.api.io.http.HttpProtocolConstants;
+
+/**
+ * The FileTransfer plugin can be used to transfer files between the device and
+ * a remote server. The following actions are supported:
+ *
+ *      download - Download a file from a server to the device.
+ *      upload   - Upload a file from the device to a server.
+ */
+public class FileTransfer extends Plugin {
+    private static final String LOG_TAG = "FileTransfer: ";
+
+    /**
+     * Error codes
+     */
+    static int FILE_NOT_FOUND_ERR = 1;
+    static int INVALID_URL_ERR = 2;
+    static int CONNECTION_ERR = 3;
+
+    /**
+     * Possible actions
+     */
+    private static final String ACTION_DOWNLOAD = "download";
+    private static final String ACTION_UPLOAD = "upload";
+
+    private static final char SEPARATOR = '/';
+
+    /**
+     * Executes the requested action and returns a PluginResult.
+     *
+     * @param action
+     *            The action to execute.
+     * @param callbackId
+     *            The callback ID to be invoked upon action completion.
+     * @param args
+     *            JSONArry of arguments for the action.
+     * @return A PluginResult object with a status and message.
+     */
+    public PluginResult execute(String action, JSONArray args, String callbackId) {
+        String source = null;
+        String target = null;
+        PluginResult result = null;
+
+        try {
+            // Retrieve the source and target locations from the argument array.
+            source = args.isNull(0) ? null : args.getString(0).trim();
+            target = args.isNull(1) ? null : args.getString(1).trim();
+
+            if (source == null || source.length() == 0 || target == null
+                    || target.length() == 0) {
+                Logger.log(LOG_TAG + "Missing source or target");
+                return new PluginResult(PluginResult.Status.JSON_EXCEPTION,
+                        "Missing source or target");
+            }
+        } catch (JSONException e) {
+            Logger.log(LOG_TAG + e.getMessage());
+            return new PluginResult(PluginResult.Status.JSON_EXCEPTION,
+                    "Invalid or missing parameter");
+        }
+
+        if (ACTION_UPLOAD.equals(action)) {
+            // Source needs to follow the file URI protocol so add "file:///"
+            // prefix if it doesn't exist.
+            if (!source.startsWith("file:///")) {
+                if (source.indexOf(SEPARATOR) != 0) {
+                    source = "file://" + SEPARATOR + source;
+                } else {
+                    source = "file://" + source;
+                }
+            }
+
+            try {
+                // Setup the options
+                String fileKey = getArgument(args, 2, "file");
+                String fileName = getArgument(args, 3, "image.jpg");
+                String mimeType = getArgument(args, 4, null);
+                JSONObject params = null;
+
+                if (args.length() > 5 && !args.isNull(5)) {
+                    params = args.getJSONObject(5);
+                }
+
+                FileUploader f = new FileUploader();
+                FileUploadResult r = f.upload(source, target, fileKey,
+                        fileName, mimeType, params);
+                result = new PluginResult(PluginResult.Status.OK,
+                        r.toJSONObject());
+            } catch (FileNotFoundException e) {
+                Logger.log(LOG_TAG + e.getMessage());
+                JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR,
+                        source, target);
+                result = new PluginResult(PluginResult.Status.IO_EXCEPTION,
+                        error);
+            } catch (IllegalArgumentException e) {
+                Logger.log(LOG_TAG + e.getMessage());
+                JSONObject error = createFileTransferError(INVALID_URL_ERR,
+                        source, target);
+                result = new PluginResult(
+                        PluginResult.Status.MALFORMED_URL_EXCEPTION, error);
+            } catch (IOException e) {
+                Logger.log(LOG_TAG + e.getMessage());
+                JSONObject error = createFileTransferError(CONNECTION_ERR,
+                        source, target);
+                result = new PluginResult(PluginResult.Status.IO_EXCEPTION,
+                        error);
+            } catch (JSONException e) {
+                Logger.log(LOG_TAG + e.getMessage());
+                result = new PluginResult(PluginResult.Status.JSON_EXCEPTION,
+                        "Invalid or missing parameter");
+            }
+        } else if (ACTION_DOWNLOAD.equals(action)) {
+            result = download(source, target);
+        } else {
+            // invalid action
+            result = new PluginResult(PluginResult.Status.INVALID_ACTION,
+                    LOG_TAG + "invalid action " + action);
+        }
+
+        return result;
+    }
+
+    /**
+     * Create an error object based on the passed in errorCode
+     *
+     * @param errorCode
+     *            the error
+     * @return JSONObject containing the error
+     */
+    private JSONObject createFileTransferError(int errorCode, String source,
+            String target) {
+        JSONObject error = null;
+        try {
+            error = new JSONObject();
+            error.put("code", errorCode);
+            error.put("source", source);
+            error.put("target", target);
+        } catch (JSONException e) {
+            Logger.log(LOG_TAG + e.getMessage());
+        }
+        return error;
+    }
+
+    /**
+     * Recurse through a specified path and create any directories that do not
+     * already exist.
+     *
+     * @param path
+     *            directory path to recurse
+     * @throws IOException
+     */
+    private void createSubDirs(String path) throws IOException {
+        FileConnection outputStream = null;
+
+        try {
+            outputStream = (FileConnection) Connector.open(path,
+                    Connector.READ_WRITE);
+            if (!outputStream.exists()) {
+                int dirIndex = path.lastIndexOf(SEPARATOR, path.length() - 2);
+                // This code assumes file protocol is specified so stop
+                // recursion once "file:///" is hit.
+                if (dirIndex != -1 && dirIndex > 7) {
+                    createSubDirs(path.substring(0, dirIndex + 1));
+                }
+                outputStream.mkdir();
+            }
+        } finally {
+            try {
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+            } catch (IOException e) {
+                Logger.log(LOG_TAG + e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * Download a file from a given URL and save it to the specified location.
+     *
+     * @param source
+     *            URL of the server to receive the file
+     * @param target
+     *            Full path of the file on the file system
+     * @return JSONObject a file entry object in JSON form describing the
+     *         downloaded file.
+     */
+    private PluginResult download(String source, String target) {
+        HttpConnection httpConn = null;
+        FileConnection fileConn = null;
+        OutputStream outputStream = null;
+        String filename = null;
+        String path = null;
+
+        // Target needs to follow the file URI protocol so add "file:///"
+        // prefix if it doesn't exist.
+        if (!target.startsWith("file:///")) {
+            if (target.indexOf(SEPARATOR) != 0) {
+                target = "file://" + SEPARATOR + target;
+            } else {
+                target = "file://" + target;
+            }
+        }
+
+        // Parse the target filename and directory path. If the target does not
+        // specify a file name (only directory), try to get the file name from
+        // the source.
+        int dirIndex = target.lastIndexOf(SEPARATOR);
+        if (dirIndex == (target.length() - 1)) {
+            int srcdirIndex = source.lastIndexOf(SEPARATOR);
+            if (srcdirIndex != (source.length() - 1)) {
+                path = target;
+                filename = source.substring(srcdirIndex + 1);
+                target = path + filename;
+            }
+        } else if (dirIndex != -1) {
+            filename = target.substring(dirIndex + 1);
+            path = target.substring(0, dirIndex + 1);
+        }
+
+        // If no filename or path could be determined for the target, error out.
+        if (filename == null || path == null) {
+            Logger.log(LOG_TAG + "Target filename could not be determined.");
+            JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR,
+                    source, target);
+            return new PluginResult(PluginResult.Status.JSON_EXCEPTION, error);
+        }
+
+        try {
+            // Create any directories in the path that do not already exist.
+            createSubDirs(path);
+
+            // Open connection to the target file.
+            fileConn = (FileConnection) Connector.open(target,
+                    Connector.READ_WRITE);
+
+            // Create the target file if it doesn't exist, otherwise truncate.
+            if (!fileConn.exists()) {
+                fileConn.create();
+            } else {
+                fileConn.truncate(0);
+            }
+
+            // Open the http connection to the server.
+            httpConn = HttpUtils.getHttpConnection(source);
+            if (httpConn == null) {
+                Logger.log(LOG_TAG + "Failed to create http connection.");
+                JSONObject error = createFileTransferError(INVALID_URL_ERR,
+                        source, target);
+                return new PluginResult(
+                        PluginResult.Status.MALFORMED_URL_EXCEPTION, error);
+            }
+
+            // Set the request headers
+            httpConn.setRequestMethod(HttpConnection.GET);
+            httpConn.setRequestProperty(
+                    HttpProtocolConstants.HEADER_USER_AGENT,
+                    System.getProperty("browser.useragent"));
+            httpConn.setRequestProperty(
+                    HttpProtocolConstants.HEADER_KEEP_ALIVE, "300");
+            httpConn.setRequestProperty(
+                    HttpProtocolConstants.HEADER_CONNECTION, "keep-alive");
+
+            // Set the cookie
+            String cookie = HttpUtils.getCookie(source);
+            if (cookie != null) {
+                httpConn.setRequestProperty(
+                        HttpProtocolConstants.HEADER_COOKIE, cookie);
+            }
+
+            InputStream inputStream = httpConn.openInputStream();
+            outputStream = fileConn.openOutputStream();
+
+            // Read from the connection and write bytes to the file.
+            byte[] buffer = new byte[1024];
+            int bytesRead = 0;
+            while ((bytesRead = inputStream.read(buffer)) > 0) {
+                outputStream.write(buffer, 0, bytesRead);
+            }
+        } catch (IOException e) {
+            Logger.log(LOG_TAG + e.getMessage());
+            JSONObject error = createFileTransferError(CONNECTION_ERR, source,
+                    target);
+            return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
+        } catch (ClassCastException e) {
+            // in case something really funky gets passed in
+            Logger.log(LOG_TAG + e.getMessage());
+            JSONObject error = createFileTransferError(INVALID_URL_ERR, source,
+                    target);
+            return new PluginResult(
+                    PluginResult.Status.MALFORMED_URL_EXCEPTION, error);
+        } finally {
+            try {
+                if (httpConn != null) {
+                    httpConn.close();
+                }
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+                if (fileConn != null) {
+                    fileConn.close();
+                }
+            } catch (IOException e) {
+                Logger.log(LOG_TAG + "IOException in finally: "
+                        + e.getMessage());
+            }
+        }
+
+        // create a new Entry
+        Entry entry = new Entry();
+        entry.setDirectory(false);
+        entry.setName(filename);
+        entry.setFullPath(target);
+
+        return new PluginResult(PluginResult.Status.OK, entry.toJSONObject());
+    }
+
+    /**
+     * Convenience method to read a parameter from the list of JSON args.
+     *
+     * @param args
+     *            the args passed to the Plugin
+     * @param position
+     *            the position to retrieve the arg from
+     * @param defaultString
+     *            the default to be used if the arg does not exist
+     * @return String with the retrieved value
+     */
+    private String getArgument(JSONArray args, int position,
+            String defaultString) {
+        String arg = defaultString;
+        if (args.length() >= position) {
+            arg = args.optString(position);
+            if (arg == null || "null".equals(arg)) {
+                arg = defaultString;
+            }
+        }
+        return arg;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/05319d3c/framework/ext/src/org/apache/cordova/http/FileUploadResult.java
----------------------------------------------------------------------
diff --git a/framework/ext/src/org/apache/cordova/http/FileUploadResult.java b/framework/ext/src/org/apache/cordova/http/FileUploadResult.java
new file mode 100644
index 0000000..4b00159
--- /dev/null
+++ b/framework/ext/src/org/apache/cordova/http/FileUploadResult.java
@@ -0,0 +1,63 @@
+/*
+ * 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.http;
+
+import org.apache.cordova.json4j.JSONException;
+import org.apache.cordova.json4j.JSONObject;
+
+/**
+ * Encapsulates the result and/or status of uploading a file to a remote server.
+ */
+public class FileUploadResult {
+
+    private long bytesSent = 0;         // bytes sent
+    private int responseCode = -1;      // HTTP response code
+    private String response = null;     // HTTP response
+
+    public long getBytesSent() {
+        return bytesSent;
+    }
+
+    public void setBytesSent(long bytes) {
+        this.bytesSent = bytes;
+    }
+
+    public int getResponseCode() {
+        return responseCode;
+    }
+
+    public void setResponseCode(int responseCode) {
+        this.responseCode = responseCode;
+    }
+
+    public String getResponse() {
+        return response;
+    }
+
+    public void setResponse(String response) {
+        this.response = response;
+    }
+
+    public JSONObject toJSONObject() throws JSONException {
+        return new JSONObject(
+                "{bytesSent:" + bytesSent +
+                ",responseCode:" + responseCode +
+                ",response:" + JSONObject.quote(response) + "}");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/05319d3c/framework/ext/src/org/apache/cordova/http/FileUploader.java
----------------------------------------------------------------------
diff --git a/framework/ext/src/org/apache/cordova/http/FileUploader.java b/framework/ext/src/org/apache/cordova/http/FileUploader.java
new file mode 100644
index 0000000..9926695
--- /dev/null
+++ b/framework/ext/src/org/apache/cordova/http/FileUploader.java
@@ -0,0 +1,258 @@
+/*
+ * 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.http;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+
+import javax.microedition.io.Connector;
+import javax.microedition.io.HttpConnection;
+import javax.microedition.io.file.FileConnection;
+
+import org.apache.cordova.CordovaExtension;
+import org.apache.cordova.api.PluginResult;
+import org.apache.cordova.json4j.JSONException;
+import org.apache.cordova.json4j.JSONObject;
+import org.apache.cordova.util.Logger;
+
+import net.rim.device.api.io.FileNotFoundException;
+import net.rim.device.api.io.IOUtilities;
+import net.rim.device.api.io.MIMETypeAssociations;
+import net.rim.device.api.io.http.HttpProtocolConstants;
+import net.rim.device.api.ui.UiApplication;
+
+/**
+ * The FileUploader uses an HTTP multipart request to upload files on the
+ * device to a remote server.  It currently supports a single file per HTTP
+ * request.
+ */
+public class FileUploader {
+
+    /**
+     * Constants
+     */
+    private static final String BOUNDARY = "----0x2fc1b3ef7cecbf14L";
+    private static final String LINE_END = "\r\n";
+    private static final String TD = "--";
+
+    /**
+     * Uploads the specified file to the server URL provided using an HTTP
+     * multipart request.
+     * @param filePath      Full path of the file on the file system
+     * @param server        URL of the server to receive the file
+     * @param fileKey       Name of file request parameter
+     * @param fileName      File name to be used on server
+     * @param mimeType      Describes file content type
+     * @param params        key:value pairs of user-defined parameters
+     * @return FileUploadResult containing result of upload request
+     */
+    public FileUploadResult upload(String filePath, String server, String fileKey,
+            String fileName, String mimeType, JSONObject params)
+    throws FileNotFoundException, IllegalArgumentException, IOException {
+
+        Logger.log(this.getClass().getName() + ": uploading " + filePath + " to " + server);
+        FileUploadResult result = new FileUploadResult();
+
+        InputStream in = null;
+        OutputStream out = null;
+        FileConnection fconn = null;
+        HttpConnection httpConn = null;
+        try {
+            // open connection to the file
+            try {
+                fconn = (FileConnection)Connector.open(filePath, Connector.READ);
+            } catch (ClassCastException e) {
+                // in case something really funky gets passed in
+                throw new IllegalArgumentException("Invalid file path");
+            }
+            if (!fconn.exists()) {
+                throw new FileNotFoundException(filePath + " not found");
+            }
+
+            // determine mime type by
+            //     1) user-provided type
+            //     2) retrieve from file system
+            //     3) default to JPEG
+            if (mimeType == null) {
+                mimeType = MIMETypeAssociations.getMIMEType(filePath);
+                if (mimeType == null) {
+                    mimeType = HttpProtocolConstants.CONTENT_TYPE_IMAGE_JPEG;
+                }
+            }
+
+            // boundary messages
+            String boundaryMsg = getBoundaryMessage(fileKey, fileName, mimeType);
+            String lastBoundary = getEndBoundary();
+
+            // user-defined request parameters
+            String customParams = (params != null) ? getParameterContent(params) : "";
+            Logger.log(this.getClass().getName() + ": params=" + customParams);
+
+            // determine content length
+            long fileSize = fconn.fileSize();
+            Logger.log(this.getClass().getName() + ": " + filePath + " size=" + fileSize + " bytes");
+            long contentLength = fileSize +
+                (long)boundaryMsg.length() +
+                (long)lastBoundary.length() +
+                (long)customParams.length();
+
+            // get HttpConnection
+            httpConn = HttpUtils.getHttpConnection(server);
+            if (httpConn == null) {
+                throw new IllegalArgumentException("Invalid URL: " + server);
+            }
+            Logger.log(this.getClass().getName() + ": server URL=" + httpConn.getURL());
+
+            // set request headers
+            httpConn.setRequestMethod(HttpConnection.POST);
+            httpConn.setRequestProperty(
+                    HttpProtocolConstants.HEADER_USER_AGENT,
+                    System.getProperty("browser.useragent"));
+            httpConn.setRequestProperty(
+                    HttpProtocolConstants.HEADER_KEEP_ALIVE, "300");
+            httpConn.setRequestProperty(
+                    HttpProtocolConstants.HEADER_CONNECTION, "keep-alive");
+            httpConn.setRequestProperty(
+                    HttpProtocolConstants.HEADER_CONTENT_TYPE,
+                    HttpProtocolConstants.CONTENT_TYPE_MULTIPART_FORM_DATA + "; boundary=" + BOUNDARY);
+            httpConn.setRequestProperty(
+                    HttpProtocolConstants.HEADER_CONTENT_LENGTH,
+                    Long.toString(contentLength));
+
+            // set cookie
+            String cookie = HttpUtils.getCookie(server);
+            if (cookie != null) {
+                httpConn.setRequestProperty(HttpProtocolConstants.HEADER_COOKIE, cookie);
+                Logger.log(this.getClass().getName() + ": cookie=" + cookie);
+            }
+
+            // write...
+            out = httpConn.openDataOutputStream();
+
+            // parameters
+            out.write(customParams.getBytes());
+
+            // boundary
+            out.write(boundaryMsg.getBytes());
+
+            // file data
+            in = fconn.openInputStream();
+            byte[] data = IOUtilities.streamToBytes(in);
+            out.write(data);
+            in.close();
+
+            // end boundary
+            out.write(lastBoundary.getBytes());
+
+            // send request and get response
+            in = httpConn.openDataInputStream();
+            int rc = httpConn.getResponseCode();
+            result.setResponse(new String(IOUtilities.streamToBytes(in)));
+            result.setResponseCode(rc);
+            result.setBytesSent(contentLength);
+            Logger.log(this.getClass().getName() + ": sent " + contentLength + " bytes");
+        }
+        finally {
+            try {
+                if (fconn != null) fconn.close();
+                if (in != null) in.close();
+                if (out != null) out.close();
+                if (httpConn != null) httpConn.close();
+            }
+            catch (IOException e) {
+                Logger.log(this.getClass().getName() + ": " + e);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Sends an upload progress notification back to JavaScript engine.
+     * @param result        FileUploadResult containing bytes sent of total
+     * @param callbackId    identifier of callback function to invoke
+     */
+    protected void sendProgress(FileUploadResult result, final String callbackId) {
+        JSONObject o = null;
+        try {
+            o = result.toJSONObject();
+        }
+        catch (JSONException e) {
+            Logger.log(this.getClass().getName() + ": " + e);
+            return;
+        }
+
+        // send a progress result
+        final PluginResult r = new PluginResult(PluginResult.Status.OK, o);
+        r.setKeepCallback(true);
+        UiApplication.getUiApplication().invokeAndWait(
+            new Runnable() {
+                public void run() {
+                    CordovaExtension.invokeSuccessCallback(callbackId, r);
+                }
+            }
+        );
+    }
+
+    /**
+     * Returns the boundary string that represents the beginning of a file
+     * in a multipart HTTP request.
+     * @param fileKey       Name of file request parameter
+     * @param fileName      File name to be used on server
+     * @param mimeType      Describes file content type
+     * @return string representing the boundary message in a multipart HTTP request
+     */
+    protected String getBoundaryMessage(String fileKey, String fileName, String mimeType) {
+        return (new StringBuffer())
+            .append(LINE_END)
+            .append(TD).append(BOUNDARY).append(LINE_END)
+            .append("Content-Disposition: form-data; name=\"").append(fileKey)
+            .append("\"; filename=\"").append(fileName).append("\"").append(LINE_END)
+            .append("Content-Type: ").append(mimeType).append(LINE_END)
+            .append(LINE_END)
+            .toString();
+    }
+
+    /**
+     * Returns the boundary string that represents the end of a file in a
+     * multipart HTTP request.
+     * @return string representing the end boundary message in a multipart HTTP request
+     */
+    protected String getEndBoundary() {
+        return LINE_END + TD + BOUNDARY + TD + LINE_END;
+    }
+
+    /**
+     * Returns HTTP form content containing specified parameters.
+     */
+    protected String getParameterContent(JSONObject params) {
+        StringBuffer buf = new StringBuffer();
+        for (Enumeration e = params.keys(); e.hasMoreElements();) {
+            String key = e.nextElement().toString();
+            String value = params.optString(key);
+            buf.append(TD).append(BOUNDARY).append(LINE_END)
+                .append("Content-Disposition: form-data; name=\"").append(key).append("\"")
+                .append(LINE_END).append(LINE_END)
+                .append(value).append(LINE_END);
+        }
+        return buf.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/05319d3c/framework/ext/src/org/apache/cordova/http/HttpUtils.java
----------------------------------------------------------------------
diff --git a/framework/ext/src/org/apache/cordova/http/HttpUtils.java b/framework/ext/src/org/apache/cordova/http/HttpUtils.java
new file mode 100644
index 0000000..af6ada6
--- /dev/null
+++ b/framework/ext/src/org/apache/cordova/http/HttpUtils.java
@@ -0,0 +1,66 @@
+/*
+ * 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.http;
+
+import javax.microedition.io.HttpConnection;
+
+import org.apache.cordova.CordovaExtension;
+
+import net.rim.device.api.io.transport.ConnectionDescriptor;
+import net.rim.device.api.io.transport.ConnectionFactory;
+
+/**
+ * BlackBerry devices can connect to the network using a variety of transport
+ * types, such as: WI-FI, BES/MDS, BIS, WAP (cellular).  A connection URL must
+ * have the appropriate suffix to match the transport type.  This class contains
+ * utility methods to retrieve the correct URL for the appropriate transport.
+ */
+public class HttpUtils
+{
+    /**
+     * This method will open an HTTP connection over the best available transport type.
+     * @param url   Connection URL
+     */
+    public static HttpConnection getHttpConnection(String url)
+    {
+        HttpConnection httpConn = null;
+
+        // Create ConnectionFactory
+        ConnectionFactory factory = new ConnectionFactory();
+
+        // use the factory to get a connection
+        ConnectionDescriptor conDescriptor = factory.getConnection(url);
+
+        if (conDescriptor != null) {
+           // using the connection
+           httpConn = (HttpConnection) conDescriptor.getConnection();
+        }
+
+        return httpConn;
+    }
+
+    /**
+     * Retrieves the cookie from the application browser instance for the specified URL.
+     * @param url   Connection URL
+     */
+    public static String getCookie(String url)
+    {
+        return CordovaExtension.getBrowserField().getCookieManager().getCookie(url);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-blackberry-webworks/blob/05319d3c/framework/ext/src/org/apache/cordova/json4j/JSON.java
----------------------------------------------------------------------
diff --git a/framework/ext/src/org/apache/cordova/json4j/JSON.java b/framework/ext/src/org/apache/cordova/json4j/JSON.java
new file mode 100644
index 0000000..adbe514
--- /dev/null
+++ b/framework/ext/src/org/apache/cordova/json4j/JSON.java
@@ -0,0 +1,208 @@
+/*
+ * 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.json4j;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import org.apache.cordova.json4j.internal.JSON4JPBackReader;
+
+/**
+ * Helper class that does generic parsing of a JSON stream and returns the appropriate
+ * JSON structure (JSONArray or JSONObject).  Note that it is slightly more efficient to directly
+ * parse with the appropriate object than to use this class to do a generalized parse.
+ */
+public class JSON {
+
+    /**
+     * A constant for representing null.
+     * In this case, it is just null.
+     */
+    public static final Object NULL = null;
+
+    /**
+     * Parse a Reader of JSON text into a JSONArtifact.
+     * @param reader The character reader to read the JSON data from.
+     * @param order Boolean flag indicating if the order of the JSON data should be preserved.  This parameter only has an effect if the stream is JSON Object { ... } formatted data.
+     * Note:  The provided reader is not closed on completion of read; that is left to the caller.
+     * Note:  This is the same as calling parse(reader, order, false);
+     *
+     * @return Returns an instance of JSONArtifact (JSONObject, OrderedJSONObject, or JSONArray), corrisponding to if the input stream was Object or Array notation.
+     *
+     * @throws JSONException Thrown on errors during parse.
+     * @throws NullPointerException Thrown if reader is null
+     */
+    public static JSONArtifact parse(Reader reader, boolean order) throws JSONException, NullPointerException {
+        return parse(reader,order,false);
+    }
+
+    /**
+     * Parse a Reader of JSON text into a JSONArtifact.
+     * @param reader The character reader to read the JSON data from.
+     * @param order Boolean flag indicating if the order of the JSON data should be preserved.  This parameter only has an effect if the stream is JSON Object { ... } formatted data.
+     * @param strict Boolean flag to indicate if the content should be parsed in strict mode or not, meaning comments and unquoted strings are not allowed.
+     * Note:  The provided reader is not closed on completion of read; that is left to the caller.
+     *
+     * @return Returns an instance of JSONArtifact (JSONObject, OrderedJSONObject, or JSONArray), corrisponding to if the input stream was Object or Array notation.
+     *
+     * @throws JSONException Thrown on errors during parse.
+     * @throws NullPointerException Thrown if reader is null
+     */
+    public static JSONArtifact parse(Reader reader, boolean order, boolean strict) throws JSONException, NullPointerException {
+
+        try {
+            if (reader != null) {
+
+                JSON4JPBackReader pReader = null;
+
+                //Determine if we should buffer-wrap the reader before passing it on
+                //to the appropriate parser.
+                //boolean bufferIt = false;
+
+                Class readerClass = reader.getClass();
+
+               /* if (!StringReader.class.isAssignableFrom(readerClass) &&
+                    !CharArrayReader.class.isAssignableFrom(readerClass) &&
+                    !PushbackReader.class.isAssignableFrom(readerClass) &&
+                    !BufferedReader.class.isAssignableFrom(readerClass)) {
+                    bufferIt = true;
+                } */
+
+                //MSN IMPLEMENT PUSHBACKREADER!!
+                if (JSON4JPBackReader.class.isAssignableFrom(readerClass)) {
+                    pReader = (JSON4JPBackReader) reader;
+                } else {
+                    pReader = new JSON4JPBackReader(reader);
+                }
+
+                Reader rdr = pReader;
+                int ch = pReader.read();
+                while (ch != -1) {
+                    switch (ch) {
+                        case '{':
+                            pReader.unread(ch);
+                           /* if (bufferIt) {
+                                rdr = new BufferedReader(pReader);
+                            } */
+                            return new JSONObject(rdr,strict);
+                        case '[':
+                            pReader.unread(ch);
+                            /*if (bufferIt) {
+                                rdr = new BufferedReader(pReader);
+                            } */
+                            return new JSONArray(rdr, strict);
+                        case ' ':
+                        case '\t':
+                        case '\f':
+                        case '\r':
+                        case '\n':
+                        case '\b':
+                            ch = pReader.read();
+                            break;
+                        default:
+                            throw new JSONException("Unexpected character: [" + (char)ch + "] while scanning JSON String for JSON type.  Invalid JSON.");
+                    }
+                }
+                throw new JSONException("Encountered end of stream before JSON data was read.  Invalid JSON");
+            } else {
+                throw new NullPointerException("reader cannot be null.");
+            }
+        } catch (IOException iox) {
+            JSONException jex = new JSONException("Error occurred during input read.");
+            jex.setCause(iox);
+            throw jex;
+        }
+    }
+
+    /**
+     * Parse a Reader of JSON text into a JSONArtifact.
+     * This call is the same as JSON.parse(reader, false, false).
+     * Note that the provided reader is not closed on completion of read; that is left to the caller.
+     * @param reader The character reader to read the JSON data from.
+     *
+     * @return Returns an instance of JSONArtifact (JSONObject, OrderedJSONObject, or JSONArray), corrisponding to if the input stream was Object or Array notation.
+     *
+     * @throws JSONException Thrown on errors during parse.
+     * @throws NullPointerException Thrown if reader is null
+     */
+    public static JSONArtifact parse(Reader reader) throws JSONException, NullPointerException {
+        return parse(reader,false, false);
+    }
+
+    /**
+     * Parse a InputStream of JSON text into a JSONArtifact.
+     * Note:  The provided InputStream is not closed on completion of read; that is left to the caller.
+     * @param is The input stream to read from.  The content is assumed to be UTF-8 encoded and handled as such.
+     * @param order Boolean flag indicating if the order of the JSON data should be preserved.  This parameter only has an effect if the stream is JSON Object { ... } formatted data.
+     *
+     * @return Returns an instance of JSONArtifact (JSONObject or JSONArray), corrisponding to if the input stream was Object or Array notation.
+     *
+     * @throws JSONException Thrown on errors during parse.
+     * @throws NullPointerException Thrown if reader is null
+     */
+    public static JSONArtifact parse(InputStream is, boolean order) throws JSONException, NullPointerException {
+        return parse(is,order, false);
+    }
+
+    /**
+     * Parse a InputStream of JSON text into a JSONArtifact.
+     * Note that the provided InputStream is not closed on completion of read; that is left to the caller.
+     * @param is The input stream to read from.  The content is assumed to be UTF-8 encoded and handled as such.
+     * @param order Boolean flag indicating if the order of the JSON data should be preserved.  This parameter only has an effect if the stream is JSON Object { ... } formatted data.
+     * @param strict Boolean flag to indicate if the content should be parsed in strict mode or not, meaning comments and unquoted strings are not allowed.
+     *
+     * @return Returns an instance of JSONArtifact (JSONObject or JSONArray), corrisponding to if the input stream was Object or Array notation.
+     *
+     * @throws JSONException Thrown on errors during parse.
+     * @throws NullPointerException Thrown if reader is null
+     */
+    public static JSONArtifact parse(InputStream is, boolean order, boolean strict) throws JSONException, NullPointerException {
+        if (is != null) {
+            //BufferedReader reader = null;
+            InputStreamReader reader = null;
+            try {
+                reader = new InputStreamReader(is, "UTF-8");
+            } catch (Exception ex) {
+                JSONException iox = new JSONException("Could not construct UTF-8 character reader for the InputStream");
+                iox.setCause(ex);
+                throw iox;
+            }
+            return parse(reader,order);
+        } else {
+            throw new NullPointerException("is cannot be null");
+        }
+    }
+
+    /**
+     * Parse an InputStream of JSON text into a JSONArtifact.
+     * This call is the same as JSON.parse(is, false, false).
+     * Note that the provided InputStream is not closed on completion of read; that is left to the caller.
+     * @param is The input stream to read from.  The content is assumed to be UTF-8 encoded and handled as such.
+     *
+     * @return Returns an instance of JSONArtifact (JSONObject, OrderedJSONObject, or JSONArray), corrisponding to if the input stream was Object or Array notation.
+     *
+     * @throws JSONException Thrown on errors during parse.
+     * @throws NullPointerException Thrown if reader is null
+     */
+    public static JSONArtifact parse(InputStream is) throws JSONException, NullPointerException {
+        return parse(is,false, false);
+    }
+}