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