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