PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Web/System.Web/HttpApplication.jvm.cs

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