**** Merged from MCS ****
[mono-project.git] / mcs / class / System.Web / System.Web / HttpApplication.cs
blob61c82c2daf26dd115c1341ad626356be2bec0b69
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 // (c) Copyright 2002-2003 Ximian, Inc. (http://www.ximian.com)
10 // (c) Copyright 2004 Novell, Inc. (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System;
34 using System.Collections;
35 using System.ComponentModel;
36 using System.Globalization;
37 using System.IO;
38 using System.Threading;
39 using System.Security.Principal;
40 using System.Runtime.Remoting.Messaging;
41 using System.Web.UI;
42 using System.Web.Configuration;
43 using System.Web.SessionState;
45 namespace System.Web
48 [ToolboxItem(true)]
49 public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable
52 #region Event Handlers
54 // Async event holders
55 AsyncEvents _acquireRequestStateAsync;
56 AsyncEvents _authenticateRequestAsync;
57 AsyncEvents _endRequestAsync;
58 AsyncEvents _beginRequestAsync;
59 AsyncEvents _authorizeRequestAsync;
60 AsyncEvents _updateRequestCacheAsync;
61 AsyncEvents _resolveRequestCacheAsync;
62 AsyncEvents _releaseRequestStateAsync;
63 AsyncEvents _preRequestHandlerExecuteAsync;
64 AsyncEvents _postRequestHandlerExecuteAsync;
66 // ID objects used to indentify the event
67 static object AcquireRequestStateId = new Object ();
68 static object AuthenticateRequestId = new Object ();
69 static object DefaultAuthenticationId = new Object ();
70 static object EndRequestId = new Object ();
71 static object DisposedId = new Object ();
72 static object BeginRequestId = new Object ();
73 static object AuthorizeRequestId = new Object ();
74 static object UpdateRequestCacheId = new Object ();
75 static object ResolveRequestCacheId = new Object ();
76 static object ReleaseRequestStateId = new Object ();
77 static object PreSendRequestContentId = new Object ();
78 static object PreSendRequestHeadersId = new Object ();
79 static object PreRequestHandlerExecuteId = new Object ();
80 static object PostRequestHandlerExecuteId = new Object ();
81 static object ErrorId = new Object ();
83 // List of events
84 private EventHandlerList _Events;
86 public event EventHandler AcquireRequestState {
87 add { Events.AddHandler (AcquireRequestStateId, value); }
88 remove { Events.RemoveHandler (AcquireRequestStateId, value); }
91 public event EventHandler AuthenticateRequest {
92 add { Events.AddHandler (AuthenticateRequestId, value); }
93 remove { Events.RemoveHandler (AuthenticateRequestId, value); }
96 public event EventHandler AuthorizeRequest {
97 add { Events.AddHandler (AuthorizeRequestId, value); }
98 remove { Events.RemoveHandler (AuthorizeRequestId, value); }
101 public event EventHandler BeginRequest {
102 add { Events.AddHandler (BeginRequestId, value); }
103 remove { Events.RemoveHandler (BeginRequestId, value); }
106 public event EventHandler Disposed {
107 add { Events.AddHandler (DisposedId, value); }
108 remove { Events.RemoveHandler (DisposedId, value); }
111 public event EventHandler EndRequest {
112 add { Events.AddHandler (EndRequestId, value); }
113 remove { Events.RemoveHandler (EndRequestId, value); }
116 public event EventHandler Error {
117 add { Events.AddHandler (ErrorId, value); }
118 remove { Events.RemoveHandler (ErrorId, value); }
121 public event EventHandler PostRequestHandlerExecute {
122 add { Events.AddHandler (PostRequestHandlerExecuteId, value); }
123 remove { Events.RemoveHandler (PostRequestHandlerExecuteId, value); }
126 public event EventHandler PreRequestHandlerExecute {
127 add { Events.AddHandler (PreRequestHandlerExecuteId, value); }
128 remove { Events.RemoveHandler (PreRequestHandlerExecuteId, value); }
131 public event EventHandler PreSendRequestContent {
132 add { Events.AddHandler (PreSendRequestContentId, value); }
133 remove { Events.RemoveHandler (PreSendRequestContentId, value); }
136 public event EventHandler ReleaseRequestState {
137 add { Events.AddHandler (ReleaseRequestStateId, value); }
138 remove { Events.RemoveHandler (ReleaseRequestStateId, value); }
141 public event EventHandler ResolveRequestCache
143 add { Events.AddHandler (ResolveRequestCacheId, value); }
144 remove { Events.RemoveHandler (ResolveRequestCacheId, value); }
147 public event EventHandler UpdateRequestCache {
148 add { Events.AddHandler (UpdateRequestCacheId, value); }
149 remove { Events.RemoveHandler (UpdateRequestCacheId, value); }
152 public event EventHandler PreSendRequestHeaders {
153 add { Events.AddHandler (PreSendRequestHeadersId, value); }
154 remove { Events.RemoveHandler (PreSendRequestHeadersId, value); }
157 internal event EventHandler DefaultAuthentication {
158 add { Events.AddHandler (DefaultAuthenticationId, value); }
159 remove { Events.RemoveHandler (DefaultAuthenticationId, value); }
162 public void AddOnAcquireRequestStateAsync (BeginEventHandler beg, EndEventHandler end)
164 if (null == _acquireRequestStateAsync)
165 _acquireRequestStateAsync = new AsyncEvents ();
167 _acquireRequestStateAsync.Add (beg, end);
170 public void AddOnAuthenticateRequestAsync(BeginEventHandler beg, EndEventHandler end)
172 if (null == _authenticateRequestAsync)
173 _authenticateRequestAsync = new AsyncEvents ();
175 _authenticateRequestAsync.Add (beg, end);
178 public void AddOnAuthorizeRequestAsync (BeginEventHandler beg, EndEventHandler end)
180 if (null == _authorizeRequestAsync)
181 _authorizeRequestAsync = new AsyncEvents ();
183 _authorizeRequestAsync.Add (beg, end);
186 public void AddOnBeginRequestAsync (BeginEventHandler beg, EndEventHandler end)
188 if (null == _beginRequestAsync)
189 _beginRequestAsync = new AsyncEvents ();
191 _beginRequestAsync.Add (beg, end);
194 public void AddOnEndRequestAsync (BeginEventHandler beg, EndEventHandler end)
196 if (null == _endRequestAsync)
197 _endRequestAsync = new AsyncEvents ();
199 _endRequestAsync.Add (beg, end);
202 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler beg, EndEventHandler end)
204 if (null == _postRequestHandlerExecuteAsync)
205 _postRequestHandlerExecuteAsync = new AsyncEvents ();
207 _postRequestHandlerExecuteAsync.Add (beg, end);
210 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler beg, EndEventHandler end)
212 if (null == _preRequestHandlerExecuteAsync)
213 _preRequestHandlerExecuteAsync = new AsyncEvents ();
215 _preRequestHandlerExecuteAsync.Add (beg, end);
218 public void AddOnReleaseRequestStateAsync (BeginEventHandler beg, EndEventHandler end)
220 if (null == _releaseRequestStateAsync)
221 _releaseRequestStateAsync = new AsyncEvents ();
223 _releaseRequestStateAsync.Add (beg, end);
226 public void AddOnResolveRequestCacheAsync (BeginEventHandler beg, EndEventHandler end)
228 if (null == _resolveRequestCacheAsync)
229 _resolveRequestCacheAsync = new AsyncEvents ();
231 _resolveRequestCacheAsync.Add (beg, end);
234 public void AddOnUpdateRequestCacheAsync (BeginEventHandler beg, EndEventHandler end)
236 if (null == _updateRequestCacheAsync)
237 _updateRequestCacheAsync = new AsyncEvents ();
239 _updateRequestCacheAsync.Add (beg, end);
242 #endregion
244 #region Recycle Helper
245 class HandlerFactory
247 public IHttpHandler Handler;
248 public IHttpHandlerFactory Factory;
250 public HandlerFactory (IHttpHandler handler, IHttpHandlerFactory factory)
252 this.Handler = handler;
253 this.Factory = factory;
256 #endregion
258 #region State Machine
260 interface IStateHandler
262 void Execute();
263 bool CompletedSynchronously { get; }
264 bool PossibleToTimeout { get; }
267 class EventState : IStateHandler
269 HttpApplication _app;
270 EventHandler _event;
272 public EventState (HttpApplication app, EventHandler evt)
274 _app = app;
275 _event = evt;
278 public void Execute ()
280 if (null != _event)
281 _event (_app, EventArgs.Empty);
284 public bool CompletedSynchronously {
285 get { return true; }
288 public bool PossibleToTimeout {
289 get { return true; }
293 class AsyncEventState : IStateHandler
295 HttpApplication _app;
296 BeginEventHandler _begin;
297 EndEventHandler _end;
298 AsyncCallback _callback;
299 bool _async;
301 public AsyncEventState (HttpApplication app,
302 BeginEventHandler begin,
303 EndEventHandler end)
305 _async = false;
306 _app = app;
307 _begin = begin;
308 _end = end;
309 _callback = new AsyncCallback (OnAsyncReady);
312 public void Execute ()
314 _async = true;
315 IAsyncResult ar = _begin (_app, EventArgs.Empty, _callback, null);
316 if (ar.CompletedSynchronously) {
317 _async = false;
318 _end (ar);
322 public bool CompletedSynchronously {
323 get { return !_async; }
326 public bool PossibleToTimeout {
327 get {
328 // We can't cancel a async event
329 return false;
333 private void OnAsyncReady (IAsyncResult ar)
335 if (ar.CompletedSynchronously)
336 return;
338 Exception error = null;
340 try {
341 // Invoke end handler
342 _end(ar);
343 } catch (Exception exc) {
344 // Flow this error to the next state (handle during state execution)
345 error = exc;
348 _app._state.ExecuteNextAsync (error);
352 class AsyncEvents
354 ArrayList _events;
355 class EventRecord {
356 public EventRecord(BeginEventHandler beg, EndEventHandler end)
358 Begin = beg;
359 End = end;
362 public BeginEventHandler Begin;
363 public EndEventHandler End;
366 public AsyncEvents ()
368 _events = new ArrayList ();
371 public void Add (BeginEventHandler begin, EndEventHandler end)
373 _events.Add (new EventRecord (begin, end));
376 public void GetAsStates (HttpApplication app, ArrayList states)
378 foreach (object obj in _events)
379 states.Add (new AsyncEventState (app,
380 ((EventRecord) obj).Begin,
381 ((EventRecord) obj).End));
386 class ExecuteHandlerState : IStateHandler
388 HttpApplication _app;
389 AsyncCallback _callback;
390 IHttpAsyncHandler _handler;
391 bool _async;
393 public ExecuteHandlerState (HttpApplication app)
395 _app = app;
396 _callback = new AsyncCallback (OnAsyncReady);
399 private void OnAsyncReady (IAsyncResult ar)
401 if (ar.CompletedSynchronously)
402 return;
404 Exception error = null;
406 try {
407 // Invoke end handler
408 _handler.EndProcessRequest(ar);
409 } catch (Exception exc) {
410 // Flow this error to the next state (handle during state execution)
411 error = exc;
414 _handler = null;
415 _app._state.ExecuteNextAsync (error);
418 public void Execute ()
420 IHttpHandler handler = _app.Context.Handler;
421 if (handler == null)
422 return;
424 // Check if we can execute async
425 if (handler is IHttpAsyncHandler) {
426 _async = true;
427 _handler = (IHttpAsyncHandler) handler;
429 IAsyncResult ar = _handler.BeginProcessRequest (_app.Context,
430 _callback,
431 null);
433 if (ar.CompletedSynchronously) {
434 _async = false;
435 _handler = null;
436 ((IHttpAsyncHandler) handler).EndProcessRequest (ar);
438 } else {
439 _async = false;
441 // Sync handler
442 handler.ProcessRequest (_app.Context);
446 public bool CompletedSynchronously {
447 get { return !_async; }
450 public bool PossibleToTimeout {
451 get {
452 if (_app.Context.Handler is IHttpAsyncHandler)
453 return false;
455 return true;
460 class CreateHandlerState : IStateHandler
462 HttpApplication _app;
464 public CreateHandlerState (HttpApplication app)
466 _app = app;
469 public void Execute ()
471 _app.Context.Handler = _app.CreateHttpHandler ( _app.Context,
472 _app.Request.RequestType,
473 _app.Request.FilePath,
474 _app.Request.PhysicalPath);
477 public bool CompletedSynchronously {
478 get { return true; }
481 public bool PossibleToTimeout {
482 get { return false; }
486 class FilterHandlerState : IStateHandler
488 HttpApplication _app;
490 public FilterHandlerState (HttpApplication app)
492 _app = app;
495 public void Execute ()
497 _app.Context.Response.DoFilter (true);
500 public bool CompletedSynchronously {
501 get { return true; }
504 public bool PossibleToTimeout {
505 get { return true; }
509 class StateMachine
511 HttpApplication _app;
512 WaitCallback _asynchandler;
514 IStateHandler [] _handlers;
515 int _currentStateIdx;
516 int _endStateIdx;
517 int _endRequestStateIdx;
518 int _countSteps;
519 int _countSyncSteps;
521 // Helper to create the states for a normal event
522 private void GetAsStates (object Event, ArrayList states)
524 // Get list of clients for the sync events
525 Delegate evnt = _app.Events [Event];
526 if (evnt == null)
527 return;
529 System.Delegate [] clients = evnt.GetInvocationList();
530 foreach (Delegate client in clients)
531 states.Add (new EventState (_app, (EventHandler) client));
534 internal StateMachine (HttpApplication app)
536 _app = app;
539 internal void Init ()
541 _asynchandler = new WaitCallback (OnAsyncCallback);
543 // Create a arraylist of states to execute
544 ArrayList states = new ArrayList ();
546 // BeginRequest
547 if (null != _app._beginRequestAsync)
548 _app._beginRequestAsync.GetAsStates (_app, states);
549 GetAsStates (HttpApplication.BeginRequestId, states);
551 // AuthenticateRequest
552 if (null != _app._authenticateRequestAsync)
553 _app._authenticateRequestAsync.GetAsStates (_app, states);
554 GetAsStates (HttpApplication.AuthenticateRequestId, states);
556 // DefaultAuthentication
557 EventHandler defaultAuthHandler = (EventHandler) _app.Events [HttpApplication.DefaultAuthenticationId];
558 states.Add (new EventState (_app, defaultAuthHandler));
560 // AuthorizeRequest
561 if (null != _app._authorizeRequestAsync)
562 _app._authorizeRequestAsync.GetAsStates (_app, states);
563 GetAsStates (HttpApplication.AuthorizeRequestId, states);
565 // ResolveRequestCache
566 if (null != _app._resolveRequestCacheAsync)
567 _app._resolveRequestCacheAsync.GetAsStates (_app, states);
568 GetAsStates (HttpApplication.ResolveRequestCacheId, states);
570 // [A handler (a page corresponding to the request URL) is created at this point.]
571 states.Add (new CreateHandlerState (_app));
573 // AcquireRequestState
574 if (null != _app._acquireRequestStateAsync)
575 _app._acquireRequestStateAsync.GetAsStates (_app, states);
576 GetAsStates (HttpApplication.AcquireRequestStateId, states);
578 // PreRequestHandlerExecute
579 if (null != _app._preRequestHandlerExecuteAsync)
580 _app._preRequestHandlerExecuteAsync.GetAsStates (_app, states);
581 GetAsStates (HttpApplication.PreRequestHandlerExecuteId, states);
583 // [The handler is executed.]
584 states.Add (new ExecuteHandlerState (_app));
586 // PostRequestHandlerExecute
587 if (null != _app._postRequestHandlerExecuteAsync)
588 _app._postRequestHandlerExecuteAsync.GetAsStates (_app, states);
589 GetAsStates (HttpApplication.PostRequestHandlerExecuteId, states);
591 // ReleaseRequestState
592 if (null != _app._releaseRequestStateAsync)
593 _app._releaseRequestStateAsync.GetAsStates (_app, states);
594 GetAsStates (HttpApplication.ReleaseRequestStateId, states);
596 // [Response filters, if any, filter the output.]
597 states.Add (new FilterHandlerState (_app));
599 // UpdateRequestCache
600 if (null != _app._updateRequestCacheAsync)
601 _app._updateRequestCacheAsync.GetAsStates (_app, states);
602 GetAsStates (HttpApplication.UpdateRequestCacheId, states);
604 // EndRequest
605 _endRequestStateIdx = states.Count;
606 if (null != _app._endRequestAsync)
607 _app._endRequestAsync.GetAsStates (_app, states);
608 GetAsStates (HttpApplication.EndRequestId, states);
610 // Make list ready to execute
611 _handlers = new IStateHandler [states.Count];
612 states.CopyTo (_handlers);
616 internal void Reset ()
618 _countSyncSteps = 0;
619 _countSteps = 0;
620 _currentStateIdx = -1;
621 _endStateIdx = _handlers.Length - 1;
624 internal void Start ()
626 Reset ();
627 ExecuteNextAsync (null);
630 internal void ExecuteNextAsync (Exception lasterror)
632 if (!Thread.CurrentThread.IsThreadPoolThread)
633 ThreadPool.QueueUserWorkItem (_asynchandler, lasterror);
634 else
635 ExecuteNext (lasterror);
638 internal void ExecuteNext (Exception lasterror)
640 bool ready_sync = false;
641 IStateHandler handler;
642 bool timeoutPossible = false;
644 lock (_app) {
645 _app.OnStateExecuteEnter ();
646 try {
647 do {
648 if (null != lasterror) {
649 _app.HandleError (lasterror);
650 lasterror = null;
653 // Check if request flow is to be stopped
654 if ((_app.GetLastError () != null || _app._CompleteRequest) &&
655 _currentStateIdx < _endRequestStateIdx) {
656 _currentStateIdx = _endRequestStateIdx;
657 // MS does not filter on error
658 _app._Context.Response.DoFilter (false);
659 } else if (_currentStateIdx < _endStateIdx) {
660 // Get next state handler
661 _currentStateIdx++;
664 handler = _handlers [_currentStateIdx];
665 _countSteps++;
666 timeoutPossible = handler.PossibleToTimeout;
667 try {
668 if (timeoutPossible)
669 HttpRuntime.TimeoutManager.Add (_app.Context);
671 lasterror = ExecuteState (handler, ref ready_sync);
672 if (ready_sync)
673 _countSyncSteps++;
674 } finally {
675 if (timeoutPossible)
676 HttpRuntime.TimeoutManager.Remove (_app.Context);
678 } while (_currentStateIdx < _endStateIdx);
680 if (null != lasterror)
681 _app.HandleError (lasterror);
682 } finally {
683 _app.OnStateExecuteLeave ();
688 // Finish the request off..
689 if (lasterror != null || _currentStateIdx == _endStateIdx) {
690 _app._asyncWebResult.Complete ((_countSyncSteps == _countSteps),
691 null,
692 null);
694 _app.Context.Handler = null;
695 _app.Context.ApplicationInstance = null;
696 _app.RecycleHandlers ();
697 _app._asyncWebResult = null;
699 HttpApplicationFactory.RecycleInstance (_app);
703 private void OnAsyncCallback (object obj)
705 ExecuteNext ((Exception) obj);
708 private Exception ExecuteState (IStateHandler state, ref bool readysync)
710 Exception lasterror = null;
711 try {
712 if (state.PossibleToTimeout) {
713 _app.Context.BeginTimeoutPossible ();
716 try {
717 state.Execute ();
718 } finally {
719 if (state.PossibleToTimeout) {
720 _app.Context.EndTimeoutPossible ();
724 if (state.PossibleToTimeout) {
725 // Async Execute
726 _app.Context.TryWaitForTimeout ();
729 readysync = state.CompletedSynchronously;
730 } catch (ThreadAbortException obj) {
731 object o = obj.ExceptionState;
732 Type type = (o != null) ? o.GetType () : null;
733 if (type == typeof (StepTimeout)) {
734 Thread.ResetAbort ();
735 lasterror = new HttpException ("The request timed out.");
736 _app.CompleteRequest ();
737 } else if (type == typeof (StepCompleteRequest)) {
738 Thread.ResetAbort ();
739 _app.CompleteRequest ();
741 } catch (Exception obj) {
742 lasterror = obj;
745 return lasterror;
749 #endregion
751 #region Fields
753 StateMachine _state;
755 bool _CompleteRequest;
756 HttpContext _Context;
757 Exception _lastError;
759 HttpContext _savedContext;
760 IPrincipal _savedUser;
761 HttpAsyncResult _asyncWebResult;
763 ISite _Site;
764 HttpModuleCollection _ModuleCollection;
765 HttpSessionState _Session;
766 HttpApplicationState _appState;
767 string assemblyLocation;
768 ArrayList _recycleHandlers;
770 bool _InPreRequestResponseMode;
772 CultureInfo appCulture;
773 CultureInfo appUICulture;
774 CultureInfo prevAppCulture;
775 CultureInfo prevAppUICulture;
776 #endregion
778 #region Constructor
780 public HttpApplication ()
782 assemblyLocation = GetType ().Assembly.Location;
785 #endregion
787 #region Methods
788 internal IHttpHandler CreateHttpHandler (HttpContext context,
789 string type,
790 string file,
791 string path)
793 HandlerFactoryConfiguration handler =
794 HttpContext.GetAppConfig ("system.web/httpHandlers")
795 as HandlerFactoryConfiguration;
797 if (handler == null)
798 throw new HttpException ("Cannot get system.web/httpHandlers handler.");
800 object result = handler.FindHandler (type, file).Create ();
801 if (result is IHttpHandler)
802 return (IHttpHandler) result;
804 if (result is IHttpHandlerFactory) {
805 IHttpHandlerFactory factory = (IHttpHandlerFactory) result;
806 try {
807 IHttpHandler ret = factory.GetHandler (context, type, file, path);
808 if (null != ret) {
809 if (null == _recycleHandlers)
810 _recycleHandlers = new ArrayList();
812 _recycleHandlers.Add (new HandlerFactory (ret, factory));
815 return ret;
816 } catch (DirectoryNotFoundException) {
817 throw new HttpException (404, "Cannot find '" + file + "'.");
818 } catch (FileNotFoundException fnf) {
819 string fname = fnf.FileName;
820 if (fname != null && fname != "") {
821 file = Path.GetFileName (fname);
824 throw new HttpException (404, "Cannot find '" + file + "'.");
828 throw new HttpException ("Handler not found");
831 internal void RecycleHandlers ()
833 if (null == _recycleHandlers || _recycleHandlers.Count == 0)
834 return;
836 foreach (HandlerFactory item in _recycleHandlers)
837 item.Factory.ReleaseHandler (item.Handler);
839 _recycleHandlers.Clear ();
842 internal void InitModules ()
844 ModulesConfiguration modules;
846 modules = (ModulesConfiguration) HttpContext.GetAppConfig ("system.web/httpModules");
847 if (null == modules)
848 throw new HttpException (
849 HttpRuntime.FormatResourceString ("missing_modules_config"));
851 _ModuleCollection = modules.CreateCollection ();
852 if (_ModuleCollection == null)
853 return;
855 int pos, count;
857 count = _ModuleCollection.Count;
858 for (pos = 0; pos != count; pos++)
859 ((IHttpModule) _ModuleCollection.Get (pos)).Init (this);
862 internal void InitCulture ()
864 GlobalizationConfiguration cfg = GlobalizationConfiguration.GetInstance (null);
865 if (cfg != null) {
866 appCulture = cfg.Culture;
867 appUICulture = cfg.UICulture;
871 void SaveThreadCulture ()
873 Thread th = Thread.CurrentThread;
875 if (appCulture != null) {
876 prevAppCulture = th.CurrentCulture;
877 th.CurrentCulture = appCulture;
880 if (appUICulture != null) {
881 prevAppUICulture = th.CurrentUICulture;
882 th.CurrentUICulture = appUICulture;
886 void RestoreThreadCulture ()
888 Thread th = Thread.CurrentThread;
890 if (prevAppCulture != null) {
891 th.CurrentCulture = prevAppCulture;
892 prevAppCulture = null;
895 if (prevAppUICulture != null) {
896 th.CurrentUICulture = prevAppUICulture;
897 prevAppUICulture = null;
901 internal void OnStateExecuteEnter ()
903 SaveThreadCulture ();
904 _savedContext = HttpContext.Context;
905 HttpContext.Context = _Context;
906 SetPrincipal (Context.User);
909 internal void OnStateExecuteLeave ()
911 RestoreThreadCulture ();
912 HttpContext.Context = _savedContext;
913 RestorePrincipal ();
916 internal void SetPrincipal (IPrincipal principal)
918 // Don't overwrite _savedUser if called from inside a step
919 if (_savedUser == null)
920 _savedUser = Thread.CurrentPrincipal;
922 Thread.CurrentPrincipal = principal;
925 internal void RestorePrincipal ()
927 if (_savedUser == null)
928 return;
930 Thread.CurrentPrincipal = _savedUser;
931 _savedUser = null;
934 internal void ClearError ()
936 _lastError = null;
939 internal Exception GetLastError ()
941 if (_Context == null)
942 return _lastError;
944 return _Context.Error;
947 internal void HandleError (Exception obj)
949 EventHandler handler;
950 bool fire = true;
952 if (null != _Context) {
953 if (null != _Context.Error)
954 fire = false;
956 _Context.AddError (obj);
957 } else {
958 if (null != _lastError)
959 fire = false;
961 _lastError = obj;
964 if (!fire)
965 return;
967 // Fire OnError event here
968 handler = (EventHandler) Events [HttpApplication.ErrorId];
969 if (null != handler) {
970 try {
971 handler (this, EventArgs.Empty);
972 } catch (Exception excp) {
973 if (null != _Context)
974 _Context.AddError (excp);
979 internal void Startup (HttpContext context, HttpApplicationState state)
981 _Context = context;
983 _appState = state;
984 _state = new StateMachine (this);
986 // Initialize all IHttpModule(s)
987 InitModules ();
988 HttpApplicationFactory.AttachEvents (this);
989 InitCulture ();
991 // Initialize custom application
992 _InPreRequestResponseMode = true;
993 try {
994 Init ();
995 } catch (Exception obj) {
996 HandleError (obj);
999 _InPreRequestResponseMode = false;
1001 _state.Init ();
1004 internal void Cleanup ()
1006 try {
1007 Dispose ();
1008 } catch (Exception obj) {
1009 HandleError (obj);
1012 if (null != _ModuleCollection) {
1013 int pos;
1014 int count = _ModuleCollection.Count;
1016 for (pos = 0; pos != count; pos++)
1017 ((IHttpModule) _ModuleCollection.Get (pos)).Dispose ();
1019 _ModuleCollection = null;
1022 _state = null;
1025 public void CompleteRequest ()
1027 _CompleteRequest = true;
1030 public virtual void Dispose ()
1032 _Site = null;
1033 EventHandler disposed = (EventHandler) Events [HttpApplication.DisposedId];
1034 if (null != disposed)
1035 disposed (this, EventArgs.Empty);
1038 public virtual void Init ()
1042 public virtual string GetVaryByCustomString (HttpContext context, string custom)
1044 if (custom.ToLower () == "browser")
1045 return context.Request.Browser.Type;
1047 return null;
1050 IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context,
1051 AsyncCallback cb,
1052 object extraData)
1054 _Context = context;
1055 _Context.ApplicationInstance = this;
1056 _CompleteRequest = false;
1058 _asyncWebResult = new HttpAsyncResult (cb, extraData);
1060 _state.Start ();
1062 return _asyncWebResult;
1065 void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
1067 HttpAsyncResult ar = (HttpAsyncResult) result;
1069 if (null != ar.Error)
1070 throw ar.Error;
1073 void IHttpHandler.ProcessRequest (HttpContext context)
1075 throw new NotSupportedException (HttpRuntime.FormatResourceString("sync_not_supported"));
1078 bool IHttpHandler.IsReusable {
1079 get { return true; }
1081 #endregion
1083 #region Properties
1085 internal string AssemblyLocation {
1086 get { return assemblyLocation; }
1089 [Browsable (false)]
1090 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1091 public HttpApplicationState Application {
1092 get { return _appState; }
1095 [Browsable (false)]
1096 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1097 public HttpContext Context {
1098 get { return _Context; }
1101 protected EventHandlerList Events {
1102 get {
1103 if (null == _Events)
1104 _Events = new EventHandlerList ();
1106 return _Events;
1110 [Browsable (false)]
1111 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1112 public HttpModuleCollection Modules {
1113 get {
1114 if (null == _ModuleCollection)
1115 _ModuleCollection = new HttpModuleCollection ();
1117 return _ModuleCollection;
1121 [Browsable (false)]
1122 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1123 public HttpRequest Request {
1124 get {
1125 if (null != _Context && (!_InPreRequestResponseMode))
1126 return _Context.Request;
1128 throw new HttpException ("Can't get request object");
1132 [Browsable (false)]
1133 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1134 public HttpResponse Response {
1135 get {
1136 if (null != _Context && (!_InPreRequestResponseMode))
1137 return _Context.Response;
1139 throw new HttpException ("Can't get response object");
1143 [Browsable (false)]
1144 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1145 public HttpServerUtility Server {
1146 get {
1147 if (null != _Context)
1148 return _Context.Server;
1150 return new HttpServerUtility (this);
1154 [Browsable (false)]
1155 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1156 public HttpSessionState Session {
1157 get {
1158 if (null != _Session)
1159 return _Session;
1161 if (null != _Context && null != _Context.Session)
1162 return _Context.Session;
1164 throw new HttpException ("Failed to get session object");
1168 [Browsable (false)]
1169 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1170 public IPrincipal User {
1171 get { return _Context.User; }
1174 [Browsable (false)]
1175 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1176 public ISite Site {
1177 get { return _Site; }
1178 set { _Site = value; }
1180 #endregion Properties
1183 // Used in HttpResponse.End ()
1184 class StepCompleteRequest