Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.Channels / SoapServerFormatterSink.cs
index 1fb925e2640636ac763ee88e55b7a7a6aef12484..d818bca48c7d190ac2309ed9459ba150728e93dc 100644 (file)
@@ -7,6 +7,27 @@
 // 2002 (C) Copyright, Ximian, Inc.\r
 //\r
 \r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
 using System.Collections;\r
 using System.IO;\r
 using System.Reflection;\r
@@ -14,6 +35,7 @@ using System.Runtime.Remoting.Messaging;
 using System.Runtime.Serialization;\r
 using System.Runtime.Serialization.Formatters;\r
 using System.Runtime.Serialization.Formatters.Soap;\r
+using System.Runtime.InteropServices;\r
 \r
 \r
 namespace System.Runtime.Remoting.Channels {\r
@@ -30,8 +52,7 @@ namespace System.Runtime.Remoting.Channels {
        {\r
                IServerChannelSink next_sink;\r
                IChannelReceiver _receiver;\r
-               private SoapFormatter _serializationFormatter;\r
-               private SoapFormatter _deserializationFormatter;\r
+               private SoapCore _soapCore = SoapCore.DefaultInstance;\r
                \r
                public SoapServerFormatterSink (SoapServerFormatterSink.Protocol protocol,\r
                                                IServerChannelSink nextSink,\r
@@ -39,12 +60,14 @@ namespace System.Runtime.Remoting.Channels {
                {\r
                        this.next_sink = nextSink;\r
                        _receiver = receiver;\r
-                       RemotingSurrogateSelector surrogateSelector = new RemotingSurrogateSelector();\r
-                       StreamingContext context = new StreamingContext(StreamingContextStates.Other);\r
-                       _serializationFormatter = new SoapFormatter(surrogateSelector, context);\r
-                       _deserializationFormatter = new SoapFormatter(null, context);\r
                }\r
 \r
+               internal SoapCore SoapCore\r
+               {\r
+                       get { return _soapCore; }\r
+                       set { _soapCore = value; }\r
+               }\r
+               \r
                /// <summary>\r
                //      Gets the next channel sink in the channel sink chain\r
                //  </summary>\r
@@ -63,6 +86,18 @@ namespace System.Runtime.Remoting.Channels {
                        }\r
                }\r
 \r
+               [ComVisible(false)]\r
+               public TypeFilterLevel TypeFilterLevel\r
+               {\r
+                       get { return _soapCore.TypeFilterLevel; }\r
+                       set \r
+                       {\r
+                               IDictionary props = (IDictionary) ((ICloneable)_soapCore.Properties).Clone ();\r
+                               props ["typeFilterLevel"] = value;\r
+                               _soapCore = new SoapCore (this, props, SoapServerFormatterSinkProvider.AllowedProperties);\r
+                       }\r
+               }\r
+\r
                public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,\r
                                                  IMessage msg, ITransportHeaders headers, Stream stream)\r
                                                  \r
@@ -76,9 +111,10 @@ namespace System.Runtime.Remoting.Channels {
 \r
                        SoapMessage soapMessage = (SoapMessage) soapMsgFormatter.BuildSoapMessageFromMethodResponse((IMethodReturnMessage)msg, out responseHeaders);\r
 \r
-                       _serializationFormatter.Serialize(stream, soapMessage, null);\r
+                       _soapCore.Serializer.Serialize(stream, soapMessage, null);\r
 \r
                        if(stream is MemoryStream) stream.Position = 0;\r
+                       sinkStack.AsyncProcessResponse (msg, responseHeaders, stream);\r
                }\r
 \r
                public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,\r
@@ -92,11 +128,36 @@ namespace System.Runtime.Remoting.Channels {
                                                        IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,\r
                                                        out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)\r
                {\r
+                       // Check whether the request was already processed by another\r
+                       // formatter sink and pass the request to the next sink if so.\r
+                       if (requestMsg != null)\r
+                               return next_sink.ProcessMessage (sinkStack,\r
+                                                                requestMsg,\r
+                                                                requestHeaders,\r
+                                                                requestStream,\r
+                                                                out responseMsg,\r
+                                                                out responseHeaders,\r
+                                                                out responseStream);\r
+\r
+                       // Check whether the request is suitable for this formatter\r
+                       // and pass the request to the next sink if not.\r
+                       // Note that a null content-type is handled as suitable,\r
+                       // otherwise no other sink will be able to handle the request.\r
+                       string contentType = requestHeaders["Content-Type"] as string;\r
+                       if (contentType == null || !contentType.StartsWith ("text/xml") || requestHeaders["SOAPAction"] == null) {\r
+                               return next_sink.ProcessMessage (sinkStack,\r
+                                       requestMsg,\r
+                                       requestHeaders,\r
+                                       requestStream,\r
+                                       out responseMsg,\r
+                                       out responseHeaders,\r
+                                       out responseStream);\r
+                       }\r
+\r
                        responseMsg = null;\r
                        responseHeaders = null;\r
                        responseStream = null;\r
 \r
-                       Exception exception;\r
                        ServerProcessing sp;\r
                        SoapMessageFormatter soapMsgFormatter = new SoapMessageFormatter();\r
                        sinkStack.Push(this, soapMsgFormatter);\r
@@ -109,10 +170,10 @@ namespace System.Runtime.Remoting.Channels {
                                Type serverType = RemotingServices.GetServerTypeForUri(uri);\r
                                if (serverType == null) throw new RemotingException ("No receiver for uri " + uri);\r
                        \r
-                               SoapMessage soapMessage = new SoapMessage();\r
-                               _deserializationFormatter.TopObject = soapMessage;\r
-                               requestStream.Position = 0;\r
-                               _deserializationFormatter.Deserialize(requestStream);\r
+                               SoapFormatter fm = _soapCore.GetSafeDeserializer ();\r
+                               SoapMessage soapMessage = soapMsgFormatter.CreateSoapMessage (true);\r
+                               fm.TopObject = soapMessage;\r
+                               fm.Deserialize(requestStream);\r
 \r
                                requestMsg = soapMsgFormatter.BuildMethodCallFromSoapMessage(soapMessage, uri);\r
                                \r
@@ -123,7 +184,8 @@ namespace System.Runtime.Remoting.Channels {
 \r
                                                object rtnMessageObject = soapMsgFormatter.BuildSoapMessageFromMethodResponse((IMethodReturnMessage) responseMsg, out responseHeaders);\r
                                                responseStream = new MemoryStream();\r
-                                               _serializationFormatter.Serialize(responseStream, rtnMessageObject);\r
+                                               _soapCore.Serializer.Serialize(responseStream, rtnMessageObject);\r
+                                               responseStream.Position = 0;\r
                                        }\r
                                }\r
                        }\r
@@ -132,7 +194,8 @@ namespace System.Runtime.Remoting.Channels {
                                responseMsg = (IMethodReturnMessage)new ReturnMessage(e, (IMethodCallMessage)requestMsg);\r
                                object rtnMessageObject = soapMsgFormatter.BuildSoapMessageFromMethodResponse((IMethodReturnMessage) responseMsg, out responseHeaders);\r
                                responseStream = new MemoryStream();\r
-                               _serializationFormatter.Serialize(responseStream, rtnMessageObject);\r
+                               _soapCore.Serializer.Serialize(responseStream, rtnMessageObject);\r
+                               responseStream.Position = 0;\r
                                sp = ServerProcessing.Complete;\r
                        }\r
 \r
@@ -143,13 +206,6 @@ namespace System.Runtime.Remoting.Channels {
                        \r
                }\r
 \r
-               private object HH(Header[] headers) {\r
-                       foreach(Header h in headers) {\r
-                               Console.WriteLine("Name: {0} Value:{0}", h.Name, h.Value);\r
-                       }\r
-                       return null;\r
-               }\r
-               \r
                [Serializable]\r
                public enum Protocol\r
                {\r