source: xmlrpcnet/trunk/fuentes/src/XmlRpcServerFormatterSink.cs @ 379

Last change on this file since 379 was 379, checked in by hectorgh, 5 years ago

adding project files

File size: 6.7 KB
Line 
1/*
2XML-RPC.NET library
3Copyright (c) 2001-2006, Charles Cook <charlescook@cookcomputing.com>
4
5Permission is hereby granted, free of charge, to any person
6obtaining a copy of this software and associated documentation
7files (the "Software"), to deal in the Software without restriction,
8including without limitation the rights to use, copy, modify, merge,
9publish, distribute, sublicense, and/or sell copies of the Software,
10and to permit persons to whom the Software is furnished to do so,
11subject to the following conditions:
12
13The above copyright notice and this permission notice shall be
14included in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23DEALINGS IN THE SOFTWARE.
24*/
25
26using System;
27using System.Collections;
28using System.IO;
29using System.Reflection;
30using System.Runtime.Remoting;
31using System.Runtime.Remoting.Channels;
32using System.Runtime.Remoting.Messaging;
33
34using CookComputing.XmlRpc;
35
36namespace CookComputing.XmlRpc
37{
38  public class XmlRpcServerFormatterSink : IServerChannelSink
39  {
40    //constructors
41    //
42    public XmlRpcServerFormatterSink(
43      IServerChannelSink Next)
44    {
45      m_next = Next;
46    }
47
48    // properties
49    //
50    public IServerChannelSink NextChannelSink
51    {
52      get { return m_next; }
53    }
54 
55    public IDictionary Properties
56    {
57      get { return null; }
58    }
59
60    // public methods
61    //
62    public void AsyncProcessResponse(
63      IServerResponseChannelSinkStack sinkStack,
64      object state,
65      IMessage msg,
66      ITransportHeaders headers,
67      Stream stream
68      )
69    {
70      throw new NotSupportedException();
71    }
72
73    public Stream GetResponseStream(
74      IServerResponseChannelSinkStack sinkStack, 
75      object state, 
76      IMessage msg, 
77      ITransportHeaders headers) 
78    {
79      throw new NotSupportedException();
80    }
81
82    public ServerProcessing ProcessMessage(
83      IServerChannelSinkStack sinkStack,
84      IMessage requestMsg,
85      ITransportHeaders requestHeaders,
86      Stream requestStream,
87      out IMessage responseMsg,
88      out ITransportHeaders responseHeaders,
89      out Stream responseStream
90      )
91    {
92      // use presence of SOAPAction header to determine if this is a SOAP
93      // request - if so pass onto next sink in chain
94      string soapAction = (string) requestHeaders["SOAPAction"];
95      if (soapAction != null)
96      {
97        return m_next.ProcessMessage(sinkStack, requestMsg, requestHeaders, 
98          requestStream, out responseMsg, out responseHeaders, 
99          out responseStream);
100      }
101
102      // for time being assume we have an XML-RPC request (need to improve
103      // this in case there are other non-SOAP formatters in the chain)
104      try
105      {
106        MethodCall mthdCall = DeserializeRequest(requestHeaders, requestStream);
107        sinkStack.Push(this, mthdCall);
108        // forward to next sink in chain - pass request stream as null to
109        // indicate that we have deserialized the request
110        m_next.ProcessMessage(sinkStack, mthdCall, requestHeaders, null, 
111          out responseMsg, out responseHeaders, out responseStream);
112        SerializeResponse(responseMsg, ref responseHeaders, ref responseStream);
113      }
114      catch (Exception ex)
115      {
116        responseMsg = new ReturnMessage(ex, (IMethodCallMessage)requestMsg);
117        responseStream = new MemoryStream();
118        XmlRpcFaultException fex = new XmlRpcFaultException(0, ex.Message);
119        XmlRpcSerializer serializer = new XmlRpcSerializer();
120        serializer.SerializeFaultResponse(responseStream, 
121          (XmlRpcFaultException)fex);
122        responseHeaders = new TransportHeaders();
123      }
124      return ServerProcessing.Complete;
125    }
126
127    // private methods
128    //
129    MethodCall DeserializeRequest(
130      ITransportHeaders requestHeaders, 
131      Stream requestStream)
132    {
133      string requestUri = (string) requestHeaders["__RequestUri"];
134      Type svcType = GetServiceType(requestUri);
135      XmlRpcSerializer serializer = new XmlRpcSerializer();
136      XmlRpcRequest xmlRpcReq
137        = serializer.DeserializeRequest(requestStream, svcType);
138      Header[] headers = GetChannelHeaders(requestHeaders, xmlRpcReq, svcType);
139      MethodCall mthdCall = new MethodCall(headers);
140      mthdCall.ResolveMethod();
141      return mthdCall;
142    }
143
144    void SerializeResponse(
145      IMessage responseMsg,
146      ref ITransportHeaders responseHeaders, 
147      ref Stream responseStream)
148    {
149      XmlRpcSerializer serializer = new XmlRpcSerializer();
150      responseStream = new MemoryStream();
151      responseHeaders = new TransportHeaders();
152
153      ReturnMessage retMsg = (ReturnMessage)responseMsg;
154      if (retMsg.Exception == null)
155      {
156        XmlRpcResponse xmlRpcResp = new XmlRpcResponse(retMsg.ReturnValue);
157        serializer.SerializeResponse(responseStream, xmlRpcResp);
158      }
159      else if (retMsg.Exception is XmlRpcFaultException)
160      {
161        serializer.SerializeFaultResponse(responseStream, 
162          (XmlRpcFaultException)retMsg.Exception);
163      }
164      else
165      {
166        serializer.SerializeFaultResponse(responseStream,
167          new XmlRpcFaultException(1, retMsg.Exception.Message));
168      }
169      responseHeaders["Content-Type"] = "text/xml; charset=\"utf-8\"";
170    }
171
172    Header[] GetChannelHeaders(
173      ITransportHeaders requestHeaders,
174      XmlRpcRequest xmlRpcReq,
175      Type svcType) 
176    {
177      string requestUri = (string) requestHeaders["__RequestUri"];
178      XmlRpcServiceInfo svcInfo = XmlRpcServiceInfo.CreateServiceInfo(svcType);
179      ArrayList hdrList = new ArrayList();
180      hdrList.Add(new Header("__Uri", requestUri));
181      hdrList.Add(new Header("__TypeName", svcType.AssemblyQualifiedName));
182      hdrList.Add(new Header("__MethodName", 
183        svcInfo.GetMethodName(xmlRpcReq.method)));
184      hdrList.Add(new Header("__Args", xmlRpcReq.args));
185      return (Header[])hdrList.ToArray(typeof(Header));
186    }
187       
188    public static Type GetServiceType(String Uri)
189    {
190      Type type = RemotingServices.GetServerTypeForUri(Uri);
191      if (type != null)
192        return type;
193      throw new Exception(string.Format("No service type registered "
194        + "for uri {0}", Uri));
195    }
196
197    IServerChannelSink m_next;
198  }
199}
Note: See TracBrowser for help on using the repository browser.