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