Got rid of those Internal(1) warnings
[mono.git] / mcs / class / System.Web / System.Web / HttpApplication.cs
1 // 
2 // System.Web.HttpApplication
3 //
4 // Authors:
5 //      Patrik Torstensson (ptorsten@hotmail.com)
6 //      Tim Coleman (tim@timcoleman.com)
7 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 //
9 using System;
10 using System.Collections;
11 using System.ComponentModel;
12 using System.IO;
13 using System.Threading;
14 using System.Security.Principal;
15 using System.Runtime.Remoting.Messaging;
16 using System.Web.UI;
17 using System.Web.Configuration;
18 using System.Web.SessionState;
19
20 namespace System.Web
21 {
22
23         [ToolboxItem(true)]
24         public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable
25         {
26
27 #region Event Handlers
28
29                 // Async event holders
30                 AsyncEvents _acquireRequestStateAsync;
31                 AsyncEvents _authenticateRequestAsync;
32                 AsyncEvents _endRequestAsync;
33                 AsyncEvents _beginRequestAsync;
34                 AsyncEvents _authorizeRequestAsync;
35                 AsyncEvents _updateRequestCacheAsync;
36                 AsyncEvents _resolveRequestCacheAsync;
37                 AsyncEvents _releaseRequestStateAsync;
38                 AsyncEvents _preRequestHandlerExecuteAsync;
39                 AsyncEvents _postRequestHandlerExecuteAsync;
40
41                 // ID objects used to indentify the event
42                 static object AcquireRequestStateId = new Object ();
43                 static object AuthenticateRequestId = new Object ();
44                 static object DefaultAuthenticationId = new Object ();
45                 static object EndRequestId = new Object ();
46                 static object DisposedId = new Object ();
47                 static object BeginRequestId = new Object ();
48                 static object AuthorizeRequestId = new Object ();
49                 static object UpdateRequestCacheId = new Object ();
50                 static object ResolveRequestCacheId = new Object ();
51                 static object ReleaseRequestStateId = new Object ();
52                 static object PreSendRequestContentId = new Object ();
53                 static object PreSendRequestHeadersId = new Object ();
54                 static object PreRequestHandlerExecuteId = new Object ();
55                 static object PostRequestHandlerExecuteId = new Object ();
56                 static object ErrorId = new Object ();
57
58                 // List of events
59                 private EventHandlerList _Events;
60
61                 public event EventHandler AcquireRequestState {
62                         add { Events.AddHandler (AcquireRequestStateId, value); }
63                         remove { Events.RemoveHandler (AcquireRequestStateId, value); }
64                 }
65
66                 public event EventHandler AuthenticateRequest {
67                         add { Events.AddHandler (AuthenticateRequestId, value); }
68                         remove { Events.RemoveHandler (AuthenticateRequestId, value); }
69                 }
70
71                 public event EventHandler AuthorizeRequest {
72                         add { Events.AddHandler (AuthorizeRequestId, value); }
73                         remove { Events.RemoveHandler (AuthorizeRequestId, value); }
74                 }
75
76                 public event EventHandler BeginRequest {
77                         add { Events.AddHandler (BeginRequestId, value); }
78                         remove { Events.RemoveHandler (BeginRequestId, value); }
79                 }
80
81                 public event EventHandler Disposed {
82                         add { Events.AddHandler (DisposedId, value); }
83                         remove { Events.RemoveHandler (DisposedId, value); }
84                 }
85
86                 public event EventHandler EndRequest {
87                         add { Events.AddHandler (EndRequestId, value); }
88                         remove { Events.RemoveHandler (EndRequestId, value); }
89                 }
90
91                 public event EventHandler Error {
92                         add { Events.AddHandler (ErrorId, value); }
93                         remove { Events.RemoveHandler (ErrorId, value); }
94                 }
95
96                 public event EventHandler PostRequestHandlerExecute {
97                         add { Events.AddHandler (PostRequestHandlerExecuteId, value); }
98                         remove { Events.RemoveHandler (PostRequestHandlerExecuteId, value); }
99                 }
100
101                 public event EventHandler PreRequestHandlerExecute {
102                         add { Events.AddHandler (PreRequestHandlerExecuteId, value); }
103                         remove { Events.RemoveHandler (PreRequestHandlerExecuteId, value); }
104                 }
105
106                 public event EventHandler PreSendRequestContent {
107                         add { Events.AddHandler (PreSendRequestContentId, value); }
108                         remove { Events.RemoveHandler (PreSendRequestContentId, value); }
109                 }
110
111                 public event EventHandler ReleaseRequestState {
112                         add { Events.AddHandler (ReleaseRequestStateId, value); }
113                         remove { Events.RemoveHandler (ReleaseRequestStateId, value); }
114                 }
115
116                 public event EventHandler ResolveRequestCache
117                 {
118                         add { Events.AddHandler (ResolveRequestCacheId, value); }
119                         remove { Events.RemoveHandler (ResolveRequestCacheId, value); }
120                 }
121
122                 public event EventHandler UpdateRequestCache {
123                         add { Events.AddHandler (UpdateRequestCacheId, value); }
124                         remove { Events.RemoveHandler (UpdateRequestCacheId, value); }
125                 }
126
127                 public event EventHandler PreSendRequestHeaders {
128                         add { Events.AddHandler (PreSendRequestHeadersId, value); }
129                         remove { Events.RemoveHandler (PreSendRequestHeadersId, value); }
130                 }
131
132                 internal event EventHandler DefaultAuthentication {
133                         add { Events.AddHandler (DefaultAuthenticationId, value); }
134                         remove { Events.RemoveHandler (DefaultAuthenticationId, value); }
135                 }
136
137                 public void AddOnAcquireRequestStateAsync (BeginEventHandler beg, EndEventHandler end)
138                 {
139                         if (null == _acquireRequestStateAsync)
140                                 _acquireRequestStateAsync = new AsyncEvents ();
141
142                         _acquireRequestStateAsync.Add (beg, end);
143                 }
144
145                 public void AddOnAuthenticateRequestAsync(BeginEventHandler beg, EndEventHandler end)
146                 {
147                         if (null == _authenticateRequestAsync)
148                                 _authenticateRequestAsync = new AsyncEvents ();
149
150                         _authenticateRequestAsync.Add (beg, end);
151                 }
152
153                 public void AddOnAuthorizeRequestAsync (BeginEventHandler beg, EndEventHandler end)
154                 {
155                         if (null == _authorizeRequestAsync)
156                                 _authorizeRequestAsync = new AsyncEvents ();
157
158                         _authorizeRequestAsync.Add (beg, end);
159                 }
160
161                 public void AddOnBeginRequestAsync (BeginEventHandler beg, EndEventHandler end)
162                 {
163                         if (null == _beginRequestAsync)
164                                 _beginRequestAsync = new AsyncEvents ();
165
166                         _beginRequestAsync.Add (beg, end);
167                 }
168
169                 public void AddOnEndRequestAsync (BeginEventHandler beg, EndEventHandler end)
170                 {
171                         if (null == _endRequestAsync)
172                                 _endRequestAsync = new AsyncEvents ();
173
174                         _endRequestAsync.Add (beg, end);
175                 }
176
177                 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler beg, EndEventHandler end)
178                 {
179                         if (null == _postRequestHandlerExecuteAsync)
180                                 _postRequestHandlerExecuteAsync = new AsyncEvents ();
181
182                         _postRequestHandlerExecuteAsync.Add (beg, end);
183                 }
184
185                 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler beg, EndEventHandler end)
186                 {
187                         if (null == _preRequestHandlerExecuteAsync)
188                                 _preRequestHandlerExecuteAsync = new AsyncEvents ();
189
190                         _preRequestHandlerExecuteAsync.Add (beg, end);
191                 }
192
193                 public void AddOnReleaseRequestStateAsync (BeginEventHandler beg, EndEventHandler end)
194                 {
195                         if (null == _releaseRequestStateAsync)
196                                 _releaseRequestStateAsync = new AsyncEvents ();
197
198                         _releaseRequestStateAsync.Add (beg, end);
199                 }
200
201                 public void AddOnResolveRequestCacheAsync (BeginEventHandler beg, EndEventHandler end)
202                 {
203                         if (null == _resolveRequestCacheAsync)
204                                 _resolveRequestCacheAsync = new AsyncEvents ();
205
206                         _resolveRequestCacheAsync.Add (beg, end);
207                 }
208
209                 public void AddOnUpdateRequestCacheAsync (BeginEventHandler beg, EndEventHandler end)
210                 {
211                         if (null == _updateRequestCacheAsync)
212                                 _updateRequestCacheAsync = new AsyncEvents ();
213
214                         _updateRequestCacheAsync.Add (beg, end);
215                 }
216
217 #endregion
218
219 #region State Machine 
220
221                 interface IStateHandler
222                 {
223                         void Execute();
224                         bool CompletedSynchronously { get; }
225                         bool PossibleToTimeout { get; }
226                 }
227
228                 class EventState : IStateHandler
229                 {
230                         HttpApplication _app;
231                         EventHandler _event;
232
233                         public EventState (HttpApplication app, EventHandler evt)
234                         {
235                                 _app = app;
236                                 _event = evt;
237                         }
238
239                         public void Execute ()
240                         {
241                                 if (null != _event)
242                                         _event (_app, EventArgs.Empty); 
243                         }
244
245                         public bool CompletedSynchronously {
246                                 get { return true; }
247                         }
248
249                         public bool PossibleToTimeout {
250                                 get { return true; }
251                         }
252                 }
253
254                 class AsyncEventState : IStateHandler
255                 {
256                         HttpApplication  _app;
257                         BeginEventHandler _begin;
258                         EndEventHandler _end;
259                         AsyncCallback _callback;
260                         bool _async;
261
262                         public AsyncEventState (HttpApplication app,
263                                                 BeginEventHandler begin,
264                                                 EndEventHandler end)
265                         {
266                                 _async = false;
267                                 _app = app;
268                                 _begin = begin;
269                                 _end = end;
270                                 _callback = new AsyncCallback (OnAsyncReady);
271                         }
272
273                         public void Execute ()
274                         {
275                                 _async = true;
276                                 IAsyncResult ar = _begin (_app, EventArgs.Empty, _callback, null);
277                                 if (ar.CompletedSynchronously) {
278                                         _async = false;
279                                         _end (ar);
280                                 }
281                         }
282
283                         public bool CompletedSynchronously {
284                                 get { return !_async; }
285                         }
286
287                         public bool PossibleToTimeout {
288                                 get {
289                                         // We can't cancel a async event
290                                         return false;
291                                 }
292                         }
293
294                         private void OnAsyncReady (IAsyncResult ar)
295                         {
296                                 if (ar.CompletedSynchronously)
297                                         return;
298
299                                 Exception error = null;
300
301                                 try {
302                                         // Invoke end handler
303                                         _end(ar);
304                                 } catch (Exception exc) {
305                                         // Flow this error to the next state (handle during state execution)
306                                         error = exc;
307                                 }
308
309                                 _app._state.ExecuteNextAsync (error);
310                         }
311                 }
312
313                 class AsyncEvents
314                 {
315                         ArrayList _events;
316                         class EventRecord {
317                                 public EventRecord(BeginEventHandler beg, EndEventHandler end)
318                                 {
319                                         Begin = beg;
320                                         End = end;
321                                 }
322
323                                 public BeginEventHandler        Begin;
324                                 public EndEventHandler          End;
325                         }
326
327                         public AsyncEvents ()
328                         {
329                                 _events = new ArrayList ();
330                         }
331
332                         public void Add (BeginEventHandler begin, EndEventHandler end)
333                         {
334                                 _events.Add (new EventRecord (begin, end));
335                         }
336
337                         public void GetAsStates (HttpApplication app, ArrayList states)
338                         {
339                                 foreach (object obj in _events)
340                                         states.Add (new AsyncEventState (app,
341                                                                         ((EventRecord) obj).Begin,
342                                                                         ((EventRecord) obj).End));
343                         }
344                 }
345
346
347                 class ExecuteHandlerState : IStateHandler
348                 {
349                         HttpApplication _app;
350                         AsyncCallback _callback;
351                         IHttpAsyncHandler _handler;
352                         bool _async;
353
354                         public ExecuteHandlerState (HttpApplication app)
355                         {
356                                 _app = app;
357                                 _callback = new AsyncCallback (OnAsyncReady);
358                         }
359
360                         private void OnAsyncReady (IAsyncResult ar)
361                         {
362                                 if (ar.CompletedSynchronously)
363                                         return;
364
365                                 Exception error = null;
366
367                                 try {
368                                         // Invoke end handler
369                                         _handler.EndProcessRequest(ar);
370                                 } catch (Exception exc) {
371                                         // Flow this error to the next state (handle during state execution)
372                                         error = exc;
373                                 }
374
375                                 _handler = null;
376                                 _app._state.ExecuteNextAsync (error);
377                         }
378
379                         public void Execute ()
380                         {
381                                 IHttpHandler handler = _app.Context.Handler;
382                                 if (handler == null)
383                                         return;
384
385                                 // Check if we can execute async
386                                 if (handler is IHttpAsyncHandler) {
387                                         _async = true;
388                                         _handler = (IHttpAsyncHandler) handler;
389
390                                         IAsyncResult ar = _handler.BeginProcessRequest (_app.Context,
391                                                                                         _callback,
392                                                                                         null);
393
394                                         if (ar.CompletedSynchronously) {
395                                                 _async = false;
396                                                 _handler = null;
397                                                 ((IHttpAsyncHandler) handler).EndProcessRequest (ar);
398                                         }
399                                 } else {
400                                         _async = false;
401
402                                         // Sync handler
403                                         handler.ProcessRequest (_app.Context);
404                                 }
405                         }
406
407                         public bool CompletedSynchronously {
408                                 get { return !_async; }
409                         }
410
411                         public bool PossibleToTimeout {
412                                 get {
413                                         if (_app.Context.Handler is IHttpAsyncHandler)
414                                                 return false;
415
416                                         return true;
417                                 }
418                         }
419                 }
420
421                 class CreateHandlerState : IStateHandler
422                 {
423                         HttpApplication _app;
424
425                         public CreateHandlerState (HttpApplication app)
426                         {
427                                 _app = app;
428                         }
429
430                         public void Execute ()
431                         {
432                         _app.Context.Handler = _app.CreateHttpHandler ( _app.Context,
433                                                                         _app.Request.RequestType,
434                                                                         _app.Request.FilePath,
435                                                                         _app.Request.PhysicalPath);
436                         }
437
438                         public bool CompletedSynchronously {
439                                 get { return true; }
440                         }
441
442                         public bool PossibleToTimeout {
443                                 get { return false; }
444                         }
445                 }
446
447                 class FilterHandlerState : IStateHandler
448                 {
449                         HttpApplication _app;
450
451                         public FilterHandlerState (HttpApplication app)
452                         {
453                                 _app = app;
454                         }
455
456                         public void Execute ()
457                         {
458                                 _app.Context.Response.DoFilter (true);
459                         }
460
461                         public bool CompletedSynchronously {
462                                 get { return true; }
463                         }
464
465                         public bool PossibleToTimeout {
466                                 get { return true; }
467                         }
468                 }
469
470                 class StateMachine
471                 {
472                         HttpApplication _app;
473                         WaitCallback _asynchandler;
474
475                         IStateHandler [] _handlers;
476                         int _currentStateIdx;
477                         int _endStateIdx;
478                         int _endRequestStateIdx;
479                         int _countSteps;
480                         int _countSyncSteps;
481
482                         // Helper to create the states for a normal event
483                         private void GetAsStates (object Event, ArrayList states)
484                         {
485                                 // Get list of clients for the sync events
486                                 Delegate evnt = _app.Events [Event];
487                                 if (evnt == null)
488                                         return;
489
490                                 System.Delegate [] clients = evnt.GetInvocationList();
491                                 foreach (Delegate client in clients)
492                                         states.Add (new EventState (_app, (EventHandler) client));
493                         }
494
495                         internal StateMachine (HttpApplication app)
496                         {
497                                 _app = app;
498                         }
499
500                         internal void Init ()
501                         {
502                                 _asynchandler = new WaitCallback (OnAsyncCallback);
503
504                                 // Create a arraylist of states to execute
505                                 ArrayList states = new ArrayList ();
506
507                                 // BeginRequest
508                                 if (null != _app._beginRequestAsync)
509                                         _app._beginRequestAsync.GetAsStates (_app, states);
510                                 GetAsStates (HttpApplication.BeginRequestId, states);
511
512                                 // AuthenticateRequest
513                                 if (null != _app._authenticateRequestAsync)
514                                         _app._authenticateRequestAsync.GetAsStates (_app, states);
515                                 GetAsStates (HttpApplication.AuthenticateRequestId, states);
516
517                                 // DefaultAuthentication
518                                 EventHandler defaultAuthHandler = (EventHandler) _app.Events [HttpApplication.DefaultAuthenticationId];
519                                 states.Add (new EventState (_app, defaultAuthHandler));
520
521                                 // AuthorizeRequest
522                                 if (null != _app._authorizeRequestAsync)
523                                         _app._authorizeRequestAsync.GetAsStates (_app, states);
524                                 GetAsStates (HttpApplication.AuthorizeRequestId, states);
525
526                                 // ResolveRequestCache
527                                 if (null != _app._resolveRequestCacheAsync)
528                                         _app._resolveRequestCacheAsync.GetAsStates (_app, states);
529                                 GetAsStates (HttpApplication.ResolveRequestCacheId, states);
530
531                                 // [A handler (a page corresponding to the request URL) is created at this point.]
532                                 states.Add (new CreateHandlerState (_app));
533
534                                 // AcquireRequestState
535                                 if (null != _app._acquireRequestStateAsync)
536                                         _app._acquireRequestStateAsync.GetAsStates (_app, states);
537                                 GetAsStates (HttpApplication.AcquireRequestStateId, states);
538
539                                 // PreRequestHandlerExecute
540                                 if (null != _app._preRequestHandlerExecuteAsync)
541                                         _app._preRequestHandlerExecuteAsync.GetAsStates (_app, states);
542                                 GetAsStates (HttpApplication.PreRequestHandlerExecuteId, states);
543
544                                 // [The handler is executed.]
545                                 states.Add (new ExecuteHandlerState (_app));
546
547                                 // PostRequestHandlerExecute
548                                 if (null != _app._postRequestHandlerExecuteAsync)
549                                         _app._postRequestHandlerExecuteAsync.GetAsStates (_app, states);
550                                 GetAsStates (HttpApplication.PostRequestHandlerExecuteId, states);
551
552                                 // ReleaseRequestState
553                                 if (null != _app._releaseRequestStateAsync)
554                                         _app._releaseRequestStateAsync.GetAsStates (_app, states);
555                                 GetAsStates (HttpApplication.ReleaseRequestStateId, states);
556
557                                 // [Response filters, if any, filter the output.]
558                                 states.Add (new FilterHandlerState (_app));
559
560                                 // UpdateRequestCache
561                                 if (null != _app._updateRequestCacheAsync)
562                                         _app._updateRequestCacheAsync.GetAsStates (_app, states);
563                                 GetAsStates (HttpApplication.UpdateRequestCacheId, states);
564
565                                 // EndRequest
566                                 _endRequestStateIdx = states.Count;
567                                 if (null != _app._endRequestAsync)
568                                         _app._endRequestAsync.GetAsStates (_app, states);
569                                 GetAsStates (HttpApplication.EndRequestId, states);
570
571                                 // Make list ready to execute
572                                 _handlers = new IStateHandler [states.Count];
573                                 states.CopyTo (_handlers);
574                         }
575
576
577                         internal void Reset ()
578                         {
579                                 _countSyncSteps = 0;
580                                 _countSteps = 0;
581                                 _currentStateIdx = -1;
582                                 _endStateIdx = _handlers.Length - 1;
583                         }
584
585                         internal void Start ()
586                         {
587                                 Reset ();
588                                 ExecuteNextAsync (null);
589                         }
590
591                         internal void ExecuteNextAsync (Exception lasterror)
592                         {
593                                 if (!Thread.CurrentThread.IsThreadPoolThread)
594                                         ThreadPool.QueueUserWorkItem (_asynchandler, lasterror);
595                                 else
596                                         ExecuteNext (lasterror);
597                         }
598
599                         internal void ExecuteNext (Exception lasterror)
600                         {
601                                 bool ready_sync = false;
602                                 IStateHandler handler;
603
604                                 lock (_app) {
605                                         _app.OnStateExecuteEnter ();
606                                         try {
607                                                 do {
608                                                         if (null != lasterror) {
609                                                                 _app.HandleError (lasterror);
610                                                                 lasterror = null;
611                                                         }
612
613                                                         // Check if request flow is to be stopped
614                                                         if ((_app.GetLastError () != null || _app._CompleteRequest) &&
615                                                             _currentStateIdx < _endRequestStateIdx) {
616                                                                 _currentStateIdx = _endRequestStateIdx;
617                                                                 // MS does not filter on error
618                                                                 _app._Context.Response.DoFilter (false);
619                                                         } else if (_currentStateIdx < _endStateIdx) {
620                                                                 // Get next state handler
621                                                                 _currentStateIdx++;
622                                                         }
623
624                                                         handler = _handlers [_currentStateIdx];
625                                                         _countSteps++;
626                                                         lasterror = ExecuteState (handler, ref ready_sync);
627                                                         if (ready_sync) 
628                                                                 _countSyncSteps++;
629                                                 } while (ready_sync && _currentStateIdx < _endStateIdx);
630
631                                                 if (null != lasterror)
632                                                         _app.HandleError (lasterror);
633                                         } finally {
634                                                 _app.OnStateExecuteLeave ();
635                                         }
636                                 }
637                                 
638
639                                 // Finish the request off..
640                                 if (lasterror != null || _currentStateIdx == _endStateIdx) {
641                                         _app._asyncWebResult.Complete ((_countSyncSteps == _countSteps),
642                                                                        null,
643                                                                        null);
644
645                                         _app.Context.Handler = null;
646                                         _app.Context.ApplicationInstance = null;
647                                         _app.RecycleHandlers ();
648                                         _app._asyncWebResult = null;
649
650                                         HttpApplicationFactory.RecycleInstance (_app);
651                                 }
652                         }
653
654                         private void OnAsyncCallback (object obj)
655                         {
656                                 ExecuteNext ((Exception) obj);
657                         }
658
659                         private Exception ExecuteState (IStateHandler state, ref bool readysync)
660                         {
661                                 Exception lasterror = null;
662                                 try {
663                                         if (state.PossibleToTimeout) {
664                                                 _app.Context.BeginTimeoutPossible ();
665                                         }
666
667                                         try {
668                                                 state.Execute ();       
669                                         } finally {
670                                                 if (state.PossibleToTimeout) {
671                                                         _app.Context.EndTimeoutPossible ();
672                                                 }
673                                         }
674
675                                         if (state.PossibleToTimeout) {
676                                                 // Async Execute
677                                                 _app.Context.TryWaitForTimeout ();
678                                         }
679
680                                         readysync = state.CompletedSynchronously;
681                                 } catch (ThreadAbortException obj) {
682                                         object o = obj.ExceptionState;
683                                         Type type = (o != null) ? o.GetType () : null;
684                                         if (type == typeof (StepTimeout)) {
685                                                 Thread.ResetAbort ();
686                                                 lasterror = new HttpException ("The request timed out.");
687                                                 _app.CompleteRequest ();
688                                         } else if (type == typeof (StepCompleteRequest)) {
689                                                 Thread.ResetAbort ();
690                                                 _app.CompleteRequest ();
691                                         }
692                                 } catch (Exception obj) {
693                                         lasterror = obj;
694                                 }
695
696                                 return lasterror;
697                         }
698                 }
699
700 #endregion
701
702 #region Fields
703
704                 StateMachine _state;
705
706                 bool _CompleteRequest;
707                 HttpContext _Context;
708                 Exception _lastError;
709
710                 HttpContext _savedContext;
711                 IPrincipal _savedUser;
712                 HttpAsyncResult _asyncWebResult;
713
714                 ISite _Site;
715                 HttpModuleCollection _ModuleCollection;
716                 HttpSessionState _Session;
717                 HttpApplicationState _appState;
718                 string assemblyLocation;
719
720                 bool _InPreRequestResponseMode;
721 #endregion
722
723 #region Constructor
724
725                 public HttpApplication ()
726                 {
727                         assemblyLocation = GetType ().Assembly.Location;
728                 }
729
730 #endregion
731
732 #region Methods
733                 internal IHttpHandler CreateHttpHandler (HttpContext context,
734                                                         string type,
735                                                         string file,
736                                                         string path)
737                 {
738                         HandlerFactoryConfiguration handler =
739                                 HttpContext.GetAppConfig ("system.web/httpHandlers")
740                                 as HandlerFactoryConfiguration;
741
742                         if (handler == null)
743                                 throw new HttpException ("Cannot get system.web/httpHandlers handler.");
744
745                         object result = handler.FindHandler (type, file).Create ();
746                         if (result is IHttpHandler)
747                                 return (IHttpHandler) result;
748
749                         if (result is IHttpHandlerFactory) {
750                                 IHttpHandlerFactory factory = (IHttpHandlerFactory) result;
751                                 try {
752                                         return factory.GetHandler (context, type, file, path);
753                                 } catch (DirectoryNotFoundException) {
754                                         throw new HttpException (404, "Cannot find '" + file + "'.");
755                                 } catch (FileNotFoundException) {
756                                         throw new HttpException (404, "Cannot find '" + file + "'.");
757                                 }
758                         }
759
760                         throw new HttpException ("Handler not found");
761                 }
762
763                 [MonoTODO()]
764                 internal void RecycleHandlers ()
765                 {
766                         // TODO: Recycle the created handlers (via factory?)
767                 }
768
769                 internal void InitModules ()
770                 {
771                         ModulesConfiguration modules;
772
773                         modules = (ModulesConfiguration) HttpContext.GetAppConfig ("system.web/httpModules");
774                         if (null == modules)
775                                 throw new HttpException (
776                                                 HttpRuntime.FormatResourceString ("missing_modules_config"));
777
778                         _ModuleCollection = modules.CreateCollection ();
779                         if (_ModuleCollection == null)
780                                 return;
781
782                         int pos, count;
783
784                         count = _ModuleCollection.Count;
785                         for (pos = 0; pos != count; pos++)
786                                 ((IHttpModule) _ModuleCollection.Get (pos)).Init (this);
787                 }
788
789                 internal void InitCulture ()
790                 {
791                         // TODO: Read culture info from globalization from config
792                 }
793
794                 internal void OnStateExecuteEnter ()
795                 {
796                         // TODO: Set correct culture for the thread
797
798                         _savedContext = HttpContext.Context;
799                         HttpContext.Context = _Context;
800                         HttpRuntime.TimeoutManager.Add (_Context);
801
802                         _savedUser = Thread.CurrentPrincipal;
803                         Thread.CurrentPrincipal = Context.User; 
804                 }
805
806                 internal void OnStateExecuteLeave ()
807                 {
808                         // TODO: Restore culture for the thread
809
810                         HttpRuntime.TimeoutManager.Remove (_Context);
811                         HttpContext.Context = _savedContext;
812                         if (null != _savedUser)  {
813                                 Thread.CurrentPrincipal = _savedUser;
814                                 _savedUser = null;
815                         }
816                 }
817
818                 internal void ClearError ()
819                 {
820                         _lastError = null;
821                 }
822
823                 internal Exception GetLastError ()
824                 {
825                         if (_Context == null)
826                                 return _lastError;
827
828                         return _Context.Error;
829                 }
830                 
831                 internal void HandleError (Exception obj)
832                 {
833                         EventHandler handler;                   
834                         bool fire = true;
835
836                         if (null != _Context) {
837                                 if (null != _Context.Error) 
838                                         fire = false;
839
840                                 _Context.AddError (obj);
841                         } else {
842                                 if (null != _lastError)
843                                         fire = false;
844
845                                 _lastError = obj;
846                         }
847
848                         if (!fire)
849                                 return;
850
851                         // Fire OnError event here
852                         handler = (EventHandler) Events [HttpApplication.ErrorId];
853                         if (null != handler) {
854                                 try {
855                                         handler (this, EventArgs.Empty);
856                                 } catch (Exception excp) {
857                                         if (null != _Context)
858                                                 _Context.AddError (excp);
859                                 }
860                         }
861                 }
862
863                 internal void Startup (HttpContext context, HttpApplicationState state)
864                 {
865                         _Context = context;
866
867                         _appState = state;
868                         _state = new StateMachine (this);
869
870                         // Initialize all IHttpModule(s)
871                         InitModules ();
872                         HttpApplicationFactory.AttachEvents (this);
873                         InitCulture ();
874
875                         // Initialize custom application
876                         _InPreRequestResponseMode = true;
877                         try {
878                                 Init ();
879                         } catch (Exception obj) {
880                                 HandleError (obj);
881                         }
882
883                         _InPreRequestResponseMode = false;
884
885                         _state.Init ();
886                 }
887
888                 internal void Cleanup ()
889                 {
890                         try {
891                                 Dispose ();
892                         } catch (Exception obj) {
893                                 HandleError (obj);
894                         }
895
896                         if (null != _ModuleCollection) {
897                                 int pos;
898                                 int count = _ModuleCollection.Count;
899
900                                 for (pos = 0; pos != count; pos++)
901                                         ((IHttpModule) _ModuleCollection.Get (pos)).Dispose ();
902
903                                 _ModuleCollection = null;
904                         }
905
906                         _state = null;
907                 }
908
909                 public void CompleteRequest ()
910                 {
911                         _CompleteRequest = true;
912                 }
913
914                 public virtual void Dispose ()
915                 {
916                         _Site = null;
917                         EventHandler disposed = (EventHandler) Events [HttpApplication.DisposedId];
918                         if (null != disposed) 
919                                 disposed (this, EventArgs.Empty);
920                 }
921
922                 public virtual void Init ()
923                 {
924                 }
925
926                 public virtual string GetVaryByCustomString (HttpContext context, string custom)
927                 {
928                         if (custom.ToLower () == "browser")
929                                 return context.Request.Browser.Type;
930
931                         return null;
932                 }
933
934                 IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context,
935                                                                     AsyncCallback cb,
936                                                                     object extraData)
937                 {
938                         _Context = context;
939                         _Context.ApplicationInstance = this;
940                         _CompleteRequest = false;
941
942                         _asyncWebResult = new HttpAsyncResult (cb, extraData);
943
944                         _state.Start ();
945
946                         return _asyncWebResult;
947                 }
948
949                 void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
950                 {
951                         HttpAsyncResult ar = (HttpAsyncResult) result;
952
953                         if (null != ar.Error) 
954                                 throw ar.Error;
955                 }
956
957                 void IHttpHandler.ProcessRequest (HttpContext context)
958                 {
959                         throw new NotSupportedException (HttpRuntime.FormatResourceString("sync_not_supported"));
960                 }
961
962                 bool IHttpHandler.IsReusable {
963                         get { return true; }
964                 }
965 #endregion              
966
967 #region Properties
968
969                 internal string AssemblyLocation {
970                         get { return assemblyLocation; }
971                 }
972                 
973                 [Browsable (false)]
974                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
975                 public HttpApplicationState Application {
976                         get { return _appState; }
977                 }
978
979                 [Browsable (false)]
980                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
981                 public HttpContext Context {
982                         get { return _Context; }
983                 }
984
985                 protected EventHandlerList Events {
986                         get {
987                                 if (null == _Events)
988                                         _Events = new EventHandlerList ();
989
990                                 return _Events;
991                         }
992                 }
993
994                 [Browsable (false)]
995                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
996                 public HttpModuleCollection Modules {
997                         get {
998                                 if (null == _ModuleCollection)
999                                         _ModuleCollection = new HttpModuleCollection ();
1000
1001                                 return _ModuleCollection;
1002                         }
1003                 }
1004
1005                 [Browsable (false)]
1006                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1007                 public HttpRequest Request {
1008                         get {
1009                                 if (null != _Context && (!_InPreRequestResponseMode))
1010                                         return _Context.Request;
1011
1012                                 throw new HttpException ("Can't get request object");
1013                         }
1014                 }
1015
1016                 [Browsable (false)]
1017                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1018                 public HttpResponse Response {
1019                         get {
1020                                 if (null != _Context && (!_InPreRequestResponseMode))
1021                                         return _Context.Response;
1022
1023                                 throw new HttpException ("Can't get response object");
1024                         }
1025                 }
1026
1027                 [Browsable (false)]
1028                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1029                 public HttpServerUtility Server {
1030                         get {
1031                                 if (null != _Context)
1032                                         return _Context.Server;
1033
1034                                 return new HttpServerUtility (this);
1035                         }
1036                 }
1037
1038                 [Browsable (false)]
1039                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1040                 public HttpSessionState Session {
1041                         get {
1042                                 if (null != _Session)
1043                                         return _Session;
1044
1045                                 if (null != _Context && null != _Context.Session) {
1046                                         _Session = _Context.Session;
1047                                         return _Session;
1048                                 }
1049
1050                                 throw new HttpException ("Failed to get session object");
1051                         }
1052                 }
1053
1054                 [Browsable (false)]
1055                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1056                 public IPrincipal User {
1057                         get { return _Context.User; }
1058                 }
1059
1060                 [Browsable (false)]
1061                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1062                 public ISite Site {
1063                         get { return _Site; }
1064                         set { _Site = value; }
1065                 }
1066 #endregion Properties
1067         }
1068
1069         // Used in HttpResponse.End ()
1070         class StepCompleteRequest
1071         {
1072         }
1073 }
1074