679e38bb85aeada3fff177a8e3cd3cf7f216c2d8
[mono.git] / mcs / class / System.Web / System.Web.J2EE / BaseHttpServlet.cs
1 //
2 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
3 //
4
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 //
25
26 #define USE_APPSERVER_THREAD
27
28 using System;
29
30 using System.Configuration;
31 using System.Web.Configuration;
32 using System.Threading;
33 using System.Web.Hosting;
34 using System.IO;
35
36 using javax.servlet;
37 using javax.servlet.http;
38 using vmw.common;
39
40 namespace System.Web.J2EE
41 {
42         public class BaseHttpServlet : HttpServlet
43         {
44                 //private AppDomain _servletDomain;
45                 static LocalDataStoreSlot _servletRequestSlot = Thread.GetNamedDataSlot(J2EEConsts.SERVLET_REQUEST);
46                 static LocalDataStoreSlot _servletResponseSlot = Thread.GetNamedDataSlot(J2EEConsts.SERVLET_RESPONSE);
47                 static LocalDataStoreSlot _servletSlot = Thread.GetNamedDataSlot(J2EEConsts.CURRENT_SERVLET);
48
49                 public BaseHttpServlet()
50                 {
51                 }
52
53                 override public void init(ServletConfig config)
54                 {
55                         base.init(config);
56                         InitServlet(config);
57                         
58                 }
59
60                 protected virtual void InitServlet(ServletConfig config)
61                 {
62                         try 
63                         {
64                                 AppDomain servletDomain = createServletDomain(config);
65                                 vmw.@internal.EnvironmentUtils.setAppDomain(servletDomain);
66
67                                 //GH Infromation Initizalization
68                                 int nowInt = DateTime.Now.ToString().GetHashCode();
69                                 servletDomain.SetData(".domainId", nowInt.ToString("x"));
70                                 nowInt += "/".GetHashCode ();
71                                 servletDomain.SetData(".appId", nowInt.ToString("x"));
72                                 servletDomain.SetData(".appName", nowInt.ToString("x"));
73
74                                 servletDomain.SetData(J2EEConsts.CLASS_LOADER, vmw.common.TypeUtils.ToClass(this).getClassLoader());
75                                 servletDomain.SetData(J2EEConsts.SERVLET_CONFIG, config);
76                                 servletDomain.SetData(J2EEConsts.RESOURCE_LOADER, new vmw.@internal.j2ee.ServletResourceLoader(config.getServletContext()));
77
78                                 config.getServletContext().setAttribute(J2EEConsts.APP_DOMAIN, servletDomain);
79                         }
80                         finally 
81                         {
82                                 vmw.@internal.EnvironmentUtils.cleanTLS();
83                                 vmw.@internal.EnvironmentUtils.clearAppDomain();
84                         }
85                 }
86
87                 override protected void service (HttpServletRequest req, HttpServletResponse resp)
88                 {
89 #if !USE_APPSERVER_THREAD
90                         // temporary workaround
91                         PersonalServiceThread pt = new PersonalServiceThread (new PersonalServiceThread.ServiceDelegate (service2), req, resp);
92                         pt.RunWait ();
93                 }
94
95                 protected void service2(HttpServletRequest req, HttpServletResponse resp)
96                 {
97 #endif
98                         try 
99                         {
100                                 // Very important - to update Virtual Path!!!
101                                 AppDomain servletDomain = (AppDomain)this.getServletContext().getAttribute(J2EEConsts.APP_DOMAIN);
102                                 servletDomain.SetData(IAppDomainConfig.APP_VIRT_DIR, req.getContextPath());
103                                 servletDomain.SetData(".hostingVirtualPath", req.getContextPath());
104
105                                 // Put to the TLS current AppDomain of the servlet, so anyone can use it.
106                                 vmw.@internal.EnvironmentUtils.setAppDomain(servletDomain);
107
108                                 //put request to the TLS
109                                 Thread.SetData(_servletRequestSlot, req);
110                                 //put response to the TLS
111                                 Thread.SetData(_servletResponseSlot, resp);
112                                 //put the servlet object to the TLS
113                                 Thread.SetData(_servletSlot, this);
114                                 
115
116
117                                 resp.setHeader("X-Powered-By", "ASP.NET");
118                                 resp.setHeader("X-AspNet-Version", "1.1.4322");
119
120                                 //PageMapper.LoadFileList();
121
122                                 resp.setContentType("text/html");
123                                 HttpWorkerRequest gwr = new ServletWorkerRequest(this, req, resp);
124                                 HttpRuntime.ProcessRequest(gwr);
125                         }
126                         finally 
127                         {
128                                 HttpContext.Current = null;
129                                 Thread.SetData(_servletRequestSlot, null);
130                                 Thread.SetData(_servletResponseSlot, null);
131                                 Thread.SetData(_servletSlot, null);
132                                 vmw.@internal.EnvironmentUtils.clearAppDomain();
133                                 //cleaning
134                                 //vmw.Utils.cleanTLS(); //clean up all TLS entries for current Thread.
135                                 //java.lang.Thread.currentThread().setContextClassLoader(null);
136                         }
137                 }
138
139                 override public void destroy()
140                 {
141                         try 
142                         {
143                                 AppDomain servletDomain = (AppDomain)this.getServletContext().getAttribute(J2EEConsts.APP_DOMAIN);
144                                 vmw.@internal.EnvironmentUtils.setAppDomain(servletDomain);
145 #if DEBUG
146                                 Console.WriteLine("Destroy of GhHttpServlet");
147 #endif
148                                 base.destroy();
149                                 HttpRuntime.Close();
150                                 vmw.@internal.EnvironmentUtils.cleanAllBeforeServletDestroy(this);
151                                 this.getServletContext().removeAttribute(J2EEConsts.APP_DOMAIN);
152                                 java.lang.Thread.currentThread().setContextClassLoader(null);
153                         }
154                         catch(Exception e) 
155                         {
156 #if DEBUG
157                                 Console.WriteLine("ERROR in Servlet Destroy {0},{1}",e.GetType(), e.Message);
158                                 Console.WriteLine(e.StackTrace);
159 #endif
160                         }
161                         finally
162                         {
163                                 vmw.@internal.EnvironmentUtils.clearAppDomain();
164                         }
165                 }
166
167                 private AppDomain createServletDomain(ServletConfig config)
168                 {
169                                 string rootPath = J2EEUtils.GetApplicationRealPath(config);
170                                 AppDomainSetup domainSetup = new AppDomainSetup();
171                                 string name = config.getServletName();//.getServletContextName();
172                                 if (name == null)
173                                         name = "GH Application";
174                                 domainSetup.ApplicationName = name;
175                                 domainSetup.ConfigurationFile = rootPath + "/Web.config";
176
177                                 AppDomain servletDomain = AppDomain.CreateDomain(name, null, domainSetup);
178
179
180
181
182
183                                 //servletDomain.SetData(IAppDomainConfig.APP_PHYS_DIR, J2EEUtils.GetApplicationPhysicalPath(config));
184                                 //servletDomain.SetData(IAppDomainConfig.WEB_APP_DIR, rootPath);
185
186                                 servletDomain.SetData(IAppDomainConfig.APP_PHYS_DIR, J2EEUtils.GetApplicationPhysicalPath(config));
187                                 servletDomain.SetData(IAppDomainConfig.WEB_APP_DIR, rootPath);
188
189                                 //Set DataDirectory substitution string (http://blogs.msdn.com/dataaccess/archive/2005/10/28/486273.aspx)
190                                 string realPath = config.getServletContext ().getRealPath ("/");
191                                 if (realPath == null)
192                                         realPath = String.Empty;
193                                 string dataDirectory = Path.Combine (realPath, "App_Data");
194                                 dataDirectory = dataDirectory.Replace ('\\', '/');
195
196                                 if (dataDirectory [dataDirectory.Length - 1] != '/')
197                                         dataDirectory += "/";
198
199                                 servletDomain.SetData ("DataDirectory", dataDirectory);
200
201                                 // The BaseDir is the full path to the physical dir of the app
202                                 // and allows the application to modify files in the case of
203                                 // open deployment.
204                                 string webApp_baseDir = config.getServletContext().getRealPath("");
205                                 if (webApp_baseDir == null || webApp_baseDir == "")
206                                         webApp_baseDir = rootPath;
207                                 servletDomain.SetData(IAppDomainConfig.APP_BASE_DIR , webApp_baseDir);
208 #if DEBUG
209                                 Console.WriteLine("Initialization of webapp " + webApp_baseDir);
210 #endif
211                                 // Mordechai : setting the web app deserializer object.
212                                 servletDomain.SetData(J2EEConsts.DESERIALIZER_CONST , this.GetDeserializer());
213                                 servletDomain.SetData(vmw.@internal.EnvironmentUtils.GH_DRIVER_UTILS_CONST, this.getDriverUtils());
214                                 //servletDomain.SetData(".hostingVirtualPath", "/");
215                                 //servletDomain.SetData(".hostingInstallDir", "/");
216                                 return servletDomain;
217                 }
218         
219                 virtual protected vmw.@internal.io.IObjectsDeserializer GetDeserializer()
220                 {
221                         if (m_deseializer == null)
222                                 m_deseializer = new GHWebDeseserializer();
223                         return m_deseializer;
224                 }
225
226                 protected vmw.@internal.io.IObjectsDeserializer m_deseializer = null;
227                 /// Mordechai: This class comes to solve a problem in class deserialize
228                 /// within web application. The problem is that the classloader that created 
229                 /// some user web class (for example aspx page) is not the class loader
230                 /// that de-serialize it - thus we end with ClassDefNotFoundException.
231                 /// To prevent this situation we delegate the serialization back the the 
232                 /// web app (which has the correct class loader...)
233                 /// 
234
235                 virtual protected vmw.@internal.IDriverUtils getDriverUtils()
236                 {
237                         //by default no driver utils, the specific servlet will override this method
238                         return null;
239                 }
240         }
241
242         public class GHWebDeseserializer : vmw.@internal.io.IObjectsDeserializer 
243         {
244
245                         Object vmw.@internal.io.IObjectsDeserializer.Deserialize(java.io.ObjectInputStream stream)
246                         {
247                                 object obj = stream.readObject();
248                                 return obj;
249                         }
250         }
251 #if !USE_APPSERVER_THREAD
252         public class PersonalServiceThread
253         {
254                 public delegate void ServiceDelegate (HttpServletRequest req, HttpServletResponse resp);
255                 HttpServletRequest _req = null;
256                 HttpServletResponse _resp = null;
257                 Thread _worker = null;
258                 ServiceDelegate _service = null;
259
260                 public PersonalServiceThread (ServiceDelegate service, HttpServletRequest req, HttpServletResponse resp)
261                 {
262                         _service = service;
263                         _req = req;
264                         _resp = resp;
265
266                         _worker = new Thread (new ThreadStart (Run));
267                 }
268
269                 public void RunWait ()
270                 {
271                         _worker.Start ();
272                         _worker.Join ();
273                 }
274
275                 private void Run ()
276                 {
277                         _service(_req, _resp);
278                 }
279         }
280 #endif
281
282 }
283
284 namespace System.Web.GH
285 {
286         public class BaseHttpServlet : System.Web.J2EE.BaseHttpServlet
287         {
288         }
289
290 }