* BinaryClientFormatterSinkProvider.cs, BinaryServerFormatterSinkProvider.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                         sinkStack.AsyncProcessResponse (msg, responseHeaders, stream);\r
84                 }\r
85 \r
86                 public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,\r
87                                                 IMessage msg, ITransportHeaders headers)\r
88                 {\r
89                         // this method shouldn't be called\r
90                         throw new NotSupportedException ();\r
91                 }\r
92                 \r
93                 public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,\r
94                                                         IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,\r
95                                                         out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)\r
96                 {\r
97                         responseMsg = null;\r
98                         responseHeaders = null;\r
99                         responseStream = null;\r
100 \r
101                         Exception exception;\r
102                         ServerProcessing sp;\r
103                         SoapMessageFormatter soapMsgFormatter = new SoapMessageFormatter();\r
104                         sinkStack.Push(this, soapMsgFormatter);\r
105 \r
106                         try {\r
107                                 string url = (string)requestHeaders[CommonTransportKeys.RequestUri];\r
108                                 string uri;\r
109                                 _receiver.Parse(url, out uri);\r
110                                 if(uri == null) uri = url;\r
111                                 Type serverType = RemotingServices.GetServerTypeForUri(uri);\r
112                                 if (serverType == null) throw new RemotingException ("No receiver for uri " + uri);\r
113                         \r
114                                 SoapFormatter fm = _soapCore.GetSafeDeserializer ();\r
115                                 SoapMessage soapMessage = new SoapMessage();\r
116                                 fm.TopObject = soapMessage;\r
117                                 requestStream.Position = 0;\r
118                                 fm.Deserialize(requestStream);\r
119 \r
120                                 requestMsg = soapMsgFormatter.BuildMethodCallFromSoapMessage(soapMessage, uri);\r
121                                 \r
122                                 sp = next_sink.ProcessMessage(sinkStack, requestMsg, requestHeaders, null, out responseMsg, out responseHeaders, out responseStream);\r
123                                 \r
124                                 if(sp == ServerProcessing.Complete) {\r
125                                         if(responseMsg != null && responseStream == null) {\r
126 \r
127                                                 object rtnMessageObject = soapMsgFormatter.BuildSoapMessageFromMethodResponse((IMethodReturnMessage) responseMsg, out responseHeaders);\r
128                                                 responseStream = new MemoryStream();\r
129                                                 _soapCore.Serializer.Serialize(responseStream, rtnMessageObject);\r
130                                         }\r
131                                 }\r
132                         }\r
133                         catch(Exception e)\r
134                         {\r
135                                 responseMsg = (IMethodReturnMessage)new ReturnMessage(e, (IMethodCallMessage)requestMsg);\r
136                                 object rtnMessageObject = soapMsgFormatter.BuildSoapMessageFromMethodResponse((IMethodReturnMessage) responseMsg, out responseHeaders);\r
137                                 responseStream = new MemoryStream();\r
138                                 _soapCore.Serializer.Serialize(responseStream, rtnMessageObject);\r
139                                 sp = ServerProcessing.Complete;\r
140                         }\r
141 \r
142                         if (sp == ServerProcessing.Complete)\r
143                                 sinkStack.Pop(this);\r
144 \r
145                         return sp;\r
146                         \r
147                 }\r
148 \r
149                 private object HH(Header[] headers) {\r
150                         foreach(Header h in headers) {\r
151                                 Console.WriteLine("Name: {0} Value:{0}", h.Name, h.Value);\r
152                         }\r
153                         return null;\r
154                 }\r
155                 \r
156                 [Serializable]\r
157                 public enum Protocol\r
158                 {\r
159                         Http = 0,\r
160                         Other = 1,\r
161                 }\r
162         }\r
163 \r
164 }\r