You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ma...@apache.org on 2012/05/24 02:55:43 UTC

[2/2] android commit: [CB-792] Add HTTP status code to FileTransferError

[CB-792] Add HTTP status code to FileTransferError


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/commit/5dacb8d2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/tree/5dacb8d2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/diff/5dacb8d2

Branch: refs/heads/master
Commit: 5dacb8d2d5bb1e8a9806f07185f510a608586f15
Parents: fc50a0d
Author: Don Coleman <dc...@chariotsolutions.com>
Authored: Thu May 17 14:51:41 2012 -0400
Committer: Don Coleman <dc...@chariotsolutions.com>
Committed: Thu May 17 14:51:41 2012 -0400

----------------------------------------------------------------------
 framework/src/org/apache/cordova/FileTransfer.java |  553 ++++++++-------
 1 files changed, 305 insertions(+), 248 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/5dacb8d2/framework/src/org/apache/cordova/FileTransfer.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/FileTransfer.java b/framework/src/org/apache/cordova/FileTransfer.java
index a631a05..368d97a 100644
--- a/framework/src/org/apache/cordova/FileTransfer.java
+++ b/framework/src/org/apache/cordova/FileTransfer.java
@@ -27,6 +27,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
@@ -35,7 +36,6 @@ import java.util.Iterator;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
@@ -57,7 +57,7 @@ public class FileTransfer extends Plugin {
     private static final String LOG_TAG = "FileTransfer";
     private static final String LINE_START = "--";
     private static final String LINE_END = "\r\n";
-    private static final String BOUNDRY =  "*****";
+    private static final String BOUNDARY =  "*****";
 
     public static int FILE_NOT_FOUND_ERR = 1;
     public static int INVALID_URL_ERR = 2;
@@ -82,49 +82,251 @@ public class FileTransfer extends Plugin {
             return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing source or target");
         }
 
+        if (action.equals("upload")) {
+            return upload(source, target, args);
+        } else if (action.equals("download")) {
+            return download(source, target);
+        } else {
+            return new PluginResult(PluginResult.Status.INVALID_ACTION);
+        }
+    }
+
+    /**
+     * Uploads the specified file to the server URL provided using an HTTP multipart request.
+     * @param source        Full path of the file on the file system
+     * @param target        URL of the server to receive the file
+     * @param args          JSON Array of args
+     *
+     * args[2] fileKey       Name of file request parameter
+     * args[3] fileName      File name to be used on server
+     * args[4] mimeType      Describes file content type
+     * args[5] params        key:value pairs of user-defined parameters
+     * @return FileUploadResult containing result of upload request
+     */
+    private PluginResult upload(String source, String target, JSONArray args) {
+        Log.d(LOG_TAG, "upload " + source + " to " +  target);
+
+        HttpURLConnection conn = null;
         try {
-            if (action.equals("upload")) {
-                // Setup the options
-                String fileKey = null;
-                String fileName = null;
-                String mimeType = null;
-
-                fileKey = getArgument(args, 2, "file");
-                fileName = getArgument(args, 3, "image.jpg");
-                mimeType = getArgument(args, 4, "image/jpeg");
-                JSONObject params = args.optJSONObject(5);
-                boolean trustEveryone = args.optBoolean(6);
-                boolean chunkedMode = args.optBoolean(7) || args.isNull(7); //Always use chunked mode unless set to false as per API
-                FileUploadResult r = upload(source, target, fileKey, fileName, mimeType, params, trustEveryone, chunkedMode);
-                Log.d(LOG_TAG, "****** About to return a result from upload");
-                return new PluginResult(PluginResult.Status.OK, r.toJSONObject());
-            } else if (action.equals("download")) {
-                JSONObject r = download(source, target);
-                Log.d(LOG_TAG, "****** About to return a result from download");
-                return new PluginResult(PluginResult.Status.OK, r);
-            } else {
-                return new PluginResult(PluginResult.Status.INVALID_ACTION);
+            // Setup the options
+            String fileKey = getArgument(args, 2, "file");
+            String fileName = getArgument(args, 3, "image.jpg");
+            String mimeType = getArgument(args, 4, "image/jpeg");
+            JSONObject params = args.optJSONObject(5);
+            if (params == null) params = new JSONObject();
+            boolean trustEveryone = args.optBoolean(6);
+            boolean chunkedMode = args.optBoolean(7) || args.isNull(7); //Always use chunked mode unless set to false as per API
+
+            Log.d(LOG_TAG, "fileKey: " + fileKey);
+            Log.d(LOG_TAG, "fileName: " + fileName);
+            Log.d(LOG_TAG, "mimeType: " + mimeType);
+            Log.d(LOG_TAG, "params: " + params);
+            Log.d(LOG_TAG, "trustEveryone: " + trustEveryone);
+            Log.d(LOG_TAG, "chunkedMode: " + chunkedMode);
+
+            // Create return object
+            FileUploadResult result = new FileUploadResult();
+
+            // Get a input stream of the file on the phone
+            FileInputStream fileInputStream = (FileInputStream) getPathFromUri(source);
+
+            DataOutputStream dos = null;
+
+            int bytesRead, bytesAvailable, bufferSize;
+            long totalBytes;
+            byte[] buffer;
+            int maxBufferSize = 8096;
+
+            //------------------ CLIENT REQUEST
+            // open a URL connection to the server
+            URL url = new URL(target);
+
+            // Open a HTTP connection to the URL based on protocol
+            if (url.getProtocol().toLowerCase().equals("https")) {
+                // Using standard HTTPS connection. Will not allow self signed certificate
+                if (!trustEveryone) {
+                    conn = (HttpsURLConnection) url.openConnection();
+                }
+                // Use our HTTPS connection that blindly trusts everyone.
+                // This should only be used in debug environments
+                else {
+                    // Setup the HTTPS connection class to trust everyone
+                    trustAllHosts();
+                    HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
+                    // Save the current hostnameVerifier
+                    defaultHostnameVerifier = https.getHostnameVerifier();
+                    // Setup the connection not to verify hostnames
+                    https.setHostnameVerifier(DO_NOT_VERIFY);
+                    conn = https;
+                }
+            }
+            // Return a standard HTTP connection
+            else {
+                conn = (HttpURLConnection) url.openConnection();
+            }
+
+            // Allow Inputs
+            conn.setDoInput(true);
+
+            // Allow Outputs
+            conn.setDoOutput(true);
+
+            // Don't use a cached copy.
+            conn.setUseCaches(false);
+
+            // Use a post method.
+            conn.setRequestMethod("POST");
+            conn.setRequestProperty("Connection", "Keep-Alive");
+            conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
+
+            // Handle the other headers
+            try {
+              JSONObject headers = params.getJSONObject("headers");
+              for (Iterator iter = headers.keys(); iter.hasNext();)
+              {
+                String headerKey = iter.next().toString();
+                conn.setRequestProperty(headerKey, headers.getString(headerKey));
+              }
+            } catch (JSONException e1) {
+              // No headers to be manipulated!
+            }
+
+            // Set the cookies on the response
+            String cookie = CookieManager.getInstance().getCookie(target);
+            if (cookie != null) {
+                conn.setRequestProperty("Cookie", cookie);
+            }
+
+
+            /*
+                * Store the non-file portions of the multipart data as a string, so that we can add it
+                * to the contentSize, since it is part of the body of the HTTP request.
+                */
+            String extraParams = "";
+            try {
+                for (Iterator iter = params.keys(); iter.hasNext();) {
+                    Object key = iter.next();
+                    if(!String.valueOf(key).equals("headers"))
+                    {
+                      extraParams += LINE_START + BOUNDARY + LINE_END;
+                      extraParams += "Content-Disposition: form-data; name=\"" +  key.toString() + "\";";
+                      extraParams += LINE_END + LINE_END;
+                      extraParams += params.getString(key.toString());
+                      extraParams += LINE_END;
+                    }
+                }
+            } catch (JSONException e) {
+                Log.e(LOG_TAG, e.getMessage(), e);
+            }
+
+            extraParams += LINE_START + BOUNDARY + LINE_END;
+            extraParams += "Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"";
+
+            String midParams = "\"" + LINE_END + "Content-Type: " + mimeType + LINE_END + LINE_END;
+            String tailParams = LINE_END + LINE_START + BOUNDARY + LINE_START + LINE_END;
+
+            // Should set this up as an option
+            if (chunkedMode) {
+                conn.setChunkedStreamingMode(maxBufferSize);
             }
+            else
+            {
+              int stringLength = extraParams.length() + midParams.length() + tailParams.length() + fileName.getBytes("UTF-8").length;
+              Log.d(LOG_TAG, "String Length: " + stringLength);
+              int fixedLength = (int) fileInputStream.getChannel().size() + stringLength;
+              Log.d(LOG_TAG, "Content Length: " + fixedLength);
+              conn.setFixedLengthStreamingMode(fixedLength);
+            }
+
+
+            dos = new DataOutputStream( conn.getOutputStream() );
+            dos.writeBytes(extraParams);
+            //We don't want to chagne encoding, we just want this to write for all Unicode.
+            dos.write(fileName.getBytes("UTF-8"));
+            dos.writeBytes(midParams);
+
+            // create a buffer of maximum size
+            bytesAvailable = fileInputStream.available();
+            bufferSize = Math.min(bytesAvailable, maxBufferSize);
+            buffer = new byte[bufferSize];
+
+            // read file and write it into form...
+            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
+            totalBytes = 0;
+
+            while (bytesRead > 0) {
+                totalBytes += bytesRead;
+                result.setBytesSent(totalBytes);
+                dos.write(buffer, 0, bufferSize);
+                bytesAvailable = fileInputStream.available();
+                bufferSize = Math.min(bytesAvailable, maxBufferSize);
+                bytesRead = fileInputStream.read(buffer, 0, bufferSize);
+            }
+
+            // send multipart form data necesssary after file data...
+            dos.writeBytes(tailParams);
+
+            // close streams
+            fileInputStream.close();
+            dos.flush();
+            dos.close();
+
+            //------------------ read the SERVER RESPONSE
+            StringBuffer responseString = new StringBuffer("");
+            DataInputStream inStream;
+            try {
+                inStream = new DataInputStream ( conn.getInputStream() );
+            } catch(FileNotFoundException e) {
+                Log.e(LOG_TAG, e.toString(), e);
+                throw new IOException("Received error from server");
+            }
+
+            String line;
+            while (( line = inStream.readLine()) != null) {
+                responseString.append(line);
+            }
+            Log.d(LOG_TAG, "got response from server");
+            Log.d(LOG_TAG, responseString.toString());
+
+            // send request and retrieve response
+            result.setResponseCode(conn.getResponseCode());
+            result.setResponse(responseString.toString());
+
+            inStream.close();
+
+            // Revert back to the proper verifier and socket factories
+            if (trustEveryone && url.getProtocol().toLowerCase().equals("https")) {
+                ((HttpsURLConnection) conn).setHostnameVerifier(defaultHostnameVerifier);
+                HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSocketFactory);
+            }
+
+            Log.d(LOG_TAG, "****** About to return a result from upload");
+            return new PluginResult(PluginResult.Status.OK, result.toJSONObject());
+
         } catch (FileNotFoundException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-            JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target);
-            return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
-        } catch (IllegalArgumentException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-            JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target);
+            JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target, conn);
+            Log.e(LOG_TAG, error.toString(), e);
             return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
-        } catch (SSLException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-            Log.d(LOG_TAG, "Got my ssl exception!!!");
-            JSONObject error = createFileTransferError(CONNECTION_ERR, source, target);
+        } catch (MalformedURLException e) {
+            JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, conn);
+            Log.e(LOG_TAG, error.toString(), e);
             return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
         } catch (IOException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-            JSONObject error = createFileTransferError(CONNECTION_ERR, source, target);
+            JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, conn);
+            Log.e(LOG_TAG, error.toString(), e);
             return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
         } catch (JSONException e) {
             Log.e(LOG_TAG, e.getMessage(), e);
             return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+        } catch (Throwable t) {
+            // Shouldn't happen, but will
+            JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, conn);
+            Log.wtf(LOG_TAG, error.toString(), t);
+            return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
+        } finally {
+            if (conn != null) {
+                conn.disconnect();
+            }
         }
     }
 
@@ -172,18 +374,36 @@ public class FileTransfer extends Plugin {
         }
     }
 
-    /**
-     * 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) {
+    private JSONObject createFileTransferError(int errorCode, String source, String target, HttpURLConnection connection) {
+
+        Integer httpStatus = null;
+
+        if (connection != null) {
+            try {
+                httpStatus = connection.getResponseCode();
+            } catch (IOException e) {
+                Log.w(LOG_TAG, "Error getting HTTP status code from connection.", e);
+            }
+        }
+
+        return createFileTransferError(errorCode, source, target, httpStatus);
+    }
+
+        /**
+        * 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, Integer httpStatus) {
         JSONObject error = null;
         try {
             error = new JSONObject();
             error.put("code", errorCode);
             error.put("source", source);
             error.put("target", target);
+            if (httpStatus != null) {
+                error.put("http_status", httpStatus);
+            }
         } catch (JSONException e) {
             Log.e(LOG_TAG, e.getMessage(), e);
         }
@@ -208,198 +428,6 @@ public class FileTransfer extends Plugin {
         return arg;
     }
 
-    /**
-     * Uploads the specified file to the server URL provided using an HTTP
-     * multipart request.
-     * @param file      Full path of the file on the file system
-     * @param server        URL of the server to receive the file
-     * @param fileKey       Name of file request parameter
-     * @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 file, String server, final String fileKey, final String fileName,
-            final String mimeType, JSONObject params, boolean trustEveryone, boolean chunkedMode) throws IOException, SSLException {
-        // Create return object
-        FileUploadResult result = new FileUploadResult();
-
-        // Get a input stream of the file on the phone
-        FileInputStream fileInputStream = (FileInputStream) getPathFromUri(file);
-
-        HttpURLConnection conn = null;
-        DataOutputStream dos = null;
-
-        int bytesRead, bytesAvailable, bufferSize;
-        long totalBytes;
-        byte[] buffer;
-        int maxBufferSize = 8096;
-
-        //------------------ CLIENT REQUEST
-        // open a URL connection to the server
-        URL url = new URL(server);
-
-        // Open a HTTP connection to the URL based on protocol
-        if (url.getProtocol().toLowerCase().equals("https")) {
-            // Using standard HTTPS connection. Will not allow self signed certificate
-            if (!trustEveryone) {
-                conn = (HttpsURLConnection) url.openConnection();
-            }
-            // Use our HTTPS connection that blindly trusts everyone.
-            // This should only be used in debug environments
-            else {
-                // Setup the HTTPS connection class to trust everyone
-                trustAllHosts();
-                HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
-                // Save the current hostnameVerifier
-                defaultHostnameVerifier = https.getHostnameVerifier();
-                // Setup the connection not to verify hostnames
-                https.setHostnameVerifier(DO_NOT_VERIFY);
-                conn = https;
-            }
-        }
-        // Return a standard HTTP connection
-        else {
-            conn = (HttpURLConnection) url.openConnection();
-        }
-
-        // Allow Inputs
-        conn.setDoInput(true);
-
-        // Allow Outputs
-        conn.setDoOutput(true);
-
-        // Don't use a cached copy.
-        conn.setUseCaches(false);
-
-        // Use a post method.
-        conn.setRequestMethod("POST");
-        conn.setRequestProperty("Connection", "Keep-Alive");
-        conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+BOUNDRY);
-
-        // Handle the other headers
-        try {
-          JSONObject headers = params.getJSONObject("headers");
-          for (Iterator iter = headers.keys(); iter.hasNext();)
-          {
-            String headerKey = iter.next().toString();
-            conn.setRequestProperty(headerKey, headers.getString(headerKey));
-          }
-        } catch (JSONException e1) {
-          // No headers to be manipulated!
-        }
-        
-        // Set the cookies on the response
-        String cookie = CookieManager.getInstance().getCookie(server);
-        if (cookie != null) {
-            conn.setRequestProperty("Cookie", cookie);
-        }
-        
-
-        /*
-         * Store the non-file portions of the multipart data as a string, so that we can add it 
-         * to the contentSize, since it is part of the body of the HTTP request.
-         */
-        String extraParams = "";
-        try {
-            for (Iterator iter = params.keys(); iter.hasNext();) {
-                Object key = iter.next();
-                if(key.toString() != "headers")
-                {
-                  extraParams += LINE_START + BOUNDRY + LINE_END;
-                  extraParams += "Content-Disposition: form-data; name=\"" +  key.toString() + "\";";
-                  extraParams += LINE_END + LINE_END;
-                  extraParams += params.getString(key.toString());
-                  extraParams += LINE_END;
-                }
-            }
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        
-        extraParams += LINE_START + BOUNDRY + LINE_END;
-        extraParams += "Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"";
-        
-        String midParams = "\"" + LINE_END + "Content-Type: " + mimeType + LINE_END + LINE_END;
-        String tailParams = LINE_END + LINE_START + BOUNDRY + LINE_START + LINE_END;
-        
-        // Should set this up as an option
-        if (chunkedMode) {
-            conn.setChunkedStreamingMode(maxBufferSize);
-        }
-        else
-        {
-          int stringLength = extraParams.length() + midParams.length() + tailParams.length() + fileName.getBytes("UTF-8").length;
-          Log.d(LOG_TAG, "String Length: " + stringLength);
-          int fixedLength = (int) fileInputStream.getChannel().size() + stringLength;
-          Log.d(LOG_TAG, "Content Length: " + fixedLength);
-          conn.setFixedLengthStreamingMode(fixedLength);
-        }
-        
-
-        dos = new DataOutputStream( conn.getOutputStream() );
-        dos.writeBytes(extraParams);
-        //We don't want to chagne encoding, we just want this to write for all Unicode.
-        dos.write(fileName.getBytes("UTF-8"));
-        dos.writeBytes(midParams);
-
-        // create a buffer of maximum size
-        bytesAvailable = fileInputStream.available();
-        bufferSize = Math.min(bytesAvailable, maxBufferSize);
-        buffer = new byte[bufferSize];
-
-        // read file and write it into form...
-        bytesRead = fileInputStream.read(buffer, 0, bufferSize);
-        totalBytes = 0;
-
-        while (bytesRead > 0) {
-            totalBytes += bytesRead;
-            result.setBytesSent(totalBytes);
-            dos.write(buffer, 0, bufferSize);
-            bytesAvailable = fileInputStream.available();
-            bufferSize = Math.min(bytesAvailable, maxBufferSize);
-            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
-        }
-
-        // send multipart form data necesssary after file data...
-        dos.writeBytes(tailParams);
-
-        // close streams
-        fileInputStream.close();
-        dos.flush();
-        dos.close();
-
-        //------------------ read the SERVER RESPONSE
-        StringBuffer responseString = new StringBuffer("");
-        DataInputStream inStream;
-        try {
-            inStream = new DataInputStream ( conn.getInputStream() );
-        } catch(FileNotFoundException e) {
-            throw new IOException("Received error from server");
-        }
-
-        String line;
-        while (( line = inStream.readLine()) != null) {
-            responseString.append(line);
-        }
-        Log.d(LOG_TAG, "got response from server");
-        Log.d(LOG_TAG, responseString.toString());
-
-        // send request and retrieve response
-        result.setResponseCode(conn.getResponseCode());
-        result.setResponse(responseString.toString());
-
-        inStream.close();
-        conn.disconnect();
-
-        // Revert back to the proper verifier and socket factories
-        if (trustEveryone && url.getProtocol().toLowerCase().equals("https")) {
-            ((HttpsURLConnection)conn).setHostnameVerifier(defaultHostnameVerifier);
-            HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSocketFactory);
-        }
-
-        return result;
-    }
 
     /**
      * Downloads a file form a given URL and saves it to the specified directory.
@@ -408,7 +436,10 @@ public class FileTransfer extends Plugin {
      * @param target      	Full path of the file on the file system
      * @return JSONObject 	the downloaded file
      */
-    public JSONObject download(String source, String target) throws IOException {
+    private PluginResult download(String source, String target) {
+        Log.d(LOG_TAG, "download " + source + " to " +  target);
+
+        HttpURLConnection connection = null;
         try {
             File file = getFileFromPath(target);
 
@@ -419,7 +450,7 @@ public class FileTransfer extends Plugin {
             if(this.ctx.isUrlWhiteListed(source))
             {
               URL url = new URL(source);
-              HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+              connection = (HttpURLConnection) url.openConnection();
               connection.setRequestMethod("GET");
               
               //Add cookie support
@@ -431,7 +462,7 @@ public class FileTransfer extends Plugin {
               
               connection.connect();
 
-              Log.d(LOG_TAG, "Download file:" + url);
+              Log.d(LOG_TAG, "Download file: " + url);
 
               InputStream inputStream = connection.getInputStream();
               byte[] buffer = new byte[1024];
@@ -450,23 +481,40 @@ public class FileTransfer extends Plugin {
 
               // create FileEntry object
               FileUtils fileUtil = new FileUtils();
+              JSONObject fileEntry = fileUtil.getEntry(file);
 
-              return fileUtil.getEntry(file);
+              return new PluginResult(PluginResult.Status.OK, fileEntry);
             }
             else
             {
-              throw new IOException("Error: Unable to connect to domain");
+                Log.w(LOG_TAG, "Source URL is not in white list: '" + source + "'");
+                JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, 401);
+                return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
+            }
+
+        } catch (FileNotFoundException e) {
+            JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target, connection);
+            Log.e(LOG_TAG, error.toString(), e);
+            return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
+        } catch (MalformedURLException e) {
+            JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, connection);
+            Log.e(LOG_TAG, error.toString(), e);
+            return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
+        } catch (Exception e) {  // IOException, JSONException, NullPointer
+            JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection);
+            Log.e(LOG_TAG, error.toString(), e);
+            return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
             }
-        } catch (Exception e) {
-            Log.d(LOG_TAG, e.getMessage(), e);
-            throw new IOException("Error while downloading");
         }
     }
 
     /**
      * Get an input stream based on file path or content:// uri
      *
-     * @param path
+     * @param path foo
      * @return an input stream
      * @throws FileNotFoundException
      */
@@ -491,14 +539,23 @@ public class FileTransfer extends Plugin {
     /**
      * Get a File object from the passed in path
      * 
-     * @param path
-     * @return
+     * @param path file path
+     * @return file object
      */
-    private File getFileFromPath(String path) {
-        if (path.startsWith("file://")) {
-            return new File(path.substring(7));
+    private File getFileFromPath(String path) throws FileNotFoundException {
+        File file;
+        String prefix = "file://";
+
+        if (path.startsWith(prefix)) {
+            file = new File(path.substring(prefix.length()));
         } else {
-            return new File(path);
+            file = new File(path);
+        }
+
+        if (file.getParent() == null) {
+            throw new FileNotFoundException();
         }
+
+        return file;
     }
 }