You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pu...@apache.org on 2013/05/09 08:16:52 UTC

[1/2] wp7 commit: Fixes for overlapping API calls - File API is passing a bunch more tests.

Updated Branches:
  refs/heads/master 9bdabf0af -> 4a79e5853


Fixes for overlapping API calls - File API is passing a bunch more tests.


Project: http://git-wip-us.apache.org/repos/asf/cordova-wp7/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-wp7/commit/21ecd2a3
Tree: http://git-wip-us.apache.org/repos/asf/cordova-wp7/tree/21ecd2a3
Diff: http://git-wip-us.apache.org/repos/asf/cordova-wp7/diff/21ecd2a3

Branch: refs/heads/master
Commit: 21ecd2a3ca58cc4b87ea0c988c06f664decaa13c
Parents: 9bdabf0
Author: Jesse MacFadyen <pu...@gmail.com>
Authored: Wed May 8 17:47:14 2013 -0700
Committer: Jesse MacFadyen <pu...@gmail.com>
Committed: Wed May 8 17:47:14 2013 -0700

----------------------------------------------------------------------
 templates/standalone/Plugins/File.cs               |  482 +++++++++------
 templates/standalone/Plugins/Notification.cs       |   63 ++-
 .../standalone/cordovalib/Commands/BaseCommand.cs  |   73 ++-
 .../standalone/cordovalib/CordovaCommandCall.cs    |   22 +-
 templates/standalone/cordovalib/NativeExecution.cs |   36 +-
 templates/standalone/cordovalib/PluginResult.cs    |    2 +
 6 files changed, 435 insertions(+), 243 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/21ecd2a3/templates/standalone/Plugins/File.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/Plugins/File.cs b/templates/standalone/Plugins/File.cs
index 62f8ab1..cde7a1c 100644
--- a/templates/standalone/Plugins/File.cs
+++ b/templates/standalone/Plugins/File.cs
@@ -14,12 +14,14 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.IO;
 using System.IO.IsolatedStorage;
 using System.Runtime.Serialization;
 using System.Security;
 using System.Text;
-using System.Diagnostics;
+using System.Windows;
+using System.Windows.Resources;
 
 namespace WPCordovaClassLib.Cordova.Commands
 {
@@ -233,19 +235,41 @@ namespace WPCordovaClassLib.Cordova.Commands
             {
                 using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
                 {
-                    if ((string.IsNullOrEmpty(filePath)) || (!isoFile.FileExists(filePath)))
+                    if (string.IsNullOrEmpty(filePath))
                     {
                         throw new FileNotFoundException("File doesn't exist");
                     }
-                    //TODO get file size the other way if possible                
-                    using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, FileAccess.Read, isoFile))
+                    else if (!isoFile.FileExists(filePath))
+                    {
+                        // attempt to get it from the resources
+                        if (filePath.IndexOf("www") == 0)
+                        {
+                            Uri fileUri = new Uri(filePath, UriKind.Relative);
+                            StreamResourceInfo streamInfo = Application.GetResourceStream(fileUri);
+                            if (streamInfo != null)
+                            {
+                                this.Size = streamInfo.Stream.Length;
+                                this.FileName = filePath.Substring(filePath.LastIndexOf("/") + 1);
+                                this.FullPath = filePath;
+                            }
+                        }
+                        else
+                        {
+                            throw new FileNotFoundException("File doesn't exist");
+                        }
+                    }
+                    else
                     {
-                        this.Size = stream.Length;
+                        //TODO get file size the other way if possible                
+                        using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, FileAccess.Read, isoFile))
+                        {
+                            this.Size = stream.Length;
+                        }
+                        this.FullPath = filePath;
+                        this.FileName = System.IO.Path.GetFileName(filePath);
+                        this.LastModifiedDate = isoFile.GetLastWriteTime(filePath).DateTime.ToString();
                     }
-                    this.FullPath = filePath;
-                    this.FileName = System.IO.Path.GetFileName(filePath);
-                    this.Type = MimeTypeMapper.GetMimeType(filePath);
-                    this.LastModifiedDate = isoFile.GetLastWriteTime(filePath).DateTime.ToString();
+                    this.Type = MimeTypeMapper.GetMimeType(this.FileName);
                 }
             }
         }
@@ -294,12 +318,14 @@ namespace WPCordovaClassLib.Cordova.Commands
             [DataMember(Name = "fullPath")]
             public string FullPath { get; set; }
 
-            public static FileEntry GetEntry(string filePath)
+            public bool IsResource { get; set; }
+
+            public static FileEntry GetEntry(string filePath, bool bIsRes=false)
             {
                 FileEntry entry = null;
                 try
                 {
-                    entry = new FileEntry(filePath);
+                    entry = new FileEntry(filePath, bIsRes);
 
                 }
                 catch (Exception ex)
@@ -313,7 +339,7 @@ namespace WPCordovaClassLib.Cordova.Commands
             /// Creates object and sets necessary properties
             /// </summary>
             /// <param name="filePath"></param>
-            public FileEntry(string filePath)
+            public FileEntry(string filePath, bool bIsRes = false)
             {
                 if (string.IsNullOrEmpty(filePath))
                 {
@@ -327,8 +353,9 @@ namespace WPCordovaClassLib.Cordova.Commands
 
                 using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
                 {
-                    this.IsFile = isoFile.FileExists(filePath);
-                    this.IsDirectory = isoFile.DirectoryExists(filePath);
+                    IsResource = bIsRes;
+                    IsFile = isoFile.FileExists(filePath);
+                    IsDirectory = isoFile.DirectoryExists(filePath);
                     if (IsFile)
                     {
                         this.Name = Path.GetFileName(filePath);
@@ -343,7 +370,14 @@ namespace WPCordovaClassLib.Cordova.Commands
                     }
                     else
                     {
-                        throw new FileNotFoundException();
+                        if (IsResource)
+                        {
+                            this.Name = Path.GetFileName(filePath);
+                        }
+                        else
+                        {
+                            throw new FileNotFoundException();
+                        }
                     }
 
                     try
@@ -431,38 +465,19 @@ namespace WPCordovaClassLib.Cordova.Commands
 
         }
 
-        /// <summary>
-        /// File options
-        /// </summary>
-        private FileOptions fileOptions;
-
-        private bool LoadFileOptions(string options)
-        {
-            try
-            {
-                fileOptions = JSON.JsonHelper.Deserialize<FileOptions>(options);
-            }
-            catch (Exception)
-            {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
-                return false;
-            }
-            return true;
-        }
-
         // returns null value if it fails.
-        private string getSingleStringOption(string options)
+        private string[] getOptionStrings(string options)
         {
-            string result = null;
+            string[] optStings = null;
             try
             {
-                result = JSON.JsonHelper.Deserialize<string[]>(options)[0];
+                optStings = JSON.JsonHelper.Deserialize<string[]>(options);
             }
             catch (Exception)
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), CurrentCommandCallbackId);
             }
-            return result;
+            return optStings;
         }
 
         /// <summary>
@@ -471,22 +486,24 @@ namespace WPCordovaClassLib.Cordova.Commands
         /// <param name="options">No options is needed for this method</param>
         public void getFreeDiskSpace(string options)
         {
+            string callbackId = getOptionStrings(options)[0];
+
             try
             {
                 using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isoFile.AvailableFreeSpace));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isoFile.AvailableFreeSpace), callbackId);
                 }
             }
             catch (IsolatedStorageException)
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
             }
             catch (Exception ex)
             {
                 if (!this.HandleException(ex))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
                 }
             }
         }
@@ -516,9 +533,14 @@ namespace WPCordovaClassLib.Cordova.Commands
         /// <param name="isDirectory">Flag to recognize what we should check</param>
         public void IsDirectoryOrFileExist(string options, bool isDirectory)
         {
-            if (!LoadFileOptions(options))
+            string[] args = getOptionStrings(options);
+            string callbackId = args[1];
+            FileOptions fileOptions = JSON.JsonHelper.Deserialize<FileOptions>(args[0]);
+            string filePath = args[0];
+
+            if (fileOptions == null)
             {
-                return;
+                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
             }
 
             try
@@ -534,18 +556,18 @@ namespace WPCordovaClassLib.Cordova.Commands
                     {
                         isExist = isoFile.FileExists(fileOptions.FilePath);
                     }
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isExist));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isExist), callbackId);
                 }
             }
             catch (IsolatedStorageException) // default handler throws INVALID_MODIFICATION_ERR
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
             }
             catch (Exception ex)
             {
                 if (!this.HandleException(ex))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                 }
             }
 
@@ -553,8 +575,12 @@ namespace WPCordovaClassLib.Cordova.Commands
 
         public void readAsDataURL(string options)
         {
-            // exception+PluginResult are handled by getSingleStringOptions 
-            string filePath = getSingleStringOption(options);
+            string[] optStrings = getOptionStrings(options);
+            string filePath = optStrings[0];
+            int startPos = int.Parse(optStrings[1]);
+            int endPos = int.Parse(optStrings[2]);
+            string callbackId = optStrings[3];
+
             if (filePath != null)
             {
                 try
@@ -565,7 +591,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                     {
                         if (!isoFile.FileExists(filePath))
                         {
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                             return;
                         }
                         string mimeType = MimeTypeMapper.GetMimeType(filePath);
@@ -577,35 +603,56 @@ namespace WPCordovaClassLib.Cordova.Commands
                         }
                     }
 
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, base64URL));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, base64URL), callbackId);
                 }
                 catch (Exception ex)
                 {
                     if (!this.HandleException(ex))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
                     }
                 }
             }
         }
 
+        public void readAsArrayBuffer(string options)
+        {
+            string[] optStrings = getOptionStrings(options);
+            string filePath = optStrings[0];
+            int startPos = int.Parse(optStrings[1]);
+            int endPos = int.Parse(optStrings[2]);
+            string callbackId = optStrings[3];
+            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR), callbackId);
+        }
+
+        public void readAsBinaryString(string options)
+        {
+            string[] optStrings = getOptionStrings(options);
+            string filePath = optStrings[0];
+            int startPos = int.Parse(optStrings[1]);
+            int endPos = int.Parse(optStrings[2]);
+            string callbackId = optStrings[3];
+            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR), callbackId);
+        }
+
         public void readAsText(string options)
         {
-            // TODO: try/catch
-            string[] optStrings = JSON.JsonHelper.Deserialize<string[]>(options);
+            string[] optStrings = getOptionStrings(options);
             string filePath = optStrings[0];
             string encStr = optStrings[1];
-
+            int startPos = int.Parse(optStrings[2]);
+            int endPos = int.Parse(optStrings[3]);
+            string callbackId = optStrings[4];
 
             try
             {
-                string text;
+                string text = "";
 
                 using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
                 {
                     if (!isoFile.FileExists(filePath))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        readResourceAsText(options);
                         return;
                     }
                     Encoding encoding = Encoding.GetEncoding(encStr);
@@ -613,16 +660,37 @@ namespace WPCordovaClassLib.Cordova.Commands
                     using (TextReader reader = new StreamReader(isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read), encoding))
                     {
                         text = reader.ReadToEnd();
+                        if (startPos < 0)
+                        {
+                            startPos = Math.Max(text.Length + startPos, 0);
+                        }
+                        else if (startPos > 0)
+                        {
+                            startPos = Math.Min(text.Length, startPos);
+                        }
+
+                        if (endPos > 0)
+                        {
+                            endPos = Math.Min(text.Length, endPos);
+                        }
+                        else if (endPos < 0)
+                        {
+                            endPos = Math.Max(endPos + text.Length, 0);
+                        }
+                        
+                        
+                        text = text.Substring(startPos, endPos - startPos);
+                        
                     }
                 }
 
-                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, text));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, text), callbackId);
             }
             catch (Exception ex)
             {
-                if (!this.HandleException(ex))
+                if (!this.HandleException(ex, callbackId))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
                 }
             }
         }
@@ -633,18 +701,13 @@ namespace WPCordovaClassLib.Cordova.Commands
         /// <param name="options">Path to a resource</param>
         public void readResourceAsText(string options)
         {
-            string pathToResource;
-            try 
-            {
-                string[] optStrings = JSON.JsonHelper.Deserialize<string[]>(options);
-                pathToResource = optStrings[0];
-            }
-            catch (Exception)
-            {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
-                return;
-            }
-            
+            string[] optStrings = getOptionStrings(options);
+            string pathToResource = optStrings[0];
+            string encStr = optStrings[1];
+            int start = int.Parse(optStrings[2]);
+            int endMarker = int.Parse(optStrings[3]);
+            string callbackId = optStrings[4];
+
             try
             {
                 if (pathToResource.StartsWith("/"))
@@ -652,36 +715,36 @@ namespace WPCordovaClassLib.Cordova.Commands
                     pathToResource = pathToResource.Remove(0, 1);
                 }
                 
-                var resource = System.Windows.Application.GetResourceStream(new Uri(pathToResource, UriKind.Relative));
+                var resource = Application.GetResourceStream(new Uri(pathToResource, UriKind.Relative));
                 
                 if (resource == null)
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                     return;
                 }
 
                 string text;
                 StreamReader streamReader = new StreamReader(resource.Stream);
                 text = streamReader.ReadToEnd();
-                
-                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, text));
+
+                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, text), callbackId);
             }
             catch (Exception ex)
             {
-                if (!this.HandleException(ex))
+                if (!this.HandleException(ex, callbackId))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
                 }
             }
         }
 
         public void truncate(string options)
         {
-            // TODO: try/catch
-            string[] optStrings = JSON.JsonHelper.Deserialize<string[]>(options);
+            string[] optStrings = getOptionStrings(options);
 
             string filePath = optStrings[0];
             int size = int.Parse(optStrings[1]);
+            string callbackId = optStrings[2];
 
             try
             {
@@ -691,7 +754,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                 {
                     if (!isoFile.FileExists(filePath))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                         return;
                     }
 
@@ -701,18 +764,17 @@ namespace WPCordovaClassLib.Cordova.Commands
                         {
                             stream.SetLength(size);
                         }
-
                         streamLength = stream.Length;
                     }
                 }
 
-                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, streamLength));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, streamLength), callbackId);
             }
             catch (Exception ex)
             {
-                if (!this.HandleException(ex))
+                if (!this.HandleException(ex, callbackId))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
                 }
             }
         }
@@ -721,18 +783,19 @@ namespace WPCordovaClassLib.Cordova.Commands
         public void write(string options)
         {
             // TODO: try/catch
-            string[] optStrings = JSON.JsonHelper.Deserialize<string[]>(options);
+            string[] optStrings = getOptionStrings(options);
 
             string filePath = optStrings[0];
             string data = optStrings[1];
             int position = int.Parse(optStrings[2]);
+            string callbackId = optStrings[3];
 
             try
             {
                 if (string.IsNullOrEmpty(data))
                 {
                     Debug.WriteLine("Expected some data to be send in the write command to {0}", filePath);
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
                     return;
                 }
 
@@ -759,13 +822,13 @@ namespace WPCordovaClassLib.Cordova.Commands
                     }
                 }
 
-                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, data.Length));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, data.Length), callbackId);
             }
             catch (Exception ex)
             {
-                if (!this.HandleException(ex))
+                if (!this.HandleException(ex, callbackId))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
                 }
             }
         }
@@ -776,7 +839,9 @@ namespace WPCordovaClassLib.Cordova.Commands
         /// <param name="options">filePath to entry</param>   
         public void getMetadata(string options)
         {
-            string filePath = getSingleStringOption(options);
+            string[] optStings = getOptionStrings(options);
+            string filePath = optStings[0];
+            string callbackId = optStings[1];
 
             if (filePath != null)
             {
@@ -787,29 +852,29 @@ namespace WPCordovaClassLib.Cordova.Commands
                         if (isoFile.FileExists(filePath))
                         {
                             DispatchCommandResult(new PluginResult(PluginResult.Status.OK,
-                                new ModificationMetadata() { modificationTime = isoFile.GetLastWriteTime(filePath).DateTime.ToString() }));
+                                new ModificationMetadata() { modificationTime = isoFile.GetLastWriteTime(filePath).DateTime.ToString() }), callbackId);
                         }
                         else if (isoFile.DirectoryExists(filePath))
                         {
                             string modTime = isoFile.GetLastWriteTime(filePath).DateTime.ToString();
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new ModificationMetadata() { modificationTime = modTime }));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new ModificationMetadata() { modificationTime = modTime }), callbackId);
                         }
                         else
                         {
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                         }
 
                     }
                 }
                 catch (IsolatedStorageException)
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
                 }
                 catch (Exception ex)
                 {
                     if (!this.HandleException(ex))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
                     }
                 }
             }
@@ -824,23 +889,26 @@ namespace WPCordovaClassLib.Cordova.Commands
         /// <returns></returns>
         public void getFileMetadata(string options)
         {
-            string filePath = getSingleStringOption(options);
+            string[] optStings = getOptionStrings(options);
+            string filePath = optStings[0];
+            string callbackId = optStings[1];
+
             if (filePath != null)
             {
                 try
                 {
                     FileMetadata metaData = new FileMetadata(filePath);
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, metaData));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, metaData), callbackId);
                 }
                 catch (IsolatedStorageException)
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
                 }
                 catch (Exception ex)
                 {
                     if (!this.HandleException(ex))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
                     }
                 }
             }
@@ -853,14 +921,17 @@ namespace WPCordovaClassLib.Cordova.Commands
         /// <param name="options"></param>
         public void getParent(string options)
         {
-            string filePath = getSingleStringOption(options);
+            string[] optStings = getOptionStrings(options);
+            string filePath = optStings[0];
+            string callbackId = optStings[1];
+
             if (filePath != null)
             {
                 try
                 {
                     if (string.IsNullOrEmpty(filePath))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION),callbackId);
                         return;
                     }
 
@@ -874,11 +945,11 @@ namespace WPCordovaClassLib.Cordova.Commands
                              
                             string path = this.GetParentDirectory(filePath);
                             entry = FileEntry.GetEntry(path);
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry),callbackId);
                         }
                         else
                         {
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR),callbackId);
                         }
 
                     }
@@ -887,7 +958,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                 {
                     if (!this.HandleException(ex))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR),callbackId);
                     }
                 }
             }
@@ -895,7 +966,10 @@ namespace WPCordovaClassLib.Cordova.Commands
 
         public void remove(string options)
         {
-            string filePath = getSingleStringOption(options);
+            string[] args = getOptionStrings(options);
+            string filePath = args[0];
+            string callbackId = args[1];
+
             if (filePath != null)
             {
                 try
@@ -918,18 +992,18 @@ namespace WPCordovaClassLib.Cordova.Commands
                             }
                             else
                             {
-                                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR),callbackId);
                                 return;
                             }
                         }
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK),callbackId);
                     }
                 }
                 catch (Exception ex)
                 {
                     if (!this.HandleException(ex))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR),callbackId);
                     }
                 }
             }
@@ -937,31 +1011,39 @@ namespace WPCordovaClassLib.Cordova.Commands
 
         public void removeRecursively(string options)
         {
-            string filePath = getSingleStringOption(options);
+            string[] args = getOptionStrings(options);
+            string filePath = args[0];
+            string callbackId = args[1];
+
             if (filePath != null)
             {
                 if (string.IsNullOrEmpty(filePath))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION),callbackId);
                 }
                 else
                 {
-                    removeDirRecursively(filePath);
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
+                    if (removeDirRecursively(filePath, callbackId))
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId);
+                    }
                 }
             }
         }
 
         public void readEntries(string options)
         {
-            string filePath = getSingleStringOption(options);
+            string[] args = getOptionStrings(options);
+            string filePath = args[0];
+            string callbackId = args[1];
+
             if (filePath != null)
             {
                 try
                 {
                     if (string.IsNullOrEmpty(filePath))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION),callbackId);
                         return;
                     }
 
@@ -981,11 +1063,11 @@ namespace WPCordovaClassLib.Cordova.Commands
                             {
                                 entries.Add(FileEntry.GetEntry(path + dir + "/"));
                             }
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entries));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entries),callbackId);
                         }
                         else
                         {
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR),callbackId);
                         }
                     }
                 }
@@ -993,7 +1075,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                 {
                     if (!this.HandleException(ex))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR),callbackId);
                     }
                 }
             }
@@ -1002,16 +1084,18 @@ namespace WPCordovaClassLib.Cordova.Commands
         public void requestFileSystem(string options)
         {
             // TODO: try/catch
-            double[] optVals = JSON.JsonHelper.Deserialize<double[]>(options);
+            string[] optVals = getOptionStrings(options);
+            //FileOptions fileOptions = new FileOptions();
+            int fileSystemType = int.Parse(optVals[0]);
+            double size = double.Parse(optVals[1]);
+            string callbackId = optVals[2];
 
-            double fileSystemType = optVals[0];
-            double size = optVals[1];
 
             IsolatedStorageFile.GetUserStoreForApplication();
 
-            if (size > (10 * 1024 * 1024)) // 10 MB, compiler will clean this up!
+            if (size > (10 * 1024 * 1024)) // 10 MB, compier will clean this up!
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, QUOTA_EXCEEDED_ERR));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, QUOTA_EXCEEDED_ERR), callbackId);
                 return;
             }
 
@@ -1024,7 +1108,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                         long availableSize = isoFile.AvailableFreeSpace;
                         if (size > availableSize)
                         {
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, QUOTA_EXCEEDED_ERR));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, QUOTA_EXCEEDED_ERR), callbackId);
                             return;
                         }
                     }
@@ -1033,7 +1117,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                 if (fileSystemType == PERSISTENT)
                 {
                     // TODO: this should be in it's own folder to prevent overwriting of the app assets, which are also in ISO
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("persistent", FileEntry.GetEntry("/"))));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("persistent", FileEntry.GetEntry("/"))), callbackId);
                 }
                 else if (fileSystemType == TEMPORARY)
                 {
@@ -1047,19 +1131,19 @@ namespace WPCordovaClassLib.Cordova.Commands
 
                     string tmpFolder = "/" + TMP_DIRECTORY_NAME + "/";
 
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("temporary", FileEntry.GetEntry(tmpFolder))));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("temporary", FileEntry.GetEntry(tmpFolder))), callbackId);
                 }
-                else if (fileOptions.FileSystemType == RESOURCE)
+                else if (fileSystemType == RESOURCE)
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("resource")));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("resource")), callbackId);
                 }
-                else if (fileOptions.FileSystemType == APPLICATION)
+                else if (fileSystemType == APPLICATION)
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("application")));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("application")), callbackId);
                 }
                 else
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR), callbackId);
                 }
 
             }
@@ -1067,22 +1151,24 @@ namespace WPCordovaClassLib.Cordova.Commands
             {
                 if (!this.HandleException(ex))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR), callbackId);
                 }
             }
         }
 
         public void resolveLocalFileSystemURI(string options)
         {
-            string uri = getSingleStringOption(options).Split('?')[0];
+
+            string[] optVals = getOptionStrings(options);
+            string uri = optVals[0].Split('?')[0];
+            string callbackId = optVals[1];
 
             if (uri != null)
             {
                 // a single '/' is valid, however, '/someDir' is not, but '/tmp//somedir' and '///someDir' are valid
                 if (uri.StartsWith("/") && uri.IndexOf("//") < 0 && uri != "/")
                 {
-                     Debug.WriteLine("Starts with / ::: " + uri);
-                     DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR));
+                     DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR), callbackId);
                      return;
                 }
                 try
@@ -1093,18 +1179,18 @@ namespace WPCordovaClassLib.Cordova.Commands
                     FileEntry uriEntry = FileEntry.GetEntry(path);
                     if (uriEntry != null)
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, uriEntry));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, uriEntry), callbackId);
                     }
                     else
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                     }
                 }
                 catch (Exception ex)
                 {
-                    if (!this.HandleException(ex))
+                    if (!this.HandleException(ex, callbackId))
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR), callbackId);
                     }
                 }
             }
@@ -1158,14 +1244,14 @@ namespace WPCordovaClassLib.Cordova.Commands
             return result;
         }
 
-        private void removeDirRecursively(string fullPath)
+        private bool removeDirRecursively(string fullPath,string callbackId)
         {
             try
             {
                 if (fullPath == "/")
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
-                    return;
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR),callbackId);
+                    return false;
                 }
 
                 using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
@@ -1186,14 +1272,17 @@ namespace WPCordovaClassLib.Cordova.Commands
                         {
                             foreach (string dir in dirs)
                             {
-                                removeDirRecursively(tempPath + dir);
+                                if (!removeDirRecursively(tempPath + dir, callbackId))
+                                {
+                                    return false;
+                                }
                             }
                         }
                         isoFile.DeleteDirectory(fullPath);
                     }
                     else
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR),callbackId);
                     }
                 }
             }
@@ -1201,9 +1290,11 @@ namespace WPCordovaClassLib.Cordova.Commands
             {
                 if (!this.HandleException(ex))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR),callbackId);
+                    return false;
                 }
             }
+            return true;
         }
 
         private bool CanonicalCompare(string pathA, string pathB)
@@ -1221,16 +1312,17 @@ namespace WPCordovaClassLib.Cordova.Commands
         private void TransferTo(string options, bool move)
         {
             // TODO: try/catch
-            string[] optStrings = JSON.JsonHelper.Deserialize<string[]>(options);
+            string[] optStrings = getOptionStrings(options);
             string fullPath = optStrings[0];
             string parent = optStrings[1];
             string newFileName = optStrings[2];
+            string callbackId = optStrings[3];
 
             char[] invalids = Path.GetInvalidPathChars();
             
             if (newFileName.IndexOfAny(invalids) > -1 || newFileName.IndexOf(":") > -1 )
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR), callbackId);
                 return;
             }
 
@@ -1238,7 +1330,7 @@ namespace WPCordovaClassLib.Cordova.Commands
             {
                 if ((parent == null) || (string.IsNullOrEmpty(parent)) || (string.IsNullOrEmpty(fullPath)))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                     return;
                 }
 
@@ -1253,7 +1345,7 @@ namespace WPCordovaClassLib.Cordova.Commands
 
                     if ( ( !isFileExist && !isDirectoryExist ) || !isParentExist )
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                         return;
                     }
                     string newName;
@@ -1270,13 +1362,13 @@ namespace WPCordovaClassLib.Cordova.Commands
                         // cannot copy file onto itself
                         if (CanonicalCompare(newPath,currentPath)) //(parent + newFileName))
                         {
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_MODIFICATION_ERR));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_MODIFICATION_ERR), callbackId);
                             return;
                         }
                         else if (isoFile.DirectoryExists(newPath)) 
                         {
                             // there is already a folder with the same name, operation is not allowed
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_MODIFICATION_ERR));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_MODIFICATION_ERR), callbackId);
                             return;
                         }
                         else if (isoFile.FileExists(newPath))
@@ -1320,50 +1412,51 @@ namespace WPCordovaClassLib.Cordova.Commands
                     FileEntry entry = FileEntry.GetEntry(newPath);
                     if (entry != null)
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry), callbackId);
                     }
                     else
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                     }
                 }
 
             }
             catch (Exception ex)
             {
-                if (!this.HandleException(ex))
+                if (!this.HandleException(ex, callbackId))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR), callbackId);
                 }
             }
         }
 
-        private bool HandleException(Exception ex)
+        private bool HandleException(Exception ex, string cbId="")
         {
             bool handled = false;
+            string callbackId = String.IsNullOrEmpty(cbId) ? this.CurrentCommandCallbackId : cbId;
             if (ex is SecurityException)
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR), callbackId);
                 handled = true;
             }
             else if (ex is FileNotFoundException)
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                 handled = true;
             }
             else if (ex is ArgumentException)
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR), callbackId);
                 handled = true;
             }
             else if (ex is IsolatedStorageException)
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_MODIFICATION_ERR));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_MODIFICATION_ERR), callbackId);
                 handled = true;
             }
             else if (ex is DirectoryNotFoundException)
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                 handled = true;
             }
             return handled;
@@ -1404,17 +1497,20 @@ namespace WPCordovaClassLib.Cordova.Commands
         private void GetFileOrDirectory(string options, bool getDirectory)
         {
             FileOptions fOptions = new FileOptions();
+            string[] args = getOptionStrings(options);
+
+            fOptions.FullPath = args[0];
+            fOptions.Path = args[1];
+
+            string callbackId = args[3];
+
             try
             {
-                string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
-
-                fOptions.FullPath = args[0];
-                fOptions.Path = args[1];
                 fOptions.CreatingOpt = JSON.JsonHelper.Deserialize<CreatingOptions>(args[2]);
             }
             catch (Exception)
             {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
                 return;
             }
 
@@ -1422,7 +1518,7 @@ namespace WPCordovaClassLib.Cordova.Commands
             {
                 if ((string.IsNullOrEmpty(fOptions.Path)) || (string.IsNullOrEmpty(fOptions.FullPath)))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                     return;
                 }
 
@@ -1430,7 +1526,7 @@ namespace WPCordovaClassLib.Cordova.Commands
 
                 if (fOptions.Path.Split(':').Length > 2)
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR), callbackId);
                     return;
                 }
 
@@ -1440,9 +1536,9 @@ namespace WPCordovaClassLib.Cordova.Commands
                 }
                 catch (Exception)
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR), callbackId);
                     return;
-                }
+                }        
 
                 using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
                 {
@@ -1454,14 +1550,13 @@ namespace WPCordovaClassLib.Cordova.Commands
                     {
                         if (exclusive && (isoFile.FileExists(path) || isoFile.DirectoryExists(path)))
                         {
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, PATH_EXISTS_ERR));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, PATH_EXISTS_ERR), callbackId);
                             return;
                         }
 
-
                         // need to make sure the parent exists
                         // it is an error to create a directory whose immediate parent does not yet exist
-			// see issue: https://issues.apache.org/jira/browse/CB-339
+			            // see issue: https://issues.apache.org/jira/browse/CB-339
                         string[] pathParts = path.Split('/');
                         string builtPath = pathParts[0];
                         for (int n = 1; n < pathParts.Length - 1; n++)
@@ -1470,7 +1565,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                             if (!isoFile.DirectoryExists(builtPath))
                             {
                                 Debug.WriteLine(String.Format("Error :: Parent folder \"{0}\" does not exist, when attempting to create \"{1}\"",builtPath,path));
-                                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                                 return;
                             }
                         }
@@ -1489,27 +1584,54 @@ namespace WPCordovaClassLib.Cordova.Commands
                             }
                         }
                     }
-                    else
+                    else // (not create)
                     {
                         if ((!isFile) && (!isDirectory))
                         {
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                            if (path.IndexOf("//www") == 0)
+                            {
+                                Uri fileUri = new Uri(path.Remove(0,2), UriKind.Relative);
+                                StreamResourceInfo streamInfo = Application.GetResourceStream(fileUri);
+                                if (streamInfo != null)
+                                {
+                                    FileEntry _entry = FileEntry.GetEntry(fileUri.OriginalString,true);
+
+                                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, _entry), callbackId);
+
+                                    //using (BinaryReader br = new BinaryReader(streamInfo.Stream))
+                                    //{
+                                    //    byte[] data = br.ReadBytes((int)streamInfo.Stream.Length);
+                                   
+                                    //}
+
+                                }
+                                else
+                                {
+                                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
+                                }
+
+
+                            }
+                            else
+                            {
+                                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
+                            }
                             return;
                         }
                         if (((getDirectory) && (!isDirectory)) || ((!getDirectory) && (!isFile)))
                         {
-                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, TYPE_MISMATCH_ERR));
+                            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, TYPE_MISMATCH_ERR), callbackId);
                             return;
                         }
                     }
                     FileEntry entry = FileEntry.GetEntry(path);
                     if (entry != null)
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry), callbackId);
                     }
                     else
                     {
-                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR));
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
                     }
                 }
             }
@@ -1517,7 +1639,7 @@ namespace WPCordovaClassLib.Cordova.Commands
             {
                 if (!this.HandleException(ex))
                 {
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR));
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR), callbackId);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/21ecd2a3/templates/standalone/Plugins/Notification.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/Plugins/Notification.cs b/templates/standalone/Plugins/Notification.cs
index 58aaf43..11f14bd 100644
--- a/templates/standalone/Plugins/Notification.cs
+++ b/templates/standalone/Plugins/Notification.cs
@@ -22,6 +22,7 @@ using System.Windows.Resources;
 using Microsoft.Phone.Controls;
 using Microsoft.Xna.Framework.Audio;
 using WPCordovaClassLib.Cordova.UI;
+using System.Diagnostics;
 
 
 namespace WPCordovaClassLib.Cordova.Commands
@@ -33,6 +34,12 @@ namespace WPCordovaClassLib.Cordova.Commands
 
         private NotificationBox notifyBox;
 
+        private class NotifBoxData
+        {
+            public NotificationBox previous;
+            public string callbackId;
+        }
+
         private PhoneApplicationPage Page
         {
             get
@@ -48,7 +55,7 @@ namespace WPCordovaClassLib.Cordova.Commands
         }
 
         // blink api - doesn't look like there is an equivalent api we can use...
-        
+
         [DataContract]
         public class AlertOptions
         {
@@ -82,14 +89,15 @@ namespace WPCordovaClassLib.Cordova.Commands
 
         public void alert(string options)
         {
+            string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
+            AlertOptions alertOpts = new AlertOptions();
+            alertOpts.message = args[0];
+            alertOpts.title = args[1];
+            alertOpts.buttonLabel = args[2];
+            string aliasCurrentCommandCallbackId = args[3];
+
             Deployment.Current.Dispatcher.BeginInvoke(() =>
             {
-                string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
-                AlertOptions alertOpts = new AlertOptions();
-                alertOpts.message = args[0];
-                alertOpts.title = args[1];
-                alertOpts.buttonLabel = args[2];
-
                 PhoneApplicationPage page = Page;
                 if (page != null)
                 {
@@ -98,7 +106,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                     {
                         var previous = notifyBox;
                         notifyBox = new NotificationBox();
-                        notifyBox.Tag = previous;
+                        notifyBox.Tag = new NotifBoxData{ previous = previous, callbackId = aliasCurrentCommandCallbackId };
                         notifyBox.PageTitle.Text = alertOpts.title;
                         notifyBox.SubTitle.Text = alertOpts.message;
                         Button btnOK = new Button();
@@ -123,14 +131,15 @@ namespace WPCordovaClassLib.Cordova.Commands
 
         public void confirm(string options)
         {
+            string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
+            AlertOptions alertOpts = new AlertOptions();
+            alertOpts.message = args[0];
+            alertOpts.title = args[1];
+            alertOpts.buttonLabel = args[2];
+            string aliasCurrentCommandCallbackId = args[3];
+
             Deployment.Current.Dispatcher.BeginInvoke(() =>
             {
-                string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
-                AlertOptions alertOpts = new AlertOptions();
-                alertOpts.message = args[0];
-                alertOpts.title = args[1];
-                alertOpts.buttonLabel = args[2];
-
                 PhoneApplicationPage page = Page;
                 if (page != null)
                 {
@@ -139,7 +148,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                     {
                         var previous = notifyBox;
                         notifyBox = new NotificationBox();
-                        notifyBox.Tag = previous; 
+                        notifyBox.Tag = new NotifBoxData{ previous = previous, callbackId = aliasCurrentCommandCallbackId };
                         notifyBox.PageTitle.Text = alertOpts.title;
                         notifyBox.SubTitle.Text = alertOpts.message;
 
@@ -149,6 +158,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                         {
                             labels = alertOpts.buttonLabel.Split(',');
                         }
+
                         for (int n = 0; n < labels.Length; n++)
                         {
                             Button btn = new Button();
@@ -175,14 +185,16 @@ namespace WPCordovaClassLib.Cordova.Commands
         void page_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
         {
             PhoneApplicationPage page = sender as PhoneApplicationPage;
-
+            string callbackId = "";
             if (page != null && notifyBox != null)
             {
                 Grid grid = page.FindName("LayoutRoot") as Grid;
                 if (grid != null)
                 {
                     grid.Children.Remove(notifyBox);
-                    notifyBox = notifyBox.Tag as NotificationBox;
+                    NotifBoxData notifBoxData = notifyBox.Tag as NotifBoxData;
+                    notifyBox = notifBoxData.previous;
+                    callbackId = notifBoxData.callbackId;
                 }
                 if (notifyBox == null)
                 {
@@ -191,7 +203,7 @@ namespace WPCordovaClassLib.Cordova.Commands
                 e.Cancel = true;
             }
 
-            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, 0));
+            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, 0), callbackId);
         }
 
         void btnOK_Click(object sender, RoutedEventArgs e)
@@ -199,13 +211,14 @@ namespace WPCordovaClassLib.Cordova.Commands
             Button btn = sender as Button;
             FrameworkElement notifBoxParent = null;
             int retVal = 0;
+            string callbackId = "";
             if (btn != null)
             {
                 retVal = (int)btn.Tag + 1;
 
                 notifBoxParent = btn.Parent as FrameworkElement;
                 while ((notifBoxParent = notifBoxParent.Parent as FrameworkElement) != null &&
-                       !(notifBoxParent is NotificationBox));
+                       !(notifBoxParent is NotificationBox)) ;
             }
             if (notifBoxParent != null)
             {
@@ -217,15 +230,19 @@ namespace WPCordovaClassLib.Cordova.Commands
                     {
                         grid.Children.Remove(notifBoxParent);
                     }
-                    notifyBox = notifBoxParent.Tag as NotificationBox;
+
+                    NotifBoxData notifBoxData = notifBoxParent.Tag as NotifBoxData;
+                    notifyBox = notifBoxData.previous;
+                    callbackId = notifBoxData.callbackId;
+
                     if (notifyBox == null)
                     {
                         page.BackKeyPress -= page_BackKeyPress;
                     }
                 }
-                
+
             }
-            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, retVal));
+            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, retVal),callbackId);
         }
 
 
@@ -323,7 +340,7 @@ namespace WPCordovaClassLib.Cordova.Commands
 
         public void vibrate(string vibrateDuration)
         {
-            
+
             int msecs = 200; // set default
 
             try

http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/21ecd2a3/templates/standalone/cordovalib/Commands/BaseCommand.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/Commands/BaseCommand.cs b/templates/standalone/cordovalib/Commands/BaseCommand.cs
index 237b72a..ac1d2d6 100644
--- a/templates/standalone/cordovalib/Commands/BaseCommand.cs
+++ b/templates/standalone/cordovalib/Commands/BaseCommand.cs
@@ -16,13 +16,15 @@ using System;
 using System.Reflection;
 using Microsoft.Phone.Shell;
 using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
 
 namespace WPCordovaClassLib.Cordova.Commands
 {
     public abstract class BaseCommand : IDisposable
     {
         /*
-         *  All commands + plugins must extend BaseCommand, because they are dealt with as BaseCommands in PGView.xaml.cs
+         *  All commands + plugins must extend BaseCommand, because they are dealt with as BaseCommands in CordovaView.xaml.cs
          *  
          **/
 
@@ -30,17 +32,37 @@ namespace WPCordovaClassLib.Cordova.Commands
 
         public event EventHandler<ScriptCallback> OnCustomScript;
 
+        public string CurrentCommandCallbackId { get; set; }
+
         public BaseCommand()
         {
+            ResultHandlers = new Dictionary<string, EventHandler<PluginResult>>();
             PhoneApplicationService service = PhoneApplicationService.Current;
             service.Activated += this.OnResume;
             service.Deactivated += this.OnPause;
         }
 
+        protected Dictionary<string, EventHandler<PluginResult>> ResultHandlers;
+        public void AddResultHandler(string callbackId, EventHandler<PluginResult> handler)
+        {
+            ResultHandlers.Add(callbackId, handler);
+        }
+        public bool RemoveResultHandler(string callbackId)
+        {
+            return ResultHandlers.Remove(callbackId);
+        }
+
         /*
          *  InvokeMethodNamed will call the named method of a BaseCommand subclass if it exists and pass the variable arguments list along.
          **/
 
+        public object InvokeMethodNamed(string callbackId, string methodName, params object[] args)
+        {
+            //Debug.WriteLine(string.Format("InvokeMethodNamed:{0} callbackId:{1}",methodName,callbackId));
+            this.CurrentCommandCallbackId = callbackId;
+            return InvokeMethodNamed(methodName, args);
+        }
+
         public object InvokeMethodNamed(string methodName, params object[] args)
         {
             MethodInfo mInfo = this.GetType().GetMethod(methodName);
@@ -58,7 +80,6 @@ namespace WPCordovaClassLib.Cordova.Commands
                 PropertyInfo pInfo = this.GetType().GetProperty(methodName);
                 if (pInfo != null)
                 {
-
                     object res = pInfo.GetValue(this, null);
 
                     DispatchCommandResult(new PluginResult(PluginResult.Status.OK, res));
@@ -89,51 +110,59 @@ namespace WPCordovaClassLib.Cordova.Commands
             this.DispatchCommandResult(new PluginResult(PluginResult.Status.NO_RESULT));
         }
 
-        public void DispatchCommandResult(PluginResult result)
+        public void DispatchCommandResult(PluginResult result, string callbackId = "")
         {
-            if (this.OnCommandResult != null)
+            if (!string.IsNullOrEmpty(callbackId)) 
+            {
+                result.CallbackId = callbackId;
+            }
+            else
             {
-                this.OnCommandResult(this, result);
+                result.CallbackId = this.CurrentCommandCallbackId;
+            }
 
-                if (!result.KeepCallback)
-                {
-                    this.Dispose();
-                }
+            if (ResultHandlers.ContainsKey(result.CallbackId))
+            {
+                ResultHandlers[result.CallbackId](this, result);
+            }
+            else if (this.OnCommandResult != null)
+            {
+                OnCommandResult(this, result);
+            }
+            else
+            {
+                Debug.WriteLine("Failed to locate callback for id : " + result.CallbackId);
+            }
 
+            if (!result.KeepCallback)
+            {
+                this.Dispose();
             }
+
         }
 
 
         /// <summary>
         /// Occurs when the application is being deactivated.
         /// </summary>        
-        public virtual void OnReset()
-        {
-        }
+        public virtual void OnReset() {}
 
         /// <summary>
         /// Occurs when the application is being loaded, and the config.xml has an autoload entry
         /// </summary>    
-        public virtual void OnInit()
-        {
-
-        }
+        public virtual void OnInit() {}
 
 
         /// <summary>
         /// Occurs when the application is being deactivated.
         /// </summary>        
-        public virtual void OnPause(object sender, DeactivatedEventArgs e)
-        {
-        }
+        public virtual void OnPause(object sender, DeactivatedEventArgs e) {}
 
         /// <summary>
         /// Occurs when the application is being made active after previously being put
         /// into a dormant state or tombstoned.
         /// </summary>        
-        public virtual void OnResume(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e)
-        {
-        }
+        public virtual void OnResume(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e) {}
 
         public void Dispose()
         {

http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/21ecd2a3/templates/standalone/cordovalib/CordovaCommandCall.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/CordovaCommandCall.cs b/templates/standalone/cordovalib/CordovaCommandCall.cs
index a864fe6..810f5e2 100644
--- a/templates/standalone/cordovalib/CordovaCommandCall.cs
+++ b/templates/standalone/cordovalib/CordovaCommandCall.cs
@@ -23,6 +23,7 @@ using System.Windows.Media;
 using System.Windows.Media.Animation;
 using System.Windows.Shapes;
 using System.Linq;
+using System.Collections.Generic;
 
 namespace WPCordovaClassLib.Cordova
 {
@@ -46,7 +47,6 @@ namespace WPCordovaClassLib.Cordova
             if (string.IsNullOrEmpty(commandStr))
             {
                 return null;
-                //throw new ArgumentNullException("commandStr");
             }
 
             string[] split = commandStr.Split('/');
@@ -56,21 +56,33 @@ namespace WPCordovaClassLib.Cordova
             }
 
             CordovaCommandCall commandCallParameters = new CordovaCommandCall();
-
             commandCallParameters.Service = split[0];
             commandCallParameters.Action = split[1];
             commandCallParameters.CallbackId = split[2];
-            commandCallParameters.Args = split.Length <= 3 ? String.Empty : String.Join("/", split.Skip(3));
 
+            try
+            {
+                string arg = split.Length <= 3 ? "[]" : String.Join("/", split.Skip(3));
+                if (!arg.StartsWith("[")) // save the exception
+                {
+                    arg = string.Format("[{0}]", arg);
+                }
+                List<string> args = JSON.JsonHelper.Deserialize<List<string>>(arg);
+                args.Add(commandCallParameters.CallbackId);
+                commandCallParameters.Args = JSON.JsonHelper.Serialize(args.ToArray());
+            }
+            catch (Exception)
+            {
+                return null; 
+            }
             // sanity check for illegal names
             // was failing with ::
-            // 1, Device1, {"status":1,"message":"{\"name\":\"XD.....
+            // CordovaCommandResult :: 1, Device1, {"status":1,"message":"{\"name\":\"XD.....
             if (commandCallParameters.Service.IndexOfAny(new char[] { '@', ':', ',', '!', ' ' }) > -1)
             {
                 return null;
             }
 
-
             return commandCallParameters;
         }
 

http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/21ecd2a3/templates/standalone/cordovalib/NativeExecution.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/NativeExecution.cs b/templates/standalone/cordovalib/NativeExecution.cs
index c0d768e..af6b207 100644
--- a/templates/standalone/cordovalib/NativeExecution.cs
+++ b/templates/standalone/cordovalib/NativeExecution.cs
@@ -95,36 +95,40 @@ namespace WPCordovaClassLib.Cordova
 
                 EventHandler<PluginResult> OnCommandResultHandler = delegate(object o, PluginResult res)
                 {
-                    this.OnCommandResult(commandCallParams.CallbackId, res);
+                    if (res.CallbackId == null || res.CallbackId == commandCallParams.CallbackId)
+                    {
+                        this.OnCommandResult(commandCallParams.CallbackId, res);
+                        if (!res.KeepCallback)
+                        {
+                            bc.RemoveResultHandler(commandCallParams.CallbackId);
+                        }
+                    }
                 };
 
-                bc.OnCommandResult += OnCommandResultHandler;
+                //bc.OnCommandResult += OnCommandResultHandler;
+                bc.AddResultHandler(commandCallParams.CallbackId, OnCommandResultHandler);
 
                 EventHandler<ScriptCallback> OnCustomScriptHandler = delegate(object o, ScriptCallback script)
                 {
                     this.InvokeScriptCallback(script);
                 };
 
-
                 bc.OnCustomScript += OnCustomScriptHandler;
 
-                ThreadStart methodInvocation = () =>
+                ThreadStart methodInvokation = () =>
                 {
-
                     try
                     {
-                        bc.InvokeMethodNamed(commandCallParams.Action, commandCallParams.Args);
+                        bc.InvokeMethodNamed(commandCallParams.CallbackId,commandCallParams.Action, commandCallParams.Args);
                     }
                     catch (Exception ex)
                     {
                         Debug.WriteLine("ERROR: Exception in ProcessCommand :: " + ex.Message);
-                        bc.OnCommandResult -= OnCommandResultHandler;
+                        bc.RemoveResultHandler(commandCallParams.CallbackId);
                         bc.OnCustomScript -= OnCustomScriptHandler;
 
                         Debug.WriteLine("ERROR: failed to InvokeMethodNamed :: " + commandCallParams.Action + " on Object :: " + commandCallParams.Service);
-
                         this.OnCommandResult(commandCallParams.CallbackId, new PluginResult(PluginResult.Status.INVALID_ACTION));
-
                         return;
                     }
                 };
@@ -133,19 +137,19 @@ namespace WPCordovaClassLib.Cordova
                 {
                     // Due to some issues with the IsolatedStorage in current version of WP8 SDK we have to run all File Api commands synchronously.
                     // TODO: test this in WP8 RTM
-                    methodInvocation.Invoke();
+                    methodInvokation.Invoke();
                 }
                 else
                 {
-                    new Thread(methodInvocation).Start();
+                    new Thread(methodInvokation).Start();
                 }
 
-                    
+
             }
             catch (Exception ex)
             {
                 // ERROR
-                Debug.WriteLine(String.Format("ERROR: Unable to execute command :: {0}:{1}:{2} ",
+                Debug.WriteLine(String.Format("ERROR: Unable to execute command :: {0}:{1}:{3} ",
                     commandCallParams.Service, commandCallParams.Action, ex.Message));
 
                 this.OnCommandResult(commandCallParams.CallbackId, new PluginResult(PluginResult.Status.ERROR));
@@ -174,6 +178,12 @@ namespace WPCordovaClassLib.Cordova
                 return;
             }
 
+            if (!String.IsNullOrEmpty(result.CallbackId) && callbackId != result.CallbackId)
+            {
+                Debug.WriteLine("Multiple Overlapping Results :: " + result.CallbackId + " :: " + callbackId);
+                return;
+            }
+
             #endregion
 
             string jsonResult = result.ToJSONString();

http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/21ecd2a3/templates/standalone/cordovalib/PluginResult.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/PluginResult.cs b/templates/standalone/cordovalib/PluginResult.cs
index e6d0c56..00017d2 100644
--- a/templates/standalone/cordovalib/PluginResult.cs
+++ b/templates/standalone/cordovalib/PluginResult.cs
@@ -69,6 +69,7 @@ namespace WPCordovaClassLib.Cordova
         public Status Result { get; private set; }
         public string Message { get; set; }
         public bool KeepCallback { get; set; }
+        public string CallbackId { get; set; }
 
         /// <summary>
         /// Whether command succeded or not
@@ -113,6 +114,7 @@ namespace WPCordovaClassLib.Cordova
 
         }
 
+        [Obsolete]
         public string ToCallbackString(string callbackId, string successCallback, string errorCallback)
         {
             if (this.IsSuccess)


[2/2] wp7 commit: Merge pull request #20 from purplecabbage/CB-2671

Posted by pu...@apache.org.
Merge pull request #20 from purplecabbage/CB-2671

Fixes for overlapping API calls - File API is passing a bunch more tests...

Project: http://git-wip-us.apache.org/repos/asf/cordova-wp7/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-wp7/commit/4a79e585
Tree: http://git-wip-us.apache.org/repos/asf/cordova-wp7/tree/4a79e585
Diff: http://git-wip-us.apache.org/repos/asf/cordova-wp7/diff/4a79e585

Branch: refs/heads/master
Commit: 4a79e5853929eb857ee0c366c5d78a667fb7a9b4
Parents: 9bdabf0 21ecd2a
Author: Jesse MacFadyen <pu...@gmail.com>
Authored: Wed May 8 21:08:14 2013 -0700
Committer: Jesse MacFadyen <pu...@gmail.com>
Committed: Wed May 8 21:08:14 2013 -0700

----------------------------------------------------------------------
 templates/standalone/Plugins/File.cs               |  482 +++++++++------
 templates/standalone/Plugins/Notification.cs       |   63 ++-
 .../standalone/cordovalib/Commands/BaseCommand.cs  |   73 ++-
 .../standalone/cordovalib/CordovaCommandCall.cs    |   22 +-
 templates/standalone/cordovalib/NativeExecution.cs |   36 +-
 templates/standalone/cordovalib/PluginResult.cs    |    2 +
 6 files changed, 435 insertions(+), 243 deletions(-)
----------------------------------------------------------------------