This is an automated email from the ASF dual-hosted git repository.
gregdove pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
The following commit(s) were added to refs/heads/develop by this push:
new 53a001e First cut at addressing issue #466 (support for legacy
decoding only, not for encoding).
53a001e is described below
commit 53a001ef38465e6483052360b0e4ba5f6ee64be4
Author: greg-dove <[email protected]>
AuthorDate: Wed Oct 16 14:27:37 2019 +1300
First cut at addressing issue #466 (support for legacy decoding only, not
for encoding).
---
.../main/royale/mx/rpc/http/AbstractOperation.as | 135 ++++++------
.../src/main/royale/mx/rpc/xml/ComplexString.as | 57 +++++
.../src/main/royale/mx/rpc/xml/SimpleXMLDecoder.as | 240 +++++++++++++++++++++
frameworks/projects/XML/src/main/royale/XMLList.as | 7 +
4 files changed, 373 insertions(+), 66 deletions(-)
diff --git
a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/http/AbstractOperation.as
b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/http/AbstractOperation.as
index e37a252..fc4926a 100644
---
a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/http/AbstractOperation.as
+++
b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/http/AbstractOperation.as
@@ -44,6 +44,7 @@ package mx.rpc.http
import mx.rpc.Fault;
import mx.rpc.events.FaultEvent;
import mx.rpc.mxml.Concurrency;
+ import mx.rpc.xml.SimpleXMLDecoder;
import mx.utils.ObjectProxy;
import mx.utils.ObjectUtil;
import mx.utils.StringUtil;
@@ -1037,79 +1038,81 @@ package mx.rpc.http
{
if (/*resultFormat == RESULT_FORMAT_XML ||
*/resultFormat == RESULT_FORMAT_OBJECT
|| resultFormat == RESULT_FORMAT_ARRAY)
- {/*
- //old XML style
- var tmp:Object = new XMLDocument();
- XMLDocument(tmp).ignoreWhite = true;
- try
- {
- XMLDocument(tmp).parseXML(String(body));
- }
- catch(parseError:Error)
- {
- var fault:Fault = new
Fault(ERROR_DECODING, parseError.message);
-
dispatchRpcEvent(FaultEvent.createEvent(fault, token, message));
- return false;
- }
- if (resultFormat ==
RESULT_FORMAT_OBJECT || resultFormat == RESULT_FORMAT_ARRAY)
- {
- var decoded:Object;
- var msg:String;
- if (xmlDecode != null)
- {
- decoded = xmlDecode(tmp);
- if (decoded == null)
- {
- msg = resourceManager.getString(
- "rpc", "xmlDecodeReturnNull");
- var fault1:Fault = new
Fault(ERROR_DECODING, msg);
-
dispatchRpcEvent(FaultEvent.createEvent(fault1, token, message));
- }
- }
- else
- {
- var decoder:SimpleXMLDecoder = new
SimpleXMLDecoder(makeObjectsBindable);
-
- decoded =
decoder.decodeXML(XMLNode(tmp));
-
- if (decoded == null)
- {
- msg = resourceManager.getString(
- "rpc", "defaultDecoderFailed");
- var fault2:Fault = new
Fault(ERROR_DECODING, msg);
-
dispatchRpcEvent(FaultEvent.createEvent(fault2, token, message));
- }
- }
-
- if (decoded == null)
- {
- return false;
- }
+ {
- if (makeObjectsBindable &&
(getQualifiedClassName(decoded) == "Object"))
- {
- decoded = new ObjectProxy(decoded);
- }
- else
+ try{
+ var temp:XMLList = new
XMLList(String(body));
+ var tmp:XML = new
XML('<root>'+temp.toXMLString()+'</root>');
+ } catch(parseError:Error)
{
- decoded = decoded;
+ var fault:Fault = new
Fault(ERROR_DECODING, parseError.message);
+
dispatchRpcEvent(FaultEvent.createEvent(fault, token, message));
+ return false;
}
-
- if (resultFormat == RESULT_FORMAT_ARRAY)
+ if (resultFormat ==
RESULT_FORMAT_OBJECT || resultFormat == RESULT_FORMAT_ARRAY)
{
- decoded = decodeArray(decoded);
- }
-
- _result = decoded;
+ var decoded:Object;
+ var msg:String;
+ if (xmlDecode != null)
+ {
+ decoded =
xmlDecode(tmp);
+ if (decoded == null)
+ {
+ /*msg =
resourceManager.getString(
+
"rpc", "xmlDecodeReturnNull");*/
+ msg =
'XMLDecode returned null';
+ var
fault1:Fault = new Fault(ERROR_DECODING, msg);
+
dispatchRpcEvent(FaultEvent.createEvent(fault1, token, message));
+ }
+ }
+ else
+ {
+ var
decoder:SimpleXMLDecoder = new SimpleXMLDecoder(makeObjectsBindable);
+
+ decoded =
decoder.decodeXML(tmp);
+
+ if (decoded == null)
+ {
+ /*msg =
resourceManager.getString(
+
"rpc", "defaultDecoderFailed");*/
+ msg =
"defaultDecoderFailed";
+
+ var
fault2:Fault = new Fault(ERROR_DECODING, msg);
+
dispatchRpcEvent(FaultEvent.createEvent(fault2, token, message));
+ }
+ }
+
+ if (decoded == null)
+ {
+ return false;
+ }
+
+ if (makeObjectsBindable &&
false /*(getQualifiedClassName(decoded) == "Object")*/)
+ {
+ decoded = new
ObjectProxy(decoded);
+ }
+ else
+ {
+ decoded = decoded;
+ }
+
+ if (resultFormat ==
RESULT_FORMAT_ARRAY)
+ {
+ decoded =
decodeArray(decoded);
+ }
+
+ _result = decoded;
}
- else
+ /*else
{
- if (tmp.childNodes.length == 1)
- {
- tmp = tmp.firstChild;
- }
- _result = tmp;
+ if (tmp.children().length() ==
1)
+ {
+ tmp = tmp.children()[0];
+ }
+ // key difference here is that
it will also be E4X:
+ _result = tmp;
}*/
+
}
else if (resultFormat == RESULT_FORMAT_E4X)
{
diff --git
a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/xml/ComplexString.as
b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/xml/ComplexString.as
new file mode 100644
index 0000000..8eaa846
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/xml/ComplexString.as
@@ -0,0 +1,57 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.rpc.xml
+{
+
+ [ExcludeClass]
+
+ /**
+ * This internal utility class is used by SimpleXMLDecoder. The class is
+ * basically a dynamic version of the String class (other properties can be
+ * attached to it).
+ *
+ * When you try to get the value of a ComplexString, we attempt to convert
the
+ * value to a number or boolean before returning it.
+ *
+ * @private
+ */
+ internal dynamic class ComplexString
+ {
+ public var value:String;
+
+ public function ComplexString(val:String)
+ {
+ super();
+ value = val;
+ }
+
+ public function toString():String
+ {
+ return value;
+ }
+
+ COMPILE::JS {override}
+ public function valueOf():*
+ {
+ return SimpleXMLDecoder.simpleType(value);
+ }
+ }
+
+}
diff --git
a/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/xml/SimpleXMLDecoder.as
b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/xml/SimpleXMLDecoder.as
new file mode 100644
index 0000000..b8a5a41
--- /dev/null
+++
b/frameworks/projects/MXRoyale/src/main/royale/mx/rpc/xml/SimpleXMLDecoder.as
@@ -0,0 +1,240 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.rpc.xml
+{
+
+ /* import flash.xml.XMLNode;
+ import flash.xml.XMLNodeType;*/
+ import mx.collections.ArrayCollection;
+ import mx.utils.ObjectProxy;
+
+ /**
+ * The SimpleXMLDecoder class deserialize XML into a graph of
ActionScript objects.
+ * Use this class when no schema information is available.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public class SimpleXMLDecoder
+ {
+
//--------------------------------------------------------------------------
+ //
+ // Class Methods
+ //
+
//--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ public static function simpleType(val:String):Object
+ {
+ var result:Object = val;
+
+ if (val != null)
+ {
+ //return the value as a string, a boolean or a number.
+ //numbers that start with 0 are left as strings
+ //bForceObject removed since we'll take care of converting to
a String or Number object later
+ if (val is String && String(val) == "")
+ {
+ result = val.toString();
+ }
+ else if (isNaN(Number(val)) || (val.charAt(0) == '0') ||
((val.charAt(0) == '-') && (val.charAt(1) == '0')) || val.charAt(val.length -1)
== 'E')
+ {
+ var valStr:String = val.toString();
+
+ //Bug 101205: Also check for boolean
+ var valStrLC:String = valStr.toLowerCase();
+ if (valStrLC == "true")
+ result = true;
+ else if (valStrLC == "false")
+ result = false;
+ else
+ result = valStr;
+ }
+ else
+ {
+ result = Number(val);
+ }
+ }
+
+ return result;
+ }
+
+
//--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+
//--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * Constructor.
+ */
+ public function SimpleXMLDecoder(makeObjectsBindable:Boolean = false)
+ {
+ super();
+
+ this.makeObjectsBindable = makeObjectsBindable;
+ }
+
+
//--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+
//--------------------------------------------------------------------------
+
+ /**
+ * Converts a tree of XMLNodes into a tree of ActionScript Objects.
+ *
+ * @param dataNode An XMLNode to be converted into a tree of
ActionScript Objects.
+ *
+ * @return A tree of ActionScript Objects.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function decodeXML(dataNode:XML):Object
+ {
+ var result:Object;
+ var isSimpleType:Boolean = false;
+
+ if (dataNode == null)
+ return null;
+
+ // Cycle through the subnodes
+ var children:XMLList = dataNode.children();
+ if (children.length() == 1 && children[0].nodeKind() == 'text')
+ {
+ // If exactly one text node subtype, we must want a simple
+ // value.
+ isSimpleType = true;
+ result = SimpleXMLDecoder.simpleType(children[0].toString());
+ }
+ else if (children.length() > 0)
+ {
+ result = {};
+ if (makeObjectsBindable)
+ result = new ObjectProxy(result);
+
+ for (var i:uint = 0; i < children.length(); i++)
+ {
+ var partNode:XML = children[i];
+
+ // skip text nodes, which are part of mixed content
+ if (partNode.nodeKind() != 'element')
+ {
+ continue;
+ }
+
+ var partName:String = getLocalName(partNode);
+ var partObj:Object = decodeXML(partNode);
+
+ // Enable processing multiple copies of the same element
(sequences)
+ var existing:Object = result[partName];
+ if (existing != null)
+ {
+ if (existing is Array)
+ {
+ existing.push(partObj);
+ }
+ else if (existing is ArrayCollection)
+ {
+ existing.source.push(partObj);
+ }
+ else
+ {
+ existing = [existing];
+ existing.push(partObj);
+
+ if (makeObjectsBindable)
+ existing = new ArrayCollection(existing as
Array);
+
+ result[partName] = existing;
+ }
+ }
+ else
+ {
+ result[partName] = partObj;
+ }
+ }
+ }
+
+ // Cycle through the attributes
+ var attributes:XMLList = dataNode.attributes();
+ for each (var attribute:XML in attributes)
+ {
+ /* if (attribute == "xmlns" || attribute.indexOf("xmlns:") !=
-1)
+ continue;*/
+
+ // result can be null if it contains no children.
+ if (result == null)
+ {
+ result = {};
+ if (makeObjectsBindable)
+ result = new ObjectProxy(result);
+ }
+
+ // If result is not currently an Object (it is a Number,
Boolean,
+ // or String), then convert it to be a ComplexString so that we
+ // can attach attributes to it. (See comment in
ComplexString.as)
+ if (isSimpleType && !(result is ComplexString))
+ {
+ result = new ComplexString(result.toString());
+ isSimpleType = false;
+ }
+
+ result[attribute.localName()] =
SimpleXMLDecoder.simpleType(attribute.toString());
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the local name of an XMLNode.
+ *
+ * @param xmlNode The XMLNode.
+ *
+ * @return The local name of an XMLNode.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public static function getLocalName(xml:XML):String
+ {
+ var name:String = xml.localName().toString();
+ /*var myPrefixIndex:int = name.indexOf(":");
+ if (myPrefixIndex != -1)
+ {
+ name = name.substring(myPrefixIndex+1);
+ }*/
+ return name;
+ }
+
+ private var makeObjectsBindable:Boolean;
+ }
+
+}
diff --git a/frameworks/projects/XML/src/main/royale/XMLList.as
b/frameworks/projects/XML/src/main/royale/XMLList.as
index 7b877f1..bd1bf45 100644
--- a/frameworks/projects/XML/src/main/royale/XMLList.as
+++ b/frameworks/projects/XML/src/main/royale/XMLList.as
@@ -23,6 +23,11 @@ package
{
import org.apache.royale.debugging.throwError;
+ /**
+ * regex to match the xml declaration
+ */
+ private static const xmlDecl:RegExp = /^\s*<\?xml[^?]*\?>/im;
+
/**
* mimics the top-level XMLList function (supports 'this'
correctly)
@@ -67,6 +72,8 @@ package
{
if (typeof(expression) === "string")
{
+ var decl:String =
xmlDecl.exec(expression);
+ if (decl) expression =
expression.replace(decl,'');
// try adding a wrapping node and then grab the
children
expression = "<root>" + expression + "</root>";
try