2006-01-04 Chris Toshok <toshok@ximian.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 #if NET_2_0 && CONFIGURATION_2_0
43 using WSConfig = System.Web.Services.Configuration.WebServicesSection;
44 using WSProtocol = System.Web.Services.Configuration.WebServiceProtocols;
45 #endif
46
47 namespace System.Web.Services.Protocols
48 {
49         class SessionWrapperHandler : IHttpHandler, IRequiresSessionState
50         {
51                 IHttpHandler handler;
52
53                 public SessionWrapperHandler (IHttpHandler handler)
54                 {
55                         this.handler = handler;
56                 }
57                 
58                 public bool IsReusable {
59                         get { return handler.IsReusable; }
60                 }
61
62                 public void ProcessRequest (HttpContext context)
63                 {
64                         handler.ProcessRequest (context);
65                 }
66         }
67
68         class ReadOnlySessionWrapperHandler : IHttpHandler, IRequiresSessionState, IReadOnlySessionState
69         {
70                 IHttpHandler handler;
71
72                 public ReadOnlySessionWrapperHandler (IHttpHandler handler)
73                 {
74                         this.handler = handler;
75                 }
76                 
77                 public bool IsReusable {
78                         get { return handler.IsReusable; }
79                 }
80
81                 public void ProcessRequest (HttpContext context)
82                 {
83                         handler.ProcessRequest (context);
84                 }
85         }
86         public class WebServiceHandlerFactory : IHttpHandlerFactory
87         {
88
89                 #region Constructors
90
91                 public WebServiceHandlerFactory () 
92                 {
93                 }
94                 
95                 #endregion // Constructors
96
97                 #region Methods
98
99                 public IHttpHandler GetHandler (HttpContext context, string verb, string url, string filePath)
100                 {
101                         Type type = WebServiceParser.GetCompiledType (filePath, context);
102
103                         WSProtocol protocol = GuessProtocol (context, verb);
104                         bool supported = false;
105                         IHttpHandler handler = null;
106
107                         supported = WSConfig.IsSupported (protocol);
108                         if (!supported) {
109                                 switch (protocol) {
110                                         case WSProtocol.HttpSoap:
111                                                 supported = WSConfig.IsSupported (WSProtocol.HttpSoap12);
112                                                 break;
113                                         case WSProtocol.HttpPost:
114                                                 if (WSConfig.IsSupported (WSProtocol.HttpPostLocalhost)) {
115                                                         string localAddr = context.Request.ServerVariables ["LOCAL_ADDR"];
116
117                                                         supported = localAddr != null &&
118                                                                 (localAddr == context.Request.ServerVariables ["REMOTE_ADDR"] ||
119                                                                 IPAddress.IsLoopback (IPAddress.Parse (localAddr)));
120                                                 }
121                                                 break;
122                                 }
123                         }
124                         if (!supported)
125                                 throw new InvalidOperationException ("Unsupported request format.");
126
127                         switch (protocol) {
128                         case WSProtocol.HttpSoap:
129                                 handler = GetTypeHandler (context, new HttpSoapWebServiceHandler (type));
130                                 break;
131                         case WSProtocol.HttpPost:
132                         case WSProtocol.HttpGet:
133                                 handler = GetTypeHandler (context, new HttpSimpleWebServiceHandler (type, protocol.ToString ()));
134                                 break;
135                         case WSProtocol.Documentation:
136                                 SoapDocumentationHandler soapHandler;
137                                 soapHandler = new SoapDocumentationHandler (type, context);
138                                 if (soapHandler.PageHandler is IRequiresSessionState) {
139                                         if (soapHandler.PageHandler is IReadOnlySessionState)
140                                                 handler = new ReadOnlySessionWrapperHandler (soapHandler);
141                                         else
142                                                 handler = new SessionWrapperHandler (soapHandler);
143                                 } else {
144                                         handler = soapHandler;
145                                 }
146                                 break;
147                         }
148
149                         return handler;
150                 }
151                 
152                 IHttpHandler GetTypeHandler (HttpContext context, WebServiceHandler handler)
153                 {
154                         MethodStubInfo method = handler.GetRequestMethod (context);
155                         if (method == null) return null;
156                         
157                         if (method.MethodInfo.EnableSession)
158                                 return new SessionWrapperHandler (handler);
159                         else
160                                 return handler;
161                 }
162
163                 static WSProtocol GuessProtocol (HttpContext context, string verb)
164                 {
165                         if (context.Request.PathInfo == null || context.Request.PathInfo == "")
166                         {
167                                 if (context.Request.RequestType == "GET")
168                                         return WSProtocol.Documentation;
169                                 else
170                                         return WSProtocol.HttpSoap;
171                         }
172                         else
173                         {
174                                 if (context.Request.RequestType == "GET")
175                                         return WSProtocol.HttpGet;
176                                 else
177                                         return WSProtocol.HttpPost;
178                         }
179                 }
180
181                 public void ReleaseHandler (IHttpHandler handler)
182                 {
183                 }
184
185                 #endregion // Methods
186         }
187 }