Merge pull request #2942 from jogibear9988/patch-2
[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.Compilation;
38 using System.Web.Services;
39 using System.Web.Services.Configuration;
40 using System.Web.SessionState;
41 using System.Web.UI;
42 using System.Collections.Specialized;
43 using WSConfig = System.Web.Services.Configuration.WebServicesSection;
44 using WSProtocol = System.Web.Services.Configuration.WebServiceProtocols;
45
46 namespace System.Web.Services.Protocols
47 {
48         class SessionWrapperHandler : IHttpHandler, IRequiresSessionState
49         {
50                 IHttpHandler handler;
51
52                 public SessionWrapperHandler (IHttpHandler handler)
53                 {
54                         this.handler = handler;
55                 }
56                 
57                 public bool IsReusable {
58                         get { return handler.IsReusable; }
59                 }
60
61                 public void ProcessRequest (HttpContext context)
62                 {
63                         handler.ProcessRequest (context);
64                 }
65         }
66
67         class ReadOnlySessionWrapperHandler : IHttpHandler, IRequiresSessionState, IReadOnlySessionState
68         {
69                 IHttpHandler handler;
70
71                 public ReadOnlySessionWrapperHandler (IHttpHandler handler)
72                 {
73                         this.handler = handler;
74                 }
75                 
76                 public bool IsReusable {
77                         get { return handler.IsReusable; }
78                 }
79
80                 public void ProcessRequest (HttpContext context)
81                 {
82                         handler.ProcessRequest (context);
83                 }
84         }
85         public class WebServiceHandlerFactory : IHttpHandlerFactory
86         {
87
88                 #region Constructors
89
90                 public WebServiceHandlerFactory () 
91                 {
92                 }
93                 
94                 #endregion // Constructors
95
96                 #region Methods
97
98                 public IHttpHandler GetHandler (HttpContext context, string verb, string url, string filePath)
99                 {
100                         string fp = filePath != null ? filePath.Replace (HttpRuntime.AppDomainAppPath, "/").Replace (Path.DirectorySeparatorChar, '/') : null;
101
102                         Type type;
103                         type = BuildManager.GetCompiledType (url);
104
105                         WSProtocol protocol = GuessProtocol (context, verb);
106                         context.Items ["WebServiceSoapVersion"] =
107                                 protocol == WSProtocol.HttpSoap12 ?
108                                 SoapProtocolVersion.Soap12 :
109                                 SoapProtocolVersion.Default;
110                         bool supported = false;
111                         IHttpHandler handler = null;
112
113                         supported = WSConfig.IsSupported (protocol);
114                         if (!supported) {
115                                 switch (protocol) {
116                                         default:
117                                                 if (((protocol & WSProtocol.AnyHttpSoap) != WSProtocol.Unknown) &&
118                                                         (WSConfig.Current.EnabledProtocols & WSProtocol.AnyHttpSoap) != WSProtocol.Unknown)
119                                                         throw new InvalidOperationException ("Possible SOAP version mismatch.");
120                                                 break;
121                                         case WSProtocol.HttpPost:
122                                                 if (WSConfig.IsSupported (WSProtocol.HttpPostLocalhost)) {
123                                                         supported = context.Request.IsLocal;
124                                                 }
125                                                 break;
126                                 }
127                         }
128                         if (!supported)
129                                 throw new InvalidOperationException ("Unsupported request format.");
130
131                         switch (protocol) {
132                         case WSProtocol.HttpSoap12:
133                         case WSProtocol.HttpSoap:
134                                 handler = GetTypeHandler (context, new HttpSoapWebServiceHandler (type));
135                                 break;
136                         case WSProtocol.HttpPost:
137                         case WSProtocol.HttpGet:
138                                 handler = GetTypeHandler (context, new HttpSimpleWebServiceHandler (type, protocol.ToString ()));
139                                 break;
140                         case WSProtocol.Documentation:
141                                 SoapDocumentationHandler soapHandler;
142                                 soapHandler = new SoapDocumentationHandler (type, context);
143                                 if (soapHandler.PageHandler is IRequiresSessionState) {
144                                         if (soapHandler.PageHandler is IReadOnlySessionState)
145                                                 handler = new ReadOnlySessionWrapperHandler (soapHandler);
146                                         else
147                                                 handler = new SessionWrapperHandler (soapHandler);
148                                 } else {
149                                         handler = soapHandler;
150                                 }
151                                 break;
152                         }
153
154                         return handler;
155                 }
156                 
157                 IHttpHandler GetTypeHandler (HttpContext context, WebServiceHandler handler)
158                 {
159                         MethodStubInfo method = handler.GetRequestMethod (context);
160                         if (method == null) return null;
161
162                         int cache_duration = method.MethodInfo.CacheDuration;
163                         if (cache_duration > 0)
164                                 context.Response.ExpiresAbsolute = DateTime.Now.AddSeconds (cache_duration);
165                         if (method.MethodInfo.EnableSession)
166                                 return new SessionWrapperHandler (handler);
167                         else
168                                 return handler;
169                 }
170
171                 static WSProtocol GuessProtocol (HttpContext context, string verb)
172                 {
173                         if (context.Request.PathInfo == null || context.Request.PathInfo == "")
174                         {
175                                 if (context.Request.RequestType == "GET")
176                                         return WSProtocol.Documentation;
177                                 else
178                                         return context.Request.Headers ["SOAPAction"] != null ?
179                                                 WSProtocol.HttpSoap : WSProtocol.HttpSoap12;
180                         }
181                         else
182                         {
183                                 if (context.Request.RequestType == "GET")
184                                         return WSProtocol.HttpGet;
185                                 else
186                                         return WSProtocol.HttpPost;
187                         }
188                 }
189
190                 public void ReleaseHandler (IHttpHandler handler)
191                 {
192                 }
193
194                 #endregion // Methods
195         }
196 }