* BinaryClientFormatterSink.cs, BinaryClientFormatterSinkProvider.cs,
[mono.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.Channels / SoapServerFormatterSink.cs
1 //\r
2 // System.Runtime.Remoting.Channels.SoapServerFormatterSink.cs\r
3 //\r
4 // Authors:     Duncan Mak (duncan@ximian.com)\r
5 //              Jean-Marc Andre (jean-marc.andre@polymtl.ca)\r
6 //\r
7 // 2002 (C) Copyright, Ximian, Inc.\r
8 //\r
9 \r
10 using System.Collections;\r
11 using System.IO;\r
12 using System.Reflection;\r
13 using System.Runtime.Remoting.Messaging;\r
14 using System.Runtime.Serialization;\r
15 using System.Runtime.Serialization.Formatters;\r
16 using System.Runtime.Serialization.Formatters.Soap;\r
17 \r
18 \r
19 namespace System.Runtime.Remoting.Channels {\r
20 \r
21         /// <summary>\r
22         //      The formatter sink that uses SoapFormatter\r
23         /// </summary>\r
24         // <remarks>\r
25         //      The formatter sink deserializes the message from the channel sink\r
26         //      and passes the result to the remoting infrastructure\r
27         // </remark>\r
28         //      \r
29         public class SoapServerFormatterSink : IServerChannelSink, IChannelSinkBase\r
30         {\r
31                 IServerChannelSink next_sink;\r
32                 IChannelReceiver _receiver;\r
33                 private SoapCore _soapCore = SoapCore.DefaultInstance;\r
34                 \r
35                 public SoapServerFormatterSink (SoapServerFormatterSink.Protocol protocol,\r
36                                                 IServerChannelSink nextSink,\r
37                                                 IChannelReceiver receiver)\r
38                 {\r
39                         this.next_sink = nextSink;\r
40                         _receiver = receiver;\r
41                 }\r
42 \r
43                 internal SoapCore SoapCore\r
44                 {\r
45                         get { return _soapCore; }\r
46                         set { _soapCore = value; }\r
47                 }\r
48                 \r
49                 /// <summary>\r
50                 //      Gets the next channel sink in the channel sink chain\r
51                 //  </summary>\r
52                 /// <value>\r
53                 //      The next channel sink in the sink chain\r
54                 //  </value>\r
55                 public IServerChannelSink NextChannelSink {\r
56                         get {\r
57                                 return next_sink;\r
58                         }\r
59                 }\r
60 \r
61                 public IDictionary Properties {\r
62                         get {\r
63                                 return null;\r
64                         }\r
65                 }\r
66 \r
67                 public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,\r
68                                                   IMessage msg, ITransportHeaders headers, Stream stream)\r
69                                                   \r
70                 {\r
71                         ITransportHeaders responseHeaders = new TransportHeaders();\r
72 \r
73                         if(sinkStack != null) stream = sinkStack.GetResponseStream(msg, responseHeaders);\r
74                         if(stream == null) stream = new MemoryStream();\r
75 \r
76                         SoapMessageFormatter soapMsgFormatter = (SoapMessageFormatter)state;\r
77 \r
78                         SoapMessage soapMessage = (SoapMessage) soapMsgFormatter.BuildSoapMessageFromMethodResponse((IMethodReturnMessage)msg, out responseHeaders);\r
79 \r
80                         _soapCore.Serializer.Serialize(stream, soapMessage, null);\r
81 \r
82                         if(stream is MemoryStream) stream.Position = 0;\r
83                 }\r
84 \r
85                 public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,\r
86                                                 IMessage msg, ITransportHeaders headers)\r
87                 {\r
88                         // this method shouldn't be called\r
89                         throw new NotSupportedException ();\r
90                 }\r
91                 \r
92                 public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,\r
93                                                         IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,\r
94                                                         out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)\r
95                 {\r
96                         responseMsg = null;\r
97                         responseHeaders = null;\r
98                         responseStream = null;\r
99 \r
100                         Exception exception;\r
101                         ServerProcessing sp;\r
102                         SoapMessageFormatter soapMsgFormatter = new SoapMessageFormatter();\r
103                         sinkStack.Push(this, soapMsgFormatter);\r
104 \r
105                         try {\r
106                                 string url = (string)requestHeaders[CommonTransportKeys.RequestUri];\r
107                                 string uri;\r
108                                 _receiver.Parse(url, out uri);\r
109                                 if(uri == null) uri = url;\r
110                                 Type serverType = RemotingServices.GetServerTypeForUri(uri);\r
111                                 if (serverType == null) throw new RemotingException ("No receiver for uri " + uri);\r
112                         \r
113                                 SoapFormatter fm = _soapCore.GetSafeDeserializer ();\r
114                                 SoapMessage soapMessage = new SoapMessage();\r
115                                 fm.TopObject = soapMessage;\r
116                                 requestStream.Position = 0;\r
117                                 fm.Deserialize(requestStream);\r
118 \r
119                                 requestMsg = soapMsgFormatter.BuildMethodCallFromSoapMessage(soapMessage, uri);\r
120                                 \r
121                                 sp = next_sink.ProcessMessage(sinkStack, requestMsg, requestHeaders, null, out responseMsg, out responseHeaders, out responseStream);\r
122                                 \r
123                                 if(sp == ServerProcessing.Complete) {\r
124                                         if(responseMsg != null && responseStream == null) {\r
125 \r
126                                                 object rtnMessageObject = soapMsgFormatter.BuildSoapMessageFromMethodResponse((IMethodReturnMessage) responseMsg, out responseHeaders);\r
127                                                 responseStream = new MemoryStream();\r
128                                                 _soapCore.Serializer.Serialize(responseStream, rtnMessageObject);\r
129                                         }\r
130                                 }\r
131                         }\r
132                         catch(Exception e)\r
133                         {\r
134                                 responseMsg = (IMethodReturnMessage)new ReturnMessage(e, (IMethodCallMessage)requestMsg);\r
135                                 object rtnMessageObject = soapMsgFormatter.BuildSoapMessageFromMethodResponse((IMethodReturnMessage) responseMsg, out responseHeaders);\r
136                                 responseStream = new MemoryStream();\r
137                                 _soapCore.Serializer.Serialize(responseStream, rtnMessageObject);\r
138                                 sp = ServerProcessing.Complete;\r
139                         }\r
140 \r
141                         if (sp == ServerProcessing.Complete)\r
142                                 sinkStack.Pop(this);\r
143 \r
144                         return sp;\r
145                         \r
146                 }\r
147 \r
148                 private object HH(Header[] headers) {\r
149                         foreach(Header h in headers) {\r
150                                 Console.WriteLine("Name: {0} Value:{0}", h.Name, h.Value);\r
151                         }\r
152                         return null;\r
153                 }\r
154                 \r
155                 [Serializable]\r
156                 public enum Protocol\r
157                 {\r
158                         Http = 0,\r
159                         Other = 1,\r
160                 }\r
161         }\r
162 \r
163 }\r