revert changes from r 96616
[mono.git] / mcs / class / Mainsoft.Web / Mainsoft.Web.Hosting / BaseHttpServlet.cs
index f659b5e7c61576abafa1b083334f445d77d1218d..e00b3142c609315a518a7c28181c5bc9742c692e 100644 (file)
@@ -39,129 +39,135 @@ using java.util;
 using vmw.@internal;
 using java.lang.reflect;
 using java.net;
+using System.Globalization;
+using System.Diagnostics;
+using javax.faces;
+using javax.faces.context;
+using javax.faces.lifecycle;
+using javax.faces.webapp;
+using javax.faces.render;
 
 namespace Mainsoft.Web.Hosting
 {
-       public class BaseHttpServlet : HttpServlet
+       public interface IJDBCDriverDeregisterer
+       {
+               void DeregisterDriver (java.sql.Driver driver);
+       }
+       /// <summary>
+       /// <para>This class supports the Framework infrastructure and is not intended to be used directly from your code.</para>
+       /// </summary>
+       public class BaseHttpServlet : HttpServlet, IJDBCDriverDeregisterer
        {
-               //private AppDomain _servletDomain;
-               static readonly LocalDataStoreSlot _servletRequestSlot = Thread.GetNamedDataSlot(J2EEConsts.SERVLET_REQUEST);
-               static readonly LocalDataStoreSlot _servletResponseSlot = Thread.GetNamedDataSlot(J2EEConsts.SERVLET_RESPONSE);
-               static readonly LocalDataStoreSlot _servletSlot = Thread.GetNamedDataSlot(J2EEConsts.CURRENT_SERVLET);
-
-               bool _performedInit = false;
                bool _appVirDirInited = false;
-               Field _derbyContextService;
-               java.lang.ThreadLocal _derbyLocal;
+
+               static FacesContextFactory _facesContextFactory;
+               static Lifecycle _lifecycle;
+               static RenderKitFactory _renderKitFactory;
 
                public BaseHttpServlet()
                {
                }
 
-               override public void init(ServletConfig config)
-               {
-                       base.init(config);
-                       InitServlet(config);
-                       
+               public static RenderKitFactory RenderKitFactory {
+                       get { return _renderKitFactory; }
                }
 
-               void InitDerby () {
-                       try {
-                               java.lang.ClassLoader loader = vmw.common.TypeUtils.ToClass (this).getClassLoader ();
-                               java.lang.Class derbyContextService = loader.loadClass ("org.apache.derby.iapi.services.context.ContextService");
-                               if (derbyContextService.getClassLoader () == loader)
-                                       _derbyContextService = derbyContextService.getDeclaredField ("factory");
-                       }
-                       catch {
-                               _derbyContextService = null;
-                       }
+               public static FacesContextFactory FacesContextFactory {
+                       get { return _facesContextFactory; }
                }
 
-               internal void CleanupDerby () {
-                       if (_derbyContextService == null)
-                               return;
-                       try {
+               public static Lifecycle Lifecycle {
+                       get { return _lifecycle; }
+               }
 
-                               if (_derbyLocal == null) {
-                                       _derbyContextService.setAccessible (true);
-                                       object contextServiceFact = _derbyContextService.get (null);
-                                       if (contextServiceFact == null)
-                                               return;
+               override public void init(ServletConfig config)
+               {
+                       base.init(config);
+                       InitRuntime (config, this);
+               }
 
-                                       Field derbyLocalField = vmw.common.TypeUtils.ToClass (contextServiceFact).getDeclaredField ("threadContextList");
-                                       if (derbyLocalField == null) {
-                                               _derbyContextService = null;
-                                               return;
-                                       }
+               public static void InitRuntime (ServletConfig config, object evidence) {
 
-                                       derbyLocalField.setAccessible (true);
-                                       object derbyLocal = derbyLocalField.get (contextServiceFact);
-                                       if (derbyLocal == null || !(derbyLocal is java.lang.ThreadLocal)) {
-                                               _derbyContextService = null;
-                                               return;
-                                       }
-                                       _derbyLocal = (java.lang.ThreadLocal) derbyLocal;
-                               }
+                       ServletContext context = config.getServletContext ();
 
+                       if (context.getAttribute (J2EEConsts.APP_DOMAIN) != null)
+                               return;
 
-                               _derbyLocal.set (null);
-                       }
-                       catch (Exception e) {
-#if DEBUG
-                               Console.WriteLine (e.ToString ());
-                               _derbyContextService = null;
-#endif
-                       }
-               }
+                       _facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory (FactoryFinder.FACES_CONTEXT_FACTORY);
+                       //TODO: null-check for Weblogic, that tries to initialize Servlet before ContextListener
 
-               protected virtual void InitServlet(ServletConfig config)
-               {
-                       if (config.getServletContext().getAttribute(J2EEConsts.APP_DOMAIN) != null)
-                               return;
+                       //Javadoc says: Lifecycle instance is shared across multiple simultaneous requests, it must be implemented in a thread-safe manner.
+                       //So we can acquire it here once:
+                       LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory (FactoryFinder.LIFECYCLE_FACTORY);
+                       _lifecycle = lifecycleFactory.getLifecycle (context.getInitParameter (FacesServlet.LIFECYCLE_ID_ATTR) ?? LifecycleFactory.DEFAULT_LIFECYCLE);
 
-                       try 
-                       {
-                               AppDomain servletDomain = createServletDomain(config);
-                               vmw.@internal.EnvironmentUtils.setAppDomain(servletDomain);
+                       _renderKitFactory = (RenderKitFactory) FactoryFinder.getFactory (FactoryFinder.RENDER_KIT_FACTORY);
+
+                       AppDomain servletDomain = createServletDomain (config);
+                       vmw.@internal.EnvironmentUtils.setAppDomain (servletDomain);
 
+                       try {
                                //GH Infromation Initizalization
-                               int nowInt = DateTime.Now.ToString().GetHashCode();
-                               servletDomain.SetData(".domainId", nowInt.ToString("x"));
-                               nowInt += "/".GetHashCode ();
-                               servletDomain.SetData(".appId", nowInt.ToString("x"));
-                               servletDomain.SetData(".appName", nowInt.ToString("x"));
-
-                               servletDomain.SetData(J2EEConsts.CLASS_LOADER, vmw.common.TypeUtils.ToClass(this).getClassLoader());
-                               servletDomain.SetData(J2EEConsts.SERVLET_CONFIG, config);
-                               servletDomain.SetData(J2EEConsts.RESOURCE_LOADER, new vmw.@internal.j2ee.ServletResourceLoader(config.getServletContext()));
-
-                               InitDerby ();
-                               config.getServletContext().setAttribute(J2EEConsts.APP_DOMAIN, servletDomain);
-                               config.getServletContext ().setAttribute (J2EEConsts.CURRENT_SERVLET, this);
-                               
-                               _performedInit = true;
+                               long currentTime = java.lang.System.currentTimeMillis ();
+                               servletDomain.SetData (".domainId", currentTime.ToString ("x"));
+                               currentTime = ~currentTime;
+                               servletDomain.SetData (".appId", currentTime.ToString ("x"));
+                               servletDomain.SetData (".appName", servletDomain.SetupInformation.ApplicationName);
+
+                               servletDomain.SetData (J2EEConsts.CLASS_LOADER, java.lang.Thread.currentThread ().getContextClassLoader ());
+                               //servletDomain.SetData (J2EEConsts.CLASS_LOADER, vmw.common.TypeUtils.ToClass (evidence).getClassLoader ());
+                               //servletDomain.SetData(J2EEConsts.SERVLET_CONFIG, config);
+                               servletDomain.SetData (J2EEConsts.RESOURCE_LOADER, new ServletResourceLoader (context));
+
+                               lock (evidence) {
+                                       if (context.getAttribute (J2EEConsts.APP_DOMAIN) == null)
+                                               context.setAttribute (J2EEConsts.APP_DOMAIN, servletDomain);
+                               }
+                               //config.getServletContext ().setAttribute (J2EEConsts.CURRENT_SERVLET, this);
                        }
-                       finally 
-                       {
-                               vmw.@internal.EnvironmentUtils.cleanTLS();
-                               vmw.@internal.EnvironmentUtils.clearAppDomain();
+                       finally {
+                               vmw.@internal.EnvironmentUtils.cleanTLS ();
+                               vmw.@internal.EnvironmentUtils.clearAppDomain ();
                        }
                }
 
                protected override void service (HttpServletRequest req, HttpServletResponse resp)
                {
-                       resp.setContentType("text/html");
-                       service(req, resp, resp.getOutputStream());
-               }
+                       const string assemblies = "/assemblies";
+                       const string getping = "getping";
+                       const string setping = "setping";
+                       string servletPath = req.getServletPath ();
+
+                       if (String.CompareOrdinal (assemblies, 0, servletPath, 0, assemblies.Length) == 0) {
+                               if (servletPath.Length == assemblies.Length ||
+                                               servletPath [assemblies.Length] == '/') {
+                                       string requestURI = req.getRequestURI ();
+                                       bool getp = requestURI.EndsWith (getping, StringComparison.Ordinal);
+                                       if (!getp && requestURI.EndsWith (setping, StringComparison.Ordinal)) {
+                                               getServletContext ().setAttribute (getping, "1");
+                                               getp = true;
+                                       }
+
+                                       if (getp) {
+                                               string ping = (string) getServletContext ().getAttribute (getping);
+                                               if (ping == null)
+                                                       ping = "0";
+                                               resp.getOutputStream ().print (ping);
+                                               return;
+                                       }
+                               }
+                       }
+                       resp.setContentType ("text/html");
 
-               public virtual void service(HttpServletRequest req, HttpServletResponse resp, java.io.OutputStream output)
-               {
                        try 
                        {
                                // Very important - to update Virtual Path!!!
                                AppDomain servletDomain = (AppDomain)this.getServletContext().getAttribute(J2EEConsts.APP_DOMAIN);
                                if (!_appVirDirInited) {
-                                       servletDomain.SetData (IAppDomainConfig.APP_VIRT_DIR, req.getContextPath ());
+                                       string appVPath = req.getContextPath ();
+                                       if (appVPath == null || appVPath.Length == 0)
+                                               appVPath = "/";
+                                       servletDomain.SetData (IAppDomainConfig.APP_VIRT_DIR, appVPath);
                                        servletDomain.SetData (".hostingVirtualPath", req.getContextPath ());
                                        _appVirDirInited = true;
                                }
@@ -170,69 +176,79 @@ namespace Mainsoft.Web.Hosting
                                vmw.@internal.EnvironmentUtils.setAppDomain(servletDomain);
 
                                // put request to the TLS
-                               Thread.SetData(_servletRequestSlot, req);
-                               // put response to the TLS
-                               Thread.SetData(_servletResponseSlot, resp);
-                               // put the servlet object to the TLS
-                               Thread.SetData(_servletSlot, this);
+                               //Thread.SetData(_servletRequestSlot, req);
+                               //// put response to the TLS
+                               //Thread.SetData(_servletResponseSlot, resp);
+                               //// put the servlet object to the TLS
+                               //Thread.SetData(_servletSlot, this);
 
                                resp.setHeader("X-Powered-By", "ASP.NET");
                                resp.setHeader("X-AspNet-Version", "1.1.4322");
 
-                               HttpWorkerRequest gwr = new ServletWorkerRequest(this, req, resp, output);
+                               HttpWorkerRequest gwr = new ServletWorkerRequest (this, req, resp);
+                               CultureInfo culture = (CultureInfo) vmw.@internal.EnvironmentUtils.getCultureInfoFromLocale (req.getLocale ());
+                               Thread currentTread = Thread.CurrentThread;
+                               currentTread.CurrentCulture = culture;
+                               currentTread.CurrentUICulture = culture;
                                HttpRuntime.ProcessRequest(gwr);
                        }
                        finally 
                        {
                                HttpContext.Current = null;
-                               Thread.SetData(_servletRequestSlot, null);
-                               Thread.SetData(_servletResponseSlot, null);
-                               Thread.SetData(_servletSlot, null);
+                               //Thread.SetData(_servletRequestSlot, null);
+                               //Thread.SetData(_servletResponseSlot, null);
+                               //Thread.SetData(_servletSlot, null);
                                vmw.@internal.EnvironmentUtils.clearAppDomain();
-                               CleanupDerby ();
                        }
                }
 
                override public void destroy()
                {
                        base.destroy();
-                       if (!_performedInit)
+                       DestroyRuntime (getServletContext (), this);
+               }
+
+               public static void DestroyRuntime (ServletContext context, IJDBCDriverDeregisterer evidence) {
+                       AppDomain servletDomain = (AppDomain) context.getAttribute (J2EEConsts.APP_DOMAIN);
+                       if (servletDomain == null)
                                return;
 
-                       try 
-                       {
-                               AppDomain servletDomain = (AppDomain)this.getServletContext().getAttribute(J2EEConsts.APP_DOMAIN);
-                               vmw.@internal.EnvironmentUtils.setAppDomain(servletDomain);
-#if DEBUG
-                               Console.WriteLine("Destroy of GhHttpServlet");
-#endif
-                               HttpRuntime.Close();
-                               vmw.@internal.EnvironmentUtils.cleanAllBeforeServletDestroy(this);
-                               this.getServletContext().removeAttribute(J2EEConsts.APP_DOMAIN);
-                               java.lang.Thread.currentThread().setContextClassLoader(null);
+                       try {
+                               vmw.@internal.EnvironmentUtils.setAppDomain (servletDomain);
+                               Debug.WriteLine ("Destroy of GhHttpServlet");
+                               HttpRuntime.Close ();
+                               vmw.@internal.EnvironmentUtils.cleanAllBeforeServletDestroy (evidence);
+                               context.removeAttribute (J2EEConsts.APP_DOMAIN);
+                               try {
+                                       FactoryFinder.releaseFactories ();
+                               }
+                               catch (FacesException) { }
+
+                               java.lang.ClassLoader appClassLoader = vmw.common.TypeUtils.ToClass (evidence).getClassLoader ();
+
+                               IJDBCDriverDeregisterer dereg = evidence;
+
+                               java.util.Enumeration en = java.sql.DriverManager.getDrivers ();
+                               while (en.hasMoreElements ()) {
+                                       Object o = en.nextElement ();
+                                       if (vmw.common.TypeUtils.ToClass (o).getClassLoader () == appClassLoader)
+                                               dereg.DeregisterDriver ((java.sql.Driver) o);
+                               }
+
+                               java.lang.Thread.currentThread ().setContextClassLoader (null);
                        }
-                       catch(Exception e) 
-                       {
-#if DEBUG
-                               Console.WriteLine("ERROR in Servlet Destroy {0},{1}",e.GetType(), e.Message);
-                               Console.WriteLine(e.StackTrace);
-#endif
+                       catch (Exception e) {
+                               Debug.WriteLine (String.Format ("ERROR in Servlet Destroy {0},{1}", e.GetType (), e.Message));
+                               Debug.WriteLine (e.StackTrace);
                        }
-                       finally
-                       {
-                               vmw.@internal.EnvironmentUtils.clearAppDomain();
-                               CleanupDerby ();
-                               if (_derbyContextService != null) {
-                                       URL u = vmw.common.TypeUtils.ToClass (this).getClassLoader ().getResource ("org/apache/derby/iapi/services/context/ContextService.class");
-                                       if (u != null)
-                                               ((JarURLConnection) u.openConnection ()).getJarFile ().close ();
-                               }
+                       finally {
+                               vmw.@internal.EnvironmentUtils.clearAppDomain ();
                        }
                }
 
-               private AppDomain createServletDomain(ServletConfig config)
+               private static AppDomain createServletDomain(ServletConfig config)
                {
-                               string rootPath = J2EEUtils.GetApplicationRealPath(config);
+                               string rootPath = J2EEUtils.GetApplicationRealPath(config.getServletContext ());
                                AppDomainSetup domainSetup = new AppDomainSetup();
                                string name = config.getServletName();//.getServletContextName();
                                if (name == null)
@@ -250,11 +266,11 @@ namespace Mainsoft.Web.Hosting
                                //servletDomain.SetData(IAppDomainConfig.APP_PHYS_DIR, J2EEUtils.GetApplicationPhysicalPath(config));
                                //servletDomain.SetData(IAppDomainConfig.WEB_APP_DIR, rootPath);
 
-                               servletDomain.SetData(IAppDomainConfig.APP_PHYS_DIR, J2EEUtils.GetApplicationPhysicalPath(config));
+                               servletDomain.SetData(IAppDomainConfig.APP_PHYS_DIR, J2EEUtils.GetApplicationPhysicalPath(config.getServletContext ()));
                                servletDomain.SetData(IAppDomainConfig.WEB_APP_DIR, rootPath);
 
                                //Set DataDirectory substitution string (http://blogs.msdn.com/dataaccess/archive/2005/10/28/486273.aspx)
-                               string dataDirectory = J2EEUtils.GetInitParameterByHierarchy(config, "DataDirectory");
+                               string dataDirectory = config.getServletContext ().getInitParameter ("DataDirectory");
                                if (dataDirectory == null)
                                        dataDirectory = "App_Data";
 
@@ -295,53 +311,27 @@ namespace Mainsoft.Web.Hosting
                                if (webApp_baseDir == null || webApp_baseDir == "")
                                        webApp_baseDir = rootPath;
                                servletDomain.SetData(IAppDomainConfig.APP_BASE_DIR , webApp_baseDir);
-#if DEBUG
-                               Console.WriteLine("Initialization of webapp " + webApp_baseDir);
-#endif
-                               // Mordechai : setting the web app deserializer object.
-                               servletDomain.SetData(J2EEConsts.DESERIALIZER_CONST , this.GetDeserializer());
-                               servletDomain.SetData(vmw.@internal.EnvironmentUtils.GH_DRIVER_UTILS_CONST, this.getDriverUtils());
+                               Debug.WriteLine("Initialization of webapp " + webApp_baseDir);
                                //servletDomain.SetData(".hostingVirtualPath", "/");
                                //servletDomain.SetData(".hostingInstallDir", "/");
                                return servletDomain;
                }
-       
-               virtual protected vmw.@internal.io.IObjectsDeserializer GetDeserializer()
-               {
-                       if (m_deseializer == null)
-                               m_deseializer = new GHWebDeseserializer();
-                       return m_deseializer;
-               }
 
-               protected vmw.@internal.io.IObjectsDeserializer m_deseializer = null;
-               /// Mordechai: This class comes to solve a problem in class deserialize
-               /// within web application. The problem is that the classloader that created 
-               /// some user web class (for example aspx page) is not the class loader
-               /// that de-serialize it - thus we end with ClassDefNotFoundException.
-               /// To prevent this situation we delegate the serialization back the the 
-               /// web app (which has the correct class loader...)
-               /// 
+               #region IJDBCDriverDeregisterer Members
 
-               virtual protected vmw.@internal.IDriverUtils getDriverUtils()
-               {
-                       //by default no driver utils, the specific servlet will override this method
-                       return null;
+               public void DeregisterDriver (java.sql.Driver driver) {
+                       java.sql.DriverManager.deregisterDriver (driver);
                }
-       }
 
-       public class GHWebDeseserializer : vmw.@internal.io.IObjectsDeserializer 
-       {
-
-                       Object vmw.@internal.io.IObjectsDeserializer.Deserialize(java.io.ObjectInputStream stream)
-                       {
-                               object obj = stream.readObject();
-                               return obj;
-                       }
+               #endregion
        }
 }
 
 namespace System.Web.GH
 {
+       /// <summary>
+       /// <para>This class supports the Framework infrastructure and is not intended to be used directly from your code.</para>
+       /// </summary>
        public class BaseHttpServlet : Mainsoft.Web.Hosting.BaseHttpServlet
        {
        }
@@ -350,8 +340,55 @@ namespace System.Web.GH
 
 namespace System.Web.J2EE
 {
+       /// <summary>
+       /// <para>This class supports the Framework infrastructure and is not intended to be used directly from your code.</para>
+       /// </summary>
        public class BaseHttpServlet : Mainsoft.Web.Hosting.BaseHttpServlet
        {
        }
 
 }
+
+public class GhDynamicHttpServlet : System.Web.GH.BaseHttpServlet
+{
+}
+
+public class GhStaticHttpServlet : System.Web.GH.BaseStaticHttpServlet
+{ 
+}
+
+public class GhHttpServlet : System.Web.GH.BaseHttpServlet
+{
+       GhStaticHttpServlet staticServlet;
+
+       public GhHttpServlet () {
+               staticServlet = new GhStaticHttpServlet ();
+       }
+
+       override public void init (ServletConfig config) {
+               base.init (config);
+               staticServlet.init (config);
+       }
+
+       override protected void service (HttpServletRequest req, HttpServletResponse resp) {
+               string pathInfo = req.getRequestURI ();
+               string contextPath = req.getContextPath ();
+               if (pathInfo.Equals (contextPath) ||
+                       ((pathInfo.Length - contextPath.Length) == 1) &&
+                       pathInfo [pathInfo.Length - 1] == '/' && pathInfo.StartsWith (contextPath))
+                       pathInfo = contextPath + req.getServletPath ();
+               if (pathInfo.EndsWith (".aspx") ||
+                       pathInfo.EndsWith (".asmx") ||
+                       pathInfo.EndsWith (".invoke")) {
+                       base.service (req, resp);
+               }
+               else {
+                       staticServlet.service (req, resp);
+               }
+       }
+
+       override public void destroy () {
+               staticServlet.destroy ();
+               base.destroy ();
+       }
+}