2003-07-09: Jean-Marc Andr�� <jean-marc.andre@polymtl.cs>
authorJean-Marc Andre <jeanmarc@mono-cvs.ximian.com>
Wed, 9 Jul 2003 17:13:46 +0000 (17:13 -0000)
committerJean-Marc Andre <jeanmarc@mono-cvs.ximian.com>
Wed, 9 Jul 2003 17:13:46 +0000 (17:13 -0000)
* SoapClientFormatterSink.cs, SoapClientFormatterSinkProvider.cs SoapServerFormatterSink.cs, SoapServerFormatterSinkProvider.cs, SoapMessageFormatter.cs: Support for the soap serialization added to the remoting infrastructure

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

mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/ChangeLog
mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/SoapClientFormatterSink.cs
mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/SoapClientFormatterSinkProvider.cs [new file with mode: 0644]
mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/SoapMessageFormatter.cs [new file with mode: 0644]
mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/SoapServerFormatterSink.cs
mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/SoapServerFormatterSinkProvider.cs

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..91e701833d3f3041afab5f6474a06738bf51a6b4 100644 (file)
@@ -0,0 +1,6 @@
+2003-07-09:  Jean-Marc André <jean-marc.andre@polymtl.ca>
+
+       * SoapClientFormatterSink.cs, SoapClientFormatterSinkProvider.cs, 
+       SoapServerFormatterSink.cs, SoapServerFormatterSinkProvider.cs, 
+       SoapMessageFormatter.cs: Support for the soap serialization added to
+       the remoting infrastructure.
index b0a2cb80f9e3a4ac0c96bafad9d9392ddc9d9e29..1d58b719ecb3a9488a94857c007b02b953e94a09 100644 (file)
-//
-// System.Runtime.Remoting.Channels.SoapClientFormatterSink.cs
-//
-// Author: Rodrigo Moya (rodrigo@ximian.com)
-//
-// 2002 (C) Copyright, Ximian, Inc.
-//
-
-using System.Collections;
-using System.IO;
-using System.Runtime.Remoting.Messaging;
-
-namespace System.Runtime.Remoting.Channels
-{
-       public class SoapClientFormatterSink : IClientFormatterSink,
-               IMessageSink, IClientChannelSink, IChannelSinkBase
-       {
-               private IClientChannelSink nextClientSink;
-               
-               public SoapClientFormatterSink (IClientChannelSink sink)
-               {
-                       nextClientSink = sink;
-               }
-
-               public IClientChannelSink NextChannelSink
-               {
-                       get {
-                               return nextClientSink;
-                       }
-               }
-
-               public IMessageSink NextSink
-               {
-                       [MonoTODO]
-                       get {
-                               throw new NotImplementedException ();
-                       }
-               }
-
-               public IDictionary Properties
-               {
-                       [MonoTODO]
-                       get {
-                               throw new NotImplementedException ();
-                       }
-               }
-
-               [MonoTODO]
-               public IMessageCtrl AsyncProcessMessage (IMessage msg,
-                                                        IMessageSink replySink)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public void AsyncProcessRequest (IClientChannelSinkStack sinkStack,
-                                                IMessage msg,
-                                                ITransportHeaders headers,
-                                                Stream stream)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
-                                                 object state,
-                                                 ITransportHeaders headers,
-                                                 Stream stream)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public Stream GetRequestStream (IMessage msg,
-                                               ITransportHeaders headers)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public void ProcessMessage (IMessage msg,
-                                           ITransportHeaders requestHeaders,
-                                           Stream requestStream,
-                                           out ITransportHeaders responseHeaders,
-                                           out Stream responseStream)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public IMessage SyncProcessMessage (IMessage msg)
-               {
-                       throw new NotImplementedException ();
-               }
-       }
-}
+//\r
+// System.Runtime.Remoting.Channels.SoapClientFormatterSink.cs\r
+//\r
+// Authors:    Rodrigo Moya (rodrigo@ximian.com)\r
+//             Jean-Marc André (jean-marc.andre@polymtl.ca)\r
+//\r
+// 2002 (C) Copyright, Ximian, Inc.\r
+//\r
+\r
+using System.Collections;\r
+using System.IO;\r
+using System.Reflection;\r
+using System.Runtime.Remoting.Messaging;\r
+using System.Runtime.Serialization;\r
+using System.Runtime.Serialization.Formatters;\r
+using System.Runtime.Serialization.Formatters.Soap;\r
+\r
+namespace System.Runtime.Remoting.Channels\r
+{\r
+       public class SoapClientFormatterSink : IClientFormatterSink,\r
+               IMessageSink, IClientChannelSink, IChannelSinkBase\r
+       {\r
+               private IClientChannelSink _nextChannelSink;\r
+               private SoapFormatter _serializationFormatter;\r
+               private SoapFormatter _deserializationFormatter;\r
+               \r
+               public SoapClientFormatterSink (IClientChannelSink sink)\r
+               {\r
+                       _nextChannelSink = sink;\r
+                       RemotingSurrogateSelector surrogateSelector = new RemotingSurrogateSelector();\r
+                       StreamingContext context = new StreamingContext(StreamingContextStates.Remoting);\r
+                       _serializationFormatter = new SoapFormatter(surrogateSelector, context);\r
+                       _deserializationFormatter = new SoapFormatter(null, context);\r
+               }\r
+               \r
+               // IClientChannelSink\r
+               public IClientChannelSink NextChannelSink\r
+               {\r
+                       get {\r
+                               return _nextChannelSink;\r
+                       }\r
+               }\r
+               \r
+               // IMessageSink\r
+               public IMessageSink NextSink\r
+               {\r
+                       get {\r
+                               return null ;\r
+                       }\r
+               }\r
+               \r
+               // IChannelSinkBase\r
+               public IDictionary Properties\r
+               {\r
+                       get {\r
+                               return null;\r
+                       }\r
+               }\r
+\r
+               public IMessageCtrl AsyncProcessMessage (IMessage msg,\r
+                                                        IMessageSink replySink)\r
+               {\r
+                       Stream requestStream;\r
+                       ITransportHeaders requestHeaders;\r
+                       SoapMessageFormatter soapMsgFormatter;\r
+                       \r
+                       SerializeMessage(msg, out requestStream, out requestHeaders, out soapMsgFormatter);\r
+\r
+                       ClientChannelSinkStack stack = new ClientChannelSinkStack(replySink);\r
+                       stack.Push(this, soapMsgFormatter);\r
+\r
+                       _nextChannelSink.AsyncProcessRequest(stack, msg, requestHeaders, requestStream);\r
+\r
+                       return null;\r
+               }\r
+\r
+               public void AsyncProcessRequest (IClientChannelSinkStack sinkStack,\r
+                                                IMessage msg,\r
+                                                ITransportHeaders headers,\r
+                                                Stream stream)\r
+               {\r
+                       // this method should never be called\r
+                       throw new NotSupportedException ();\r
+               }\r
+\r
+               public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,\r
+                                                 object state,\r
+                                                 ITransportHeaders headers,\r
+                                                 Stream stream)\r
+               {\r
+                       SoapMessageFormatter soapMsgFormatter = (SoapMessageFormatter)state;\r
+\r
+                       IMessage replyMessage = (IMessage) DeserializeMessage(stream, headers, (IMethodCallMessage)state, soapMsgFormatter);\r
+\r
+                       sinkStack.DispatchReplyMessage(replyMessage);\r
+                       \r
+               }\r
+\r
+               public Stream GetRequestStream (IMessage msg,\r
+                                               ITransportHeaders headers)\r
+               {\r
+                       // First sink in the chain so this method should never\r
+                       // be called\r
+                       throw new NotSupportedException ();\r
+               }\r
+\r
+               public void ProcessMessage (IMessage msg,\r
+                                           ITransportHeaders requestHeaders,\r
+                                           Stream requestStream,\r
+                                           out ITransportHeaders responseHeaders,\r
+                                           out Stream responseStream)\r
+               {\r
+                       // First sink in the chain so this method should never\r
+                       // be called\r
+                       throw new NotSupportedException ();\r
+                       \r
+               }\r
+\r
+//             ////[MonoTODO]\r
+               public IMessage SyncProcessMessage (IMessage msg)\r
+               {\r
+                       Stream requestStream, responseStream;\r
+                       ITransportHeaders requestHeaders, responseHeaders;\r
+                       SoapMessageFormatter soapMsgFormatter;\r
+                       \r
+                       SerializeMessage(msg, out requestStream, out requestHeaders, out soapMsgFormatter);\r
+                       _nextChannelSink.ProcessMessage(msg, requestHeaders, requestStream, out responseHeaders, out responseStream);\r
+                       \r
+                       return DeserializeMessage(responseStream, responseHeaders, (IMethodCallMessage)msg, soapMsgFormatter);\r
+               }\r
+               \r
+               \r
+               private void SerializeMessage(IMessage msg, out Stream requestStream, out ITransportHeaders requestHeaders, out SoapMessageFormatter soapMsgFormatter) {\r
+                       SoapMessage soapMsg;\r
+                       soapMsgFormatter = new SoapMessageFormatter();\r
+                       soapMsg = soapMsgFormatter.BuildSoapMessageFromMethodCall((IMethodCallMessage) msg, out requestHeaders);\r
+                       \r
+                       // Get the stream where the message will be serialized\r
+                       requestStream = _nextChannelSink.GetRequestStream(msg, requestHeaders);\r
+                       \r
+                       if(requestStream == null) requestStream = new MemoryStream();\r
+                       \r
+                       // Serialize the message into the stream\r
+                       _serializationFormatter.Serialize(requestStream, soapMsg, null);\r
+                       \r
+                       if(requestStream is MemoryStream){\r
+                               requestStream.Position = 0;\r
+                       }\r
+\r
+                       \r
+               }\r
+               \r
+               \r
+               private IMessage DeserializeMessage(Stream responseStream, ITransportHeaders responseHeaders,IMethodCallMessage mcm, SoapMessageFormatter soapMsgFormatter) {\r
+                       SoapMessage rtnMessage = new SoapMessage();\r
+                       _deserializationFormatter.TopObject = rtnMessage;\r
+                       object objReturn = _deserializationFormatter.Deserialize(responseStream);\r
+                       \r
+                       return soapMsgFormatter.FormatResponse((ISoapMessage) objReturn, mcm);\r
+                       \r
+                       \r
+               }\r
+       }\r
+}\r
diff --git a/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/SoapClientFormatterSinkProvider.cs b/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/SoapClientFormatterSinkProvider.cs
new file mode 100644 (file)
index 0000000..0da38c2
--- /dev/null
@@ -0,0 +1,41 @@
+// created on 20/05/2003 at 12:33\r
+using System.Collections;\r
+using System.Runtime.Remoting.Messaging;\r
+\r
+\r
+namespace System.Runtime.Remoting.Channels {\r
+       public class SoapClientFormatterSinkProvider: IClientFormatterSinkProvider, \r
+               IClientChannelSinkProvider \r
+       {\r
+               private IClientChannelSinkProvider _nextClientChannelSinkProvider;\r
+               private IDictionary _properties;\r
+               private ICollection _providerData;\r
+               \r
+               public SoapClientFormatterSinkProvider() {\r
+                       \r
+               }\r
+               \r
+               public SoapClientFormatterSinkProvider(IDictionary properties,\r
+                                                      ICollection providerData)\r
+               {\r
+                       _properties = properties;\r
+                       _providerData = providerData;\r
+               }\r
+               \r
+               public virtual IClientChannelSinkProvider Next {\r
+                       get { return _nextClientChannelSinkProvider;}\r
+                       set { _nextClientChannelSinkProvider = value;}\r
+               }\r
+               \r
+               public virtual IClientChannelSink CreateSink( IChannelSender channel, \r
+                                                            string url, \r
+                                                            object remoteChannelData)\r
+               {\r
+                       IClientChannelSink _nextSink = _nextClientChannelSinkProvider.CreateSink(channel, url, remoteChannelData);\r
+                       \r
+                       IClientChannelSink scfs = new SoapClientFormatterSink(_nextSink); \r
+                       return scfs;\r
+                       \r
+               }\r
+       }\r
+}\r
diff --git a/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/SoapMessageFormatter.cs b/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels/SoapMessageFormatter.cs
new file mode 100644 (file)
index 0000000..6e09c2a
--- /dev/null
@@ -0,0 +1,267 @@
+// created on 03/04/2003 at 14:09\r
+// \r
+// System.Runtime.Remoting.Channels.SoapMessageFormatter\r
+//\r
+// Author:     Jean-Marc Andre (jean-marc.andre@polymtl.ca)\r
+//\r
+//\r
+\r
+using System;\r
+using System.Collections;\r
+using System.Reflection;\r
+using System.Runtime.Remoting.Messaging;\r
+using System.Runtime.Serialization;\r
+using System.Runtime.Serialization.Formatters;\r
+\r
+\r
+\r
+namespace System.Runtime.Remoting.Channels {\r
+       enum RemMessageType {\r
+               MethodCall, MethodResponse, ServerFault, NotRecognize\r
+       }\r
+       \r
+       internal class SoapMessageFormatter {\r
+               private static FieldInfo _serverFaultExceptionField;\r
+               private Type _serverType;\r
+               private MethodInfo _methodCallInfo;\r
+               private ParameterInfo[] _methodCallParameters;\r
+               private string _xmlNamespace;\r
+               \r
+               static SoapMessageFormatter() {\r
+                       // Get the ServerFault exception field FieldInfo that\r
+                       // will be used later if an exception occurs on the server\r
+                       MemberInfo[] mi = FormatterServices.GetSerializableMembers(typeof(ServerFault), new StreamingContext(StreamingContextStates.All));\r
+                       FieldInfo fi;\r
+                       for(int i = 0; i < mi.Length; i++){\r
+                               fi = mi[i] as FieldInfo;\r
+                               if(fi != null && fi.FieldType == typeof(Exception)){\r
+                                       _serverFaultExceptionField = fi; \r
+                               }\r
+                       }\r
+                       \r
+               }\r
+               \r
+               internal SoapMessageFormatter() {\r
+                       \r
+               }\r
+               \r
+               // used by the client\r
+               internal IMessage FormatResponse(ISoapMessage soapMsg, \r
+                                                       IMethodCallMessage mcm) \r
+               {\r
+                       IMessage rtnMsg;\r
+                       \r
+                       if(soapMsg.MethodName == "Fault") {\r
+                               // an exception was thrown by the server\r
+                               Exception e = new SerializationException();\r
+                               int i = Array.IndexOf(soapMsg.ParamNames, "detail");\r
+                               if(_serverFaultExceptionField != null)\r
+                                       // todo: revue this 'cause it's not safe\r
+                                       e = (Exception) _serverFaultExceptionField.GetValue(\r
+                                                       soapMsg.ParamValues[i]);\r
+                               \r
+                               rtnMsg = new ReturnMessage((System.Exception)e, mcm);\r
+                       }\r
+                       else {\r
+                               object rtnObject = null;\r
+                               ArrayList outParams = new ArrayList();\r
+                               int nbOutParams = 0;\r
+                               RemMessageType messageType;\r
+                               \r
+                               // Get the output of the function if it is not *void*\r
+                               if(_methodCallInfo.ReturnType != typeof(void)){\r
+                                       int index = Array.IndexOf(soapMsg.ParamNames, "return");\r
+                                       rtnObject = soapMsg.ParamValues[index];\r
+                                       if(rtnObject is IConvertible) \r
+                                               rtnObject = Convert.ChangeType(\r
+                                                               rtnObject, \r
+                                                               _methodCallInfo.ReturnType);\r
+                               }\r
+                               // check if there are *out* parameters\r
+                               foreach(ParameterInfo paramInfo in _methodCallParameters) {\r
+                                       \r
+                                       if(paramInfo.IsOut) {\r
+                                               int index = Array.IndexOf(soapMsg.ParamNames, paramInfo.Name);\r
+                                               nbOutParams++;\r
+                                               object outParam = soapMsg.ParamValues[index];\r
+                                               if(outParam is IConvertible)\r
+                                                       outParam = Convert.ChangeType(\r
+                                                                       outParam, \r
+                                                                       paramInfo.ParameterType);\r
+                                               outParams.Add(outParam); \r
+                                       }\r
+//                                     else outParams.Insert(paramInfo.Position - 1, null);\r
+                               }\r
+                               \r
+                               rtnMsg = new ReturnMessage(\r
+                                               rtnObject, \r
+                                               (object[]) outParams.ToArray(typeof(object)), \r
+                                               nbOutParams, \r
+                                               mcm.LogicalCallContext, \r
+                                               mcm);\r
+                       }\r
+                       return rtnMsg;\r
+               }\r
+               \r
+               // used by the client\r
+               internal SoapMessage BuildSoapMessageFromMethodCall(\r
+                               IMethodCallMessage mcm,\r
+                               out ITransportHeaders requestHeaders)\r
+               {\r
+                       \r
+                       requestHeaders = new TransportHeaders();\r
+                       SoapMessage soapMsg = new SoapMessage();\r
+                       string uri = mcm.Uri;\r
+\r
+                       GetInfoFromMethodCallMessage(mcm);\r
+\r
+                       // Format the SoapMessage that will be used to create the RPC\r
+                       soapMsg.MethodName = mcm.MethodName;\r
+                       int count = mcm.ArgCount;\r
+                       ArrayList paramNames = new ArrayList(_methodCallParameters.Length);\r
+                       ArrayList paramTypes = new ArrayList(_methodCallParameters.Length);\r
+                       ArrayList paramValues = new ArrayList(_methodCallParameters.Length);\r
+                       \r
+                       // Add the function parameters to the SoapMessage class\r
+                       foreach(ParameterInfo paramInfo in _methodCallParameters) {\r
+                               if(!paramInfo.IsOut) {\r
+                                       paramNames.Add(paramInfo.Name);\r
+                                       paramTypes.Add(paramInfo.ParameterType);\r
+                                       paramValues.Add(mcm.Args[paramInfo.Position - 1]);\r
+                               }\r
+                       }                       \r
+                       soapMsg.ParamNames = (string[]) paramNames.ToArray(typeof(string));\r
+                       soapMsg.ParamTypes = (Type[]) paramTypes.ToArray(typeof(Type));\r
+                       soapMsg.ParamValues = (object[]) paramValues.ToArray(typeof(object));\r
+                       soapMsg.XmlNameSpace = SoapServices.GetXmlNamespaceForMethodCall(_methodCallInfo);    \r
+                       \r
+                       // Format the transport headers\r
+                       requestHeaders["Content-Type"] = "text/xml; charset=\"utf-8\"";\r
+                       requestHeaders["SOAPAction"] = "\""+\r
+                               SoapServices.GetSoapActionFromMethodBase(_methodCallInfo)+"\""; \r
+                       requestHeaders[CommonTransportKeys.RequestUri] = mcm.Uri;\r
+                       \r
+                       return soapMsg;\r
+                       \r
+               }\r
+               \r
+               // used by the server\r
+               internal IMessage BuildMethodCallFromSoapMessage(SoapMessage soapMessage, string uri) {\r
+                       ArrayList headersList = new ArrayList();\r
+                       ArrayList argsList = new ArrayList();\r
+                       \r
+                       headersList.Add(new Header("__Uri", uri));\r
+                       headersList.Add(new Header("__MethodName", soapMessage.MethodName));\r
+                       string typeNamespace, assemblyName;\r
+                       bool b = SoapServices.DecodeXmlNamespaceForClrTypeNamespace(soapMessage.XmlNameSpace, out typeNamespace, out assemblyName);\r
+                       _serverType = RemotingServices.GetServerTypeForUri(uri);\r
+                       headersList.Add(new Header("__TypeName", _serverType.FullName, false));\r
+                       _xmlNamespace = soapMessage.XmlNameSpace;\r
+                       \r
+                       RemMessageType messageType;\r
+                       _methodCallInfo = _serverType.GetMethod(soapMessage.MethodName); \r
+                       \r
+                       // the *out* parameters aren't serialized\r
+                       // have to add them here\r
+                       _methodCallParameters = _methodCallInfo.GetParameters();\r
+                       foreach(ParameterInfo paramInfo in _methodCallParameters) {\r
+                               if(paramInfo.IsOut) {\r
+                                       argsList.Insert(paramInfo.Position - 1, null);\r
+                               }\r
+                               else{\r
+                                       int index = Array.IndexOf(soapMessage.ParamNames, paramInfo.Name);\r
+                                       if(soapMessage.ParamValues[index] is IConvertible) \r
+                                               soapMessage.ParamValues[index] = Convert.ChangeType(\r
+                                                               soapMessage.ParamValues[index],\r
+                                                               paramInfo.ParameterType);\r
+                                       argsList.Insert(paramInfo.Position - 1, soapMessage.ParamValues[index]);\r
+                               }\r
+                       }\r
+                       \r
+                       Object[] args = (Object[])argsList.ToArray(typeof(object));\r
+                       headersList.Add(new Header("__Args", args, false));\r
+                       Header[] headers = (Header[])headersList.ToArray(typeof(Header));\r
+                       \r
+                       // build the MethodCall from the headers\r
+                       MethodCall mthCall = new MethodCall(headers);\r
+                       return (IMessage)mthCall;\r
+               }\r
+               \r
+               // used by the server\r
+               internal object BuildSoapMessageFromMethodResponse(IMethodReturnMessage mrm, out ITransportHeaders responseHeaders)\r
+               {\r
+                       responseHeaders = new TransportHeaders();\r
+\r
+                       if(mrm.Exception == null) {\r
+                               // *normal* function return\r
+                               \r
+                               SoapMessage soapMessage = new SoapMessage();\r
+                               \r
+                               // fill the transport headers\r
+                               responseHeaders["Content-Type"] = "text/xml; charset=\"utf-8\"";\r
+\r
+                               // build the SoapMessage\r
+                               ArrayList paramNames = new ArrayList();\r
+                               ArrayList paramValues = new ArrayList();\r
+                               ArrayList paramTypes = new ArrayList();\r
+                               soapMessage.MethodName = mrm.MethodName+"Response";\r
+                               if(mrm.ReturnValue != null && mrm.ReturnValue.GetType() != typeof(void)) {\r
+                                       paramNames.Add("return");\r
+                                       paramValues.Add(mrm.ReturnValue);\r
+                                       paramTypes.Add(mrm.ReturnValue.GetType());\r
+                               }\r
+                               \r
+                               for(int i = 0; i < mrm.OutArgCount; i++){\r
+                                       paramNames.Add(mrm.GetOutArgName(i));\r
+                                       paramValues.Add(mrm.GetOutArg(i));\r
+                                       if(mrm.GetOutArg(i) != null) paramTypes.Add(mrm.GetOutArg(i).GetType());\r
+                               }\r
+                               soapMessage.ParamNames = (string[]) paramNames.ToArray(typeof(string));\r
+                               soapMessage.ParamValues = (object[]) paramValues.ToArray(typeof(object));\r
+                               soapMessage.ParamTypes = (Type[]) paramTypes.ToArray(typeof(Type));\r
+                               soapMessage.XmlNameSpace = _xmlNamespace;\r
+                               return soapMessage;\r
+                       }\r
+                       else {\r
+                               // an Exception was thrown while executing the function\r
+                               responseHeaders["__HttpStatusCode"] = "500";\r
+                               responseHeaders["__HttpReasonPhrase"] = "Internal Server Error";\r
+                               // fill the transport headers\r
+                               responseHeaders["Content-Type"] = "text/xml; charset=\"utf-8\"";\r
+                               ServerFault serverFault = CreateServerFault(mrm.Exception);\r
+                               return new SoapFault("Server", String.Format(" **** {0} - {1}", mrm.Exception.GetType().ToString(), mrm.Exception.Message), null, serverFault);\r
+                       }\r
+               }\r
+               \r
+               // used by the server when an exception is thrown\r
+               // by the called function\r
+               internal ServerFault CreateServerFault(Exception e) {\r
+                       // it's really strange here\r
+                       // a ServerFault object has a private System.Exception member called *exception*\r
+                       // (have a look at a MS Soap message when an exception occurs on the server)\r
+                       // but there is not public .ctor with an Exception as parameter...????....\r
+                       // (maybe an internal one). So I searched another way...\r
+                       ServerFault sf = (ServerFault) FormatterServices.GetUninitializedObject(typeof(ServerFault));\r
+                       MemberInfo[] mi = FormatterServices.GetSerializableMembers(typeof(ServerFault), new StreamingContext(StreamingContextStates.All));\r
+                       \r
+                       FieldInfo fi;\r
+                       object[] mv = new object[mi.Length];\r
+                       for(int i = 0; i < mi.Length; i++) {\r
+                               fi = mi[i] as FieldInfo;\r
+                               if(fi != null && fi.FieldType == typeof(Exception)) mv[i] = e;\r
+                       }\r
+                       sf = (ServerFault) FormatterServices.PopulateObjectMembers(sf, mi, mv);\r
+                       \r
+                       return sf;\r
+               }\r
+\r
+               internal void GetInfoFromMethodCallMessage(IMethodCallMessage mcm) {\r
+                       _serverType = Type.GetType(mcm.TypeName, true);\r
+                       \r
+                       _methodCallInfo = _serverType.GetMethod(mcm.MethodName);\r
+                       _methodCallParameters = _methodCallInfo.GetParameters();\r
+               }       \r
+       \r
+               \r
+       }\r
+}\r
index cad836280a2212d476d70779cd6fd9f8104924e4..6d7d57d4975e38737b7686470798f078605696b0 100644 (file)
-//
-// System.Runtime.Remoting.Channels.SoapServerFormatterSink.cs
-//
-// Author: Duncan Mak (duncan@ximian.com)
-//
-// 2002 (C) Copyright, Ximian, Inc.
-//
-
-using System.Collections;
-using System.IO;
-using System.Runtime.Remoting.Messaging;
-
-namespace System.Runtime.Remoting.Channels {
-
-       public class SoapServerFormatterSink : IServerChannelSink, IChannelSinkBase
-       {
-               IServerChannelSink next_sink;
-               
-               [MonoTODO]
-               public SoapServerFormatterSink (SoapServerFormatterSink.Protocol protocol,
-                                               IServerChannelSink nextSink,
-                                               IChannelReceiver receiver)
-               {
-                       this.next_sink = nextSink;
-               }
-
-               public IServerChannelSink NextChannelSink {
-                       get {
-                               return next_sink;
-                       }
-               }
-
-               [MonoTODO]
-               public IDictionary Properties {
-                       get {
-                               throw new NotImplementedException ();
-                       }
-               }
-
-               [MonoTODO]
-               public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
-                                                 IMessage msg, ITransportHeaders headers, Stream stream)
-                                                 
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,
-                                               IMessage msg, ITransportHeaders headers)
-               {
-                       throw new NotImplementedException ();
-               }
-               
-               [MonoTODO]
-               public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
-                                                       IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,
-                                                       out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [Serializable]
-               public enum Protocol
-               {
-                       Http = 0,
-                       Other = 1,
-               }
-       }
-}
+//\r
+// System.Runtime.Remoting.Channels.SoapServerFormatterSink.cs\r
+//\r
+// Authors:    Duncan Mak (duncan@ximian.com)\r
+//             Jean-Marc Andre (jean-marc.andre@polymtl.ca)\r
+//\r
+// 2002 (C) Copyright, Ximian, Inc.\r
+//\r
+\r
+using System.Collections;\r
+using System.IO;\r
+using System.Reflection;\r
+using System.Runtime.Remoting.Messaging;\r
+using System.Runtime.Serialization;\r
+using System.Runtime.Serialization.Formatters;\r
+using System.Runtime.Serialization.Formatters.Soap;\r
+\r
+\r
+namespace System.Runtime.Remoting.Channels {\r
+\r
+       /// <summary>\r
+       //      The formatter sink that uses SoapFormatter\r
+       /// </summary>\r
+       // <remarks>\r
+       //      The formatter sink deserializes the message from the channel sink\r
+       //      and passes the result to the remoting infrastructure\r
+       // </remark>\r
+       //      \r
+       public class SoapServerFormatterSink : IServerChannelSink, IChannelSinkBase\r
+       {\r
+               IServerChannelSink next_sink;\r
+               IChannelReceiver _receiver;\r
+               private SoapFormatter _serializationFormatter;\r
+               private SoapFormatter _deserializationFormatter;\r
+               \r
+               public SoapServerFormatterSink (SoapServerFormatterSink.Protocol protocol,\r
+                                               IServerChannelSink nextSink,\r
+                                               IChannelReceiver receiver)\r
+               {\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
+               /// <summary>\r
+               //      Gets the next channel sink in the channel sink chain\r
+               //  </summary>\r
+               /// <value>\r
+               //      The next channel sink in the sink chain\r
+               //  </value>\r
+               public IServerChannelSink NextChannelSink {\r
+                       get {\r
+                               return next_sink;\r
+                       }\r
+               }\r
+\r
+               public IDictionary Properties {\r
+                       get {\r
+                               return null;\r
+                       }\r
+               }\r
+\r
+               public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,\r
+                                                 IMessage msg, ITransportHeaders headers, Stream stream)\r
+                                                 \r
+               {\r
+                       ITransportHeaders responseHeaders = new TransportHeaders();\r
+\r
+                       if(sinkStack != null) stream = sinkStack.GetResponseStream(msg, responseHeaders);\r
+                       if(stream == null) stream = new MemoryStream();\r
+\r
+                       SoapMessageFormatter soapMsgFormatter = (SoapMessageFormatter)state;\r
+\r
+                       SoapMessage soapMessage = (SoapMessage) soapMsgFormatter.BuildSoapMessageFromMethodResponse((IMethodReturnMessage)msg, out responseHeaders);\r
+\r
+                       _serializationFormatter.Serialize(stream, soapMessage, null);\r
+\r
+                       if(stream is MemoryStream) stream.Position = 0;\r
+               }\r
+\r
+               public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,\r
+                                               IMessage msg, ITransportHeaders headers)\r
+               {\r
+                       // this method shouldn't be called\r
+                       throw new NotSupportedException ();\r
+               }\r
+               \r
+               public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,\r
+                                                       IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,\r
+                                                       out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)\r
+               {\r
+                       responseMsg = null;\r
+                       responseHeaders = null;\r
+                       responseStream = null;\r
+                       \r
+                       string url = (string)requestHeaders[CommonTransportKeys.RequestUri];\r
+                       string uri;\r
+                       _receiver.Parse(url, out uri);\r
+                       if(uri == null) uri = url;\r
+                       Type serverType = RemotingServices.GetServerTypeForUri(uri);\r
+                       \r
+                       SoapMessage soapMessage = new SoapMessage();\r
+                       _deserializationFormatter.TopObject = soapMessage;\r
+                       ServerProcessing sp;\r
+                       object rtnMessageObject;\r
+                       SoapMessageFormatter soapMsgFormatter = new SoapMessageFormatter();\r
+                       requestStream.Position = 0;\r
+                       _deserializationFormatter.Deserialize(requestStream);\r
+                       requestMsg = soapMsgFormatter.BuildMethodCallFromSoapMessage(soapMessage, uri);\r
+                               \r
+                       sinkStack.Push(this, soapMsgFormatter);\r
+\r
+                       try{\r
+                               sp = next_sink.ProcessMessage(sinkStack, requestMsg, requestHeaders, null, out responseMsg, out responseHeaders, out responseStream);\r
+                               \r
+                       }\r
+                       catch(Exception e) {\r
+                               responseMsg = (IMethodReturnMessage)new ReturnMessage(e, (IMethodCallMessage)requestMsg);\r
+                               sp = ServerProcessing.Complete;\r
+                       }\r
+                       \r
+                       if(sp == ServerProcessing.Complete) {\r
+                               if(responseMsg != null && responseStream == null) {\r
+                                       \r
+                                       rtnMessageObject = soapMsgFormatter.BuildSoapMessageFromMethodResponse((IMethodReturnMessage) responseMsg, out responseHeaders);\r
+                                       \r
+                                       responseStream = new MemoryStream();\r
+                                       \r
+                                       _serializationFormatter.Serialize(responseStream, rtnMessageObject);\r
+                               }\r
+\r
+                               sinkStack.Pop(this);\r
+                       }\r
+                       \r
+                       return sp;\r
+                       \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
+                       Http = 0,\r
+                       Other = 1,\r
+               }\r
+       }\r
+\r
+}\r
index 0dfa9a3b08d53f0e18701e71cda2d64fa53d9117..fa308e91e6628b500238a472f0925e9bd2a31bba 100644 (file)
@@ -1,54 +1,59 @@
-//
-// System.Runtime.Remoting.Channels.SoapServerFormatterSinkProvider.cs
-//
-// Author: Rodrigo Moya (rodrigo@ximian.com)
-//
-// 2002 (C) Copyright, Ximian, Inc.
-//
-
-using System.Collections;
-
-namespace System.Runtime.Remoting.Channels
-{
-       public class SoapServerFormatterSinkProvider :
-               IServerFormatterSinkProvider, IServerChannelSinkProvider
-       {
-               [MonoTODO]
-               public SoapServerFormatterSinkProvider ()
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public SoapServerFormatterSinkProvider (IDictionary properties,
-                                                       ICollection providerData)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               public IServerChannelSinkProvider Next
-               {
-                       [MonoTODO]
-                       get {
-                               throw new NotImplementedException ();
-                       }
-
-                       [MonoTODO]
-                       set {
-                               throw new NotImplementedException ();
-                       }
-               }
-
-               [MonoTODO]
-               public IServerChannelSink CreateSink (IChannelReceiver channel)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public void GetChannelData (IChannelDataStore channelData)
-               {
-                       throw new NotImplementedException ();
-               }
-       }
-}
+//\r
+// System.Runtime.Remoting.Channels.SoapServerFormatterSinkProvider.cs\r
+//\r
+// Author: Rodrigo Moya (rodrigo@ximian.com)\r
+//\r
+// 2002 (C) Copyright, Ximian, Inc.\r
+//\r
+\r
+using System.Collections;\r
+\r
+namespace System.Runtime.Remoting.Channels\r
+{\r
+       public class SoapServerFormatterSinkProvider :\r
+               IServerFormatterSinkProvider, IServerChannelSinkProvider\r
+       {\r
+               private IServerChannelSinkProvider _next;\r
+//             ////[MonoTODO]\r
+               public SoapServerFormatterSinkProvider ()\r
+               {\r
+//                     throw new NotImplementedException ();\r
+               }\r
+\r
+//             ////[MonoTODO]\r
+               public SoapServerFormatterSinkProvider (IDictionary properties,\r
+                                                       ICollection providerData)\r
+               {\r
+//                     throw new NotImplementedException ();\r
+               }\r
+\r
+               public IServerChannelSinkProvider Next\r
+               {\r
+//                     ////[MonoTODO]\r
+                       get {\r
+                               return _next;\r
+                       }\r
+\r
+//                     ////[MonoTODO]\r
+                       set {\r
+                               _next = value;\r
+                       }\r
+               }\r
+\r
+//             ////[MonoTODO]\r
+               public IServerChannelSink CreateSink (IChannelReceiver channel)\r
+               {\r
+                       IServerChannelSink chain = _next.CreateSink(channel);\r
+                       IServerChannelSink sinkFormatter = new SoapServerFormatterSink(SoapServerFormatterSink.Protocol.Http, chain, channel);\r
+                       \r
+                       return sinkFormatter;\r
+               }\r
+\r
+//             ////[MonoTODO]\r
+               public void GetChannelData (IChannelDataStore channelData)\r
+               {\r
+                       if(_next != null)\r
+                               _next.GetChannelData(channelData);\r
+               }\r
+       }\r
+}\r