Merge pull request #1319 from directhex/systemwide-per-arch-aot-cache
[mono.git] / mcs / class / System.Web / System.Web / HttpApplication.cs
1 //
2 // System.Web.HttpApplication.cs 
3 //
4 // Author:
5 //      Miguel de Icaza (miguel@novell.com)
6 //      Gonzalo Paniagua (gonzalo@ximian.com)
7 //    
8 //
9 // Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 // The Application Processing Pipeline.
31 // 
32 //     The Http application pipeline implemented in this file is a
33 //     beautiful thing.  The application pipeline invokes a number of
34 //     hooks at various stages of the processing of a request.  These
35 //     hooks can be either synchronous or can be asynchronous.
36 //     
37 //     The pipeline must ensure that every step is completed before
38 //     moving to the next step.  A trivial thing for synchronous
39 //     hooks, but asynchronous hooks introduce an extra layer of
40 //     complexity: when the hook is invoked, the thread must
41 //     relinquish its control so that the thread can be reused in
42 //     another operation while waiting.
43 //
44 //     To implement this functionality we used C# iterators manually;
45 //     we drive the pipeline by executing the various hooks from the
46 //     `RunHooks' routine which is an enumerator that will yield the
47 //     value `false' if execution must proceed or `true' if execution
48 //     must be stopped.
49 //
50 //     By yielding values we can suspend execution of RunHooks.
51 //
52 //     Special attention must be given to `in_begin' and `must_yield'
53 //     variables.  These are used in the case that an async hook
54 //     completes synchronously as its important to not yield in that
55 //     case or we would hang.
56 //    
57 //     Many of Mono modules used to be declared async, but they would
58 //     actually be completely synchronous, this might resurface in the
59 //     future with other modules.
60 //
61 // TODO:
62 //    Events Disposed
63 //
64
65 using System.IO;
66 using System.Collections;
67 using System.ComponentModel;
68 using System.Configuration;
69 using System.Diagnostics;
70 using System.Globalization;
71 using System.Reflection;
72 using System.Security.Permissions;
73 using System.Security.Principal;
74 using System.Threading;
75 using System.Web.Caching;
76 using System.Web.Compilation;
77 using System.Web.Configuration;
78 using System.Web.Management;
79 using System.Web.SessionState;
80 using System.Web.UI;
81 using System.Web.Util;
82
83 #if TARGET_J2EE
84 using Mainsoft.Web;
85 #endif
86         
87 namespace System.Web
88 {
89         // CAS
90         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
91         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
92         // attributes
93         [ToolboxItem(false)]
94         public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable
95         {
96                 static readonly object disposedEvent = new object ();
97                 static readonly object errorEvent = new object ();
98                 
99                 // we do this static rather than per HttpApplication because
100                 // mono's perfcounters use the counter instance parameter for
101                 // the process to access shared memory.
102                 internal static PerformanceCounter requests_total_counter = new PerformanceCounter ("ASP.NET", "Requests Total");
103                 
104                 internal static readonly string [] BinDirs = {"Bin", "bin"};
105                 object this_lock = new object();
106                 
107                 HttpContext context;
108                 HttpSessionState session;
109                 ISite isite;
110
111                 // The source, and the exposed API (cache).
112                 volatile HttpModuleCollection modcoll;
113
114                 string assemblyLocation;
115
116                 //
117                 // The factory for the handler currently running.
118                 //
119                 IHttpHandlerFactory factory;
120
121                 //
122                 // Whether the thread culture is to be auto-set.
123                 // Used only in the 2.0 profile, always false for 1.x
124                 //
125                 bool autoCulture;
126                 bool autoUICulture;
127                 
128                 //
129                 // Whether the pipeline should be stopped
130                 //
131                 bool stop_processing;
132
133                 //
134                 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
135                 //
136                 bool in_application_start;
137                 
138                 //
139                 // The Pipeline
140                 //
141                 IEnumerator pipeline;
142
143                 // To flag when we are done processing a request from BeginProcessRequest.
144                 ManualResetEvent done;
145
146                 // The current IAsyncResult for the running async request handler in the pipeline
147                 AsyncRequestState begin_iar;
148
149                 // Tracks the current AsyncInvocation being dispatched
150                 AsyncInvoker current_ai;
151
152                 EventHandlerList events;
153                 EventHandlerList nonApplicationEvents = new EventHandlerList ();
154                 
155                 // Culture and IPrincipal
156                 CultureInfo app_culture;
157                 CultureInfo appui_culture;
158                 CultureInfo prev_app_culture;
159                 CultureInfo prev_appui_culture;
160                 IPrincipal prev_user;
161
162                 static string binDirectory;
163                 
164 #if TARGET_J2EE
165                 const string initialization_exception_key = "System.Web.HttpApplication.initialization_exception";
166                 static Exception initialization_exception {
167                         get { return (Exception) AppDomain.CurrentDomain.GetData (initialization_exception_key); }
168                         set { AppDomain.CurrentDomain.SetData (initialization_exception_key, value); }
169                 }
170 #else
171                 static volatile Exception initialization_exception;
172 #endif
173                 bool removeConfigurationFromCache;
174                 bool fullInitComplete = false;
175                 
176                 //
177                 // These are used to detect the case where the EndXXX method is invoked
178                 // from within the BeginXXXX delegate, so we detect whether we kick the
179                 // pipeline from here, or from the the RunHook routine
180                 //
181                 bool must_yield;
182                 bool in_begin;
183
184                 public virtual event EventHandler Disposed {
185                         add { nonApplicationEvents.AddHandler (disposedEvent, value); }
186                         remove { nonApplicationEvents.RemoveHandler (disposedEvent, value); }
187                 }
188                 
189                 public virtual event EventHandler Error {
190                         add { nonApplicationEvents.AddHandler (errorEvent, value); }
191                         remove { nonApplicationEvents.RemoveHandler (errorEvent, value); }
192                 }
193
194                 public HttpApplication ()
195                 {
196                         done = new ManualResetEvent (false);
197                 }
198                 
199                 internal void InitOnce (bool full_init)
200                 {
201                         if (initialization_exception != null)
202                                 return;
203
204                         if (modcoll != null)
205                                 return;
206
207                         lock (this_lock) {
208                                 if (initialization_exception != null)
209                                         return;
210
211                                 if (modcoll != null)
212                                         return;
213
214                                 bool mustNullContext = context == null;
215                                 try {
216                                         HttpModulesSection modules;
217                                         modules = (HttpModulesSection) WebConfigurationManager.GetWebApplicationSection ("system.web/httpModules");
218                                         HttpContext saved = HttpContext.Current;
219                                         HttpContext.Current = new HttpContext (new System.Web.Hosting.SimpleWorkerRequest (String.Empty, String.Empty, new StringWriter()));
220                                         if (context == null)
221                                                 context = HttpContext.Current;
222                                         HttpModuleCollection coll = modules.LoadModules (this);
223                                         Interlocked.CompareExchange (ref modcoll, coll, null);
224                                         HttpContext.Current = saved;
225
226                                         if (full_init) {
227                                                 HttpApplicationFactory.AttachEvents (this);
228                                                 Init ();
229                                                 fullInitComplete = true;
230                                         }
231                                 } catch (Exception e) {
232                                         initialization_exception = e;
233                                         Console.Error.WriteLine("Exception while initOnce: "+e.ToString());
234                                         // Once initialization_exception != null, we always respond with this exception
235                                         // You have to restart the HttpApplication to "unlock" it
236                                         Console.Error.WriteLine("Please restart your app to unlock it");
237                                 } finally {
238                                         if (mustNullContext)
239                                                 context = null;
240                                 }
241                         }
242                 }
243
244                 internal bool InApplicationStart {
245                         get { return in_application_start; }
246                         set { in_application_start = value; }
247                 }
248                 
249                 internal string AssemblyLocation {
250                         get {
251                                 if (assemblyLocation == null)
252                                         assemblyLocation = GetType ().Assembly.Location;
253                                 return assemblyLocation;
254                         }
255                 }
256
257                 internal static Exception InitializationException {
258                         get { return initialization_exception; }
259                 }
260
261                 [Browsable (false)]
262                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
263                 public HttpApplicationState Application {
264                         get {
265                                 return HttpApplicationFactory.ApplicationState;
266                         }
267                 }
268
269                 [Browsable (false)]
270                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
271                 public HttpContext Context {
272                         get {
273                                 return context;
274                         }
275                 }
276                                          
277                 protected EventHandlerList Events {
278                         get {
279                                 if (events == null)
280                                         events = new EventHandlerList ();
281
282                                 return events;
283                         }
284                 }
285
286                 [Browsable (false)]
287                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
288                 public HttpModuleCollection Modules {
289                         [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
290                         get {
291                                 if (modcoll == null)
292                                         modcoll = new HttpModuleCollection ();
293                                 
294                                 return modcoll;
295                         }
296                 }
297
298                 [Browsable (false)]
299                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
300                 public HttpRequest Request {
301                         get {
302                                 if (context == null)
303                                         throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
304
305                                 if (false == HttpApplicationFactory.ContextAvailable)
306                                         throw HttpException.NewWithCode (Locale.GetText ("Request is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
307
308                                 return context.Request;
309                         }
310                 }
311
312                 [Browsable (false)]
313                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
314                 public HttpResponse Response {
315                         get {
316                                 if (context == null)
317                                         throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
318
319                                 if (false == HttpApplicationFactory.ContextAvailable)
320                                         throw HttpException.NewWithCode (Locale.GetText ("Response is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
321
322                                 return context.Response;
323                         }
324                 }
325
326                 [Browsable (false)]
327                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
328                 public HttpServerUtility Server {
329                         get {
330                                 if (context != null)
331                                         return context.Server;
332
333                                 //
334                                 // This is so we can get the Server and call a few methods
335                                 // which are not context sensitive, see HttpServerUtilityTest
336                                 //
337                                 return new HttpServerUtility ((HttpContext) null);
338                         }
339                 }
340
341                 [Browsable (false)]
342                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
343                 public HttpSessionState Session {
344                         get {
345                                 // Only used for Session_End
346                                 if (session != null)
347                                         return session;
348
349                                 if (context == null)
350                                         throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
351
352                                 HttpSessionState ret = context.Session;
353                                 if (ret == null)
354                                         throw HttpException.NewWithCode (Locale.GetText ("Session state is not available in the context."), WebEventCodes.RuntimeErrorRequestAbort);
355                                 
356                                 return ret;
357                         }
358                 }
359
360                 [Browsable (false)]
361                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
362                 public ISite Site {
363                         get { return isite; }
364
365                         set { isite = value; }
366                 }
367
368                 [Browsable (false)]
369                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
370                 public IPrincipal User {
371                         get {
372                                 if (context == null)
373                                         throw new HttpException (Locale.GetText ("No context is available."));
374                                 if (context.User == null)
375                                         throw new HttpException (Locale.GetText ("No currently authenticated user."));
376                                 
377                                 return context.User;
378                         }
379                 }
380                 
381                 static object PreSendRequestHeadersEvent = new object ();
382                 public event EventHandler PreSendRequestHeaders
383                 {
384                         add { AddEventHandler (PreSendRequestHeadersEvent, value); }
385                         remove { RemoveEventHandler (PreSendRequestHeadersEvent, value); }
386                 }
387                 
388                 internal void TriggerPreSendRequestHeaders ()
389                 {
390                         EventHandler handler = Events [PreSendRequestHeadersEvent] as EventHandler;
391                         if (handler != null)
392                                 handler (this, EventArgs.Empty);
393                 }
394
395                 static object PreSendRequestContentEvent = new object ();
396                 public event EventHandler PreSendRequestContent
397                 {
398                         add { AddEventHandler (PreSendRequestContentEvent, value); }
399                         remove { RemoveEventHandler (PreSendRequestContentEvent, value); }
400                 }
401                 
402                 internal void TriggerPreSendRequestContent ()
403                 {
404                         EventHandler handler = Events [PreSendRequestContentEvent] as EventHandler;
405                         if (handler != null)
406                                 handler (this, EventArgs.Empty);
407                 }
408
409                 static object AcquireRequestStateEvent = new object ();
410                 public event EventHandler AcquireRequestState
411                 {
412                         add { AddEventHandler (AcquireRequestStateEvent, value); }
413                         remove { RemoveEventHandler (AcquireRequestStateEvent, value); }
414                 }
415                 
416                 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
417                 {
418                         AsyncInvoker invoker = new AsyncInvoker (bh, eh);
419                         AcquireRequestState += new EventHandler (invoker.Invoke);
420                 }
421
422                 static object AuthenticateRequestEvent = new object ();
423                 public event EventHandler AuthenticateRequest
424                 {
425                         add { AddEventHandler (AuthenticateRequestEvent, value); }
426                         remove { RemoveEventHandler (AuthenticateRequestEvent, value); }
427                 }
428                 
429                 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
430                 {
431                         AsyncInvoker invoker = new AsyncInvoker (bh, eh);
432                         AuthenticateRequest += new EventHandler (invoker.Invoke);
433                 }
434
435                 static object AuthorizeRequestEvent = new object ();
436                 public event EventHandler AuthorizeRequest
437                 {
438                         add { AddEventHandler (AuthorizeRequestEvent, value); }
439                         remove { RemoveEventHandler (AuthorizeRequestEvent, value); }
440                 }
441                 
442                 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
443                 {
444                         AsyncInvoker invoker = new AsyncInvoker (bh, eh);
445                         AuthorizeRequest += new EventHandler (invoker.Invoke);
446                 }
447
448                 static object BeginRequestEvent = new object ();
449                 public event EventHandler BeginRequest          
450                 {
451                         add {
452                                 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
453                                 if (InApplicationStart)
454                                         return;
455                                 AddEventHandler (BeginRequestEvent, value);
456                         }
457                         remove {
458                                 if (InApplicationStart)
459                                         return;
460                                 RemoveEventHandler (BeginRequestEvent, value);
461                         }
462                 }
463                 
464                 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh)
465                 {
466                         AsyncInvoker invoker = new AsyncInvoker (bh, eh);
467                         BeginRequest += new EventHandler (invoker.Invoke);
468                 }
469
470                 static object EndRequestEvent = new object ();
471                 public event EventHandler EndRequest
472                 {
473                         add {
474                                 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
475                                 if (InApplicationStart)
476                                         return;
477                                 AddEventHandler (EndRequestEvent, value);
478                         }
479                         remove {
480                                 if (InApplicationStart)
481                                         return;
482                                 RemoveEventHandler (EndRequestEvent, value);
483                         }
484                 }
485                 
486                 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh)
487                 {
488                         AsyncInvoker invoker = new AsyncInvoker (bh, eh);
489                         EndRequest += new EventHandler (invoker.Invoke);
490                 }
491
492                 static object PostRequestHandlerExecuteEvent = new object ();
493                 public event EventHandler PostRequestHandlerExecute
494                 {
495                         add { AddEventHandler (PostRequestHandlerExecuteEvent, value); }
496                         remove { RemoveEventHandler (PostRequestHandlerExecuteEvent, value); }
497                 }
498                 
499                 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
500                 {
501                         AsyncInvoker invoker = new AsyncInvoker (bh, eh);
502                         PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
503                 }
504
505                 static object PreRequestHandlerExecuteEvent = new object ();
506                 public event EventHandler PreRequestHandlerExecute
507                 {
508                         add { AddEventHandler (PreRequestHandlerExecuteEvent, value); }
509                         remove { RemoveEventHandler (PreRequestHandlerExecuteEvent, value); }
510                 }
511                 
512                 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
513                 {
514                         AsyncInvoker invoker = new AsyncInvoker (bh, eh);
515                         PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
516                 }
517
518                 static object ReleaseRequestStateEvent = new object ();
519                 public event EventHandler ReleaseRequestState
520                 {
521                         add { AddEventHandler (ReleaseRequestStateEvent, value); }
522                         remove { RemoveEventHandler (ReleaseRequestStateEvent, value); }
523                 }
524                 
525                 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
526                 {
527                         AsyncInvoker invoker = new AsyncInvoker (bh, eh);
528                         ReleaseRequestState += new EventHandler (invoker.Invoke);
529                 }
530
531                 static object ResolveRequestCacheEvent = new object ();
532                 public event EventHandler ResolveRequestCache
533                 {
534                         add { AddEventHandler (ResolveRequestCacheEvent, value); }
535                         remove { RemoveEventHandler (ResolveRequestCacheEvent, value); }
536                 }
537                 
538                 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
539                 {
540                         AsyncInvoker invoker = new AsyncInvoker (bh, eh);
541                         ResolveRequestCache += new EventHandler (invoker.Invoke);
542                 }
543
544                 static object UpdateRequestCacheEvent = new object ();
545                 public event EventHandler UpdateRequestCache
546                 {
547                         add { AddEventHandler (UpdateRequestCacheEvent, value); }
548                         remove { RemoveEventHandler (UpdateRequestCacheEvent, value); }
549                 }
550                 
551                 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
552                 {
553                         AsyncInvoker invoker = new AsyncInvoker (bh, eh);
554                         UpdateRequestCache += new EventHandler (invoker.Invoke);
555                 }
556
557                 static object PostAuthenticateRequestEvent = new object ();
558                 public event EventHandler PostAuthenticateRequest
559                 {
560                         add { AddEventHandler (PostAuthenticateRequestEvent, value); }
561                         remove { RemoveEventHandler (PostAuthenticateRequestEvent, value); }
562                 }
563                 
564                 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
565                 {
566                         AddOnPostAuthenticateRequestAsync (bh, eh, null);
567                 }
568                         
569                 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
570                 {
571                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
572                         PostAuthenticateRequest += new EventHandler (invoker.Invoke);
573                 }
574
575                 static object PostAuthorizeRequestEvent = new object ();
576                 public event EventHandler PostAuthorizeRequest
577                 {
578                         add { AddEventHandler (PostAuthorizeRequestEvent, value); }
579                         remove { RemoveEventHandler (PostAuthorizeRequestEvent, value); }
580                 }
581                 
582                 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
583                 {
584                         AddOnPostAuthorizeRequestAsync (bh, eh, null);
585                 }
586                 
587                 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
588                 {
589                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
590                         PostAuthorizeRequest += new EventHandler (invoker.Invoke);
591                 }
592                 
593                 static object PostResolveRequestCacheEvent = new object ();
594                 public event EventHandler PostResolveRequestCache
595                 {
596                         add { AddEventHandler (PostResolveRequestCacheEvent, value); }
597                         remove { RemoveEventHandler (PostResolveRequestCacheEvent, value); }
598                 }
599                 
600                 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
601                 {
602                         AddOnPostResolveRequestCacheAsync (bh, eh, null);
603                 }
604                 
605                 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
606                 {
607                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
608                         PostResolveRequestCache += new EventHandler (invoker.Invoke);
609                 }
610
611                 static object PostMapRequestHandlerEvent = new object ();
612                 public event EventHandler PostMapRequestHandler
613                 {
614                         add { AddEventHandler (PostMapRequestHandlerEvent, value); }
615                         remove { RemoveEventHandler (PostMapRequestHandlerEvent, value); }
616                 }
617                 
618                 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
619                 {
620                         AddOnPostMapRequestHandlerAsync (bh, eh, null);
621                 }
622                 
623                 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh, object data)
624                 {
625                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
626                         PostMapRequestHandler += new EventHandler (invoker.Invoke);
627                 }
628
629                 static object PostAcquireRequestStateEvent = new object ();
630                 public event EventHandler PostAcquireRequestState
631                 {
632                         add { AddEventHandler (PostAcquireRequestStateEvent, value); }
633                         remove { RemoveEventHandler (PostAcquireRequestStateEvent, value); }
634                 }
635                 
636                 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
637                 {
638                         AddOnPostAcquireRequestStateAsync (bh, eh, null);
639                 }
640                 
641                 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
642                 {
643                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
644                         PostAcquireRequestState += new EventHandler (invoker.Invoke);
645                 }
646
647                 static object PostReleaseRequestStateEvent = new object ();
648                 public event EventHandler PostReleaseRequestState
649                 {
650                         add { AddEventHandler (PostReleaseRequestStateEvent, value); }
651                         remove { RemoveEventHandler (PostReleaseRequestStateEvent, value); }
652                 }
653                 
654                 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
655                 {
656                         AddOnPostReleaseRequestStateAsync (bh, eh, null);
657                 }
658                 
659                 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
660                 {
661                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
662                         PostReleaseRequestState += new EventHandler (invoker.Invoke);
663                 }
664
665                 static object PostUpdateRequestCacheEvent = new object ();
666                 public event EventHandler PostUpdateRequestCache
667                 {
668                         add { AddEventHandler (PostUpdateRequestCacheEvent, value); }
669                         remove { RemoveEventHandler (PostUpdateRequestCacheEvent, value); }
670                 }
671                 
672                 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
673                 {
674                         AddOnPostUpdateRequestCacheAsync (bh, eh, null);
675                 }
676                 
677                 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
678                 {
679                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
680                         PostUpdateRequestCache += new EventHandler (invoker.Invoke);
681                 }
682
683                 //
684                 // The new overloads that take a data parameter
685                 //
686                 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
687                 {
688                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
689                         AcquireRequestState += new EventHandler (invoker.Invoke);
690                 }
691
692                 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
693                 {
694                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
695                         AuthenticateRequest += new EventHandler (invoker.Invoke);
696                 }
697
698                 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
699                 {
700                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
701                         AuthorizeRequest += new EventHandler (invoker.Invoke);
702                 }
703
704                 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
705                 {
706                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
707                         BeginRequest += new EventHandler (invoker.Invoke);
708                 }
709
710                 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
711                 {
712                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
713                         EndRequest += new EventHandler (invoker.Invoke);
714                 }
715                 
716                 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
717                 {
718                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
719                         PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
720                 }
721
722                 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
723                 {
724                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
725                         PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
726                 }
727
728                 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
729                 {
730                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
731                         ReleaseRequestState += new EventHandler (invoker.Invoke);
732                 }
733
734                 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
735                 {
736                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
737                         ResolveRequestCache += new EventHandler (invoker.Invoke);
738                 }
739
740                 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
741                 {
742                         AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
743                         UpdateRequestCache += new EventHandler (invoker.Invoke);
744                 }
745
746                 // Added in 2.0 SP1
747                 // They are for use with the IIS7 integrated mode, but have been added for
748                 // compatibility
749                 static object LogRequestEvent = new object ();
750                 public event EventHandler LogRequest
751                 {
752                         add { AddEventHandler (LogRequestEvent, value); }
753                         remove { RemoveEventHandler (LogRequestEvent, value); }
754                 }
755                 
756                 public void AddOnLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
757                 {
758                         AddOnLogRequestAsync (bh, eh, null);
759                 }
760                 
761                 public void AddOnLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
762                 {
763                         AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
764                         LogRequest += new EventHandler (invoker.Invoke);
765                 }
766
767                 static object MapRequestHandlerEvent = new object ();
768                 public event EventHandler MapRequestHandler
769                 {
770                         add { AddEventHandler (MapRequestHandlerEvent, value); }
771                         remove { RemoveEventHandler (MapRequestHandlerEvent, value); }
772                 }
773                 
774                 public void AddOnMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
775                 {
776                         AddOnMapRequestHandlerAsync (bh, eh, null);
777                 }
778
779                 public void AddOnMapRequestHandlerAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
780                 {
781                         AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
782                         MapRequestHandler += new EventHandler (invoker.Invoke);
783                 }
784
785                 static object PostLogRequestEvent = new object ();
786                 public event EventHandler PostLogRequest
787                 {
788                         add { AddEventHandler (PostLogRequestEvent, value); }
789                         remove { RemoveEventHandler (PostLogRequestEvent, value); }
790                 }
791                 
792                 public void AddOnPostLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
793                 {
794                         AddOnPostLogRequestAsync (bh, eh, null);
795                 }
796
797                 public void AddOnPostLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
798                 {
799                         AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
800                         PostLogRequest += new EventHandler (invoker.Invoke);
801                 }
802                 
803                 internal event EventHandler DefaultAuthentication;
804
805                 void AddEventHandler (object key, EventHandler handler)
806                 {
807                         if (fullInitComplete)
808                                 return;
809
810                         Events.AddHandler (key, handler);
811                 }
812
813                 void RemoveEventHandler (object key, EventHandler handler)
814                 {
815                         if (fullInitComplete)
816                                 return;
817
818                         Events.RemoveHandler (key, handler);
819                 }
820                 
821                 //
822                 // Bypass all the event on the Http pipeline and go directly to EndRequest
823                 //
824                 public void CompleteRequest ()
825                 {
826                         stop_processing = true;
827                 }
828
829                 internal bool RequestCompleted {
830                         set { stop_processing = value; }
831                 }
832
833                 internal void DisposeInternal ()
834                 {
835                         Dispose ();
836                         HttpModuleCollection coll = new HttpModuleCollection ();
837                         Interlocked.Exchange (ref modcoll, coll);
838                         if (coll != null) {
839                                 for (int i = coll.Count - 1; i >= 0; i--) {
840                                         coll.Get (i).Dispose ();
841                                 }
842                                 coll = null;
843                         }
844
845                         EventHandler eh = nonApplicationEvents [disposedEvent] as EventHandler;
846                         if (eh != null)
847                                 eh (this, EventArgs.Empty);
848                         
849                         done.Close ();
850                         done = null;
851                 }
852                 
853                 public virtual void Dispose ()
854                 {
855                 }
856
857 #if NET_4_0
858                 public virtual string GetOutputCacheProviderName (HttpContext context)
859                 {
860                         // LAMESPEC: doesn't throw ProviderException if context is null
861                         return OutputCache.DefaultProviderName;
862                 }
863 #endif
864                 
865                 public virtual string GetVaryByCustomString (HttpContext context, string custom)
866                 {
867                         if (custom == null) // Sigh
868                                 throw new NullReferenceException ();
869
870                         if (0 == String.Compare (custom, "browser", true, Helpers.InvariantCulture))
871                                 return context.Request.Browser.Type;
872
873                         return null;
874                 }
875
876                 bool ShouldHandleException (Exception e)
877                 {
878                         if (e is ParseException)
879                                 return false;
880
881                         return true;
882                 }
883                 
884                 //
885                 // If we catch an error, queue this error
886                 //
887                 void ProcessError (Exception e)
888                 {
889                         bool first = context.Error == null;
890                         context.AddError (e);
891                         if (first && ShouldHandleException (e)) {
892                                 EventHandler eh = nonApplicationEvents [errorEvent] as EventHandler;
893                                 if (eh != null){
894                                         try {
895                                                 eh (this, EventArgs.Empty);
896                                                 if (stop_processing)
897                                                         context.ClearError ();
898                                         } catch (ThreadAbortException taex){
899                                                 context.ClearError ();
900                                                 if (FlagEnd.Value == taex.ExceptionState || HttpRuntime.DomainUnloading)
901                                                         // This happens on Redirect(), End() and
902                                                         // when unloading the AppDomain
903                                                         Thread.ResetAbort ();
904                                                 else
905                                                         // This happens on Thread.Abort()
906                                                         context.AddError (taex);
907                                         } catch (Exception ee){
908                                                 context.AddError (ee);
909                                         }
910                                 }
911                         }
912                         stop_processing = true;
913
914                         // we want to remove configuration from the cache in case of 
915                         // invalid resource not exists to prevent DOS attack.
916                         HttpException httpEx = e as HttpException;
917                         if (httpEx != null && httpEx.GetHttpCode () == 404) {
918                                 removeConfigurationFromCache = true;
919                         }
920                 }
921                 
922                 //
923                 // Ticks the clock: next step on the pipeline.
924                 //
925                 internal void Tick ()
926                 {
927                         try {
928 #if TARGET_J2EE
929                                 if (context.Error is UnifyRequestException) {
930                                         Exception ex = context.Error.InnerException;
931                                         context.ClearError ();
932                                         vmw.common.TypeUtils.Throw (ex);
933                                 }
934                                 try {
935 #endif          
936                                 if (pipeline.MoveNext ()){
937                                         if ((bool)pipeline.Current)
938                                                 PipelineDone ();
939                                 }
940 #if TARGET_J2EE
941                                 }
942                                 catch (Exception ex) {
943                                         if (ex is ThreadAbortException && 
944                                                 ((ThreadAbortException) ex).ExceptionState == FlagEnd.Value)
945                                                 throw;
946                                         if (context.WorkerRequest is IHttpUnifyWorkerRequest) {
947                                                 context.ClearError ();
948                                                 context.AddError (new UnifyRequestException (ex));
949                                                 return;
950                                         }
951                                         else
952                                                 throw;
953                                 }
954 #endif
955                         } catch (ThreadAbortException taex) {
956                                 object obj = taex.ExceptionState;
957                                 Thread.ResetAbort ();
958                                 if (obj is StepTimeout)
959                                         ProcessError (HttpException.NewWithCode ("The request timed out.", WebEventCodes.RequestTransactionAbort));
960                                 else {
961                                         context.ClearError ();
962                                         if (FlagEnd.Value != obj && !HttpRuntime.DomainUnloading)
963                                                 context.AddError (taex);
964                                 }
965                                 
966                                 stop_processing = true;
967                                 PipelineDone ();
968                         } catch (Exception e) {
969                                 ThreadAbortException inner = e.InnerException as ThreadAbortException;
970                                 if (inner != null && FlagEnd.Value == inner.ExceptionState && !HttpRuntime.DomainUnloading) {
971                                         context.ClearError ();
972                                         Thread.ResetAbort ();
973                                 } else {
974                                         ProcessError (e);
975                                 }
976                                 stop_processing = true;
977                                 PipelineDone ();
978                         }
979                 }
980
981                 void Resume ()
982                 {
983                         if (in_begin)
984                                 must_yield = false;
985                         else
986                                 Tick ();
987                 }
988                 
989                 //
990                 // Invoked when our async callback called from RunHooks completes,
991                 // we restart the pipeline here.
992                 //
993                 void async_callback_completed_cb (IAsyncResult ar)
994                 {
995                         if (current_ai.end != null){
996                                 try {
997                                         current_ai.end (ar);
998                                 } catch (Exception e) {
999                                         ProcessError (e);
1000                                 }
1001                         }
1002
1003                         Resume ();
1004                 }
1005
1006                 void async_handler_complete_cb (IAsyncResult ar)
1007                 {
1008                         IHttpAsyncHandler async_handler = ar != null ? ar.AsyncState as IHttpAsyncHandler : null;
1009
1010                         try {
1011                                 if (async_handler != null)
1012                                         async_handler.EndProcessRequest (ar);
1013                         } catch (Exception e){
1014                                 ProcessError (e);
1015                         }
1016                         
1017                         Resume ();
1018                 }
1019                 
1020                 //
1021                 // This enumerator yields whether processing must be stopped:
1022                 //    true:  processing of the pipeline must be stopped
1023                 //    false: processing of the pipeline must not be stopped
1024                 //
1025                 IEnumerable RunHooks (Delegate list)
1026                 {
1027                         Delegate [] delegates = list.GetInvocationList ();
1028
1029                         foreach (EventHandler d in delegates){
1030                                 if (d.Target != null && (d.Target is AsyncInvoker)){
1031                                         current_ai = (AsyncInvoker) d.Target;
1032
1033                                         try {
1034                                                 must_yield = true;
1035                                                 in_begin = true;
1036                                                 context.BeginTimeoutPossible ();
1037                                                 current_ai.begin (this, EventArgs.Empty, async_callback_completed_cb, current_ai.data);
1038                                         } finally {
1039                                                 in_begin = false;
1040                                                 context.EndTimeoutPossible ();
1041                                         }
1042
1043                                         //
1044                                         // If things are still moving forward, yield this
1045                                         // thread now
1046                                         //
1047                                         if (must_yield)
1048                                                 yield return stop_processing;
1049                                         else if (stop_processing)
1050                                                 yield return true;
1051                                 } else {
1052                                         try {
1053                                                 context.BeginTimeoutPossible ();
1054                                                 d (this, EventArgs.Empty);
1055                                         } finally {
1056                                                 context.EndTimeoutPossible ();
1057                                         }
1058                                         if (stop_processing)
1059                                                 yield return true;
1060                                 }
1061                         }
1062                 }
1063
1064                 static void FinalErrorWrite (HttpResponse response, string error)
1065                 {
1066                         try {
1067                                 response.Write (error);
1068                                 response.Flush (true);
1069                         } catch {
1070                                 response.Close ();
1071                         }
1072                 }
1073
1074                 void OutputPage ()
1075                 {
1076                         if (context.Error == null){
1077                                 try {
1078                                         context.Response.Flush (true);
1079                                 } catch (Exception e){
1080                                         context.AddError (e);
1081                                 }
1082                         }
1083
1084                         Exception error = context.Error;
1085                         if (error != null){
1086                                 HttpResponse response = context.Response;
1087
1088                                 if (!response.HeadersSent){
1089                                         response.ClearHeaders ();
1090                                         response.ClearContent ();
1091
1092                                         if (error is HttpException){
1093                                                 response.StatusCode = ((HttpException)error).GetHttpCode ();
1094                                         } else {
1095                                                 error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1096                                                 response.StatusCode = 500;
1097                                         }
1098                                         HttpException httpEx = (HttpException) error;
1099                                         if (!RedirectCustomError (ref httpEx))
1100                                                 FinalErrorWrite (response, httpEx.GetHtmlErrorMessage ());
1101                                         else
1102                                                 response.Flush (true);
1103                                 } else {
1104                                         if (!(error is HttpException))
1105                                                 error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1106                                         FinalErrorWrite (response, ((HttpException) error).GetHtmlErrorMessage ());
1107                                 }
1108                         }
1109                         
1110                 }
1111                 
1112                 //
1113                 // Invoked at the end of the pipeline execution
1114                 //
1115                 void PipelineDone ()
1116                 {
1117                         try {
1118                                 EventHandler handler = Events [EndRequestEvent] as EventHandler;
1119                                 if (handler != null)
1120                                         handler (this, EventArgs.Empty);
1121                         } catch (Exception e){
1122                                 ProcessError (e);
1123                         }
1124
1125                         try {
1126                                 OutputPage ();
1127                         } catch (ThreadAbortException taex) {
1128                                 ProcessError (taex);
1129                                 Thread.ResetAbort ();
1130                         } catch (Exception e) {
1131                                 Console.WriteLine ("Internal error: OutputPage threw an exception " + e);
1132                         } finally {
1133                                 context.WorkerRequest.EndOfRequest();
1134                                 if (factory != null && context.Handler != null){
1135                                         factory.ReleaseHandler (context.Handler);
1136                                         context.Handler = null;
1137                                         factory = null;
1138                                 }
1139                                 context.PopHandler ();
1140
1141                                 // context = null; -> moved to PostDone
1142                                 pipeline = null;
1143                                 current_ai = null;
1144                         }
1145                         PostDone ();
1146
1147                         if (begin_iar != null)
1148                                 begin_iar.Complete ();
1149                         else
1150                                 done.Set ();
1151
1152                         requests_total_counter.Increment ();
1153                 }
1154
1155                 class Tim {
1156                         string name;
1157                         DateTime start;
1158
1159                         public Tim () {
1160                         }
1161
1162                         public Tim (string name) {
1163                                 this.name = name;
1164                         }
1165
1166                         public string Name {
1167                                 get { return name; }
1168                                 set { name = value; }
1169                         }
1170
1171                         public void Start () {
1172                                 start = DateTime.UtcNow;
1173                         }
1174
1175                         public void Stop () {
1176                                 Console.WriteLine ("{0}: {1}ms", name, (DateTime.UtcNow - start).TotalMilliseconds);
1177                         }
1178                 }
1179
1180                 Tim tim;
1181                 [Conditional ("PIPELINE_TIMER")]
1182                 void StartTimer (string name)
1183                 {
1184                         if (tim == null)
1185                                 tim = new Tim ();
1186                         tim.Name = name;
1187                         tim.Start ();
1188                 }
1189
1190                 [Conditional ("PIPELINE_TIMER")]
1191                 void StopTimer ()
1192                 {
1193                         tim.Stop ();
1194                 }
1195
1196                 //
1197                 // Events fired as described in `Http Runtime Support, HttpModules,
1198                 // Handling Public Events'
1199                 //
1200                 IEnumerator Pipeline ()
1201                 {
1202                         Delegate eventHandler;
1203                         if (stop_processing)
1204                                 yield return true;
1205 #if NET_4_0
1206                         HttpRequest req = context.Request;
1207                         if (req != null)
1208                                 req.Validate ();
1209 #endif
1210                         context.MapRequestHandlerDone = false;
1211                         StartTimer ("BeginRequest");
1212                         eventHandler = Events [BeginRequestEvent];
1213                         if (eventHandler != null) {
1214                                 foreach (bool stop in RunHooks (eventHandler))
1215                                         yield return stop;
1216                         }
1217                         StopTimer ();
1218                         
1219                         StartTimer ("AuthenticateRequest");
1220                         eventHandler = Events [AuthenticateRequestEvent];
1221                         if (eventHandler != null)
1222                                 foreach (bool stop in RunHooks (eventHandler))
1223                                         yield return stop;
1224                         StopTimer ();
1225
1226                         StartTimer ("DefaultAuthentication");
1227                         if (DefaultAuthentication != null)
1228                                 foreach (bool stop in RunHooks (DefaultAuthentication))
1229                                         yield return stop;
1230                         StopTimer ();
1231
1232                         StartTimer ("PostAuthenticateRequest");
1233                         eventHandler = Events [PostAuthenticateRequestEvent];
1234                         if (eventHandler != null)
1235                                 foreach (bool stop in RunHooks (eventHandler))
1236                                         yield return stop;
1237                         StopTimer ();
1238
1239                         StartTimer ("AuthorizeRequest");
1240                         eventHandler = Events [AuthorizeRequestEvent];
1241                         if (eventHandler != null)
1242                                 foreach (bool stop in RunHooks (eventHandler))
1243                                         yield return stop;
1244                         StopTimer ();
1245
1246                         StartTimer ("PostAuthorizeRequest");
1247                         eventHandler = Events [PostAuthorizeRequestEvent];
1248                         if (eventHandler != null)
1249                                 foreach (bool stop in RunHooks (eventHandler))
1250                                         yield return stop;
1251                         StopTimer ();
1252
1253                         StartTimer ("ResolveRequestCache");
1254                         eventHandler = Events [ResolveRequestCacheEvent];
1255                         if (eventHandler != null)
1256                                 foreach (bool stop in RunHooks (eventHandler))
1257                                         yield return stop;
1258                         StopTimer ();
1259
1260                         StartTimer ("PostResolveRequestCache");
1261                         eventHandler = Events [PostResolveRequestCacheEvent];
1262                         if (eventHandler != null)
1263                                 foreach (bool stop in RunHooks (eventHandler))
1264                                         yield return stop;
1265                         StopTimer ();
1266
1267                         StartTimer ("MapRequestHandler");
1268                         // As per http://msdn2.microsoft.com/en-us/library/bb470252(VS.90).aspx
1269                         eventHandler = Events [MapRequestHandlerEvent];
1270                         if (eventHandler != null)
1271                                 foreach (bool stop in RunHooks (eventHandler))
1272                                         yield return stop;
1273                         StopTimer ();
1274                         context.MapRequestHandlerDone = true;
1275                         
1276                         StartTimer ("GetHandler");
1277                         // Obtain the handler for the request.
1278                         IHttpHandler handler = null;
1279                         try {
1280                                 handler = GetHandler (context, context.Request.CurrentExecutionFilePath);
1281                                 context.Handler = handler;
1282                                 context.PushHandler (handler);
1283                         } catch (FileNotFoundException fnf){
1284                                 if (context.Request.IsLocal)
1285                                         ProcessError (HttpException.NewWithCode (404,
1286                                                                                  String.Format ("File not found {0}", fnf.FileName),
1287                                                                                  fnf,
1288                                                                                  context.Request.FilePath,
1289                                                                                  WebEventCodes.RuntimeErrorRequestAbort));
1290                                 else
1291                                         ProcessError (HttpException.NewWithCode (404,
1292                                                                                  "File not found: " + Path.GetFileName (fnf.FileName),
1293                                                                                  context.Request.FilePath,
1294                                                                                  WebEventCodes.RuntimeErrorRequestAbort));
1295                         } catch (DirectoryNotFoundException dnf){
1296                                 if (!context.Request.IsLocal)
1297                                         dnf = null; // Do not "leak" real path information
1298                                 ProcessError (HttpException.NewWithCode (404, "Directory not found", dnf, WebEventCodes.RuntimeErrorRequestAbort));
1299                         } catch (Exception e) {
1300                                 ProcessError (e);
1301                         }
1302
1303                         StopTimer ();
1304                         if (stop_processing)
1305                                 yield return true;
1306
1307                         StartTimer ("PostMapRequestHandler");
1308                         eventHandler = Events [PostMapRequestHandlerEvent];
1309                         if (eventHandler != null)
1310                                 foreach (bool stop in RunHooks (eventHandler))
1311                                         yield return stop;
1312                         StopTimer ();
1313
1314                         StartTimer ("AcquireRequestState");
1315                         eventHandler = Events [AcquireRequestStateEvent];
1316                         if (eventHandler != null){
1317                                 foreach (bool stop in RunHooks (eventHandler))
1318                                         yield return stop;
1319                         }
1320                         StopTimer ();
1321                         
1322                         StartTimer ("PostAcquireRequestState");
1323                         eventHandler = Events [PostAcquireRequestStateEvent];
1324                         if (eventHandler != null){
1325                                 foreach (bool stop in RunHooks (eventHandler))
1326                                         yield return stop;
1327                         }
1328                         StopTimer ();
1329                         
1330                         //
1331                         // From this point on, we need to ensure that we call
1332                         // ReleaseRequestState, so the code below jumps to
1333                         // `release:' to guarantee it rather than yielding.
1334                         //
1335                         StartTimer ("PreRequestHandlerExecute");
1336                         eventHandler = Events [PreRequestHandlerExecuteEvent];
1337                         if (eventHandler != null)
1338                                 foreach (bool stop in RunHooks (eventHandler))
1339                                         if (stop)
1340                                                 goto release;
1341                         StopTimer ();
1342                         
1343                                 
1344 #if TARGET_J2EE
1345                 processHandler:
1346                         bool doProcessHandler = false;
1347 #endif
1348                         
1349                         IHttpHandler ctxHandler = context.Handler;
1350                         if (ctxHandler != null && handler != ctxHandler) {
1351                                 context.PopHandler ();
1352                                 handler = ctxHandler;
1353                                 context.PushHandler (handler);
1354                         }
1355
1356                         StartTimer ("ProcessRequest");
1357                         try {
1358                                 context.BeginTimeoutPossible ();
1359                                 if (handler != null){
1360                                         IHttpAsyncHandler async_handler = handler as IHttpAsyncHandler;
1361                                         
1362                                         if (async_handler != null){
1363                                                 must_yield = true;
1364                                                 in_begin = true;
1365                                                 async_handler.BeginProcessRequest (context, async_handler_complete_cb, handler);
1366                                         } else {
1367                                                 must_yield = false;
1368                                                 handler.ProcessRequest (context);
1369 #if TARGET_J2EE
1370                                                 IHttpExtendedHandler extHandler=handler as IHttpExtendedHandler;
1371                                                 doProcessHandler = extHandler != null && !extHandler.IsCompleted;
1372 #endif
1373                                         }
1374                                 } else
1375                                         throw new InvalidOperationException ("No handler for the current request.");
1376                                 if (context.Error != null)
1377                                         throw new TargetInvocationException(context.Error);
1378                         } finally {
1379                                 in_begin = false;
1380                                 context.EndTimeoutPossible ();
1381                         }
1382                         StopTimer ();
1383 #if TARGET_J2EE
1384                         if (doProcessHandler) {
1385                                 yield return false;
1386                                 goto processHandler;
1387                         }
1388 #endif
1389                         if (must_yield)
1390                                 yield return stop_processing;
1391                         else if (stop_processing)
1392                                 goto release;
1393                         
1394                         // These are executed after the application has returned
1395                         
1396                         StartTimer ("PostRequestHandlerExecute");
1397                         eventHandler = Events [PostRequestHandlerExecuteEvent];
1398                         if (eventHandler != null)
1399                                 foreach (bool stop in RunHooks (eventHandler))
1400                                         if (stop)
1401                                                 goto release;
1402                         StopTimer ();
1403                         
1404                 release:
1405                         StartTimer ("ReleaseRequestState");
1406                         eventHandler = Events [ReleaseRequestStateEvent];
1407                         if (eventHandler != null){
1408 #pragma warning disable 219
1409                                 foreach (bool stop in RunHooks (eventHandler)) {
1410                                         //
1411                                         // Ignore the stop signal while release the state
1412                                         //
1413                                         
1414                                 }
1415 #pragma warning restore 219
1416                         }
1417                         StopTimer ();
1418                         
1419                         if (stop_processing)
1420                                 yield return true;
1421
1422                         StartTimer ("PostReleaseRequestState");
1423                         eventHandler = Events [PostReleaseRequestStateEvent];
1424                         if (eventHandler != null)
1425                                 foreach (bool stop in RunHooks (eventHandler))
1426                                         yield return stop;
1427                         StopTimer ();
1428
1429                         StartTimer ("Filter");
1430                         if (context.Error == null)
1431                                 context.Response.DoFilter (true);
1432                         StopTimer ();
1433
1434                         StartTimer ("UpdateRequestCache");
1435                         eventHandler = Events [UpdateRequestCacheEvent];
1436                         if (eventHandler != null)
1437                                 foreach (bool stop in RunHooks (eventHandler))
1438                                         yield return stop;
1439                         StopTimer ();
1440
1441                         StartTimer ("PostUpdateRequestCache");
1442                         eventHandler = Events [PostUpdateRequestCacheEvent];
1443                         if (eventHandler != null)
1444                                 foreach (bool stop in RunHooks (eventHandler))
1445                                         yield return stop;
1446                         StopTimer ();
1447
1448                         StartTimer ("LogRequest");
1449                         eventHandler = Events [LogRequestEvent];
1450                         if (eventHandler != null)
1451                                 foreach (bool stop in RunHooks (eventHandler))
1452                                         yield return stop;
1453                         StopTimer ();
1454
1455                         StartTimer ("PostLogRequest");
1456                         eventHandler = Events [PostLogRequestEvent];
1457                         if (eventHandler != null)
1458                                 foreach (bool stop in RunHooks (eventHandler))
1459                                         yield return stop;
1460                         StopTimer ();
1461
1462                         StartTimer ("PipelineDone");
1463                         PipelineDone ();
1464                         StopTimer ();
1465                 }
1466
1467
1468                 internal CultureInfo GetThreadCulture (HttpRequest request, CultureInfo culture, bool isAuto)
1469                 {
1470                         if (!isAuto)
1471                                 return culture;
1472                         CultureInfo ret = null;
1473                         string[] languages = request.UserLanguages;
1474                         try {
1475                                 if (languages != null && languages.Length > 0)
1476                                         ret = CultureInfo.CreateSpecificCulture (languages[0]);
1477                         } catch {
1478                         }
1479                         
1480                         if (ret == null)
1481                                 ret = culture;
1482                         
1483                         return ret;
1484                 }
1485
1486
1487                 void PreStart ()
1488                 {
1489                         GlobalizationSection cfg;
1490                         cfg = (GlobalizationSection) WebConfigurationManager.GetSection ("system.web/globalization");
1491                         app_culture = cfg.GetCulture ();
1492                         autoCulture = cfg.IsAutoCulture;
1493                         appui_culture = cfg.GetUICulture ();
1494                         autoUICulture = cfg.IsAutoUICulture;
1495 #if !TARGET_J2EE
1496                         context.StartTimeoutTimer ();
1497 #endif
1498                         Thread th = Thread.CurrentThread;
1499                         if (app_culture != null) {
1500                                 prev_app_culture = th.CurrentCulture;
1501                                 CultureInfo new_app_culture = GetThreadCulture (Request, app_culture, autoCulture);
1502                                 if (!new_app_culture.Equals (Helpers.InvariantCulture))
1503                                         th.CurrentCulture = new_app_culture;
1504                         }
1505
1506                         if (appui_culture != null) {
1507                                 prev_appui_culture = th.CurrentUICulture;
1508                                 CultureInfo new_app_culture = GetThreadCulture (Request, appui_culture, autoUICulture);
1509                                 if (!new_app_culture.Equals (Helpers.InvariantCulture))
1510                                         th.CurrentUICulture = new_app_culture;
1511                         }
1512
1513                         prev_user = Thread.CurrentPrincipal;
1514                 }
1515
1516                 void PostDone ()
1517                 {
1518                         if (removeConfigurationFromCache) {
1519                                 WebConfigurationManager.RemoveConfigurationFromCache (context);
1520                                 removeConfigurationFromCache = false;
1521                         }
1522
1523                         Thread th = Thread.CurrentThread;
1524                         if (Thread.CurrentPrincipal != prev_user)
1525                                 Thread.CurrentPrincipal = prev_user;
1526                         if (prev_appui_culture != null && prev_appui_culture != th.CurrentUICulture)
1527                                 th.CurrentUICulture = prev_appui_culture;
1528                         if (prev_app_culture != null && prev_app_culture != th.CurrentCulture)
1529                                 th.CurrentCulture = prev_app_culture;
1530
1531 #if !TARGET_J2EE
1532                         if (context == null)
1533                                 context = HttpContext.Current;
1534                         context.StopTimeoutTimer ();
1535 #endif
1536                         context.Request.ReleaseResources ();
1537                         context.Response.ReleaseResources ();
1538                         context = null;
1539                         session = null;
1540                         HttpContext.Current = null;
1541                 }
1542
1543                 void Start (object x)
1544                 {
1545                         var cultures = x as CultureInfo [];
1546                         if (cultures != null && cultures.Length == 2) {
1547                                 Thread ct = Thread.CurrentThread;
1548                                 ct.CurrentCulture = cultures [0];
1549                                 ct.CurrentUICulture = cultures [1];
1550                         }
1551
1552                         InitOnce (true);
1553                         if (initialization_exception != null) {
1554                                 Exception e = initialization_exception;
1555                                 HttpException exc = HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort);
1556                                 context.Response.StatusCode = 500;
1557                                 FinalErrorWrite (context.Response, exc.GetHtmlErrorMessage ());
1558                                 PipelineDone ();
1559                                 return;
1560                         }
1561
1562                         HttpContext.Current = Context;
1563                         PreStart ();
1564                         pipeline = Pipeline ();
1565                         Tick ();
1566                 }
1567
1568                 const string HANDLER_CACHE = "@@HttpHandlerCache@@";
1569
1570                 internal static Hashtable GetHandlerCache ()
1571                 {
1572                         Cache cache = HttpRuntime.InternalCache;
1573                         Hashtable ret = cache [HANDLER_CACHE] as Hashtable;
1574
1575                         if (ret == null) {
1576                                 ret = new Hashtable ();
1577                                 cache.Insert (HANDLER_CACHE, ret);
1578                         }
1579
1580                         return ret;
1581                 }
1582                 
1583                 internal static void ClearHandlerCache ()
1584                 {
1585                         Hashtable cache = GetHandlerCache ();
1586                         cache.Clear ();
1587                 }
1588                 
1589                 object LocateHandler (HttpRequest req, string verb, string url)
1590                 {
1591                         Hashtable cache = GetHandlerCache ();
1592                         string id = String.Concat (verb, url);
1593                         object ret = cache [id];
1594
1595                         if (ret != null)
1596                                 return ret;
1597
1598                         bool allowCache;
1599                         HttpHandlersSection httpHandlersSection = WebConfigurationManager.GetSection ("system.web/httpHandlers", req.Path, req.Context) as HttpHandlersSection;
1600                         ret = httpHandlersSection.LocateHandler (verb, url, out allowCache);
1601
1602                         IHttpHandler handler = ret as IHttpHandler;
1603                         if (allowCache && handler != null && handler.IsReusable)
1604                                 cache [id] = ret;
1605                         
1606                         return ret;
1607                 }
1608
1609                 internal IHttpHandler GetHandler (HttpContext context, string url)
1610                 {
1611                         return GetHandler (context, url, false);
1612                 }
1613                 
1614                 // Used by HttpServerUtility.Execute
1615                 internal IHttpHandler GetHandler (HttpContext context, string url, bool ignoreContextHandler)
1616                 {
1617                         if (!ignoreContextHandler && context.Handler != null)
1618                                 return context.Handler;
1619                         
1620                         HttpRequest request = context.Request;
1621                         string verb = request.RequestType;
1622                         
1623                         IHttpHandler handler = null;
1624                         object o = LocateHandler (request, verb, url);
1625                         
1626                         factory = o as IHttpHandlerFactory;
1627                         if (factory == null) {
1628                                 handler = (IHttpHandler) o;
1629                         } else {
1630                                 handler = factory.GetHandler (context, verb, url, request.MapPath (url));
1631                         }
1632
1633                         return handler;
1634                 }
1635                 
1636                 void IHttpHandler.ProcessRequest (HttpContext context)
1637                 {
1638                         begin_iar = null;
1639                         this.context = context;
1640                         done.Reset ();
1641
1642                         Start (null);
1643                         done.WaitOne ();
1644                 }
1645
1646                 //
1647                 // This is used by FireOnAppStart, when we init the application
1648                 // as the context is required to be set at that point (the user
1649                 // might call methods that require it on that hook).
1650                 //
1651                 internal void SetContext (HttpContext context)
1652                 {
1653                         this.context = context;
1654                 }
1655
1656                 internal void SetSession (HttpSessionState session)
1657                 {
1658                         this.session = session;
1659                 }
1660
1661                 IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData)
1662                 {
1663                         this.context = context;
1664                         done.Reset ();
1665                         
1666                         begin_iar = new AsyncRequestState (done, cb, extraData);
1667
1668                         CultureInfo[] cultures = new CultureInfo [2];
1669                         cultures [0] = Thread.CurrentThread.CurrentCulture;
1670                         cultures [1] = Thread.CurrentThread.CurrentUICulture;
1671                         
1672                         if (Thread.CurrentThread.IsThreadPoolThread)
1673                                 Start (null);
1674                         else
1675                                 ThreadPool.QueueUserWorkItem (x => {
1676                                         try {
1677                                                 Start (x);
1678                                         } catch (Exception e) {
1679                                                 Console.Error.WriteLine (e);
1680                                         }
1681                                 });
1682                         
1683                         return begin_iar;
1684                 }
1685
1686                 void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
1687                 {
1688 #if TARGET_J2EE
1689                         if (result == null)
1690                                 result = begin_iar;
1691 #endif
1692                         if (!result.IsCompleted)
1693                                 result.AsyncWaitHandle.WaitOne ();
1694                         begin_iar = null;
1695                 }
1696
1697                 public virtual void Init ()
1698                 {
1699                 }
1700
1701                 bool IHttpHandler.IsReusable {
1702                         get {
1703                                 return true;
1704                         }
1705                 }
1706                 
1707 #region internals
1708                 internal void ClearError ()
1709                 {
1710                         context.ClearError ();
1711                 }
1712
1713                 bool RedirectErrorPage (string error_page)
1714                 {
1715                         if (context.Request.QueryString ["aspxerrorpath"] != null)
1716                                 return false;
1717
1718                         Response.Redirect (error_page + "?aspxerrorpath=" + Request.Path, false);
1719                         return true;
1720                 }
1721                                                         
1722                 bool RedirectCustomError (ref HttpException httpEx)
1723                 {
1724                         try {
1725                                 if (!context.IsCustomErrorEnabledUnsafe)
1726                                         return false;
1727                         
1728                                 CustomErrorsSection config = (CustomErrorsSection)WebConfigurationManager.GetSection ("system.web/customErrors");                       
1729                                 if (config == null) {
1730                                         if (context.ErrorPage != null)
1731                                                 return RedirectErrorPage (context.ErrorPage);
1732                                 
1733                                         return false;
1734                                 }
1735                         
1736                                 CustomError err = config.Errors [context.Response.StatusCode.ToString()];
1737                                 string redirect = err == null ? null : err.Redirect;
1738                                 if (redirect == null) {
1739                                         redirect = context.ErrorPage;
1740                                         if (redirect == null)
1741                                                 redirect = config.DefaultRedirect;
1742                                 }
1743                         
1744                                 if (redirect == null)
1745                                         return false;
1746
1747                                 if (config.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite) {
1748                                         context.Server.Execute (redirect);
1749                                         return true;
1750                                 }
1751                                 
1752                                 return RedirectErrorPage (redirect);
1753                         }
1754                         catch (Exception ex) {
1755                                 httpEx = HttpException.NewWithCode (500, String.Empty, ex, WebEventCodes.WebErrorOtherError);
1756                                 return false;
1757                         }
1758                 }
1759 #endregion              
1760                 internal static string BinDirectory
1761                 {
1762                         get {
1763                                 if (binDirectory == null) {
1764                                         AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
1765                                         string baseDir = setup.ApplicationBase;
1766                                         string bindir;
1767                                         
1768                                         foreach (string dir in BinDirs) {
1769                                                 bindir = Path.Combine (baseDir, dir);
1770                                                 if (!Directory.Exists (bindir))
1771                                                         continue;
1772                                                 binDirectory = bindir;
1773                                                 break;
1774                                         }
1775                                 }
1776
1777                                 return binDirectory;
1778                         }
1779                 }
1780
1781                 internal static string[] BinDirectoryAssemblies
1782                 {
1783                         get {
1784                                 ArrayList binDlls = null;
1785                                 string[] dlls;
1786                                 
1787                                 string bindir = BinDirectory;
1788                                 if (bindir != null) {
1789                                         binDlls = new ArrayList ();
1790                                         dlls = Directory.GetFiles (bindir, "*.dll");
1791                                         binDlls.AddRange (dlls);
1792                                 }
1793
1794                                 if (binDlls == null)
1795                                         return new string[] {};
1796                                 
1797                                 return (string[]) binDlls.ToArray (typeof (string));
1798                         }
1799                 }
1800                                         
1801                 internal static Type LoadType (string typeName)
1802                 {
1803                         return LoadType (typeName, false);
1804                 }
1805                 
1806                 internal static Type LoadType (string typeName, bool throwOnMissing)
1807                 {
1808                         Type type = Type.GetType (typeName);
1809                         if (type != null)
1810                                 return type;
1811
1812                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
1813                         foreach (Assembly ass in assemblies) {
1814                                 type = ass.GetType (typeName, false);
1815                                 if (type != null)
1816                                         return type;
1817                         }
1818
1819                         IList tla = System.Web.Compilation.BuildManager.TopLevelAssemblies;
1820                         if (tla != null && tla.Count > 0) {
1821                                 foreach (Assembly asm in tla) {
1822                                         if (asm == null)
1823                                                 continue;
1824                                         type = asm.GetType (typeName, false);
1825                                         if (type != null)
1826                                                 return type;
1827                                 }
1828                         }
1829
1830                         Exception loadException = null;
1831                         try {
1832                                 type = null;
1833                                 type = LoadTypeFromBin (typeName);
1834                         } catch (Exception ex) {
1835                                 loadException = ex;
1836                         }
1837                         
1838                         if (type != null)
1839                                 return type;
1840                         if (throwOnMissing)
1841                                 throw new TypeLoadException (String.Format ("Type '{0}' cannot be found", typeName), loadException);
1842                         
1843                         return null;
1844                 }
1845
1846                 internal static Type LoadType <TBaseType> (string typeName, bool throwOnMissing)
1847                 {
1848                         Type ret = LoadType (typeName, throwOnMissing);
1849
1850                         if (typeof (TBaseType).IsAssignableFrom (ret))
1851                                 return ret;
1852
1853                         if (throwOnMissing)
1854                                 throw new TypeLoadException (String.Format ("Type '{0}' found but it doesn't derive from base type '{1}'.", typeName, typeof (TBaseType)));
1855
1856                         return null;
1857                 }
1858                 
1859                 internal static Type LoadTypeFromBin (string typeName)
1860                 {
1861                         Type type = null;
1862                         
1863                         foreach (string s in BinDirectoryAssemblies) {
1864                                 Assembly binA = null;
1865                                 
1866                                 try {
1867                                         binA = Assembly.LoadFrom (s);
1868                                 } catch (FileLoadException) {
1869                                         // ignore
1870                                         continue;
1871                                 } catch (BadImageFormatException) {
1872                                         // ignore
1873                                         continue;
1874                                 }
1875                                 
1876                                 type = binA.GetType (typeName, false);
1877                                 if (type == null)
1878                                         continue;
1879                                 
1880                                 return type;
1881                         }
1882
1883                         return null;
1884                 }
1885         }
1886
1887         //
1888         // Based on Fritz' Onion's AsyncRequestState class for asynchronous IHttpAsyncHandlers
1889         // 
1890         class AsyncRequestState : IAsyncResult {
1891                 AsyncCallback cb;
1892                 object cb_data;
1893                 bool completed;
1894                 ManualResetEvent complete_event = null;
1895                 
1896                 internal AsyncRequestState (ManualResetEvent complete_event, AsyncCallback cb, object cb_data)
1897                 {
1898                         this.cb = cb;
1899                         this.cb_data = cb_data;
1900                         this.complete_event = complete_event;
1901                 }
1902
1903                 internal void Complete ()
1904                 {
1905                         completed = true;
1906                         try {
1907                                 //
1908                                 // TODO: if this throws an error, we have no way of reporting it
1909                                 // Not really too bad, since the only failure might be
1910                                 // `HttpRuntime.request_processed'.   
1911                                 //
1912                                 if (cb != null)
1913                                         cb (this);
1914                         } catch {
1915                         }
1916                         
1917                         complete_event.Set ();
1918                 }
1919
1920                 public object AsyncState {
1921                         get {
1922                                 return cb_data;
1923                         }
1924                 }
1925
1926                 public bool CompletedSynchronously {
1927                         get {
1928                                 return false;
1929                         }
1930                 }
1931
1932                 public bool IsCompleted {
1933                         get {
1934                                 return completed;
1935                         }
1936                 }
1937
1938                 public WaitHandle AsyncWaitHandle {
1939                         get {
1940                                 return complete_event;
1941                         }
1942                 }
1943         }
1944
1945 #region Helper classes
1946         
1947         //
1948         // A wrapper to keep track of begin/end pairs
1949         //
1950         class AsyncInvoker {
1951                 public BeginEventHandler begin;
1952                 public EndEventHandler end;
1953                 public object data;
1954                 
1955                 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, object d)
1956                 {
1957                         begin = bh;
1958                         end = eh;
1959                         data = d;
1960                 }
1961
1962                 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh)
1963                 {
1964                         begin = bh;
1965                         end = eh;
1966                 }
1967                 
1968                 public void Invoke (object sender, EventArgs e)
1969                 {
1970                         throw new Exception ("This is just a dummy");
1971                 }
1972         }
1973 #endregion
1974 }