using System.Text;
using System.Globalization;
using System.Collections;
+using System.Collections.Concurrent;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Web.Management;
using System.Web.UI;
using System.Web.Util;
-#if MONOWEB_DEP
using Mono.Web.Util;
-#endif
using System.Threading;
-#if TARGET_J2EE
-using Mainsoft.Web;
-#else
using System.CodeDom.Compiler;
using System.Web.Compilation;
-#endif
namespace System.Web
{
public sealed class HttpRuntime
{
static bool domainUnloading;
-
-#if TARGET_J2EE
- static QueueManager queue_manager { get { return _runtime._queue_manager; } }
- static TraceManager trace_manager { get { return _runtime._trace_manager; } }
- static Cache cache { get { return _runtime._cache; } }
- static Cache internalCache { get { return _runtime._internalCache; } }
- static WaitCallback do_RealProcessRequest;
-
- QueueManager _queue_manager;
- TraceManager _trace_manager;
- Cache _cache;
- Cache _internalCache;
-
- public HttpRuntime ()
- {
- WebConfigurationManager.Init ();
- _queue_manager = new QueueManager ();
- _trace_manager = new TraceManager ();
- _cache = new Cache ();
- _internalCache = new Cache();
- _internalCache.DependencyCache = _cache;
- }
-
- static HttpRuntime _runtimeInstance {
- get {
- HttpRuntime runtime = (HttpRuntime) AppDomain.CurrentDomain.GetData ("HttpRuntime");
- if (runtime == null)
- lock (typeof (HttpRuntime)) {
- runtime = (HttpRuntime) AppDomain.CurrentDomain.GetData ("HttpRuntime");
- if (runtime == null) {
- runtime = new HttpRuntime ();
- AppDomain.CurrentDomain.SetData ("HttpRuntime", runtime);
- }
- }
- return runtime;
- }
- }
- static HttpRuntime _runtime
- {
- get
- {
- if (HttpContext.Current != null)
- return HttpContext.Current.HttpRuntimeInstance;
- else
- return _runtimeInstance;
- }
- }
-#else
+ static SplitOrderedList <string, string> registeredAssemblies;
static QueueManager queue_manager;
static TraceManager trace_manager;
static Cache cache;
static Cache internalCache;
static WaitCallback do_RealProcessRequest;
+ static HttpWorkerRequest.EndOfSendNotification end_of_send_cb;
static Exception initialException;
static bool firstRun;
static bool assemblyMappingEnabled;
static object assemblyMappingLock = new object ();
static object appOfflineLock = new object ();
+ static HttpRuntimeSection runtime_section;
public HttpRuntime ()
{
}
-#endif
static HttpRuntime ()
{
-#if !TARGET_J2EE
firstRun = true;
+
try {
WebConfigurationManager.Init ();
-#if MONOWEB_DEP
SettingsMappingManager.Init ();
-#endif
+ runtime_section = (HttpRuntimeSection) WebConfigurationManager.GetSection ("system.web/httpRuntime");
} catch (Exception ex) {
initialException = ex;
}
// and TraceManager are below. The constructors themselves MUST NOT throw any exceptions - we MUST be sure
// the objects are created here. The exceptions will be dealt with below, in RealProcessRequest.
queue_manager = new QueueManager ();
- if (queue_manager.HasException)
- initialException = queue_manager.InitialException;
+ if (queue_manager.HasException) {
+ if (initialException == null)
+ initialException = queue_manager.InitialException;
+ else {
+ Console.Error.WriteLine ("Exception during QueueManager initialization:");
+ Console.Error.WriteLine (queue_manager.InitialException);
+ }
+ }
trace_manager = new TraceManager ();
- if (trace_manager.HasException)
+ if (trace_manager.HasException) {
+ if (initialException == null)
initialException = trace_manager.InitialException;
+ else {
+ Console.Error.WriteLine ("Exception during TraceManager initialization:");
+ Console.Error.WriteLine (trace_manager.InitialException);
+ }
+ }
+ registeredAssemblies = new SplitOrderedList <string, string> (StringComparer.Ordinal);
cache = new Cache ();
internalCache = new Cache ();
internalCache.DependencyCache = internalCache;
-#endif
- do_RealProcessRequest = new WaitCallback (RealProcessRequest);
+ do_RealProcessRequest = new WaitCallback (state => {
+ try {
+ RealProcessRequest (state);
+ } catch {}
+ });
+ end_of_send_cb = new HttpWorkerRequest.EndOfSendNotification (EndOfSend);
+ }
+
+ internal static SplitOrderedList <string, string> RegisteredAssemblies {
+ get { return registeredAssemblies; }
}
#region AppDomain handling
}
}
+ internal static HttpRuntimeSection Section { get { return runtime_section; } }
+
public static bool UsingIntegratedPipeline { get { return false; } }
+
+ public static Version IISVersion {
+ get {
+ // Null means not hosted by IIS
+ return null;
+ }
+ }
+
+ public static Version TargetFramework {
+ get {
+ return runtime_section.TargetFramework;
+ }
+ }
[SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
public static void Close ()
return next;
}
-#if !TARGET_J2EE
static readonly string[] app_offline_files = {"app_offline.htm", "App_Offline.htm", "APP_OFFLINE.HTM"};
static string app_offline_file;
RenamedEventHandler reh = new RenamedEventHandler (AppOfflineFileRenamed);
string app_dir = AppDomainAppPath;
- ArrayList watchers = new ArrayList ();
FileSystemWatcher watcher;
string offlineFile = null, tmp;
watcher.Created += seh;
watcher.Renamed += reh;
watcher.EnableRaisingEvents = true;
-
- watchers.Add (watcher);
tmp = Path.Combine (app_dir, f);
if (File.Exists (tmp))
SetOfflineMode (true, offlineFile);
}
}
-#endif
static void RealProcessRequest (object o)
{
+ if (domainUnloading) {
+ Console.Error.WriteLine ("Domain is unloading, not processing the request.");
+ return;
+ }
+
HttpWorkerRequest req = (HttpWorkerRequest) o;
bool started_internally = req.StartedInternally;
do {
static void Process (HttpWorkerRequest req)
{
-#if TARGET_J2EE
- HttpContext context = HttpContext.Current;
- if (context == null)
- context = new HttpContext (req);
- else
- context.SetWorkerRequest (req);
-#else
- HttpContext context = new HttpContext (req);
-#endif
- HttpContext.Current = context;
bool error = false;
-#if !TARGET_J2EE
if (firstRun) {
- SetupOfflineWatch ();
firstRun = false;
if (initialException != null) {
FinishWithException (req, HttpException.NewWithCode ("Initial exception", initialException, WebEventCodes.RuntimeErrorRequestAbort));
error = true;
}
+ SetupOfflineWatch ();
}
-
+ HttpContext context = new HttpContext (req);
+ HttpContext.Current = context;
if (AppIsOffline (context))
return;
-#endif
//
// Get application instance (create or reuse an instance of the correct class)
HttpContext.Current = null;
} else {
context.ApplicationInstance = app;
+ req.SetEndOfSendNotification (end_of_send_cb, context);
//
// Ask application to service the request
//
-#if TARGET_J2EE
- IHttpAsyncHandler ihah = app;
- if (context.Handler == null)
- ihah.BeginProcessRequest (context, new AsyncCallback (request_processed), context);
- else
- app.Tick ();
- //ihh.ProcessRequest (context);
- IHttpExtendedHandler extHandler = context.Handler as IHttpExtendedHandler;
- if (extHandler != null && !extHandler.IsCompleted)
- return;
- if (context.Error is UnifyRequestException)
- return;
-
- ihah.EndProcessRequest (null);
-#else
IHttpHandler ihh = app;
// IAsyncResult appiar = ihah.BeginProcessRequest (context, new AsyncCallback (request_processed), context);
// ihah.EndProcessRequest (appiar);
ihh.ProcessRequest (context);
-#endif
HttpApplicationFactory.Recycle (app);
}
}
-
+
+ static void EndOfSend (HttpWorkerRequest ignored1, object ignored2)
+ {
+ }
+
//
// ProcessRequest method is executed in the AppDomain of the application
//
RealProcessRequest (request);
}
-#if TARGET_J2EE
- //
- // Callback to be invoked by IHttpAsyncHandler.BeginProcessRequest
- //
- static void request_processed (IAsyncResult iar)
- {
- HttpContext context = (HttpContext) iar.AsyncState;
-
- context.Request.ReleaseResources ();
- context.Response.ReleaseResources ();
- }
-#endif
-#if TARGET_JVM
- [MonoNotSupported ("UnloadAppDomain is not supported")]
- public static void UnloadAppDomain ()
- {
- throw new NotImplementedException ("UnloadAppDomain is not supported");
- }
-#else
//
// Called when we are shutting down or we need to reload an application
// that has been modified (touch global.asax)
// TODO: call ReleaseResources
//
domainUnloading = true;
+ HttpApplicationFactory.DisableWatchers ();
ThreadPool.QueueUserWorkItem (delegate {
try {
ShutdownAppDomain ();
}
});
}
-#endif
//
// Shuts down the AppDomain
//
static void DoUnload ()
{
-#if TARGET_J2EE
- // No unload support for appdomains under Grasshopper
-#else
AppDomain.Unload (AppDomain.CurrentDomain);
-#endif
}
static string content503 = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" +
return null;
}
-#if !TARGET_J2EE
static internal void WritePreservationFile (Assembly asm, string genericNameBase)
{
if (asm == null)
AssemblyName an = new AssemblyName (e.Name);
string dynamic_base = AppDomain.CurrentDomain.SetupInformation.DynamicBase;
string compiled = Path.Combine (dynamic_base, an.Name + ".compiled");
+ string asmPath;
- if (!File.Exists (compiled))
- return null;
-
- PreservationFile pf;
- try {
- pf = new PreservationFile (compiled);
- } catch (Exception ex) {
- throw new HttpException (
- String.Format ("Failed to read preservation file {0}", an.Name + ".compiled"),
- ex);
+ if (!File.Exists (compiled)) {
+ string fn = an.FullName;
+ if (!RegisteredAssemblies.Find ((uint)fn.GetHashCode (), fn, out asmPath))
+ return null;
+ } else {
+ PreservationFile pf;
+ try {
+ pf = new PreservationFile (compiled);
+ } catch (Exception ex) {
+ throw new HttpException (
+ String.Format ("Failed to read preservation file {0}", an.Name + ".compiled"),
+ ex);
+ }
+ asmPath = Path.Combine (dynamic_base, pf.Assembly + ".dll");
}
+
+ if (String.IsNullOrEmpty (asmPath))
+ return null;
Assembly ret = null;
try {
- string asmPath = Path.Combine (dynamic_base, pf.Assembly + ".dll");
ret = Assembly.LoadFrom (asmPath);
} catch (Exception) {
// ignore
assemblyMappingEnabled = enable;
}
}
-#endif // #if !TARGET_J2EE
internal static TraceManager TraceManager {
get {