* SoapFormatter.cs: Added headers parameter to SoapWriter call.
authorLluis Sanchez <lluis@novell.com>
Wed, 26 May 2004 11:26:05 +0000 (11:26 -0000)
committerLluis Sanchez <lluis@novell.com>
Wed, 26 May 2004 11:26:05 +0000 (11:26 -0000)
* SoapReader.cs: Added support for deserialization of headers. Cache
  both member indexes and member infos in the new TypeMetadata structure.
* SoapWriter.cs: Added support for serialization of headers.

svn path=/trunk/mcs/; revision=28141

mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/ChangeLog
mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapFormatter.cs
mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapReader.cs
mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapWriter.cs

index c746524483cd8de93d699483a4148a36b6fabccc..bdff3ca4effb9b682423a2dc79c52399423aa1ae 100644 (file)
@@ -1,3 +1,10 @@
+2004-05-26  Lluis Sanchez Gual <lluis@ximian.com>
+
+       * SoapFormatter.cs: Added headers parameter to SoapWriter call.
+       * SoapReader.cs: Added support for deserialization of headers. Cache
+         both member indexes and member infos in the new TypeMetadata structure.
+       * SoapWriter.cs: Added support for serialization of headers.
+
 2004-05-10  Gert Driesen (drieseng@users.sourceforge.net)
        * SoapFormatter.cs: sealed class and added ComVisible attribute
        to FilterLevel property to match MS.NET
index 51d09abf1390445d54577120082b36ca60ec837f..0538697021db54532501a3c82dbe7dca38c6342e 100755 (executable)
@@ -85,10 +85,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        CultureInfo savedCi = CultureInfo.CurrentCulture;\r
                        try {\r
                                Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");\r
-                               _soapWriter.Serialize(\r
-                                       graph,\r
-                                       _typeFormat,\r
-                                       _assemblyFormat);\r
+                               _soapWriter.Serialize (graph, headers, _typeFormat, _assemblyFormat);\r
                        }\r
                        finally {\r
                                Thread.CurrentThread.CurrentCulture = savedCi;\r
index 843c3b168cd5c4862480f2014a9c12ee87419b50..83fbf8fbafdc405e4761d026f07bbab27aa6b209 100755 (executable)
@@ -14,6 +14,7 @@ using System.Reflection;
 using System.Collections;\r
 using System.Runtime.Remoting;\r
 using System.Runtime.Serialization;\r
+using System.Runtime.Remoting.Messaging;\r
 \r
 namespace System.Runtime.Serialization.Formatters.Soap {\r
        internal sealed class SoapReader {\r
@@ -28,6 +29,13 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                private ISurrogateSelector _surrogateSelector;\r
                private XmlTextReader xmlReader;\r
                private Hashtable _fieldIndices;\r
+               private long _topObjectId = 1;\r
+               \r
+               class TypeMetadata\r
+               {\r
+                       public MemberInfo[] MemberInfos;\r
+                       public Hashtable Indices;\r
+               }\r
 \r
                #endregion\r
 \r
@@ -60,7 +68,8 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                #region Public Methods\r
 \r
                public object Deserialize(Stream inStream, ISoapMessage soapMessage) \r
-               {\r
+               {
+                       ArrayList headers = null;\r
                        xmlReader = new XmlTextReader(inStream);\r
                        xmlReader.WhitespaceHandling = WhitespaceHandling.None;\r
                        mapper = new SoapTypeMapper(_binder);\r
@@ -69,28 +78,48 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        {\r
                                // SOAP-ENV:Envelope\r
                                xmlReader.MoveToContent();\r
-                               xmlReader.Read();\r
+                               xmlReader.ReadStartElement ();
+                               xmlReader.MoveToContent();
+                               
+                               // Read headers
+                               while (!(xmlReader.NodeType == XmlNodeType.Element && xmlReader.LocalName == "Body" && xmlReader.NamespaceURI == SoapTypeMapper.SoapEnvelopeNamespace))
+                               {\r
+                                       if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.LocalName == "Header" && xmlReader.NamespaceURI == SoapTypeMapper.SoapEnvelopeNamespace)\r
+                                       {\r
+                                               if (headers == null) headers = new ArrayList ();\r
+                                               DeserializeHeaders (headers);\r
+                                       }\r
+                                       else
+                                               xmlReader.Skip ();\r
+                                       xmlReader.MoveToContent();\r
+                               }
+                               \r
                                // SOAP-ENV:Body\r
-                               xmlReader.Read();\r
+                               xmlReader.ReadStartElement();\r
+                               xmlReader.MoveToContent();\r
 \r
                                // The root object\r
-                               if(soapMessage != null)\r
+                               if (soapMessage != null)\r
                                {\r
-                                       if(DeserializeMessage(soapMessage)) \r
-                                       {\r
-                                               RegisterObject(1, soapMessage, null, 0, null, null);\r
+                                       if (DeserializeMessage (soapMessage)) {\r
+                                               _topObjectId = NextAvailableId;\r
+                                               RegisterObject (_topObjectId, soapMessage, null, 0, null, null);\r
                                        }\r
+                                       xmlReader.MoveToContent();\r
+                                       \r
+                                       if (headers != null)\r
+                                               soapMessage.Headers = (Header[]) headers.ToArray (typeof(Header));\r
                                }\r
                                \r
-                               if(xmlReader.NodeType != XmlNodeType.EndElement)\r
-                               {\r
-                                       do\r
-                                       {\r
-                                               Deserialize();\r
+                               while (xmlReader.NodeType != XmlNodeType.EndElement)\r
+                                       Deserialize();\r
+                                       \r
+                               // SOAP-ENV:Body\r
+                               xmlReader.ReadEndElement ();\r
+                               xmlReader.MoveToContent();\r
 \r
-                                       }\r
-                                       while(xmlReader.NodeType != XmlNodeType.EndElement); \r
-                               }\r
+                               // SOAP-ENV:Envelope\r
+                               xmlReader.ReadEndElement ();\r
                        }\r
                        finally \r
                        {\r
@@ -110,7 +139,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        {\r
                                objMgr.DoFixups();\r
                                objMgr.RaiseDeserializationEvent();\r
-                               return objMgr.GetObject(1);\r
+                               return objMgr.GetObject(_topObjectId);\r
                        }\r
                }\r
 \r
@@ -220,6 +249,56 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        xmlReader.ReadEndElement();\r
                        RegisterObject(paramValuesId, message.ParamValues, null, 0, null, null);\r
                        return true;\r
+               }
+\r
+               void DeserializeHeaders (ArrayList headers)\r
+               {\r
+                       xmlReader.ReadStartElement ();\r
+                       xmlReader.MoveToContent ();\r
+                       \r
+                       while (xmlReader.NodeType != XmlNodeType.EndElement) \r
+                       {\r
+                               if (xmlReader.NodeType != XmlNodeType.Element) { xmlReader.Skip(); continue; }\r
+                               \r
+                               if (xmlReader.GetAttribute ("root", SoapTypeMapper.SoapEncodingNamespace) == "1")\r
+                                       headers.Add (DeserializeHeader ());\r
+                               else\r
+                                       Deserialize ();\r
+\r
+                               xmlReader.MoveToContent ();\r
+                       }\r
+                       \r
+                       xmlReader.ReadEndElement ();\r
+               }
+               \r               Header DeserializeHeader ()
+               {
+                       Header h = new Header (xmlReader.LocalName, null);
+                       h.HeaderNamespace = xmlReader.NamespaceURI;\r
+                       h.MustUnderstand = xmlReader.GetAttribute ("mustUnderstand", SoapTypeMapper.SoapEnvelopeNamespace) == "1";\r
+                       \r
+                       object value;\r
+                       long fieldId, fieldHref;\r
+                       long idHeader = NextAvailableId;\r
+                       FieldInfo fieldInfo = typeof(Header).GetField ("Value");\r
+\r
+                       value = DeserializeComponent (null, out fieldId, out fieldHref, idHeader, fieldInfo, null);\r
+                       h.Value = value;\r
+\r
+                       if(fieldHref != 0 && value == null)\r
+                       {\r
+                               RecordFixup (idHeader, fieldHref, h, null, null, fieldInfo, null);\r
+                       }\r
+                       else if(value != null && value.GetType().IsValueType && fieldId != 0)\r
+                       {\r
+                               RecordFixup (idHeader, fieldId, h, null, null, fieldInfo, null);\r
+                       }\r
+                       else if(fieldId != 0)\r
+                       {\r
+                               RegisterObject (fieldId, value, null, idHeader, fieldInfo, null);\r
+                       }\r
+                       \r
+                       RegisterObject (idHeader, h, null, 0, null, null);\r
+                       return h;\r
                }\r
 \r
                \r
@@ -359,7 +438,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                                string elementString = xmlReader.ReadElementString();\r
                                object obj = SoapTypeMapper.ParseXsdValue (elementString, type);\r
                                \r
-                               if(id > 0) \r
+                               if(id != 0) \r
                                        RegisterObject(id, obj, info, parentId, parentMemberInfo, indices);\r
 \r
                                return obj;\r
@@ -406,28 +485,17 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                {\r
                        hasFixup = false;\r
                        Type currentType = obj.GetType();\r
-                       MemberInfo[] memberInfos = \r
-                               FormatterServices.GetSerializableMembers(currentType, _context);\r
-                       Hashtable indices = (Hashtable) _fieldIndices[currentType];\r
-                       if(indices == null) \r
-                       {\r
-                               indices = new Hashtable();\r
-                               for(int i = 0; i < memberInfos.Length; i++) \r
-                               {\r
-                                       indices.Add(memberInfos[i].Name, i);\r
-                               }\r
-                               _fieldIndices[currentType] = indices;\r
-                       }\r
+                       TypeMetadata tm = GetTypeMetadata (currentType);\r
 \r
                        int objDepth = xmlReader.Depth;\r
-                       object[] data = new object[memberInfos.Length];\r
+                       object[] data = new object[tm.MemberInfos.Length];\r
                        xmlReader.Read();\r
-                       for(int i = 0; i < memberInfos.Length; i++)\r
+                       for(int i = 0; i < tm.MemberInfos.Length; i++)\r
                        {\r
                                object fieldObject;\r
                                long fieldId, fieldHref;\r
-                               int index = (int) indices[xmlReader.LocalName];\r
-                               FieldInfo fieldInfo = (memberInfos[index]) as FieldInfo;\r
+                               int index = (int) tm.Indices[xmlReader.LocalName];\r
+                               FieldInfo fieldInfo = (tm.MemberInfos[index]) as FieldInfo;\r
                                if(fieldInfo == null) continue;\r
 \r
                                fieldObject = \r
@@ -459,7 +527,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                                }\r
                        }\r
 \r
-                       FormatterServices.PopulateObjectMembers(obj, memberInfos, data);\r
+                       FormatterServices.PopulateObjectMembers (obj, tm.MemberInfos, data);\r
                        return obj;\r
                }\r
 \r
@@ -618,7 +686,21 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        }\r
                }\r
 \r
-\r
+               TypeMetadata GetTypeMetadata (Type type)\r
+               {\r
+                       TypeMetadata tm = _fieldIndices[type] as TypeMetadata;\r
+                       if (tm != null) return tm;\r
+                       \r
+                       tm = new TypeMetadata ();\r
+                       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
+                       \r
+                       _fieldIndices[type] = tm;\r
+                       return tm;\r
+               }\r
                \r
                #endregion\r
        }\r
index f270eb3e7ae6efadc5b4dbd4b84213b00eb6eb26..aebfff6ab05b84795a4d1f5bf84a7b8eb7f4bdcd 100755 (executable)
@@ -11,6 +11,7 @@ using System.IO;
 using System.Reflection;\r
 using System.Collections;\r
 using System.Runtime.Remoting;\r
+using System.Runtime.Remoting.Messaging;\r
 using System.Runtime.Serialization;\r
 using System.Runtime.Serialization.Formatters;\r
 using System.Xml;\r
@@ -61,6 +62,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                private ObjectIDGenerator idGen = new ObjectIDGenerator();\r
                private FormatterAssemblyStyle _assemblyFormat = FormatterAssemblyStyle.Full;\r
                private FormatterTypeStyle _typeFormat = FormatterTypeStyle.TypesWhenNeeded;\r
+               private static string defaultMessageNamespace;\r
 \r
                #endregion\r
                \r
@@ -86,7 +88,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
 \r
                static SoapWriter() \r
                {\r
-\r
+                       defaultMessageNamespace = typeof(SoapWriter).Assembly.GetName().FullName;\r
                }\r
 \r
                #endregion\r
@@ -162,10 +164,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                }\r
 \r
 \r
-               internal void Serialize(\r
-                       object objGraph,\r
-                       FormatterTypeStyle typeFormat,\r
-                       FormatterAssemblyStyle assemblyFormat)\r
+               internal void Serialize (object objGraph, Header[] headers, FormatterTypeStyle typeFormat, FormatterAssemblyStyle assemblyFormat)\r
                {\r
                        _typeFormat = typeFormat;\r
                        _assemblyFormat = assemblyFormat;\r
@@ -214,8 +213,22 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                                SoapTypeMapper.SoapEnvelopePrefix,\r
                                "encodingStyle",\r
                                SoapTypeMapper.SoapEnvelopeNamespace,\r
-                               "http://schemas.xmlsoap.org/soap/encoding/");\r
-\r
+                               "http://schemas.xmlsoap.org/soap/encoding/");
+                                               
+                       ISoapMessage msg = objGraph as ISoapMessage;\r
+                       if (msg != null)\r
+                               headers = msg.Headers;\r
+                       \r
+                       if (headers != null && headers.Length > 0)\r
+                       {\r
+                               _xmlWriter.WriteStartElement (SoapTypeMapper.SoapEnvelopePrefix, "Header", SoapTypeMapper.SoapEnvelopeNamespace);\r
+                               foreach (Header h in headers)\r
+                                       SerializeHeader (h);\r
+                                       \r
+                               WriteObjectQueue ();\r
+                               _xmlWriter.WriteEndElement ();\r
+                       }\r
+                               \r
                        // The body element\r
                        _xmlWriter.WriteStartElement(\r
                                SoapTypeMapper.SoapEnvelopePrefix,\r
@@ -225,14 +238,20 @@ namespace System.Runtime.Serialization.Formatters.Soap {
 \r
                        bool firstTime = false;\r
 \r
-                       if(objGraph is ISoapMessage)\r
-                       {\r
-                               SerializeMessage(objGraph as ISoapMessage);\r
-                               \r
-                       }\r
+                       if (msg != null)\r
+                               SerializeMessage(msg);\r
                        else\r
                                _objectQueue.Enqueue(new EnqueuedObject( objGraph, idGen.GetId(objGraph, out firstTime)));\r
 \r
+                       WriteObjectQueue ();\r
+\r
+                       _xmlWriter.WriteFullEndElement(); // the body element\r
+                       _xmlWriter.WriteFullEndElement(); // the envelope element\r
+                       _xmlWriter.Flush();\r
+               }\r
+               \r
+               private void WriteObjectQueue ()\r
+               {\r
                        while(_objectQueue.Count > 0) \r
                        {\r
                                EnqueuedObject currentEnqueuedObject;\r
@@ -242,26 +261,19 @@ namespace System.Runtime.Serialization.Formatters.Soap {
 \r
                                if(!currentType.IsValueType) _objectToIdTable[currentObject] = currentEnqueuedObject.Id;\r
 \r
-                               if(currentType.IsArray) \r
-                               {\r
-                                               SerializeArray((Array) currentObject, currentEnqueuedObject.Id);\r
-                               }\r
+                               if(currentType.IsArray)\r
+                                       SerializeArray((Array) currentObject, currentEnqueuedObject.Id);\r
                                else\r
-                               {\r
                                        SerializeObject(currentObject, currentEnqueuedObject.Id);\r
-                               }\r
-\r
                        }\r
-\r
-                       _xmlWriter.WriteFullEndElement(); // the body element\r
-                       _xmlWriter.WriteFullEndElement(); // the envelope element\r
-                       _xmlWriter.Flush();\r
                }\r
 \r
                private void SerializeMessage(ISoapMessage message) \r
                {\r
                        bool firstTime;\r
-                       _xmlWriter.WriteStartElement("i2", message.MethodName, message.XmlNameSpace);\r
+                       string ns = message.XmlNameSpace != null ? message.XmlNameSpace : defaultMessageNamespace;\r
+                       \r
+                       _xmlWriter.WriteStartElement("i2", message.MethodName, ns);\r
                        Id(idGen.GetId(message, out firstTime));\r
 \r
                        string[] paramNames = message.ParamNames;\r
@@ -277,6 +289,16 @@ namespace System.Runtime.Serialization.Formatters.Soap {
 \r
 \r
                        _xmlWriter.WriteFullEndElement();\r
+               }
+               \r               private void SerializeHeader (Header header)
+               {
+                       string ns = header.HeaderNamespace != null ? header.HeaderNamespace : "http://schemas.microsoft.com/clr/soap"; 
+                       _xmlWriter.WriteStartElement ("h4", header.Name, ns);
+                       if (header.MustUnderstand)
+                               _xmlWriter.WriteAttributeString ("mustUnderstand", SoapTypeMapper.SoapEnvelopeNamespace, "1");\r
+                       _xmlWriter.WriteAttributeString ("root", SoapTypeMapper.SoapEncodingNamespace, "1");\r
+                       SerializeComponent (header.Value, true);\r
+                       _xmlWriter.WriteEndElement();\r
                }\r
 \r
                private void SerializeObject(object currentObject, long currentObjectId) \r
@@ -358,9 +380,9 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        if(currentObjectId > 0)\r
                                _xmlWriter.WriteFullEndElement();\r
 \r
-               }\r
-\r
-               private void SerializeISerializableObject(\r
+               }
+               
+               \r               private void SerializeISerializableObject(\r
                        object currentObject,\r
                        long currentObjectId,\r
                        ISerializationSurrogate surrogate)\r