TARGET_J2EE/JVM fixes
[mono.git] / mcs / class / System.Web / System.Web / HttpApplicationFactory.cs
index 138d9b03efc7ac2e2aeb33244df3f1c70629b272..d57384dd1c87a3be1b9639d43fb3e9defb112b82 100644 (file)
-// \r
-// System.Web.HttpApplicationFactory\r
-//\r
-// Author:\r
-//     Patrik Torstensson (ptorsten@hotmail.com)\r
-//     Gonzalo Paniagua Javier (gonzalo@ximian.com)\r
-//\r
-// (c) 2002,2003 Ximian, Inc. (http://www.ximian.com)\r
-//\r
-using System;\r
-using System.Collections;\r
-using System.IO;\r
-using System.Reflection;\r
-using System.Web.UI;\r
-using System.Web.Compilation;\r
-using System.Web.SessionState;\r
-\r
-namespace System.Web {\r
-       class HttpApplicationFactory {\r
-               private string _appFilename;\r
-               private Type _appType;\r
-\r
-               private bool _appInitialized;\r
-               private bool _appFiredEnd;\r
-\r
-               private Stack                   _appFreePublicList;\r
-               private int                             _appFreePublicInstances;\r
-               static private int      _appMaxFreePublicInstances = 32;\r
-\r
-               private HttpApplicationState _state;\r
-\r
-               static IHttpHandler custApplication;\r
-\r
-               static private HttpApplicationFactory s_Factory = new HttpApplicationFactory();\r
-\r
-               public HttpApplicationFactory() {\r
-                       _appInitialized = false;\r
-                       _appFiredEnd = false;\r
-\r
-                       _appFreePublicList = new Stack();\r
-                       _appFreePublicInstances = 0;\r
-               }\r
-\r
-               static private string GetAppFilename (HttpContext context)\r
-               {\r
-                       string physicalAppPath = context.Request.PhysicalApplicationPath;\r
-                       string appFilePath = Path.Combine (physicalAppPath, "Global.asax");\r
-                       if (File.Exists (appFilePath))\r
-                               return appFilePath;\r
-\r
-                       return Path.Combine (physicalAppPath, "global.asax");\r
-               }\r
-\r
-               private void CompileApp(HttpContext context) {\r
-                       if (File.Exists(_appFilename)) {\r
-                               // Setup filemonitor for all filedepend also. CacheDependency?\r
-\r
-                               _appType = ApplicationFileParser.GetCompiledApplicationType (_appFilename, context);\r
-                               if (_appType == null) {\r
-                                       string msg = String.Format ("Error compiling application file ({0}).", _appFilename);\r
-                                       throw new ApplicationException (msg);\r
-                               }\r
-                       } else {\r
-                               _appType = typeof (System.Web.HttpApplication);\r
-                               _state = new HttpApplicationState ();\r
-                       }\r
-               }\r
-\r
-               static bool IsEventHandler (MethodInfo m)\r
-               {\r
-                       if (m.ReturnType != typeof (void))\r
-                               return false;\r
-\r
-                       ParameterInfo [] pi = m.GetParameters ();\r
-                       if (pi.Length != 2)\r
-                               return false;\r
-\r
-                       if (pi [0].ParameterType != typeof (object) ||\r
-                           pi [1].ParameterType != typeof (EventArgs))\r
-                               return false;\r
-                       \r
-                       return true;\r
-               }\r
-\r
-               static void AddEvent (MethodInfo method, Hashtable appTypeEventHandlers)\r
-               {\r
-                       string name = method.Name.Replace ("_On", "_");\r
-                       if (appTypeEventHandlers [name] == null) {\r
-                               appTypeEventHandlers [name] = method;\r
-                               return;\r
-                       }\r
-                       \r
-                       ArrayList list;\r
-                       if (appTypeEventHandlers [name] is MethodInfo)\r
-                               list = new ArrayList ();\r
-                       else\r
-                               list = appTypeEventHandlers [name] as ArrayList;\r
-\r
-                       list.Add (method);\r
-               }\r
-               \r
-               static Hashtable GetApplicationTypeEvents (HttpApplication app)\r
-               {\r
-                       Type appType = app.GetType ();\r
-                       Hashtable appTypeEventHandlers = new Hashtable ();\r
-                       ArrayList evtMethods = new ArrayList ();\r
-                       BindingFlags flags = BindingFlags.Public    |\r
-                                            BindingFlags.NonPublic | \r
-                                            BindingFlags.DeclaredOnly |\r
-                                            BindingFlags.Instance |\r
-                                            BindingFlags.Static;\r
-\r
-                       MethodInfo [] methods = appType.GetMethods (flags);\r
-                       foreach (MethodInfo m in methods) {\r
-                               if (IsEventHandler (m))\r
-                                       AddEvent (m, appTypeEventHandlers);\r
-                       }\r
-\r
-                       Type baseType = appType.BaseType;\r
-                       if (baseType == typeof (HttpApplication))\r
-                               return appTypeEventHandlers;\r
-\r
-                       flags = BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;\r
-\r
-                       methods = appType.GetMethods (flags);\r
-                       foreach (MethodInfo m in methods) {\r
-                               if (IsEventHandler (m))\r
-                                       AddEvent (m, appTypeEventHandlers);\r
-                       }\r
-\r
-                       return appTypeEventHandlers;\r
-               }\r
-\r
-               static void FireEvents (string method_name, object target, object [] args)\r
-               {\r
-                       Hashtable possibleEvents = GetApplicationTypeEvents ((HttpApplication) target);\r
-                       MethodInfo method = possibleEvents [method_name] as MethodInfo;\r
-                       if (possibleEvents [method_name] == null)\r
-                               return;\r
-\r
-                       method.Invoke (target, args);\r
-               }\r
-               \r
-               internal static void FireOnAppStart (HttpApplication app)\r
-               {\r
-                       FireEvents ("Application_Start", app, new object [] {app, EventArgs.Empty});\r
-               }\r
-\r
-               void FireOnAppEnd ()\r
-               {\r
-               //      FireEvents ("Application_End", this, new object [] {this, EventArgs.Empty});\r
-               }\r
-\r
-               void FireOnSessionStart (HttpSessionState state, object source, EventArgs args)\r
-               {\r
-               //      FireEvents ("Session_Start", state, new object [] {source, EventArgs.Empty});\r
-               }\r
-               \r
-               void FireOnSessionEnd (HttpSessionState state, object source, EventArgs args)\r
-               {\r
-               //      FireEvents ("Session_End", state, new object [] {source, args});\r
-               }\r
-       \r
-               private void InitializeFactory (HttpContext context)\r
-               {\r
-                       _appFilename = GetAppFilename (context);\r
-\r
-                       CompileApp (context);\r
-\r
-                       // Create a application object\r
-                       HttpApplication app = (HttpApplication) HttpRuntime.CreateInternalObject (_appType);\r
-\r
-                       // Startup\r
-                       app.Startup(context, HttpApplicationFactory.ApplicationState);\r
-\r
-                       // Fire OnAppStart\r
-                       HttpApplicationFactory.FireOnAppStart (app);\r
-\r
-                       // Recycle our application instance\r
-                       RecyclePublicInstance(app);\r
-               }\r
-\r
-               private void Dispose() {\r
-                       ArrayList torelease = new ArrayList();\r
-                       lock (_appFreePublicList) {\r
-                               while (_appFreePublicList.Count > 0) {\r
-                                       torelease.Add(_appFreePublicList.Pop());\r
-                                       _appFreePublicInstances--;\r
-                               }\r
-                       }\r
-\r
-                       if (torelease.Count > 0) {\r
-                               foreach (Object obj in torelease) {\r
-                                       ((HttpApplication) obj).Cleanup();\r
-                               }\r
-                       }\r
-\r
-                       if (!_appFiredEnd) {\r
-                               lock (this) {\r
-                                       if (!_appFiredEnd) {\r
-                                               FireOnAppEnd();\r
-                                               _appFiredEnd = true;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-\r
-               internal static IHttpHandler GetInstance(HttpContext context)\r
-               {\r
-                       if (custApplication != null)\r
-                               return custApplication;\r
-\r
-                       if (!s_Factory._appInitialized) {\r
-                               lock (s_Factory) {\r
-                                       if (!s_Factory._appInitialized) {\r
-                                               s_Factory.InitializeFactory(context);\r
-                                               s_Factory._appInitialized = true;\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       return s_Factory.GetPublicInstance(context);\r
-               }\r
-\r
-               internal static void RecycleInstance(HttpApplication app) {\r
-                       if (!s_Factory._appInitialized)\r
-                               throw new InvalidOperationException("Factory not intialized");\r
-\r
-                       s_Factory.RecyclePublicInstance(app);\r
-               }\r
-\r
-               internal static void AttachEvents (HttpApplication app)\r
-               {\r
-                       Hashtable possibleEvents = GetApplicationTypeEvents (app);\r
-                       foreach (string key in possibleEvents.Keys) {\r
-                               int pos = key.IndexOf ('_');\r
-                               if (pos == -1 || key.Length <= pos + 1)\r
-                                       continue;\r
-\r
-                               string moduleName = key.Substring (0, pos);\r
-                               object target;\r
-                               if (moduleName == "Application")\r
-                                       target = app;\r
-                               else\r
-                                       target = app.Modules [moduleName];\r
-\r
-                               if (target == null)\r
-                                       continue;\r
-                               \r
-                               Type targetType = target.GetType ();\r
-\r
-                               string eventName = key.Substring (pos + 1);\r
-                               EventInfo evt = targetType.GetEvent (eventName);\r
-                               if (evt == null)\r
-                                       continue;\r
-                       \r
-                               string usualName = moduleName + "_" + eventName;\r
-                               object methodData = possibleEvents [usualName];\r
-                               if (methodData == null)\r
-                                       continue;\r
-\r
-                               if (methodData is MethodInfo) {\r
-                                       MethodInfo method = (MethodInfo) methodData;\r
-                                       evt.AddEventHandler (target, Delegate.CreateDelegate (\r
-                                                               typeof (EventHandler), app, method.Name));\r
-                                       continue;\r
-                               }\r
-\r
-                               ArrayList list = (ArrayList) methodData;\r
-                               foreach (MethodInfo method in list)\r
-                                       evt.AddEventHandler (target, Delegate.CreateDelegate (\r
-                                                               typeof (EventHandler), app, method.Name));\r
-                       }\r
-               }\r
-\r
-               private IHttpHandler GetPublicInstance(HttpContext context) {\r
-                       HttpApplication app = null;\r
-\r
-                       lock (_appFreePublicList) {\r
-                               if (_appFreePublicInstances > 0) {\r
-                                       app = (HttpApplication) _appFreePublicList.Pop();\r
-                                       _appFreePublicInstances--;\r
-                               }\r
-                       }\r
-\r
-                       if (app == null) {\r
-                               // Create non-public object\r
-                               app = (HttpApplication) HttpRuntime.CreateInternalObject(_appType);\r
-\r
-                               app.Startup(context, HttpApplicationFactory.ApplicationState);\r
-                       }\r
-\r
-                       return (IHttpHandler) app;\r
-               }\r
-\r
-               internal void RecyclePublicInstance(HttpApplication app) {\r
-                       lock (_appFreePublicList) {\r
-                               if (_appFreePublicInstances < _appMaxFreePublicInstances) {\r
-                                       _appFreePublicList.Push(app);\r
-                                       _appFreePublicInstances++;\r
-\r
-                                       app = null;\r
-                               }\r
-                       }\r
-                       \r
-                       if  (app != null) {\r
-                               app.Cleanup();\r
-                       }\r
-               }\r
-\r
-               static internal HttpApplicationState ApplicationState {\r
-                       get {\r
-                               if (null == s_Factory._state) {\r
-                                       s_Factory._state = new HttpApplicationState();\r
-                               }\r
-\r
-                               return s_Factory._state;\r
-                       }\r
-               }\r
-\r
-               internal static void EndApplication() {\r
-                       s_Factory.Dispose();\r
-               }\r
-\r
-               public static void SetCustomApplication (IHttpHandler customApplication)\r
-               {\r
-                       custApplication = customApplication;\r
-               }\r
-\r
-               internal Type AppType {\r
-                       get { return _appType; }\r
-               }\r
-       }\r
-}\r
+//
+// System.Web.HttpApplicationFactory
+//
+// TODO:
+//   bin_watcher must work.
+//   
+//
+// Author:
+//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (c) 2002,2003 Ximian, Inc. (http://www.ximian.com)
+// (c) Copyright 2004 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.IO;
+using System.Reflection;
+using System.Web.UI;
+using System.Web.SessionState;
+using System.Web.Configuration;
+
+#if !TARGET_J2EE
+using System.Web.Compilation;
+#else
+using vmw.common;
+#endif
+
+namespace System.Web {
+       class HttpApplicationFactory {
+               // Initialized in InitType
+#if TARGET_J2EE
+               static HttpApplicationFactory theFactory {
+                       get
+                       {
+                               HttpApplicationFactory factory = (HttpApplicationFactory)AppDomain.CurrentDomain.GetData("HttpApplicationFactory");
+                               if (factory == null) {
+                                       lock(typeof(HttpApplicationFactory)) {
+                                               factory = (HttpApplicationFactory)AppDomain.CurrentDomain.GetData("HttpApplicationFactory");
+                                               if (factory == null) {
+                                                       factory = new HttpApplicationFactory();
+                                                       System.Threading.Thread.Sleep(1);
+                                                       AppDomain.CurrentDomain.SetData("HttpApplicationFactory", factory);
+                                               }
+                                       }
+                               }
+                               return factory;
+                       }
+               }
+#else
+               static HttpApplicationFactory theFactory = new HttpApplicationFactory();
+#endif
+
+               bool needs_init = true;
+               Type app_type;
+               HttpApplicationState app_state;
+#if !TARGET_JVM
+               FileSystemWatcher app_file_watcher;
+               FileSystemWatcher bin_watcher;
+#endif
+               Stack available = new Stack ();
+               
+               // Watch this thing out when getting an instance
+               IHttpHandler custom_application;
+
+               bool IsEventHandler (MethodInfo m)
+               {
+                       if (m.ReturnType != typeof (void))
+                               return false;
+
+                       ParameterInfo [] pi = m.GetParameters ();
+                       int length = pi.Length;
+                       if (length == 0)
+                               return true;
+
+                       if (length != 2)
+                               return false;
+
+                       if (pi [0].ParameterType != typeof (object) ||
+                           pi [1].ParameterType != typeof (EventArgs))
+                               return false;
+                       
+                       return true;
+               }
+
+               void AddEvent (MethodInfo method, Hashtable appTypeEventHandlers)
+               {
+                       string name = method.Name.Replace ("_On", "_");
+                       if (appTypeEventHandlers [name] == null) {
+                               appTypeEventHandlers [name] = method;
+                               return;
+                       }
+
+                       MethodInfo old_method = appTypeEventHandlers [name] as MethodInfo;
+                       ArrayList list;
+                       if (old_method != null){
+                               list = new ArrayList (4);
+                               list.Add (old_method);
+                               appTypeEventHandlers [name] = list;
+                       } else 
+                               list = appTypeEventHandlers [name] as ArrayList;
+
+                       list.Add (method);
+               }
+               
+               Hashtable GetApplicationTypeEvents (HttpApplication app)
+               {
+                       Type appType = app.GetType ();
+                       Hashtable appTypeEventHandlers = new Hashtable ();
+                       BindingFlags flags = BindingFlags.Public    |
+                                            BindingFlags.NonPublic | 
+                                            BindingFlags.Instance |
+                                            BindingFlags.Static;
+
+                       MethodInfo [] methods = appType.GetMethods (flags);
+                       foreach (MethodInfo m in methods) {
+                               if (IsEventHandler (m))
+                                       AddEvent (m, appTypeEventHandlers);
+                       }
+
+                       return appTypeEventHandlers;
+               }
+
+               bool FireEvent (string method_name, object target, object [] args)
+               {
+                       Hashtable possibleEvents = GetApplicationTypeEvents ((HttpApplication) target);
+                       MethodInfo method = possibleEvents [method_name] as MethodInfo;
+                       if (method == null)
+                               return false;
+
+                       if (method.GetParameters ().Length == 0)
+                               args = null;
+
+                       method.Invoke (target, args);
+
+                       return true;
+               }
+
+               void FireOnAppStart (HttpContext context)
+               {
+                       HttpApplication app = (HttpApplication) Activator.CreateInstance (app_type, true);
+                       app.SetContext (context);
+                       object [] args = new object [] {app, EventArgs.Empty};
+                       FireEvent ("Application_Start", app, args);
+                       Recycle (app);
+               }
+
+               void FireOnAppEnd ()
+               {
+                       if (app_type == null)
+                               return; // we didn't even get an application
+
+                       HttpApplication app = (HttpApplication) Activator.CreateInstance (app_type, true);
+                       FireEvent ("Application_End", app, new object [] {new object (), EventArgs.Empty});
+                       app.Dispose ();
+               }
+
+               //
+               // This is invoked by HttpRuntime.Dispose, when we unload an AppDomain
+               // To reproduce this in action, touch "global.asax" while XSP is running.
+               //
+               public static void Dispose ()
+               {
+                       theFactory.FireOnAppEnd ();
+               }
+
+#if !TARGET_JVM
+               FileSystemWatcher CreateWatcher (string file, FileSystemEventHandler hnd)
+               {
+                       FileSystemWatcher watcher = new FileSystemWatcher ();
+
+                       watcher.Path = Path.GetFullPath (Path.GetDirectoryName (file));
+                       watcher.Filter = Path.GetFileName (file);
+
+                       watcher.Changed += hnd;
+                       watcher.Created += hnd;
+                       watcher.Deleted += hnd;
+
+                       watcher.EnableRaisingEvents = true;
+
+                       return watcher;
+               }
+
+               void OnAppFileChanged (object sender, FileSystemEventArgs args)
+               {
+                       bin_watcher.EnableRaisingEvents = false;
+                       app_file_watcher.EnableRaisingEvents = false;
+                       HttpRuntime.UnloadAppDomain ();
+               }
+#endif
+
+               internal static void AttachEvents (HttpApplication app)
+               {
+                       HttpApplicationFactory factory = theFactory;
+                       Hashtable possibleEvents = factory.GetApplicationTypeEvents (app);
+                       foreach (string key in possibleEvents.Keys) {
+                               int pos = key.IndexOf ('_');
+                               if (pos == -1 || key.Length <= pos + 1)
+                                       continue;
+
+                               string moduleName = key.Substring (0, pos);
+                               object target;
+                               if (moduleName == "Application") {
+                                       target = app;
+                               } else {
+                                       target = app.Modules [moduleName];
+                                       if (target == null)
+                                               continue;
+                               }
+
+                               string eventName = key.Substring (pos + 1);
+                               EventInfo evt = target.GetType ().GetEvent (eventName);
+                               if (evt == null)
+                                       continue;
+                       
+                               string usualName = moduleName + "_" + eventName;
+                               object methodData = possibleEvents [usualName];
+                               if (methodData == null)
+                                       continue;
+
+                               if (methodData is MethodInfo) {
+                                       factory.AddHandler (evt, target, app, (MethodInfo) methodData);
+                                       continue;
+                               }
+
+                               ArrayList list = (ArrayList) methodData;
+                               foreach (MethodInfo method in list)
+                                       factory.AddHandler (evt, target, app, method);
+                       }
+               }
+
+               void AddHandler (EventInfo evt, object target, HttpApplication app, MethodInfo method)
+               {
+                       int length = method.GetParameters ().Length;
+
+                       if (length == 0) {
+                               NoParamsInvoker npi = new NoParamsInvoker (app, method.Name);
+                               evt.AddEventHandler (target, npi.FakeDelegate);
+                       } else {
+                               evt.AddEventHandler (target, Delegate.CreateDelegate (
+                                                       typeof (EventHandler), app, method.Name));
+                       }
+               }
+
+               static HttpStaticObjectsCollection MakeStaticCollection (ArrayList list)
+               {
+                       if (list == null || list.Count == 0)
+                               return null;
+
+                       HttpStaticObjectsCollection coll = new HttpStaticObjectsCollection ();
+                       foreach (ObjectTagBuilder tag in list) {
+                               coll.Add (tag);
+                       }
+
+                       return coll;
+               }
+               
+               internal static HttpApplicationState ApplicationState {
+#if TARGET_J2EE
+                       get {
+                               HttpApplicationFactory factory = theFactory;
+                               if (factory.app_state == null)
+                                       factory.app_state = new HttpApplicationState (null, null);
+                               return factory.app_state;
+                       }
+#else
+                       get {
+                               if (theFactory.app_state == null) {
+                                       HttpStaticObjectsCollection app = MakeStaticCollection (GlobalAsaxCompiler.ApplicationObjects);
+                                       HttpStaticObjectsCollection ses = MakeStaticCollection (GlobalAsaxCompiler.SessionObjects);
+
+                                       theFactory.app_state = new HttpApplicationState (app, ses);
+                               }
+                               return theFactory.app_state;
+                       }
+#endif
+               }
+
+               public static void SetCustomApplication (IHttpHandler customApplication)
+               {
+                       theFactory.custom_application = customApplication;
+               }
+
+               internal static Type AppType {
+                       get {
+                               return theFactory.app_type;
+                       }
+               }
+
+               void InitType (HttpContext context)
+               {
+                       lock (this) {
+                               if (!needs_init)
+                                       return;
+                               
+                               string physical_app_path = context.Request.PhysicalApplicationPath;
+                               string app_file;
+                               
+                               app_file = Path.Combine (physical_app_path, "Global.asax");
+                               if (!File.Exists (app_file))
+                                       app_file = Path.Combine (physical_app_path, "global.asax");
+                               
+                               WebConfigurationSettings.Init (context);
+                               
+                               if (File.Exists (app_file)) {
+#if TARGET_J2EE
+                                       app_type = System.Web.J2EE.PageMapper.GetObjectType(app_file);
+#else
+                                       app_type = ApplicationFileParser.GetCompiledApplicationType (app_file, context);
+                                       if (app_type == null) {
+                                               string msg = String.Format ("Error compiling application file ({0}).", app_file);
+                                               throw new ApplicationException (msg);
+                                       }
+                                       
+                                       app_file_watcher = CreateWatcher (app_file, new FileSystemEventHandler (OnAppFileChanged));
+#endif
+                               } else {
+                                       app_type = typeof (System.Web.HttpApplication);
+                                       app_state = new HttpApplicationState ();
+                               }
+                               needs_init = false;
+
+                               //
+                               // Now init the settings
+                               //
+
+                       }
+               }
+               
+               //
+               // Multiple-threads might hit this one on startup, and we have
+               // to delay-initialize until we have the HttpContext
+               //
+               internal static HttpApplication GetApplication (HttpContext context)
+               {
+                       HttpApplicationFactory factory = theFactory;
+                       if (factory.needs_init){
+                               if (context == null)
+                                       return null;
+
+                               factory.InitType (context);
+                               factory.FireOnAppStart (context);
+                       }
+
+                       lock (factory) {
+                               if (factory.available.Count > 0)
+                                       return (HttpApplication) factory.available.Pop ();
+                       }
+                       
+                       HttpApplication app = (HttpApplication) Activator.CreateInstance (factory.app_type, true);
+
+                       return app;
+               }
+
+               internal static void Recycle (HttpApplication app)
+               {
+                       HttpApplicationFactory factory = theFactory;
+                       lock (factory) {
+                               if (factory.available.Count < 32)
+                                       factory.available.Push (app);
+                               else
+                                       app.Dispose ();
+                       }
+               }
+       }
+}