2005-09-21 Lluis Sanchez Gual <lluis@novell.com>
[mono.git] / mcs / class / System.Runtime.Serialization.Formatters.Soap / System.Runtime.Serialization.Formatters.Soap / SoapReader.cs
old mode 100755 (executable)
new mode 100644 (file)
index 69ff966..d036174
@@ -36,6 +36,7 @@ using System.Collections;
 using System.Runtime.Remoting;\r
 using System.Runtime.Serialization;\r
 using System.Runtime.Remoting.Messaging;\r
+using System.Runtime.Remoting.Metadata;\r
 \r
 namespace System.Runtime.Serialization.Formatters.Soap {\r
        internal sealed class SoapReader {\r
@@ -150,7 +151,15 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        return TopObject;\r
                }\r
                \r
-               #endregion\r
+               #endregion
+               
+               public SoapTypeMapper Mapper {
+                       get { return mapper; }
+               }
+               \r
+               public XmlTextReader XmlReader {
+                       get { return xmlReader; }
+               }\r
 \r
                #region Private Methods\r
 \r
@@ -192,16 +201,12 @@ namespace System.Runtime.Serialization.Formatters.Soap {
 \r
                private Type GetComponentType()\r
                {\r
-                       Type type = null;\r
-                       if(GetId() != 0) return typeof(string);\r
-                       \r
                        string strValue = xmlReader["type", XmlSchema.InstanceNamespace];\r
-                       if(strValue == null) return null;\r
-                       string[] strName = strValue.Split(':');\r
-                       string namespaceURI = xmlReader.LookupNamespace(strName[0]);\r
-                       type = mapper[new Element(string.Empty, strName[1], namespaceURI)];\r
-\r
-                       return type;\r
+                       if(strValue == null) {\r
+                               if(GetId() != 0) return typeof(string);\r
+                               return null;\r
+                       }\r
+                       return GetTypeFromQName (strValue);\r
                }\r
 \r
                private bool DeserializeMessage(ISoapMessage message) \r
@@ -226,48 +231,55 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        long paramValuesId = NextAvailableId;\r
                        int[] indices = new int[1];\r
 \r
-                       int initialDepth = xmlReader.Depth;\r
-                       xmlReader.Read();\r
-                       int i = 0;\r
-                       while(xmlReader.Depth > initialDepth) \r
+                       if (!xmlReader.IsEmptyElement)\r
                        {\r
-                               long paramId, paramHref;\r
-                               object objParam = null;\r
-                               paramNames.Add (xmlReader.Name);\r
-                               Type paramType = null;\r
-                               \r
-                               if (message.ParamTypes != null) {\r
-                                       if (i >= message.ParamTypes.Length)\r
-                                               throw new SerializationException ("Not enough parameter types in SoapMessages");\r
-                                       paramType = message.ParamTypes [i];\r
-                               }\r
-                               \r
-                               indices[0] = i;\r
-                               objParam = DeserializeComponent(\r
-                                       paramType,\r
-                                       out paramId,\r
-                                       out paramHref,\r
-                                       paramValuesId,\r
-                                       null,\r
-                                       indices);\r
-                               indices[0] = paramValues.Add(objParam);\r
-                               if(paramHref != 0) \r
-                               {\r
-                                       RecordFixup(paramValuesId, paramHref, paramValues.ToArray(), null, null, null, indices);\r
-                               }\r
-                               else if(paramId != 0) \r
-                               {\r
-//                                     RegisterObject(paramId, objParam, null, paramValuesId, null, indices);\r
-                               }\r
-                               else \r
+                               int initialDepth = xmlReader.Depth;\r
+                               xmlReader.Read();\r
+                               int i = 0;\r
+                               while(xmlReader.Depth > initialDepth) \r
                                {\r
+                                       long paramId, paramHref;\r
+                                       object objParam = null;\r
+                                       paramNames.Add (xmlReader.Name);\r
+                                       Type paramType = null;\r
+                                       \r
+                                       if (message.ParamTypes != null) {\r
+                                               if (i >= message.ParamTypes.Length)\r
+                                                       throw new SerializationException ("Not enough parameter types in SoapMessages");\r
+                                               paramType = message.ParamTypes [i];\r
+                                       }\r
+                                       \r
+                                       indices[0] = i;\r
+                                       objParam = DeserializeComponent(\r
+                                               paramType,\r
+                                               out paramId,\r
+                                               out paramHref,\r
+                                               paramValuesId,\r
+                                               null,\r
+                                               indices);\r
+                                       indices[0] = paramValues.Add(objParam);\r
+                                       if(paramHref != 0) \r
+                                       {\r
+                                               RecordFixup(paramValuesId, paramHref, paramValues.ToArray(), null, null, null, indices);\r
+                                       }\r
+                                       else if(paramId != 0) \r
+                                       {\r
+//                                             RegisterObject(paramId, objParam, null, paramValuesId, null, indices);\r
+                                       }\r
+                                       else \r
+                                       {\r
+                                       }\r
+                                       i++;\r
                                }\r
-                               i++;\r
+                               xmlReader.ReadEndElement();\r
                        }\r
-\r
+                       else\r
+                       {\r
+                               xmlReader.Read();\r
+                       }\r
+                       \r
                        message.ParamNames = (string[]) paramNames.ToArray(typeof(string));\r
                        message.ParamValues = paramValues.ToArray();\r
-                       xmlReader.ReadEndElement();\r
                        RegisterObject(paramValuesId, message.ParamValues, null, 0, null, null);\r
                        return true;\r
                }
@@ -325,13 +337,23 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                \r
                private object DeserializeArray(long id)\r
                {\r
+                       // Special case for base64 byte arrays\r
+                       if (GetComponentType () == typeof(byte[])) {\r
+                               byte[] data = Convert.FromBase64String (xmlReader.ReadElementString());\r
+                               RegisterObject(id, data, null, 0, null, null);\r
+                               return data;\r
+                       }\r
+                       \r
                        // Get the array properties\r
-                       string strArrayType = xmlReader["arrayType", SoapTypeMapper.SoapEncodingNamespace];\r
-                       string[] arrayInfo = strArrayType.Split(':','[',',',']');\r
-                       int numberOfDims = arrayInfo.Length - 3;\r
-                       int[] lengths = new int[numberOfDims];\r
-                       string[] arrayDims = new String[numberOfDims];\r
-                       Array.Copy(arrayInfo, 2, arrayDims, 0, numberOfDims);\r
+                       string strArrayType = xmlReader["arrayType", SoapTypeMapper.SoapEncodingNamespace];
+                       string[] arrayInfo = strArrayType.Split(':');
+                       int arraySuffixInfo = arrayInfo[1].LastIndexOf('[');
+                       String arrayElementType = arrayInfo[1].Substring(0, arraySuffixInfo);
+                       String arraySuffix = arrayInfo[1].Substring(arraySuffixInfo);
+                       string[] arrayDims = arraySuffix.Substring(1,arraySuffix.Length-2).Trim().Split(',');
+                       int numberOfDims = arrayDims.Length;
+                       int[] lengths = new int[numberOfDims];
+                       \r
                        for (int i=0; i < numberOfDims; i++)\r
                        {\r
                                lengths[i] = Convert.ToInt32(arrayDims[i]);\r
@@ -340,23 +362,21 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        int[] indices = new int[numberOfDims];\r
 \r
                        // Create the array\r
-                       Type arrayType = mapper[new Element(arrayInfo[0], arrayInfo[1], xmlReader.LookupNamespace(arrayInfo[0]))];\r
+                       Type arrayType = mapper.GetType (arrayElementType, xmlReader.LookupNamespace(arrayInfo[0]));\r
                        Array array = Array.CreateInstance(\r
                                arrayType,\r
-                               lengths);\r
+                               lengths);
 \r
                        for(int i = 0; i < numberOfDims; i++) \r
                        {\r
                                indices[i] = array.GetLowerBound(i);\r
                        }\r
 \r
-\r
                        // Deserialize the array items\r
                        int arrayDepth = xmlReader.Depth;\r
                        xmlReader.Read();\r
                        while(xmlReader.Depth > arrayDepth)\r
                        {\r
-\r
                                Type itemType = GetComponentType();\r
                                if(itemType == null) \r
                                        itemType = array.GetType().GetElementType();\r
@@ -417,13 +437,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                private object Deserialize()\r
                {\r
                        object objReturn = null;\r
-                       Element element = new Element(\r
-                               xmlReader.Prefix,\r
-                               xmlReader.LocalName,\r
-                               xmlReader.NamespaceURI);\r
-\r
-\r
-                       Type type = mapper[element];\r
+                       Type type = mapper.GetType (xmlReader.LocalName, xmlReader.NamespaceURI);\r
 \r
                        // Get the Id\r
                        long id = GetId();\r
@@ -454,10 +468,9 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        bool NeedsSerializationInfo = false;\r
                        bool hasFixup;\r
 \r
-                       if(SoapTypeMapper.CanBeValue(type)) \r
+                       if(mapper.IsInternalSoapType (type)) \r
                        {\r
-                               string elementString = xmlReader.ReadElementString();\r
-                               object obj = SoapTypeMapper.ParseXsdValue (elementString, type);\r
+                               object obj = mapper.ReadInternalSoapValue (this, type);\r
                                \r
                                if(id != 0) \r
                                        RegisterObject(id, obj, info, parentId, parentMemberInfo, indices);\r
@@ -508,16 +521,25 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        Type currentType = obj.GetType();\r
                        TypeMetadata tm = GetTypeMetadata (currentType);\r
 \r
-                       int objDepth = xmlReader.Depth;\r
                        object[] data = new object[tm.MemberInfos.Length];\r
                        xmlReader.Read();\r
-                       for(int i = 0; i < tm.MemberInfos.Length; i++)\r
+                       xmlReader.MoveToContent ();\r
+                       while (xmlReader.NodeType != XmlNodeType.EndElement)\r
                        {\r
+                               if (xmlReader.NodeType != XmlNodeType.Element) {\r
+                                       xmlReader.Skip ();\r
+                                       continue;\r
+                               }\r
+                               \r
                                object fieldObject;\r
                                long fieldId, fieldHref;\r
-                               int index = (int) tm.Indices[xmlReader.LocalName];\r
+\r
+                               object indexob = tm.Indices [xmlReader.LocalName];\r
+                               if (indexob == null)\r
+                                       throw new SerializationException ("Field \"" + xmlReader.LocalName + "\" not found in class " + currentType.FullName);\r
+                               \r
+                               int index = (int) indexob;\r
                                FieldInfo fieldInfo = (tm.MemberInfos[index]) as FieldInfo;\r
-                               if(fieldInfo == null) continue;\r
 \r
                                fieldObject = \r
                                        DeserializeComponent(fieldInfo.FieldType,\r
@@ -569,7 +591,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        while(xmlReader.Depth > initialDepth) \r
                        {\r
                                Type fieldType = GetComponentType();\r
-                               string fieldName = xmlReader.LocalName;\r
+                               string fieldName = XmlConvert.DecodeName (xmlReader.LocalName);\r
                                object objField = DeserializeComponent(\r
                                        fieldType,\r
                                        out fieldId,\r
@@ -716,11 +738,20 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        tm.MemberInfos = FormatterServices.GetSerializableMembers (type, _context);\r
                        \r
                        tm.Indices      = new Hashtable();\r
-                       for(int i = 0; i < tm.MemberInfos.Length; i++) \r
-                               tm.Indices.Add (tm.MemberInfos[i].Name, i);\r
+                       for(int i = 0; i < tm.MemberInfos.Length; i++) {\r
+                               SoapFieldAttribute at = (SoapFieldAttribute) InternalRemotingServices.GetCachedSoapAttribute (tm.MemberInfos[i]);\r
+                               tm.Indices [XmlConvert.EncodeLocalName (at.XmlElementName)] = i;\r
+                       }\r
                        \r
                        _fieldIndices[type] = tm;\r
                        return tm;\r
+               }
+               
+               public Type GetTypeFromQName (string qname)
+               {
+                       string[] strName = qname.Split(':');\r
+                       string namespaceURI = xmlReader.LookupNamespace (strName[0]);\r
+                       return mapper.GetType (strName[1], namespaceURI);\r
                }\r
                \r
                #endregion\r