2005-06-14 Lluis Sanchez Gual <lluis@novell.com>
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Protocols / WebServiceHandlerFactory.cs
1 // 
2 // System.Web.Services.Protocols.WebServiceHandlerFactory.cs
3 //
4 // Authors:
5 //      Tim Coleman (tim@timcoleman.com)
6 //      Dave Bettin (dave@opendotnet.com)
7 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 //      Lluis Sanchez Gual (lluis@ximian.com)
9 //
10 // Copyright (C) Tim Coleman, 2002
11 // Copyright (c) 2003 Ximian, Inc. (http://www.ximian.com)
12 //
13
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System.IO;
36 using System.Net;
37 using System.Web.Services;
38 using System.Web.Services.Configuration;
39 using System.Web.SessionState;
40 using System.Web.UI;
41 using System.Collections.Specialized;
42
43 namespace System.Web.Services.Protocols
44 {
45         class SessionWrapperHandler : IHttpHandler, IRequiresSessionState
46         {
47                 IHttpHandler handler;
48
49                 public SessionWrapperHandler (IHttpHandler handler)
50                 {
51                         this.handler = handler;
52                 }
53                 
54                 public bool IsReusable {
55                         get { return handler.IsReusable; }
56                 }
57
58                 public void ProcessRequest (HttpContext context)
59                 {
60                         handler.ProcessRequest (context);
61                 }
62         }
63
64         class ReadOnlySessionWrapperHandler : IHttpHandler, IRequiresSessionState, IReadOnlySessionState
65         {
66                 IHttpHandler handler;
67
68                 public ReadOnlySessionWrapperHandler (IHttpHandler handler)
69                 {
70                         this.handler = handler;
71                 }
72                 
73                 public bool IsReusable {
74                         get { return handler.IsReusable; }
75                 }
76
77                 public void ProcessRequest (HttpContext context)
78                 {
79                         handler.ProcessRequest (context);
80                 }
81         }
82         public class WebServiceHandlerFactory : IHttpHandlerFactory
83         {
84
85                 #region Constructors
86
87                 public WebServiceHandlerFactory () 
88                 {
89                 }
90                 
91                 #endregion // Constructors
92
93                 #region Methods
94
95                 public IHttpHandler GetHandler (HttpContext context, string verb, string url, string filePath)
96                 {
97                         Type type = WebServiceParser.GetCompiledType (filePath, context);
98
99                         WSProtocol protocol = GuessProtocol (context, verb);
100                         bool supported = false;
101                         IHttpHandler handler = null;
102
103                         supported = WSConfig.IsSupported (protocol);
104                         if (!supported) {
105                                 switch (protocol) {
106                                         case WSProtocol.HttpSoap:
107                                                 supported = WSConfig.IsSupported (WSProtocol.HttpSoap12);
108                                                 break;
109                                         case WSProtocol.HttpPost:
110                                                 if (WSConfig.IsSupported (WSProtocol.HttpPostLocalhost)) {
111                                                         string localAddr = context.Request.ServerVariables ["LOCAL_ADDR"];
112
113                                                         supported = localAddr != null &&
114                                                                 (localAddr == context.Request.ServerVariables ["REMOTE_ADDR"] ||
115                                                                 IPAddress.IsLoopback (IPAddress.Parse (localAddr)));
116                                                 }
117                                                 break;
118                                 }
119                         }
120                         if (!supported)
121                                 throw new InvalidOperationException ("Unsupported request format.");
122
123                         switch (protocol) {
124                         case WSProtocol.HttpSoap:
125                                 handler = GetTypeHandler (context, new HttpSoapWebServiceHandler (type));
126                                 break;
127                         case WSProtocol.HttpPost:
128                         case WSProtocol.HttpGet:
129                                 handler = GetTypeHandler (context, new HttpSimpleWebServiceHandler (type, protocol.ToString ()));
130                                 break;
131                         case WSProtocol.Documentation:
132                                 SoapDocumentationHandler soapHandler;
133                                 soapHandler = new SoapDocumentationHandler (type, context);
134                                 if (soapHandler.PageHandler is IRequiresSessionState) {
135                                         if (soapHandler.PageHandler is IReadOnlySessionState)
136                                                 handler = new ReadOnlySessionWrapperHandler (soapHandler);
137                                         else
138                                                 handler = new SessionWrapperHandler (soapHandler);
139                                 } else {
140                                         handler = soapHandler;
141                                 }
142                                 break;
143                         }
144
145                         return handler;
146                 }
147                 
148                 IHttpHandler GetTypeHandler (HttpContext context, WebServiceHandler handler)
149                 {
150                         MethodStubInfo method = handler.GetRequestMethod (context);
151                         if (method == null) return null;
152                         
153                         if (method.MethodInfo.EnableSession)
154                                 return new SessionWrapperHandler (handler);
155                         else
156                                 return handler;
157                 }
158
159                 static WSProtocol GuessProtocol (HttpContext context, string verb)
160                 {
161                         if (context.Request.PathInfo == null || context.Request.PathInfo == "")
162                         {
163                                 if (context.Request.RequestType == "GET")
164                                         return WSProtocol.Documentation;
165                                 else
166                                         return WSProtocol.HttpSoap;
167                         }
168                         else
169                         {
170                                 if (context.Request.RequestType == "GET")
171                                         return WSProtocol.HttpGet;
172                                 else
173                                         return WSProtocol.HttpPost;
174                         }
175                 }
176
177                 public void ReleaseHandler (IHttpHandler handler)
178                 {
179                 }
180
181                 #endregion // Methods
182         }
183 }