Added AMFStorage
diff --git a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/models/TodoModel.as b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/models/TodoModel.as
index 85c630b..ed21421 100644
--- a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/models/TodoModel.as
+++ b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/models/TodoModel.as
@@ -26,7 +26,7 @@
import org.apache.royale.core.IStrand;
import org.apache.royale.events.EventDispatcher;
import org.apache.royale.routing.Router;
- import org.apache.royale.storage.LocalStorage;
+ import org.apache.royale.storage.AMFStorage;
[Bindable]
/**
@@ -72,30 +72,18 @@
*/
public function setItemStore(items:Array):void
{
- var itemStr:String = JSON.stringify(items);
- storage.setItem("todomvc",itemStr);
+ storage.data["items"] = items;
+ storage.save();
}
public function getItemStore():Array
{
- var itemArr:Array = [];
- var itemStr:String = storage.getItem("todomvc") as String;
- if(itemStr)
- {
- try{
- itemArr = JSON.parse(itemStr) as Array;
- for(var i:int=0;i<itemArr.length;i++){
- itemArr[i] = TodoVO.fromJSON(itemArr[i]);
- }
- }catch(err:Error){
- return [];
- }
- }
+ var itemArr:Array = storage.data["items"] || [];
return itemArr;
}
/**
* Local storage for the todo items
*/
- private var storage:LocalStorage = new LocalStorage();// SharedObject.getLocal("todomvc");
+ private var storage:AMFStorage = AMFStorage.getLocal("todomvc");
/**
* the list of items binded to the todo list component
diff --git a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/vos/TodoVO.as b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/vos/TodoVO.as
index 8fb4ee7..d6ba6db 100644
--- a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/vos/TodoVO.as
+++ b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/vos/TodoVO.as
@@ -43,7 +43,11 @@
{
this.label = label;
}
-
+
+ /**
+ * The following two methods could be used if we were saving and reading the data as JSON,
+ * but we're actually saving and reading as AMF, so they are not necessary.
+ */
public function toJSON():Object{
return {
"label":label,
diff --git a/frameworks/build.xml b/frameworks/build.xml
index 4020d38..db5eaba 100644
--- a/frameworks/build.xml
+++ b/frameworks/build.xml
@@ -131,9 +131,9 @@
<antcall target="JQuery"/>
<antcall target="Mobile"/>
+ <antcall target="Network"/>
<antcall target="Storage"/>
<antcall target="XML"/>
- <antcall target="Network"/>
<antcall target="Text"/>
<antcall target="TLF"/>
<antcall target="MaterialDesignLite"/>
diff --git a/frameworks/js/projects/StorageJS/src/main/config/compile-js-config.xml b/frameworks/js/projects/StorageJS/src/main/config/compile-js-config.xml
index dc0c90c..a149ae3 100644
--- a/frameworks/js/projects/StorageJS/src/main/config/compile-js-config.xml
+++ b/frameworks/js/projects/StorageJS/src/main/config/compile-js-config.xml
@@ -58,6 +58,8 @@
<path-element>../../../../../../../js/libs/cordova.swc</path-element>
<path-element>../../../../../libs/LanguageJS.swc</path-element>
<path-element>../../../../../libs/CoreJS.swc</path-element>
+ <path-element>../../../../../libs/NetworkJS.swc</path-element>
+ <path-element>../../../../../libs/ReflectionJS.swc</path-element>
</external-library-path>
<namespaces>
@@ -72,6 +74,7 @@
</source-path>
<warn-no-constructor>false</warn-no-constructor>
+ <allow-abstract-classes>true</allow-abstract-classes>
</compiler>
<include-file>
diff --git a/frameworks/projects/Storage/src/main/config/compile-swf-config.xml b/frameworks/projects/Storage/src/main/config/compile-swf-config.xml
index 0d9a221..6eccbe5 100644
--- a/frameworks/projects/Storage/src/main/config/compile-swf-config.xml
+++ b/frameworks/projects/Storage/src/main/config/compile-swf-config.xml
@@ -31,6 +31,8 @@
<external-library-path>
<path-element>${env.AIR_HOME}/frameworks/libs/air/airglobal.swc</path-element>
<path-element>../../../../../libs/Core.swc</path-element>
+ <path-element>../../../../../libs/Network.swc</path-element>
+ <path-element>../../../../../libs/Reflection.swc</path-element>
</external-library-path>
<mxml>
@@ -73,6 +75,7 @@
</source-path>
<warn-no-constructor>false</warn-no-constructor>
+ <allow-abstract-classes>true</allow-abstract-classes>
</compiler>
<include-file>
diff --git a/frameworks/projects/Storage/src/main/resources/basic-manifest.xml b/frameworks/projects/Storage/src/main/resources/basic-manifest.xml
index 00a7a5a..b2dcd21 100644
--- a/frameworks/projects/Storage/src/main/resources/basic-manifest.xml
+++ b/frameworks/projects/Storage/src/main/resources/basic-manifest.xml
@@ -20,6 +20,7 @@
<componentPackage>
+ <component id="AMFStorage" class="org.apache.royale.storage.AMFStorage"/>
<component id="LocalStorage" class="org.apache.royale.storage.LocalStorage"/>
<component id="PermanentStorage" class="org.apache.royale.storage.PermanentStorage"/>
</componentPackage>
diff --git a/frameworks/projects/Storage/src/main/royale/StorageClasses.as b/frameworks/projects/Storage/src/main/royale/StorageClasses.as
index 3955508..3ee52fb 100644
--- a/frameworks/projects/Storage/src/main/royale/StorageClasses.as
+++ b/frameworks/projects/Storage/src/main/royale/StorageClasses.as
@@ -27,6 +27,7 @@
*/
internal class StorageClasses
{
+ import org.apache.royale.storage.AMFStorage; AMFStorage;
import org.apache.royale.storage.LocalStorage; LocalStorage;
import org.apache.royale.storage.providers.LocalStorageProvider; LocalStorageProvider;
diff --git a/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/AMFStorage.as b/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/AMFStorage.as
new file mode 100644
index 0000000..c766894
--- /dev/null
+++ b/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/AMFStorage.as
@@ -0,0 +1,208 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.storage
+{
+ COMPILE::SWF{
+ import flash.events.Event;
+ import flash.net.SharedObject;
+ }
+
+ COMPILE::JS
+ {
+ import goog.DEBUG;
+ import org.apache.royale.debugging.assert;
+ import org.apache.royale.net.remoting.amf.AMFBinaryData;
+ }
+
+ import org.apache.royale.events.EventDispatcher;
+
+ public class AMFStorage extends EventDispatcher
+ {
+ private static const map:Object = {};
+
+ public static const PENDING:String = "pending";
+ public static const FLUSHED:String = "flushed";
+ public static const FAILED:String = "failed";
+
+ public static function getLocal(name:String, localPath:String = null, secure:Boolean = false):AMFStorage
+ {
+ var pathKey:String = localPath == null ? '$null$' : localPath;
+ COMPILE::JS {
+ localPath = pathKey;
+ }
+ var cached:AMFStorage = map[pathKey + '::' + name];
+ if (!cached)
+ {
+ cached = new AMFStorage();
+ map[pathKey + '::' + name] = cached;
+ cached.setName(name);
+ cached.setLocalPath(localPath);
+ cached.createSO(secure);
+ }
+ COMPILE::JS{
+ if (!map['#']) {
+ window.addEventListener('pagehide', unloadHandler);
+ map['#'] = true;
+ }
+ }
+ return cached;
+ }
+ COMPILE::JS
+ private static function unloadHandler(event:PageTransitionEvent):void{
+ //@todo consider whether we do anything different if event.persisted is true or false
+ for (var key:String in map) {
+ if (key != '#') {
+ var so:AMFStorage = map[key];
+ //@todo what to do with errors here:
+ so.save();
+ }
+ }
+ }
+
+ private function AMFStorage()
+ {
+
+ }
+ COMPILE::SWF
+ private var _so:flash.net.SharedObject;
+
+ COMPILE::JS
+ private var _ls:Storage;
+
+ /**
+ *
+ * @param minDiskSpace ignored for javascript targets
+ * @return a string indicating the flush status. This can be (on swf) FLUSHED or PENDING on swf. For JS is it FLUSHED or FAILED
+ *
+ * @throws Error #2044: Unhandled NetStatusEvent
+ */
+ public function save(minDiskSpace:int = 0):String
+ {
+ COMPILE::JS
+ {
+ if (_data)
+ {
+ try{
+ var amf:AMFBinaryData = new AMFBinaryData();
+ amf.writeObject(_data);
+ var base64:String = window['btoa'](String.fromCharCode.apply(null, amf.array));
+ _ls.setItem(_localPath + "::" + _name, base64);
+ } catch(e:Error) {
+ return FAILED;
+ }
+ }
+ //js never returns pending, because there is no way for the user to accept or decline the byte size storage limits
+ return FLUSHED;
+ }
+ COMPILE::SWF
+ {
+ return _so.flush(minDiskSpace);
+ }
+ }
+
+ public function clear():void{
+ COMPILE::SWF{
+ _so.clear();
+ }
+ COMPILE::JS{
+ if (_data) {
+ if (_ls) {
+ _ls.removeItem(_localPath + "::" + _name);
+ }
+ _data = null;
+ }
+ }
+ }
+
+ COMPILE::JS
+ private var _data:Object;
+
+ public function get data():Object
+ {
+ COMPILE::SWF
+ {
+ return _so.data;
+ }
+ COMPILE::JS
+ {
+ if (!_data)
+ {
+ _data = {};
+ }
+ return _data;
+ }
+ }
+
+ private var _name:String;
+ protected function setName(name:String):void
+ {
+ _name = name;
+ }
+
+ private var _localPath:String;
+ private function setLocalPath(localPath:String):void
+ {
+ _localPath = localPath;
+ }
+ COMPILE::SWF
+ protected function redispatch(event:flash.events.Event):void{
+ //just redispatch?
+ dispatchEvent(event.clone());
+ }
+
+ private function createSO(secure:Boolean):void
+ {
+ COMPILE::SWF{
+ _so = flash.net.SharedObject.getLocal(_name, _localPath, secure);
+ _so.addEventListener('netStatus', redispatch);
+ _so.addEventListener('asyncError', redispatch); //not sure about this one for LSO..
+ //_so.addEventListener('sync', redispatch); //only relevant for RSO, not LSO
+ }
+ COMPILE::JS{
+ _ls = window.localStorage;
+ if(goog.DEBUG)
+ {
+ if (!_ls && typeof Storage != "undefined") {
+ //this gets around an issue with local testing with file:// protocol in IE11
+ var p:String = window.location.pathname.replace(/(^..)(:)/, "$1$$");
+ window.location.href = window.location.protocol + "//127.0.0.1" + p;
+ _ls = window.localStorage;
+ }
+ }
+ assert(_ls != null,'local storage not supported');
+ var base64:String = _ls.getItem(_localPath + "::" + _name);
+ if (base64)
+ {
+ var binary_string:String = window['atob'](base64);
+ var arr:Uint8Array = new Uint8Array(
+ binary_string.split('')
+ .map(
+ function (charStr:String):uint
+ {
+ return charStr.charCodeAt(0);
+ }
+ )
+ );
+ var amf:AMFBinaryData = new AMFBinaryData(arr.buffer);
+ _data = amf.readObject();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file