// Gonzalo Paniagua (gonzalo@ximian.com)
//
//
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005-2009 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
using System.Collections;
using System.ComponentModel;
using System.Configuration;
+using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Security.Permissions;
using System.Security.Principal;
using System.Threading;
using System.Web.Caching;
+using System.Web.Compilation;
using System.Web.Configuration;
+using System.Web.Management;
using System.Web.SessionState;
using System.Web.UI;
+using System.Web.Util;
#if TARGET_J2EE
using Mainsoft.Web;
#endif
-namespace System.Web {
-
+namespace System.Web
+{
// CAS
[AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
// attributes
[ToolboxItem(false)]
- public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable {
- object this_lock = new object();
-
+ public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable
+ {
+ static readonly object disposedEvent = new object ();
+ static readonly object errorEvent = new object ();
+
+ // we do this static rather than per HttpApplication because
+ // mono's perfcounters use the counter instance parameter for
+ // the process to access shared memory.
+ internal static PerformanceCounter requests_total_counter = new PerformanceCounter ("ASP.NET", "Requests Total");
+
internal static readonly string [] BinDirs = {"Bin", "bin"};
+ object this_lock = new object();
HttpContext context;
HttpSessionState session;
//
bool stop_processing;
+ //
+ // See https://bugzilla.novell.com/show_bug.cgi?id=381971
+ //
+ bool in_application_start;
+
//
// The Pipeline
//
// Tracks the current AsyncInvocation being dispatched
AsyncInvoker current_ai;
- // We don't use the EventHandlerList here, but derived classes might do
EventHandlerList events;
-
+ EventHandlerList nonApplicationEvents = new EventHandlerList ();
+
// Culture and IPrincipal
CultureInfo app_culture;
CultureInfo appui_culture;
CultureInfo prev_appui_culture;
IPrincipal prev_user;
- static bool _runningOnWindows;
+ static string binDirectory;
-#if NET_2_0
#if TARGET_J2EE
const string initialization_exception_key = "System.Web.HttpApplication.initialization_exception";
static Exception initialization_exception {
static Exception initialization_exception;
#endif
bool removeConfigurationFromCache;
-#endif
-
+ bool fullInitComplete = false;
+
//
// These are used to detect the case where the EndXXX method is invoked
// from within the BeginXXXX delegate, so we detect whether we kick the
bool must_yield;
bool in_begin;
- static HttpApplication ()
- {
- PlatformID pid = Environment.OSVersion.Platform;
- _runningOnWindows = ((int) pid != 128 && (int) pid != 4);
+ public virtual event EventHandler Disposed {
+ add { nonApplicationEvents.AddHandler (disposedEvent, value); }
+ remove { nonApplicationEvents.RemoveHandler (disposedEvent, value); }
}
+ public virtual event EventHandler Error {
+ add { nonApplicationEvents.AddHandler (errorEvent, value); }
+ remove { nonApplicationEvents.RemoveHandler (errorEvent, value); }
+ }
+
public HttpApplication ()
{
done = new ManualResetEvent (false);
lock (this_lock) {
if (modcoll != null)
return;
-
-#if NET_2_0
+
HttpModulesSection modules;
- modules = (HttpModulesSection) WebConfigurationManager.GetSection ("system.web/httpModules", HttpRuntime.AppDomainAppVirtualPath);
-#else
- ModulesConfiguration modules;
-
- modules = (ModulesConfiguration) HttpContext.GetAppConfig ("system.web/httpModules");
-#endif
-
+ modules = (HttpModulesSection) WebConfigurationManager.GetWebApplicationSection ("system.web/httpModules");
+ HttpContext saved = HttpContext.Current;
+ HttpContext.Current = new HttpContext (new System.Web.Hosting.SimpleWorkerRequest (String.Empty, String.Empty, new StringWriter()));
modcoll = modules.LoadModules (this);
+ HttpContext.Current = saved;
if (full_init) {
HttpApplicationFactory.AttachEvents (this);
Init ();
+ fullInitComplete = true;
}
}
}
+ internal bool InApplicationStart {
+ get { return in_application_start; }
+ set { in_application_start = value; }
+ }
+
internal string AssemblyLocation {
get {
if (assemblyLocation == null)
}
}
-#if NET_2_0
internal static Exception InitializationException {
get { return initialization_exception; }
}
-#endif
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public HttpModuleCollection Modules {
[AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
get {
- if (modcoll == null)
- modcoll = new HttpModuleCollection ();
+ lock (this_lock) {
+ if (modcoll == null)
+ modcoll = new HttpModuleCollection ();
+ }
return modcoll;
}
public HttpRequest Request {
get {
if (context == null)
- throw new HttpException (Locale.GetText ("No context is available."));
+ throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
if (false == HttpApplicationFactory.ContextAvailable)
- throw new HttpException (Locale.GetText ("Request is not available in this context."));
+ throw HttpException.NewWithCode (Locale.GetText ("Request is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
return context.Request;
}
public HttpResponse Response {
get {
if (context == null)
- throw new HttpException (Locale.GetText ("No context is available."));
+ throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
if (false == HttpApplicationFactory.ContextAvailable)
- throw new HttpException (Locale.GetText ("Response is not available in this context."));
+ throw HttpException.NewWithCode (Locale.GetText ("Response is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
return context.Response;
}
return session;
if (context == null)
- throw new HttpException (Locale.GetText ("No context is available."));
- return context.Session;
+ throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
+
+ HttpSessionState ret = context.Session;
+ if (ret == null)
+ throw HttpException.NewWithCode (Locale.GetText ("Session state is not available in the context."), WebEventCodes.RuntimeErrorRequestAbort);
+
+ return ret;
}
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-#if NET_2_0
public ISite Site {
-#else
- public virtual ISite Site {
-#endif
- get {
- return isite;
- }
+ get { return isite; }
- set {
- isite = value;
- }
+ set { isite = value; }
}
[Browsable (false)]
}
}
- public virtual event EventHandler Disposed;
- public virtual event EventHandler Error;
-
- public event EventHandler PreSendRequestHeaders;
+ static object PreSendRequestHeadersEvent = new object ();
+ public event EventHandler PreSendRequestHeaders
+ {
+ add { AddEventHandler (PreSendRequestHeadersEvent, value); }
+ remove { RemoveEventHandler (PreSendRequestHeadersEvent, value); }
+ }
+
internal void TriggerPreSendRequestHeaders ()
{
- if (PreSendRequestHeaders != null)
- PreSendRequestHeaders (this, EventArgs.Empty);
+ EventHandler handler = Events [PreSendRequestHeadersEvent] as EventHandler;
+ if (handler != null)
+ handler (this, EventArgs.Empty);
}
- public event EventHandler PreSendRequestContent;
+ static object PreSendRequestContentEvent = new object ();
+ public event EventHandler PreSendRequestContent
+ {
+ add { AddEventHandler (PreSendRequestContentEvent, value); }
+ remove { RemoveEventHandler (PreSendRequestContentEvent, value); }
+ }
+
internal void TriggerPreSendRequestContent ()
{
- if (PreSendRequestContent != null)
- PreSendRequestContent (this, EventArgs.Empty);
+ EventHandler handler = Events [PreSendRequestContentEvent] as EventHandler;
+ if (handler != null)
+ handler (this, EventArgs.Empty);
+ }
+
+ static object AcquireRequestStateEvent = new object ();
+ public event EventHandler AcquireRequestState
+ {
+ add { AddEventHandler (AcquireRequestStateEvent, value); }
+ remove { RemoveEventHandler (AcquireRequestStateEvent, value); }
}
- public event EventHandler AcquireRequestState;
public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
{
AsyncInvoker invoker = new AsyncInvoker (bh, eh);
AcquireRequestState += new EventHandler (invoker.Invoke);
}
- public event EventHandler AuthenticateRequest;
+ static object AuthenticateRequestEvent = new object ();
+ public event EventHandler AuthenticateRequest
+ {
+ add { AddEventHandler (AuthenticateRequestEvent, value); }
+ remove { RemoveEventHandler (AuthenticateRequestEvent, value); }
+ }
+
public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
{
AsyncInvoker invoker = new AsyncInvoker (bh, eh);
AuthenticateRequest += new EventHandler (invoker.Invoke);
}
- public event EventHandler AuthorizeRequest;
+ static object AuthorizeRequestEvent = new object ();
+ public event EventHandler AuthorizeRequest
+ {
+ add { AddEventHandler (AuthorizeRequestEvent, value); }
+ remove { RemoveEventHandler (AuthorizeRequestEvent, value); }
+ }
+
public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
{
AsyncInvoker invoker = new AsyncInvoker (bh, eh);
AuthorizeRequest += new EventHandler (invoker.Invoke);
}
- public event EventHandler BeginRequest;
+ static object BeginRequestEvent = new object ();
+ public event EventHandler BeginRequest
+ {
+ add {
+ // See https://bugzilla.novell.com/show_bug.cgi?id=381971
+ if (InApplicationStart)
+ return;
+ AddEventHandler (BeginRequestEvent, value);
+ }
+ remove {
+ if (InApplicationStart)
+ return;
+ RemoveEventHandler (BeginRequestEvent, value);
+ }
+ }
+
public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh)
{
AsyncInvoker invoker = new AsyncInvoker (bh, eh);
BeginRequest += new EventHandler (invoker.Invoke);
}
- public event EventHandler EndRequest;
+ static object EndRequestEvent = new object ();
+ public event EventHandler EndRequest
+ {
+ add {
+ // See https://bugzilla.novell.com/show_bug.cgi?id=381971
+ if (InApplicationStart)
+ return;
+ AddEventHandler (EndRequestEvent, value);
+ }
+ remove {
+ if (InApplicationStart)
+ return;
+ RemoveEventHandler (EndRequestEvent, value);
+ }
+ }
+
public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh)
{
AsyncInvoker invoker = new AsyncInvoker (bh, eh);
EndRequest += new EventHandler (invoker.Invoke);
}
+
+ static object PostRequestHandlerExecuteEvent = new object ();
+ public event EventHandler PostRequestHandlerExecute
+ {
+ add { AddEventHandler (PostRequestHandlerExecuteEvent, value); }
+ remove { RemoveEventHandler (PostRequestHandlerExecuteEvent, value); }
+ }
- public event EventHandler PostRequestHandlerExecute;
public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
{
AsyncInvoker invoker = new AsyncInvoker (bh, eh);
PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
}
- public event EventHandler PreRequestHandlerExecute;
+ static object PreRequestHandlerExecuteEvent = new object ();
+ public event EventHandler PreRequestHandlerExecute
+ {
+ add { AddEventHandler (PreRequestHandlerExecuteEvent, value); }
+ remove { RemoveEventHandler (PreRequestHandlerExecuteEvent, value); }
+ }
+
public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
{
AsyncInvoker invoker = new AsyncInvoker (bh, eh);
PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
}
- public event EventHandler ReleaseRequestState;
+ static object ReleaseRequestStateEvent = new object ();
+ public event EventHandler ReleaseRequestState
+ {
+ add { AddEventHandler (ReleaseRequestStateEvent, value); }
+ remove { RemoveEventHandler (ReleaseRequestStateEvent, value); }
+ }
+
public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
{
AsyncInvoker invoker = new AsyncInvoker (bh, eh);
ReleaseRequestState += new EventHandler (invoker.Invoke);
}
- public event EventHandler ResolveRequestCache;
+ static object ResolveRequestCacheEvent = new object ();
+ public event EventHandler ResolveRequestCache
+ {
+ add { AddEventHandler (ResolveRequestCacheEvent, value); }
+ remove { RemoveEventHandler (ResolveRequestCacheEvent, value); }
+ }
+
public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
{
AsyncInvoker invoker = new AsyncInvoker (bh, eh);
ResolveRequestCache += new EventHandler (invoker.Invoke);
}
- public event EventHandler UpdateRequestCache;
+ static object UpdateRequestCacheEvent = new object ();
+ public event EventHandler UpdateRequestCache
+ {
+ add { AddEventHandler (UpdateRequestCacheEvent, value); }
+ remove { RemoveEventHandler (UpdateRequestCacheEvent, value); }
+ }
+
public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
{
AsyncInvoker invoker = new AsyncInvoker (bh, eh);
UpdateRequestCache += new EventHandler (invoker.Invoke);
}
-#if NET_2_0
- public event EventHandler PostAuthenticateRequest;
+ static object PostAuthenticateRequestEvent = new object ();
+ public event EventHandler PostAuthenticateRequest
+ {
+ add { AddEventHandler (PostAuthenticateRequestEvent, value); }
+ remove { RemoveEventHandler (PostAuthenticateRequestEvent, value); }
+ }
+
public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
{
AddOnPostAuthenticateRequestAsync (bh, eh, null);
AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
PostAuthenticateRequest += new EventHandler (invoker.Invoke);
}
+
+ static object PostAuthorizeRequestEvent = new object ();
+ public event EventHandler PostAuthorizeRequest
+ {
+ add { AddEventHandler (PostAuthorizeRequestEvent, value); }
+ remove { RemoveEventHandler (PostAuthorizeRequestEvent, value); }
+ }
- public event EventHandler PostAuthorizeRequest;
public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
{
AddOnPostAuthorizeRequestAsync (bh, eh, null);
AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
PostAuthorizeRequest += new EventHandler (invoker.Invoke);
}
-
- public event EventHandler PostResolveRequestCache;
+
+ static object PostResolveRequestCacheEvent = new object ();
+ public event EventHandler PostResolveRequestCache
+ {
+ add { AddEventHandler (PostResolveRequestCacheEvent, value); }
+ remove { RemoveEventHandler (PostResolveRequestCacheEvent, value); }
+ }
+
public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
{
AddOnPostResolveRequestCacheAsync (bh, eh, null);
PostResolveRequestCache += new EventHandler (invoker.Invoke);
}
- public event EventHandler PostMapRequestHandler;
+ static object PostMapRequestHandlerEvent = new object ();
+ public event EventHandler PostMapRequestHandler
+ {
+ add { AddEventHandler (PostMapRequestHandlerEvent, value); }
+ remove { RemoveEventHandler (PostMapRequestHandlerEvent, value); }
+ }
+
public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
{
AddOnPostMapRequestHandlerAsync (bh, eh, null);
AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
PostMapRequestHandler += new EventHandler (invoker.Invoke);
}
+
+ static object PostAcquireRequestStateEvent = new object ();
+ public event EventHandler PostAcquireRequestState
+ {
+ add { AddEventHandler (PostAcquireRequestStateEvent, value); }
+ remove { RemoveEventHandler (PostAcquireRequestStateEvent, value); }
+ }
- public event EventHandler PostAcquireRequestState;
public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
{
AddOnPostAcquireRequestStateAsync (bh, eh, null);
AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
PostAcquireRequestState += new EventHandler (invoker.Invoke);
}
+
+ static object PostReleaseRequestStateEvent = new object ();
+ public event EventHandler PostReleaseRequestState
+ {
+ add { AddEventHandler (PostReleaseRequestStateEvent, value); }
+ remove { RemoveEventHandler (PostReleaseRequestStateEvent, value); }
+ }
- public event EventHandler PostReleaseRequestState;
public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
{
AddOnPostReleaseRequestStateAsync (bh, eh, null);
PostReleaseRequestState += new EventHandler (invoker.Invoke);
}
- public event EventHandler PostUpdateRequestCache;
+ static object PostUpdateRequestCacheEvent = new object ();
+ public event EventHandler PostUpdateRequestCache
+ {
+ add { AddEventHandler (PostUpdateRequestCacheEvent, value); }
+ remove { RemoveEventHandler (PostUpdateRequestCacheEvent, value); }
+ }
+
public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
{
AddOnPostUpdateRequestCacheAsync (bh, eh, null);
}
// Added in 2.0 SP1
- // They are for use with the IIS7 integrated mode, but have been added for compatibility
- public event EventHandler LogRequest;
+ // They are for use with the IIS7 integrated mode, but have been added for
+ // compatibility
+ static object LogRequestEvent = new object ();
+ public event EventHandler LogRequest
+ {
+ add { AddEventHandler (LogRequestEvent, value); }
+ remove { RemoveEventHandler (LogRequestEvent, value); }
+ }
+
public void AddOnLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
{
AddOnLogRequestAsync (bh, eh, null);
LogRequest += new EventHandler (invoker.Invoke);
}
- public event EventHandler MapRequestHandler;
+ static object MapRequestHandlerEvent = new object ();
+ public event EventHandler MapRequestHandler
+ {
+ add { AddEventHandler (MapRequestHandlerEvent, value); }
+ remove { RemoveEventHandler (MapRequestHandlerEvent, value); }
+ }
+
public void AddOnMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
{
AddOnMapRequestHandlerAsync (bh, eh, null);
MapRequestHandler += new EventHandler (invoker.Invoke);
}
- public event EventHandler PostLogRequest;
+ static object PostLogRequestEvent = new object ();
+ public event EventHandler PostLogRequest
+ {
+ add { AddEventHandler (PostLogRequestEvent, value); }
+ remove { RemoveEventHandler (PostLogRequestEvent, value); }
+ }
+
public void AddOnPostLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
{
AddOnPostLogRequestAsync (bh, eh, null);
AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
PostLogRequest += new EventHandler (invoker.Invoke);
}
-
-#endif
internal event EventHandler DefaultAuthentication;
+
+ void AddEventHandler (object key, EventHandler handler)
+ {
+ if (fullInitComplete)
+ return;
+
+ Events.AddHandler (key, handler);
+ }
+
+ void RemoveEventHandler (object key, EventHandler handler)
+ {
+ if (fullInitComplete)
+ return;
+
+ Events.RemoveHandler (key, handler);
+ }
//
// Bypass all the event on the Http pipeline and go directly to EndRequest
set { stop_processing = value; }
}
- public virtual void Dispose ()
+ internal void DisposeInternal ()
{
- if (modcoll != null) {
- for (int i = modcoll.Count - 1; i >= 0; i--) {
- modcoll.Get (i).Dispose ();
+ Dispose ();
+ lock (this_lock) {
+ if (modcoll != null) {
+ for (int i = modcoll.Count - 1; i >= 0; i--) {
+ modcoll.Get (i).Dispose ();
+ }
+ modcoll = null;
}
- modcoll = null;
}
- if (Disposed != null)
- Disposed (this, EventArgs.Empty);
+ EventHandler eh = nonApplicationEvents [disposedEvent] as EventHandler;
+ if (eh != null)
+ eh (this, EventArgs.Empty);
done.Close ();
done = null;
}
+
+ public virtual void Dispose ()
+ {
+ }
+#if NET_4_0
+ public virtual string GetOutputCacheProviderName (HttpContext context)
+ {
+ // LAMESPEC: doesn't throw ProviderException if context is null
+ return OutputCache.DefaultProviderName;
+ }
+#endif
+
public virtual string GetVaryByCustomString (HttpContext context, string custom)
{
if (custom == null) // Sigh
throw new NullReferenceException ();
- if (0 == String.Compare (custom, "browser", true, CultureInfo.InvariantCulture))
+ if (0 == String.Compare (custom, "browser", true, Helpers.InvariantCulture))
return context.Request.Browser.Type;
return null;
}
+ bool ShouldHandleException (Exception e)
+ {
+ if (e is ParseException)
+ return false;
+
+ return true;
+ }
+
//
// If we catch an error, queue this error
//
{
bool first = context.Error == null;
context.AddError (e);
- if (first){
- if (Error != null){
+ if (first && ShouldHandleException (e)) {
+ EventHandler eh = nonApplicationEvents [errorEvent] as EventHandler;
+ if (eh != null){
try {
- Error (this, EventArgs.Empty);
+ eh (this, EventArgs.Empty);
+ if (stop_processing)
+ context.ClearError ();
} catch (ThreadAbortException taex){
context.ClearError ();
- if (FlagEnd.Value == taex.ExceptionState)
- // This happens on Redirect() or End()
+ if (FlagEnd.Value == taex.ExceptionState || HttpRuntime.DomainUnloading)
+ // This happens on Redirect(), End() and
+ // when unloading the AppDomain
Thread.ResetAbort ();
else
// This happens on Thread.Abort()
}
}
stop_processing = true;
-#if NET_2_0
+
// we want to remove configuration from the cache in case of
// invalid resource not exists to prevent DOS attack.
HttpException httpEx = e as HttpException;
if (httpEx != null && httpEx.GetHttpCode () == 404) {
removeConfigurationFromCache = true;
}
-#endif
}
//
internal void Tick ()
{
try {
+#if TARGET_J2EE
+ if (context.Error is UnifyRequestException) {
+ Exception ex = context.Error.InnerException;
+ context.ClearError ();
+ vmw.common.TypeUtils.Throw (ex);
+ }
+ try {
+#endif
if (pipeline.MoveNext ()){
if ((bool)pipeline.Current)
PipelineDone ();
}
+#if TARGET_J2EE
+ }
+ catch (Exception ex) {
+ if (ex is ThreadAbortException &&
+ ((ThreadAbortException) ex).ExceptionState == FlagEnd.Value)
+ throw;
+ if (context.WorkerRequest is IHttpUnifyWorkerRequest) {
+ context.ClearError ();
+ context.AddError (new UnifyRequestException (ex));
+ return;
+ }
+ else
+ throw;
+ }
+#endif
} catch (ThreadAbortException taex) {
object obj = taex.ExceptionState;
Thread.ResetAbort ();
- stop_processing = true;
if (obj is StepTimeout)
- ProcessError (new HttpException ("The request timed out."));
+ ProcessError (HttpException.NewWithCode ("The request timed out.", WebEventCodes.RequestTransactionAbort));
else {
context.ClearError ();
- if (FlagEnd.Value != obj)
+ if (FlagEnd.Value != obj && !HttpRuntime.DomainUnloading)
context.AddError (taex);
}
-
+
+ stop_processing = true;
PipelineDone ();
} catch (Exception e) {
- stop_processing = true;
ProcessError (e);
+ stop_processing = true;
PipelineDone ();
}
}
void async_handler_complete_cb (IAsyncResult ar)
{
- IHttpAsyncHandler async_handler = ((IHttpAsyncHandler) ar.AsyncState);
+ IHttpAsyncHandler async_handler = ar != null ? ar.AsyncState as IHttpAsyncHandler : null;
try {
- async_handler.EndProcessRequest (ar);
+ if (async_handler != null)
+ async_handler.EndProcessRequest (ar);
} catch (Exception e){
ProcessError (e);
}
if (error is HttpException){
response.StatusCode = ((HttpException)error).GetHttpCode ();
} else {
- error = new HttpException ("", error);
+ error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
response.StatusCode = 500;
}
HttpException httpEx = (HttpException) error;
response.Flush (true);
} else {
if (!(error is HttpException))
- error = new HttpException ("", error);
+ error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
FinalErrorWrite (response, ((HttpException) error).GetHtmlErrorMessage ());
}
}
void PipelineDone ()
{
try {
- if (EndRequest != null)
- EndRequest (this, EventArgs.Empty);
+ EventHandler handler = Events [EndRequestEvent] as EventHandler;
+ if (handler != null)
+ handler (this, EventArgs.Empty);
} catch (Exception e){
ProcessError (e);
}
try {
OutputPage ();
+ } catch (ThreadAbortException taex) {
+ ProcessError (taex);
+ Thread.ResetAbort ();
} catch (Exception e) {
Console.WriteLine ("Internal error: OutputPage threw an exception " + e);
} finally {
context.Handler = null;
factory = null;
}
-#if NET_2_0
context.PopHandler ();
-#endif
+
// context = null; -> moved to PostDone
pipeline = null;
current_ai = null;
begin_iar.Complete ();
else
done.Set ();
+
+ requests_total_counter.Increment ();
}
-
+
+ class Tim {
+ string name;
+ DateTime start;
+
+ public Tim () {
+ }
+
+ public Tim (string name) {
+ this.name = name;
+ }
+
+ public string Name {
+ get { return name; }
+ set { name = value; }
+ }
+
+ public void Start () {
+ start = DateTime.UtcNow;
+ }
+
+ public void Stop () {
+ Console.WriteLine ("{0}: {1}ms", name, (DateTime.UtcNow - start).TotalMilliseconds);
+ }
+ }
+
+ Tim tim;
+ [Conditional ("PIPELINE_TIMER")]
+ void StartTimer (string name)
+ {
+ if (tim == null)
+ tim = new Tim ();
+ tim.Name = name;
+ tim.Start ();
+ }
+
+ [Conditional ("PIPELINE_TIMER")]
+ void StopTimer ()
+ {
+ tim.Stop ();
+ }
+
//
// Events fired as described in `Http Runtime Support, HttpModules,
// Handling Public Events'
//
IEnumerator Pipeline ()
{
+ Delegate eventHandler;
if (stop_processing)
yield return true;
- if (BeginRequest != null)
- foreach (bool stop in RunHooks (BeginRequest))
+#if NET_4_0
+ if (HttpRequest.ValidateRequestNewMode) {
+ char[] invalidChars = HttpRequest.RequestPathInvalidCharacters;
+ HttpRequest req = context.Request;
+ if (invalidChars != null && req != null) {
+ string path = req.PathNoValidation;
+ int idx = path != null ? path.IndexOfAny (invalidChars) : -1;
+ if (idx != -1)
+ throw HttpException.NewWithCode (
+ String.Format ("A potentially dangerous Request.Path value was detected from the client ({0}).", path [idx]),
+ WebEventCodes.RuntimeErrorValidationFailure
+ );
+ }
+ }
+#endif
+ context.MapRequestHandlerDone = false;
+ StartTimer ("BeginRequest");
+ eventHandler = Events [BeginRequestEvent];
+ if (eventHandler != null) {
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
-
- if (AuthenticateRequest != null)
- foreach (bool stop in RunHooks (AuthenticateRequest))
+ }
+ StopTimer ();
+
+ StartTimer ("AuthenticateRequest");
+ eventHandler = Events [AuthenticateRequestEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
+ StopTimer ();
+ StartTimer ("DefaultAuthentication");
if (DefaultAuthentication != null)
foreach (bool stop in RunHooks (DefaultAuthentication))
yield return stop;
+ StopTimer ();
-#if NET_2_0
- if (PostAuthenticateRequest != null)
- foreach (bool stop in RunHooks (PostAuthenticateRequest))
+ StartTimer ("PostAuthenticateRequest");
+ eventHandler = Events [PostAuthenticateRequestEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
-#endif
- if (AuthorizeRequest != null)
- foreach (bool stop in RunHooks (AuthorizeRequest))
+ StopTimer ();
+
+ StartTimer ("AuthorizeRequest");
+ eventHandler = Events [AuthorizeRequestEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
-#if NET_2_0
- if (PostAuthorizeRequest != null)
- foreach (bool stop in RunHooks (PostAuthorizeRequest))
+ StopTimer ();
+
+ StartTimer ("PostAuthorizeRequest");
+ eventHandler = Events [PostAuthorizeRequestEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
-#endif
+ StopTimer ();
- if (ResolveRequestCache != null)
- foreach (bool stop in RunHooks (ResolveRequestCache))
+ StartTimer ("ResolveRequestCache");
+ eventHandler = Events [ResolveRequestCacheEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
+ StopTimer ();
-#if NET_2_0
- if (PostResolveRequestCache != null)
- foreach (bool stop in RunHooks (PostResolveRequestCache))
+ StartTimer ("PostResolveRequestCache");
+ eventHandler = Events [PostResolveRequestCacheEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
+ StopTimer ();
+ StartTimer ("MapRequestHandler");
// As per http://msdn2.microsoft.com/en-us/library/bb470252(VS.90).aspx
- if (MapRequestHandler != null)
- foreach (bool stop in RunHooks (MapRequestHandler))
+ eventHandler = Events [MapRequestHandlerEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
-#endif
+ StopTimer ();
+ context.MapRequestHandlerDone = true;
+ StartTimer ("GetHandler");
// Obtain the handler for the request.
IHttpHandler handler = null;
try {
- handler = GetHandler (context, context.Request.FilePath);
+ handler = GetHandler (context, context.Request.CurrentExecutionFilePath);
context.Handler = handler;
-#if NET_2_0
context.PushHandler (handler);
-#endif
} catch (FileNotFoundException fnf){
#if TARGET_JVM
Console.WriteLine ("$$$$$$$$$$:Sys.Web Pipeline");
Console.WriteLine (fnf.ToString ());
#endif
if (context.Request.IsLocal)
- ProcessError (new HttpException (404, String.Format ("File not found {0}", fnf.FileName), fnf, context.Request.FilePath));
+ ProcessError (HttpException.NewWithCode (404,
+ String.Format ("File not found {0}", fnf.FileName),
+ fnf,
+ context.Request.FilePath,
+ WebEventCodes.RuntimeErrorRequestAbort));
else
- ProcessError (new HttpException (404, "File not found: " + Path.GetFileName (fnf.FileName), context.Request.FilePath));
+ ProcessError (HttpException.NewWithCode (404,
+ "File not found: " + Path.GetFileName (fnf.FileName),
+ context.Request.FilePath,
+ WebEventCodes.RuntimeErrorRequestAbort));
} catch (DirectoryNotFoundException dnf){
if (!context.Request.IsLocal)
dnf = null; // Do not "leak" real path information
- ProcessError (new HttpException (404, "Directory not found", dnf));
+ ProcessError (HttpException.NewWithCode (404, "Directory not found", dnf, WebEventCodes.RuntimeErrorRequestAbort));
} catch (Exception e) {
ProcessError (e);
}
+ StopTimer ();
if (stop_processing)
yield return true;
-#if NET_2_0
- if (PostMapRequestHandler != null)
- foreach (bool stop in RunHooks (PostMapRequestHandler))
+ StartTimer ("PostMapRequestHandler");
+ eventHandler = Events [PostMapRequestHandlerEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
-
-#endif
- if (AcquireRequestState != null){
- foreach (bool stop in RunHooks (AcquireRequestState))
+ StopTimer ();
+
+ StartTimer ("AcquireRequestState");
+ eventHandler = Events [AcquireRequestStateEvent];
+ if (eventHandler != null){
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
}
-
-#if NET_2_0
- if (PostAcquireRequestState != null){
- foreach (bool stop in RunHooks (PostAcquireRequestState))
+ StopTimer ();
+
+ StartTimer ("PostAcquireRequestState");
+ eventHandler = Events [PostAcquireRequestStateEvent];
+ if (eventHandler != null){
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
}
-#endif
+ StopTimer ();
//
// From this point on, we need to ensure that we call
// ReleaseRequestState, so the code below jumps to
// `release:' to guarantee it rather than yielding.
//
- if (PreRequestHandlerExecute != null)
- foreach (bool stop in RunHooks (PreRequestHandlerExecute))
+ StartTimer ("PreRequestHandlerExecute");
+ eventHandler = Events [PreRequestHandlerExecuteEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
if (stop)
goto release;
+ StopTimer ();
+
#if TARGET_J2EE
processHandler:
bool doProcessHandler = false;
#endif
+
+ IHttpHandler ctxHandler = context.Handler;
+ if (ctxHandler != null && handler != ctxHandler) {
+ context.PopHandler ();
+ handler = ctxHandler;
+ context.PushHandler (handler);
+ }
+
+ StartTimer ("ProcessRequest");
try {
context.BeginTimeoutPossible ();
if (handler != null){
in_begin = false;
context.EndTimeoutPossible ();
}
+ StopTimer ();
#if TARGET_J2EE
if (doProcessHandler) {
yield return false;
// These are executed after the application has returned
- if (PostRequestHandlerExecute != null)
- foreach (bool stop in RunHooks (PostRequestHandlerExecute))
+ StartTimer ("PostRequestHandlerExecute");
+ eventHandler = Events [PostRequestHandlerExecuteEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
if (stop)
goto release;
+ StopTimer ();
release:
- if (ReleaseRequestState != null){
-#pragma warning disable 168
- foreach (bool stop in RunHooks (ReleaseRequestState)){
+ StartTimer ("ReleaseRequestState");
+ eventHandler = Events [ReleaseRequestStateEvent];
+ if (eventHandler != null){
+#pragma warning disable 219
+ foreach (bool stop in RunHooks (eventHandler)) {
//
// Ignore the stop signal while release the state
//
}
-#pragma warning restore 168
+#pragma warning restore 219
}
+ StopTimer ();
if (stop_processing)
yield return true;
-#if NET_2_0
- if (PostReleaseRequestState != null)
- foreach (bool stop in RunHooks (PostReleaseRequestState))
+ StartTimer ("PostReleaseRequestState");
+ eventHandler = Events [PostReleaseRequestStateEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
-#endif
+ StopTimer ();
+ StartTimer ("Filter");
if (context.Error == null)
context.Response.DoFilter (true);
+ StopTimer ();
- if (UpdateRequestCache != null)
- foreach (bool stop in RunHooks (UpdateRequestCache))
+ StartTimer ("UpdateRequestCache");
+ eventHandler = Events [UpdateRequestCacheEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
+ StopTimer ();
-#if NET_2_0
- if (PostUpdateRequestCache != null)
- foreach (bool stop in RunHooks (PostUpdateRequestCache))
+ StartTimer ("PostUpdateRequestCache");
+ eventHandler = Events [PostUpdateRequestCacheEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
+ StopTimer ();
- if (LogRequest != null)
- foreach (bool stop in RunHooks (LogRequest))
+ StartTimer ("LogRequest");
+ eventHandler = Events [LogRequestEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
+ StopTimer ();
- if (PostLogRequest != null)
- foreach (bool stop in RunHooks (PostLogRequest))
+ StartTimer ("PostLogRequest");
+ eventHandler = Events [PostLogRequestEvent];
+ if (eventHandler != null)
+ foreach (bool stop in RunHooks (eventHandler))
yield return stop;
-#endif
+ StopTimer ();
+
+ StartTimer ("PipelineDone");
PipelineDone ();
+ StopTimer ();
}
internal CultureInfo GetThreadCulture (HttpRequest request, CultureInfo culture, bool isAuto)
{
-#if NET_2_0
if (!isAuto)
return culture;
CultureInfo ret = null;
ret = culture;
return ret;
-#else
- return culture;
-#endif
}
void PreStart ()
{
-#if NET_2_0
GlobalizationSection cfg;
cfg = (GlobalizationSection) WebConfigurationManager.GetSection ("system.web/globalization");
app_culture = cfg.GetCulture ();
autoCulture = cfg.IsAutoCulture;
appui_culture = cfg.GetUICulture ();
autoUICulture = cfg.IsAutoUICulture;
-#else
- GlobalizationConfiguration cfg;
- cfg = GlobalizationConfiguration.GetInstance (null);
- if (cfg != null) {
- app_culture = cfg.Culture;
- appui_culture = cfg.UICulture;
- }
-#endif
-
#if !TARGET_J2EE
context.StartTimeoutTimer ();
#endif
if (app_culture != null) {
prev_app_culture = th.CurrentCulture;
CultureInfo new_app_culture = GetThreadCulture (Request, app_culture, autoCulture);
- if (!new_app_culture.Equals (CultureInfo.InvariantCulture))
+ if (!new_app_culture.Equals (Helpers.InvariantCulture))
th.CurrentCulture = new_app_culture;
}
if (appui_culture != null) {
prev_appui_culture = th.CurrentUICulture;
CultureInfo new_app_culture = GetThreadCulture (Request, appui_culture, autoUICulture);
- if (!new_app_culture.Equals (CultureInfo.InvariantCulture))
+ if (!new_app_culture.Equals (Helpers.InvariantCulture))
th.CurrentUICulture = new_app_culture;
}
void PostDone ()
{
-#if NET_2_0
if (removeConfigurationFromCache) {
WebConfigurationManager.RemoveConfigurationFromCache (context);
removeConfigurationFromCache = false;
}
-#endif
+
Thread th = Thread.CurrentThread;
#if !TARGET_JVM
if (Thread.CurrentPrincipal != prev_user)
context = HttpContext.Current;
context.StopTimeoutTimer ();
#endif
+ context.Request.ReleaseResources ();
+ context.Response.ReleaseResources ();
context = null;
session = null;
HttpContext.Current = null;
void Start (object x)
{
+ CultureInfo[] cultures = x as CultureInfo[];
+ if (cultures != null && cultures.Length == 2) {
+ Thread ct = Thread.CurrentThread;
+ ct.CurrentCulture = cultures [0];
+ ct.CurrentUICulture = cultures [1];
+ }
+
try {
InitOnce (true);
} catch (Exception e) {
-#if NET_2_0
initialization_exception = e;
-#endif
- FinalErrorWrite (context.Response, new HttpException ("", e).GetHtmlErrorMessage ());
+ FinalErrorWrite (context.Response, HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort).GetHtmlErrorMessage ());
PipelineDone ();
return;
}
cache.Clear ();
}
- internal object LocateHandler (string verb, string url)
+ object LocateHandler (HttpRequest req, string verb, string url)
{
Hashtable cache = GetHandlerCache ();
string id = String.Concat (verb, url);
if (ret != null)
return ret;
-
-#if NET_2_0
- HttpHandlersSection httpHandlersSection = (HttpHandlersSection) WebConfigurationManager.GetSection ("system.web/httpHandlers");
- ret = httpHandlersSection.LocateHandler (verb, url);
-#else
- HandlerFactoryConfiguration factory_config = (HandlerFactoryConfiguration) HttpContext.GetAppConfig ("system.web/httpHandlers");
- ret = factory_config.LocateHandler (verb, url);
-#endif
- cache [id] = ret;
+ bool allowCache;
+ HttpHandlersSection httpHandlersSection = WebConfigurationManager.GetSection ("system.web/httpHandlers", req.Path, req.Context) as HttpHandlersSection;
+ ret = httpHandlersSection.LocateHandler (verb, url, out allowCache);
+
+ IHttpHandler handler = ret as IHttpHandler;
+ if (allowCache && handler != null && handler.IsReusable)
+ cache [id] = ret;
+
return ret;
}
+
+ internal IHttpHandler GetHandler (HttpContext context, string url)
+ {
+ return GetHandler (context, url, false);
+ }
// Used by HttpServerUtility.Execute
- internal IHttpHandler GetHandler (HttpContext context,string url)
+ internal IHttpHandler GetHandler (HttpContext context, string url, bool ignoreContextHandler)
{
+ if (!ignoreContextHandler && context.Handler != null)
+ return context.Handler;
+
HttpRequest request = context.Request;
string verb = request.RequestType;
IHttpHandler handler = null;
- object o = LocateHandler (verb, url);
+ object o = LocateHandler (request, verb, url);
factory = o as IHttpHandlerFactory;
-
if (factory == null) {
handler = (IHttpHandler) o;
} else {
begin_iar = new AsyncRequestState (done, cb, extraData);
+ CultureInfo[] cultures = new CultureInfo [2];
+ cultures [0] = Thread.CurrentThread.CurrentCulture;
+ cultures [1] = Thread.CurrentThread.CurrentUICulture;
+
#if TARGET_JVM
if (true)
#else
#endif
Start (null);
else
- ThreadPool.QueueUserWorkItem (new WaitCallback (Start), null);
+ ThreadPool.QueueUserWorkItem (new WaitCallback (Start), cultures);
return begin_iar;
}
if (!context.IsCustomErrorEnabledUnsafe)
return false;
-#if NET_2_0
- CustomErrorsSection config = (CustomErrorsSection)WebConfigurationManager.GetSection ("system.web/customErrors");
-#else
- CustomErrorsConfig config = null;
- try {
- config = (CustomErrorsConfig) context.GetConfig ("system.web/customErrors");
- } catch { }
-#endif
-
+ CustomErrorsSection config = (CustomErrorsSection)WebConfigurationManager.GetSection ("system.web/customErrors");
if (config == null) {
if (context.ErrorPage != null)
return RedirectErrorPage (context.ErrorPage);
return false;
}
-#if NET_2_0
CustomError err = config.Errors [context.Response.StatusCode.ToString()];
string redirect = err == null ? null : err.Redirect;
-#else
- string redirect = config [context.Response.StatusCode];
-#endif
if (redirect == null) {
redirect = context.ErrorPage;
if (redirect == null)
return RedirectErrorPage (redirect);
}
catch (Exception ex) {
- httpEx = new HttpException (500, "", ex);
+ httpEx = HttpException.NewWithCode (500, String.Empty, ex, WebEventCodes.WebErrorOtherError);
return false;
}
}
-#endregion
- internal static bool IsRunningOnWindows {
- get { return _runningOnWindows; }
- }
-
- internal static IEnumerable BinDirectories
+#endregion
+ internal static string BinDirectory
{
get {
- AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
- string baseDir = setup.ApplicationBase;
- string bindir;
-
- if (Environment.GetEnvironmentVariable ("MONO_IOMAP") != null || IsRunningOnWindows) {
- bindir = Path.Combine (baseDir, "bin");
- if (Directory.Exists (bindir))
- yield return bindir;
- } else {
+ if (binDirectory == null) {
+ AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
+ string baseDir = setup.ApplicationBase;
+ string bindir;
+
foreach (string dir in BinDirs) {
bindir = Path.Combine (baseDir, dir);
if (!Directory.Exists (bindir))
continue;
- yield return bindir;
+ binDirectory = bindir;
+ break;
}
}
+
+ return binDirectory;
}
}
ArrayList binDlls = null;
string[] dlls;
- foreach (string bindir in BinDirectories) {
- if (binDlls == null)
- binDlls = new ArrayList ();
+ string bindir = BinDirectory;
+ if (bindir != null) {
+ binDlls = new ArrayList ();
dlls = Directory.GetFiles (bindir, "*.dll");
binDlls.AddRange (dlls);
}
if (binDlls == null)
return new string[] {};
- return (string[])binDlls.ToArray (typeof (string));
+
+ return (string[]) binDlls.ToArray (typeof (string));
}
}
return type;
}
-#if NET_2_0
IList tla = System.Web.Compilation.BuildManager.TopLevelAssemblies;
if (tla != null && tla.Count > 0) {
foreach (Assembly asm in tla) {
return type;
}
}
-#endif
- type = LoadTypeFromBin (typeName);
+ Exception loadException = null;
+ try {
+ type = null;
+ type = LoadTypeFromBin (typeName);
+ } catch (Exception ex) {
+ loadException = ex;
+ }
+
if (type != null)
return type;
#endif
if (throwOnMissing)
- throw new TypeLoadException (String.Format ("Type '{0}' cannot be found", typeName));
+ throw new TypeLoadException (String.Format ("Type '{0}' cannot be found", typeName), loadException);
return null;
}
+ internal static Type LoadType <TBaseType> (string typeName, bool throwOnMissing)
+ {
+ Type ret = LoadType (typeName, throwOnMissing);
+
+ if (typeof (TBaseType).IsAssignableFrom (ret))
+ return ret;
+
+ if (throwOnMissing)
+ throw new TypeLoadException (String.Format ("Type '{0}' found but it doesn't derive from base type '{1}'.", typeName, typeof (TBaseType)));
+
+ return null;
+ }
+
internal static Type LoadTypeFromBin (string typeName)
{
Type type = null;
foreach (string s in BinDirectoryAssemblies) {
- Assembly binA = Assembly.LoadFrom (s);
+ Assembly binA = null;
+
+ try {
+ binA = Assembly.LoadFrom (s);
+ } catch (FileLoadException) {
+ // ignore
+ continue;
+ } catch (BadImageFormatException) {
+ // ignore
+ continue;
+ }
+
type = binA.GetType (typeName, false);
if (type == null)
continue;