revert changes from r 96616
[mono.git] / mcs / class / Mainsoft.Web / Mainsoft.Web.Hosting / 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 using System;
27
28 using System.Configuration;
29 using System.Web;
30 using System.Web.Configuration;
31 using System.Threading;
32 using System.Web.Hosting;
33 using System.IO;
34
35 using javax.servlet;
36 using javax.servlet.http;
37 using vmw.common;
38 using java.util;
39 using vmw.@internal;
40 using java.lang.reflect;
41 using java.net;
42 using System.Globalization;
43 using System.Diagnostics;
44 using javax.faces;
45 using javax.faces.context;
46 using javax.faces.lifecycle;
47 using javax.faces.webapp;
48 using javax.faces.render;
49
50 namespace Mainsoft.Web.Hosting
51 {
52         public interface IJDBCDriverDeregisterer
53         {
54                 void DeregisterDriver (java.sql.Driver driver);
55         }
56         /// <summary>
57         /// <para>This class supports the Framework infrastructure and is not intended to be used directly from your code.</para>
58         /// </summary>
59         public class BaseHttpServlet : HttpServlet, IJDBCDriverDeregisterer
60         {
61                 bool _appVirDirInited = false;
62
63                 static FacesContextFactory _facesContextFactory;
64                 static Lifecycle _lifecycle;
65                 static RenderKitFactory _renderKitFactory;
66
67                 public BaseHttpServlet()
68                 {
69                 }
70
71                 public static RenderKitFactory RenderKitFactory {
72                         get { return _renderKitFactory; }
73                 }
74
75                 public static FacesContextFactory FacesContextFactory {
76                         get { return _facesContextFactory; }
77                 }
78
79                 public static Lifecycle Lifecycle {
80                         get { return _lifecycle; }
81                 }
82
83                 override public void init(ServletConfig config)
84                 {
85                         base.init(config);
86                         InitRuntime (config, this);
87                 }
88
89                 public static void InitRuntime (ServletConfig config, object evidence) {
90
91                         ServletContext context = config.getServletContext ();
92
93                         if (context.getAttribute (J2EEConsts.APP_DOMAIN) != null)
94                                 return;
95
96                         _facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory (FactoryFinder.FACES_CONTEXT_FACTORY);
97                         //TODO: null-check for Weblogic, that tries to initialize Servlet before ContextListener
98
99                         //Javadoc says: Lifecycle instance is shared across multiple simultaneous requests, it must be implemented in a thread-safe manner.
100                         //So we can acquire it here once:
101                         LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory (FactoryFinder.LIFECYCLE_FACTORY);
102                         _lifecycle = lifecycleFactory.getLifecycle (context.getInitParameter (FacesServlet.LIFECYCLE_ID_ATTR) ?? LifecycleFactory.DEFAULT_LIFECYCLE);
103
104                         _renderKitFactory = (RenderKitFactory) FactoryFinder.getFactory (FactoryFinder.RENDER_KIT_FACTORY);
105
106                         AppDomain servletDomain = createServletDomain (config);
107                         vmw.@internal.EnvironmentUtils.setAppDomain (servletDomain);
108
109                         try {
110                                 //GH Infromation Initizalization
111                                 long currentTime = java.lang.System.currentTimeMillis ();
112                                 servletDomain.SetData (".domainId", currentTime.ToString ("x"));
113                                 currentTime = ~currentTime;
114                                 servletDomain.SetData (".appId", currentTime.ToString ("x"));
115                                 servletDomain.SetData (".appName", servletDomain.SetupInformation.ApplicationName);
116
117                                 servletDomain.SetData (J2EEConsts.CLASS_LOADER, java.lang.Thread.currentThread ().getContextClassLoader ());
118                                 //servletDomain.SetData (J2EEConsts.CLASS_LOADER, vmw.common.TypeUtils.ToClass (evidence).getClassLoader ());
119                                 //servletDomain.SetData(J2EEConsts.SERVLET_CONFIG, config);
120                                 servletDomain.SetData (J2EEConsts.RESOURCE_LOADER, new ServletResourceLoader (context));
121
122                                 lock (evidence) {
123                                         if (context.getAttribute (J2EEConsts.APP_DOMAIN) == null)
124                                                 context.setAttribute (J2EEConsts.APP_DOMAIN, servletDomain);
125                                 }
126                                 //config.getServletContext ().setAttribute (J2EEConsts.CURRENT_SERVLET, this);
127                         }
128                         finally {
129                                 vmw.@internal.EnvironmentUtils.cleanTLS ();
130                                 vmw.@internal.EnvironmentUtils.clearAppDomain ();
131                         }
132                 }
133
134                 protected override void service (HttpServletRequest req, HttpServletResponse resp)
135                 {
136                         const string assemblies = "/assemblies";
137                         const string getping = "getping";
138                         const string setping = "setping";
139                         string servletPath = req.getServletPath ();
140
141                         if (String.CompareOrdinal (assemblies, 0, servletPath, 0, assemblies.Length) == 0) {
142                                 if (servletPath.Length == assemblies.Length ||
143                                                 servletPath [assemblies.Length] == '/') {
144                                         string requestURI = req.getRequestURI ();
145                                         bool getp = requestURI.EndsWith (getping, StringComparison.Ordinal);
146                                         if (!getp && requestURI.EndsWith (setping, StringComparison.Ordinal)) {
147                                                 getServletContext ().setAttribute (getping, "1");
148                                                 getp = true;
149                                         }
150
151                                         if (getp) {
152                                                 string ping = (string) getServletContext ().getAttribute (getping);
153                                                 if (ping == null)
154                                                         ping = "0";
155                                                 resp.getOutputStream ().print (ping);
156                                                 return;
157                                         }
158                                 }
159                         }
160                         resp.setContentType ("text/html");
161
162                         try 
163                         {
164                                 // Very important - to update Virtual Path!!!
165                                 AppDomain servletDomain = (AppDomain)this.getServletContext().getAttribute(J2EEConsts.APP_DOMAIN);
166                                 if (!_appVirDirInited) {
167                                         string appVPath = req.getContextPath ();
168                                         if (appVPath == null || appVPath.Length == 0)
169                                                 appVPath = "/";
170                                         servletDomain.SetData (IAppDomainConfig.APP_VIRT_DIR, appVPath);
171                                         servletDomain.SetData (".hostingVirtualPath", req.getContextPath ());
172                                         _appVirDirInited = true;
173                                 }
174
175                                 // Put to the TLS current AppDomain of the servlet, so anyone can use it.
176                                 vmw.@internal.EnvironmentUtils.setAppDomain(servletDomain);
177
178                                 // put request to the TLS
179                                 //Thread.SetData(_servletRequestSlot, req);
180                                 //// put response to the TLS
181                                 //Thread.SetData(_servletResponseSlot, resp);
182                                 //// put the servlet object to the TLS
183                                 //Thread.SetData(_servletSlot, this);
184
185                                 resp.setHeader("X-Powered-By", "ASP.NET");
186                                 resp.setHeader("X-AspNet-Version", "1.1.4322");
187
188                                 HttpWorkerRequest gwr = new ServletWorkerRequest (this, req, resp);
189                                 CultureInfo culture = (CultureInfo) vmw.@internal.EnvironmentUtils.getCultureInfoFromLocale (req.getLocale ());
190                                 Thread currentTread = Thread.CurrentThread;
191                                 currentTread.CurrentCulture = culture;
192                                 currentTread.CurrentUICulture = culture;
193                                 HttpRuntime.ProcessRequest(gwr);
194                         }
195                         finally 
196                         {
197                                 HttpContext.Current = null;
198                                 //Thread.SetData(_servletRequestSlot, null);
199                                 //Thread.SetData(_servletResponseSlot, null);
200                                 //Thread.SetData(_servletSlot, null);
201                                 vmw.@internal.EnvironmentUtils.clearAppDomain();
202                         }
203                 }
204
205                 override public void destroy()
206                 {
207                         base.destroy();
208                         DestroyRuntime (getServletContext (), this);
209                 }
210
211                 public static void DestroyRuntime (ServletContext context, IJDBCDriverDeregisterer evidence) {
212                         AppDomain servletDomain = (AppDomain) context.getAttribute (J2EEConsts.APP_DOMAIN);
213                         if (servletDomain == null)
214                                 return;
215
216                         try {
217                                 vmw.@internal.EnvironmentUtils.setAppDomain (servletDomain);
218                                 Debug.WriteLine ("Destroy of GhHttpServlet");
219                                 HttpRuntime.Close ();
220                                 vmw.@internal.EnvironmentUtils.cleanAllBeforeServletDestroy (evidence);
221                                 context.removeAttribute (J2EEConsts.APP_DOMAIN);
222                                 try {
223                                         FactoryFinder.releaseFactories ();
224                                 }
225                                 catch (FacesException) { }
226
227                                 java.lang.ClassLoader appClassLoader = vmw.common.TypeUtils.ToClass (evidence).getClassLoader ();
228
229                                 IJDBCDriverDeregisterer dereg = evidence;
230
231                                 java.util.Enumeration en = java.sql.DriverManager.getDrivers ();
232                                 while (en.hasMoreElements ()) {
233                                         Object o = en.nextElement ();
234                                         if (vmw.common.TypeUtils.ToClass (o).getClassLoader () == appClassLoader)
235                                                 dereg.DeregisterDriver ((java.sql.Driver) o);
236                                 }
237
238                                 java.lang.Thread.currentThread ().setContextClassLoader (null);
239                         }
240                         catch (Exception e) {
241                                 Debug.WriteLine (String.Format ("ERROR in Servlet Destroy {0},{1}", e.GetType (), e.Message));
242                                 Debug.WriteLine (e.StackTrace);
243                         }
244                         finally {
245                                 vmw.@internal.EnvironmentUtils.clearAppDomain ();
246                         }
247                 }
248
249                 private static AppDomain createServletDomain(ServletConfig config)
250                 {
251                                 string rootPath = J2EEUtils.GetApplicationRealPath(config.getServletContext ());
252                                 AppDomainSetup domainSetup = new AppDomainSetup();
253                                 string name = config.getServletName();//.getServletContextName();
254                                 if (name == null)
255                                         name = "GH Application";
256                                 domainSetup.ApplicationName = name;
257                                 domainSetup.ConfigurationFile = Path.Combine (rootPath, "Web.config");
258                                 domainSetup.PrivateBinPath = Path.Combine (rootPath, "WEB-INF/lib");
259
260                                 AppDomain servletDomain = AppDomain.CreateDomain(name, null, domainSetup);
261
262
263
264
265
266                                 //servletDomain.SetData(IAppDomainConfig.APP_PHYS_DIR, J2EEUtils.GetApplicationPhysicalPath(config));
267                                 //servletDomain.SetData(IAppDomainConfig.WEB_APP_DIR, rootPath);
268
269                                 servletDomain.SetData(IAppDomainConfig.APP_PHYS_DIR, J2EEUtils.GetApplicationPhysicalPath(config.getServletContext ()));
270                                 servletDomain.SetData(IAppDomainConfig.WEB_APP_DIR, rootPath);
271
272                                 //Set DataDirectory substitution string (http://blogs.msdn.com/dataaccess/archive/2005/10/28/486273.aspx)
273                                 string dataDirectory = config.getServletContext ().getInitParameter ("DataDirectory");
274                                 if (dataDirectory == null)
275                                         dataDirectory = "App_Data";
276
277                                 if (!Path.IsPathRooted (dataDirectory)) {
278                                         java.io.InputStream inputStream = config.getServletContext ().getResourceAsStream ("/WEB-INF/classes/appData.properties");
279                                         string root;
280                                         if (inputStream != null) {
281                                                 try {
282                                                         Properties props = new Properties ();
283                                                         props.load (inputStream);
284                                                         root = props.getProperty ("root.folder");
285                                                 }
286                                                 finally {
287                                                         inputStream.close ();
288                                                 }
289                                         }
290                                         else
291                                                 root = config.getServletContext ().getRealPath ("/");
292
293                                         if (root == null)
294                                                 root = String.Empty;
295
296                                         dataDirectory = Path.Combine (root, dataDirectory);
297                                 }
298
299                                 if (dataDirectory [dataDirectory.Length - 1] != Path.DirectorySeparatorChar)
300                                         dataDirectory += Path.DirectorySeparatorChar;
301
302                                 servletDomain.SetData ("DataDirectory", dataDirectory);
303
304                                 if (config.getServletContext ().getRealPath ("/") == null)
305                                         servletDomain.SetData(".appStartTime", DateTime.UtcNow);
306
307                                 // The BaseDir is the full path to the physical dir of the app
308                                 // and allows the application to modify files in the case of
309                                 // open deployment.
310                                 string webApp_baseDir = config.getServletContext().getRealPath("");
311                                 if (webApp_baseDir == null || webApp_baseDir == "")
312                                         webApp_baseDir = rootPath;
313                                 servletDomain.SetData(IAppDomainConfig.APP_BASE_DIR , webApp_baseDir);
314                                 Debug.WriteLine("Initialization of webapp " + webApp_baseDir);
315                                 //servletDomain.SetData(".hostingVirtualPath", "/");
316                                 //servletDomain.SetData(".hostingInstallDir", "/");
317                                 return servletDomain;
318                 }
319
320                 #region IJDBCDriverDeregisterer Members
321
322                 public void DeregisterDriver (java.sql.Driver driver) {
323                         java.sql.DriverManager.deregisterDriver (driver);
324                 }
325
326                 #endregion
327         }
328 }
329
330 namespace System.Web.GH
331 {
332         /// <summary>
333         /// <para>This class supports the Framework infrastructure and is not intended to be used directly from your code.</para>
334         /// </summary>
335         public class BaseHttpServlet : Mainsoft.Web.Hosting.BaseHttpServlet
336         {
337         }
338
339 }
340
341 namespace System.Web.J2EE
342 {
343         /// <summary>
344         /// <para>This class supports the Framework infrastructure and is not intended to be used directly from your code.</para>
345         /// </summary>
346         public class BaseHttpServlet : Mainsoft.Web.Hosting.BaseHttpServlet
347         {
348         }
349
350 }
351
352 public class GhDynamicHttpServlet : System.Web.GH.BaseHttpServlet
353 {
354 }
355
356 public class GhStaticHttpServlet : System.Web.GH.BaseStaticHttpServlet
357
358 }
359
360 public class GhHttpServlet : System.Web.GH.BaseHttpServlet
361 {
362         GhStaticHttpServlet staticServlet;
363
364         public GhHttpServlet () {
365                 staticServlet = new GhStaticHttpServlet ();
366         }
367
368         override public void init (ServletConfig config) {
369                 base.init (config);
370                 staticServlet.init (config);
371         }
372
373         override protected void service (HttpServletRequest req, HttpServletResponse resp) {
374                 string pathInfo = req.getRequestURI ();
375                 string contextPath = req.getContextPath ();
376                 if (pathInfo.Equals (contextPath) ||
377                         ((pathInfo.Length - contextPath.Length) == 1) &&
378                         pathInfo [pathInfo.Length - 1] == '/' && pathInfo.StartsWith (contextPath))
379                         pathInfo = contextPath + req.getServletPath ();
380                 if (pathInfo.EndsWith (".aspx") ||
381                         pathInfo.EndsWith (".asmx") ||
382                         pathInfo.EndsWith (".invoke")) {
383                         base.service (req, resp);
384                 }
385                 else {
386                         staticServlet.service (req, resp);
387                 }
388         }
389
390         override public void destroy () {
391                 staticServlet.destroy ();
392                 base.destroy ();
393         }
394 }