Fix for running against RabbitMQ 2.2
[mono.git] / mcs / class / System.Web / System.Web / HttpRuntime.cs
1 //
2 // System.Web.HttpRuntime.cs 
3 // 
4 // Authors:
5 //      Miguel de Icaza (miguel@novell.com)
6 //      Marek Habersack <mhabersack@novell.com>
7 //
8 //
9 // Copyright (C) 2005-2010 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
31 //
32 // TODO: Call HttpRequest.CloseInputStream when we finish a request, as we are using the IntPtr stream.
33 //
34 using System.IO;
35 using System.Text;
36 using System.Globalization;
37 using System.Collections;
38 using System.Reflection;
39 using System.Security;
40 using System.Security.Permissions;
41 using System.Web.Caching;
42 using System.Web.Configuration;
43 using System.Web.Management;
44 using System.Web.UI;
45 using System.Web.Util;
46 #if MONOWEB_DEP
47 using Mono.Web.Util;
48 #endif
49 using System.Threading;
50 #if TARGET_J2EE
51 using Mainsoft.Web;
52 #else
53 using System.CodeDom.Compiler;
54 using System.Web.Compilation;
55 #endif
56
57 namespace System.Web
58 {       
59         // CAS - no InheritanceDemand here as the class is sealed
60         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
61         public sealed class HttpRuntime
62         {
63                 static bool domainUnloading;
64                 
65 #if TARGET_J2EE
66                 static QueueManager queue_manager { get { return _runtime._queue_manager; } }
67                 static TraceManager trace_manager { get { return _runtime._trace_manager; } }
68                 static Cache cache { get { return _runtime._cache; } }
69                 static Cache internalCache { get { return _runtime._internalCache; } }
70                 static WaitCallback do_RealProcessRequest;
71                 
72                 QueueManager _queue_manager;
73                 TraceManager _trace_manager;
74                 Cache _cache;
75                 Cache _internalCache;
76
77                 public HttpRuntime ()
78                 {
79                         WebConfigurationManager.Init ();
80                         _queue_manager = new QueueManager ();
81                         _trace_manager = new TraceManager ();
82                         _cache = new Cache ();
83                         _internalCache = new Cache();
84                         _internalCache.DependencyCache = _cache;
85                 }
86
87                 static HttpRuntime _runtimeInstance {
88                         get {
89                                 HttpRuntime runtime = (HttpRuntime) AppDomain.CurrentDomain.GetData ("HttpRuntime");
90                                 if (runtime == null)
91                                         lock (typeof (HttpRuntime)) {
92                                                 runtime = (HttpRuntime) AppDomain.CurrentDomain.GetData ("HttpRuntime");
93                                                 if (runtime == null) {
94                                                         runtime = new HttpRuntime ();
95                                                         AppDomain.CurrentDomain.SetData ("HttpRuntime", runtime);
96                                                 }
97                                         }
98                                 return runtime;
99                         }
100                 }
101                 static HttpRuntime _runtime
102                 {
103                         get
104                         {
105                                 if (HttpContext.Current != null)
106                                         return HttpContext.Current.HttpRuntimeInstance;
107                                 else
108                                         return _runtimeInstance;
109                         }
110                 }
111 #else
112                 static QueueManager queue_manager;
113                 static TraceManager trace_manager;
114                 static Cache cache;
115                 static Cache internalCache;
116                 static WaitCallback do_RealProcessRequest;
117                 static HttpWorkerRequest.EndOfSendNotification end_of_send_cb;
118                 static Exception initialException;
119                 static bool firstRun;
120                 static bool assemblyMappingEnabled;
121                 static object assemblyMappingLock = new object ();
122                 static object appOfflineLock = new object ();
123                 static HttpRuntimeSection runtime_section;
124                 
125                 public HttpRuntime ()
126                 {
127
128                 }
129 #endif
130
131                 static HttpRuntime ()
132                 {
133 #if !TARGET_J2EE
134                         firstRun = true;
135                         try {
136                                 WebConfigurationManager.Init ();
137 #if MONOWEB_DEP
138                                 SettingsMappingManager.Init ();
139 #endif
140                                 runtime_section = (HttpRuntimeSection) WebConfigurationManager.GetSection ("system.web/httpRuntime");
141                         } catch (Exception ex) {
142                                 initialException = ex;
143                         }
144
145                         // The classes in whose constructors exceptions may be thrown, should be handled the same way QueueManager
146                         // and TraceManager are below. The constructors themselves MUST NOT throw any exceptions - we MUST be sure
147                         // the objects are created here. The exceptions will be dealt with below, in RealProcessRequest.
148                         queue_manager = new QueueManager ();
149                         if (queue_manager.HasException)
150                                 initialException = queue_manager.InitialException;
151
152                         trace_manager = new TraceManager ();
153                         if (trace_manager.HasException)
154                                         initialException = trace_manager.InitialException;
155
156                         cache = new Cache ();
157                         internalCache = new Cache ();
158                         internalCache.DependencyCache = internalCache;
159 #endif
160                         do_RealProcessRequest = new WaitCallback (state => {
161                                 try {
162                                         RealProcessRequest (state);
163                                 } catch {}
164                                 });
165                         end_of_send_cb = new HttpWorkerRequest.EndOfSendNotification (EndOfSend);
166                 }
167                 
168 #region AppDomain handling
169                 internal static bool DomainUnloading {
170                         get { return domainUnloading; }
171                 }
172
173                 [MonoDocumentationNote ("Currently returns path to the application root")]
174                 public static string AspClientScriptPhysicalPath { get { return AppDomainAppPath; } }
175
176                 [MonoDocumentationNote ("Currently returns path to the application root")]
177                 public static string AspClientScriptVirtualPath { get { return AppDomainAppVirtualPath; } }
178                 
179                 //
180                 // http://radio.weblogs.com/0105476/stories/2002/07/12/executingAspxPagesWithoutAWebServer.html
181                 //
182                 public static string AppDomainAppId {
183                         [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
184                         get {
185                                 //
186                                 // This value should not change across invocations
187                                 //
188                                 string dirname = (string) AppDomain.CurrentDomain.GetData (".appId");
189                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
190                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
191                                 }
192                                 return dirname;
193                         }
194                 }
195
196                 // Physical directory for the application
197                 public static string AppDomainAppPath {
198                         get {
199                                 string dirname = (string) AppDomain.CurrentDomain.GetData (".appPath");
200                                 if (SecurityManager.SecurityEnabled) {
201                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
202                                 }
203                                 return dirname;
204                         }
205                 }
206
207                 public static string AppDomainAppVirtualPath {
208                         get {
209                                 return (string) AppDomain.CurrentDomain.GetData (".appVPath");
210                         }
211                 }
212
213                 public static string AppDomainId {
214                         [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
215                         get {
216                                 return (string) AppDomain.CurrentDomain.GetData (".domainId");
217                         }
218                 }
219
220                 public static string AspInstallDirectory {
221                         get {
222                                 string dirname = (string) AppDomain.CurrentDomain.GetData (".hostingInstallDir");
223                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
224                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
225                                 }
226                                 return dirname;
227                         }
228                 }
229 #endregion
230
231                 static string _actual_bin_directory;
232                 public static string BinDirectory {
233                         get {
234                                 if (_actual_bin_directory == null) {
235                                         string[] parts = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath.Split (';');
236                                         string mypath = AppDomainAppPath;
237                                         string tmp;
238                                         
239                                         foreach (string p in parts) {
240                                                 tmp = Path.Combine (mypath, p);
241                                                 if (Directory.Exists (tmp)) {
242                                                         _actual_bin_directory = tmp;
243                                                         break;
244                                                 }
245                                         }
246
247                                         if (_actual_bin_directory == null)
248                                                 _actual_bin_directory = Path.Combine (mypath, "bin");
249
250                                         if (_actual_bin_directory [_actual_bin_directory.Length - 1] != Path.DirectorySeparatorChar)
251                                                 _actual_bin_directory += Path.DirectorySeparatorChar;
252                                 }
253                                 
254                                 if (SecurityManager.SecurityEnabled)
255                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, _actual_bin_directory).Demand ();
256
257                                 return _actual_bin_directory;
258                         }
259                 }
260
261                 public static Cache Cache {
262                         get {
263                                 return cache;
264                         }
265                 }
266
267                 internal static Cache InternalCache {
268                         get {
269                                 return internalCache;
270                         }
271                 }
272                 
273                 public static string ClrInstallDirectory {
274                         get {
275                                 string dirname = Path.GetDirectoryName (typeof (Object).Assembly.Location);
276                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
277                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
278                                 }
279                                 return dirname;
280                         }
281                 }
282
283                 public static string CodegenDir {
284                         get {
285                                 string dirname = AppDomain.CurrentDomain.SetupInformation.DynamicBase;
286                                 if (SecurityManager.SecurityEnabled) {
287                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
288                                 }
289                                 return dirname;
290                         }
291                 }
292
293                 public static bool IsOnUNCShare {
294                         [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Low)]
295                         get {
296                                 return RuntimeHelpers.IsUncShare;
297                         }
298                 }
299
300                 public static string MachineConfigurationDirectory {
301                         get {
302                                 string dirname = Path.GetDirectoryName (ICalls.GetMachineConfigPath ());
303                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
304                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
305                                 }
306                                 return dirname;
307                         }
308                 }
309
310                 internal static HttpRuntimeSection Section { get { return runtime_section; } }
311
312                 public static bool UsingIntegratedPipeline { get { return false; } }
313                 
314                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
315                 public static void Close ()
316                 {
317                         // Remove all items from cache.
318                 }
319
320                 internal static HttpWorkerRequest QueuePendingRequest (bool started_internally)
321                 {
322                         HttpWorkerRequest next = queue_manager.GetNextRequest (null);
323                         if (next == null)
324                                 return null;
325
326                         if (!started_internally) {
327                                 next.StartedInternally = true;
328                                 ThreadPool.QueueUserWorkItem (do_RealProcessRequest, next);
329                                 return null;
330                         }
331                         return next;
332                 }
333
334 #if !TARGET_J2EE
335                 static readonly string[] app_offline_files = {"app_offline.htm", "App_Offline.htm", "APP_OFFLINE.HTM"};
336                 static string app_offline_file;
337                 
338                 static bool AppIsOffline (HttpContext context)
339                 {
340                         if (!HttpApplicationFactory.ApplicationDisabled || app_offline_file == null)
341                                 return false;
342
343                         HttpResponse response = context.Response;
344                         response.Clear ();
345                         response.ContentType = "text/html";
346                         response.ExpiresAbsolute = DateTime.UtcNow;
347                         response.StatusCode = 503;
348                         response.TransmitFile (app_offline_file, true);
349                         
350                         context.Request.ReleaseResources ();
351                         context.Response.ReleaseResources ();
352                         HttpContext.Current = null;
353                         HttpApplication.requests_total_counter.Increment ();
354                         
355                         return true;
356                 }
357
358                 static void AppOfflineFileRenamed (object sender, RenamedEventArgs args)
359                 {
360                         AppOfflineFileChanged (sender, args);
361                 }
362
363                 static void AppOfflineFileChanged (object sender, FileSystemEventArgs args)
364                 {
365                         lock (appOfflineLock) {
366                                 bool offline;
367                                 
368                                 switch (args.ChangeType) {
369                                         case WatcherChangeTypes.Created:
370                                         case WatcherChangeTypes.Changed:
371                                                 offline = true;
372                                                 break;
373
374                                         case WatcherChangeTypes.Deleted:
375                                                 offline = false;
376                                                 break;
377
378                                         case WatcherChangeTypes.Renamed:
379                                                 RenamedEventArgs rargs = args as RenamedEventArgs;
380
381                                                 if (rargs != null &&
382                                                     String.Compare (rargs.Name, "app_offline.htm", StringComparison.OrdinalIgnoreCase) == 0)
383                                                         offline = true;
384                                                 else
385                                                         offline = false;
386                                                 break;
387
388                                         default:
389                                                 offline = false;
390                                                 break;
391                                 }
392                                 SetOfflineMode (offline, args.FullPath);
393                         }
394                 }
395
396                 static void SetOfflineMode (bool offline, string filePath)
397                 {
398                         if (!offline) {
399                                 app_offline_file = null;
400                                 if (HttpApplicationFactory.ApplicationDisabled)
401                                         HttpRuntime.UnloadAppDomain ();
402                         } else {
403                                 app_offline_file = filePath;
404                                 HttpApplicationFactory.DisableWatchers ();
405                                 HttpApplicationFactory.ApplicationDisabled = true;
406                                 InternalCache.InvokePrivateCallbacks ();
407                                 HttpApplicationFactory.Dispose ();
408                         }
409                 }
410                 
411                 static void SetupOfflineWatch ()
412                 {
413                         lock (appOfflineLock) {
414                                 FileSystemEventHandler seh = new FileSystemEventHandler (AppOfflineFileChanged);
415                                 RenamedEventHandler reh = new RenamedEventHandler (AppOfflineFileRenamed);
416
417                                 string app_dir = AppDomainAppPath;
418                                 ArrayList watchers = new ArrayList ();
419                                 FileSystemWatcher watcher;
420                                 string offlineFile = null, tmp;
421                                 
422                                 foreach (string f in app_offline_files) {
423                                         watcher = new FileSystemWatcher ();
424                                         watcher.Path = Path.GetDirectoryName (app_dir);
425                                         watcher.Filter = Path.GetFileName (f);
426                                         watcher.NotifyFilter |= NotifyFilters.Size;
427                                         watcher.Deleted += seh;
428                                         watcher.Changed += seh;
429                                         watcher.Created += seh;
430                                         watcher.Renamed += reh;
431                                         watcher.EnableRaisingEvents = true;
432                                         
433                                         watchers.Add (watcher);
434
435                                         tmp = Path.Combine (app_dir, f);
436                                         if (File.Exists (tmp))
437                                                 offlineFile = tmp;
438                                 }
439
440                                 if (offlineFile != null)
441                                         SetOfflineMode (true, offlineFile);
442                         }
443                 }
444 #endif
445                 
446                 static void RealProcessRequest (object o)
447                 {
448                         if (domainUnloading) {
449                                 Console.Error.WriteLine ("Domain is unloading, not processing the request.");
450                                 return;
451                         }
452
453                         HttpWorkerRequest req = (HttpWorkerRequest) o;
454                         bool started_internally = req.StartedInternally;
455                         do {
456                                 Process (req);
457                                 req = QueuePendingRequest (started_internally);
458                         } while (started_internally && req != null);
459                 }
460
461                 static void Process (HttpWorkerRequest req)
462                 {
463 #if TARGET_J2EE
464                         HttpContext context = HttpContext.Current;
465                         if (context == null)
466                                 context = new HttpContext (req);
467                         else
468                                 context.SetWorkerRequest (req);
469 #else
470                         HttpContext context = new HttpContext (req);
471 #endif
472                         HttpContext.Current = context;
473                         bool error = false;
474 #if !TARGET_J2EE
475                         if (firstRun) {
476                                 SetupOfflineWatch ();
477                                 firstRun = false;
478                                 if (initialException != null) {
479                                         FinishWithException (req, HttpException.NewWithCode ("Initial exception", initialException, WebEventCodes.RuntimeErrorRequestAbort));
480                                         error = true;
481                                 }
482                         }
483
484                         if (AppIsOffline (context))
485                                 return;
486 #endif
487                         
488                         //
489                         // Get application instance (create or reuse an instance of the correct class)
490                         //
491                         HttpApplication app = null;
492                         if (!error) {
493                                 try {
494                                         app = HttpApplicationFactory.GetApplication (context);
495                                 } catch (Exception e) {
496                                         FinishWithException (req, HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort));
497                                         error = true;
498                                 }
499                         }
500                         
501                         if (error) {
502                                 context.Request.ReleaseResources ();
503                                 context.Response.ReleaseResources ();
504                                 HttpContext.Current = null;
505                         } else {
506                                 context.ApplicationInstance = app;
507                                 req.SetEndOfSendNotification (end_of_send_cb, context);
508
509                                 //
510                                 // Ask application to service the request
511                                 //
512                                 
513 #if TARGET_J2EE
514                                 IHttpAsyncHandler ihah = app;
515                                 if (context.Handler == null)
516                                         ihah.BeginProcessRequest (context, new AsyncCallback (request_processed), context);
517                                 else
518                                         app.Tick ();
519                                 //ihh.ProcessRequest (context);
520                                 IHttpExtendedHandler extHandler = context.Handler as IHttpExtendedHandler;
521                                 if (extHandler != null && !extHandler.IsCompleted)
522                                         return;
523                                 if (context.Error is UnifyRequestException)
524                                         return;
525
526                                 ihah.EndProcessRequest (null);
527 #else
528                                 IHttpHandler ihh = app;
529 //                              IAsyncResult appiar = ihah.BeginProcessRequest (context, new AsyncCallback (request_processed), context);
530 //                              ihah.EndProcessRequest (appiar);
531                                 ihh.ProcessRequest (context);
532 #endif
533
534                                 HttpApplicationFactory.Recycle (app);
535                         }
536                 }
537
538                 static void EndOfSend (HttpWorkerRequest ignored1, object ignored2)
539                 {
540                 }
541
542                 //
543                 // ProcessRequest method is executed in the AppDomain of the application
544                 //
545                 // Observations:
546                 //    ProcessRequest does not guarantee that `wr' will be processed synchronously,
547                 //    the request can be queued and processed later.
548                 //
549                 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
550                 public static void ProcessRequest (HttpWorkerRequest wr)
551                 {
552                         if (wr == null)
553                                 throw new ArgumentNullException ("wr");
554                         //
555                         // Queue our request, fetch the next available one from the queue
556                         //
557                         HttpWorkerRequest request = queue_manager.GetNextRequest (wr);
558                         if (request == null)
559                                 return;
560
561                         QueuePendingRequest (false);
562                         RealProcessRequest (request);
563                 }
564
565 #if TARGET_J2EE
566                 //
567                 // Callback to be invoked by IHttpAsyncHandler.BeginProcessRequest
568                 //
569                 static void request_processed (IAsyncResult iar)
570                 {
571                         HttpContext context = (HttpContext) iar.AsyncState;
572
573                         context.Request.ReleaseResources ();
574                         context.Response.ReleaseResources ();
575                 }
576 #endif
577                 
578 #if TARGET_JVM
579                 [MonoNotSupported ("UnloadAppDomain is not supported")]
580                 public static void UnloadAppDomain ()
581                 {
582                         throw new NotImplementedException ("UnloadAppDomain is not supported");
583                 }
584 #else
585                 //
586                 // Called when we are shutting down or we need to reload an application
587                 // that has been modified (touch global.asax) 
588                 //
589                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
590                 public static void UnloadAppDomain ()
591                 {
592                         //
593                         // TODO: call ReleaseResources
594                         //
595                         domainUnloading = true;
596                         HttpApplicationFactory.DisableWatchers ();
597                         ThreadPool.QueueUserWorkItem (delegate {
598                                 try {
599                                         ShutdownAppDomain ();
600                                 } catch (Exception e){
601                                         Console.Error.WriteLine (e);
602                                 }
603                         });
604                 }
605 #endif
606                 //
607                 // Shuts down the AppDomain
608                 //
609                 static void ShutdownAppDomain ()
610                 {
611                         queue_manager.Dispose ();
612                         // This will call Session_End if needed.
613                         InternalCache.InvokePrivateCallbacks ();
614                         // Kill our application.
615                         HttpApplicationFactory.Dispose ();
616                         ThreadPool.QueueUserWorkItem (delegate {
617                                 try {
618                                         DoUnload ();
619                                 } catch {
620                                 }});
621                 }
622
623                 static void DoUnload ()
624                 {
625 #if TARGET_J2EE
626                         // No unload support for appdomains under Grasshopper
627 #else
628                         AppDomain.Unload (AppDomain.CurrentDomain);
629 #endif
630                 }
631
632                 static string content503 = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" +
633                         "<html><head>\n<title>503 Server Unavailable</title>\n</head><body>\n" +
634                         "<h1>Server Unavailable</h1>\n" +
635                         "</body></html>\n";
636
637                 static void FinishWithException (HttpWorkerRequest wr, HttpException e)
638                 {
639                         int code = e.GetHttpCode ();
640                         wr.SendStatus (code, HttpWorkerRequest.GetStatusDescription (code));
641                         wr.SendUnknownResponseHeader ("Connection", "close");
642                         Encoding enc = Encoding.ASCII;
643                         wr.SendUnknownResponseHeader ("Content-Type", "text/html; charset=" + enc.WebName);
644                         string msg = e.GetHtmlErrorMessage ();
645                         byte [] contentBytes = enc.GetBytes (msg);
646                         wr.SendUnknownResponseHeader ("Content-Length", contentBytes.Length.ToString ());
647                         wr.SendResponseFromMemory (contentBytes, contentBytes.Length);
648                         wr.FlushResponse (true);
649                         wr.CloseConnection ();
650                         HttpApplication.requests_total_counter.Increment ();
651                 }
652
653                 //
654                 // This is called from the QueueManager if a request
655                 // can not be processed (load, no resources, or
656                 // appdomain unload).
657                 //
658                 static internal void FinishUnavailable (HttpWorkerRequest wr)
659                 {
660                         wr.SendStatus (503, "Service unavailable");
661                         wr.SendUnknownResponseHeader ("Connection", "close");
662                         Encoding enc = Encoding.ASCII;
663                         wr.SendUnknownResponseHeader ("Content-Type", "text/html; charset=" + enc.WebName);
664                         byte [] contentBytes = enc.GetBytes (content503);
665                         wr.SendUnknownResponseHeader ("Content-Length", contentBytes.Length.ToString ());
666                         wr.SendResponseFromMemory (contentBytes, contentBytes.Length);
667                         wr.FlushResponse (true);
668                         wr.CloseConnection ();
669                         HttpApplication.requests_total_counter.Increment ();
670                 }
671
672                 [AspNetHostingPermissionAttribute(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Unrestricted)]
673                 [MonoDocumentationNote ("Always returns null on Mono")]
674                 public static NamedPermissionSet GetNamedPermissionSet ()
675                 {
676                         return null;
677                 }
678                 
679 #if !TARGET_J2EE
680                 static internal void WritePreservationFile (Assembly asm, string genericNameBase)
681                 {
682                         if (asm == null)
683                                 throw new ArgumentNullException ("asm");
684                         if (String.IsNullOrEmpty (genericNameBase))
685                                 throw new ArgumentNullException ("genericNameBase");
686
687                         string compiled = Path.Combine (AppDomain.CurrentDomain.SetupInformation.DynamicBase,
688                                                         genericNameBase + ".compiled");
689                         PreservationFile pf = new PreservationFile ();
690                         try {
691                                 pf.VirtualPath = String.Concat ("/", genericNameBase, "/");
692
693                                 AssemblyName an = asm.GetName ();
694                                 pf.Assembly = an.Name;
695                                 pf.ResultType = BuildResultTypeCode.TopLevelAssembly;
696                                 pf.Save (compiled);
697                         } catch (Exception ex) {
698                                 throw new HttpException (
699                                         String.Format ("Failed to write preservation file {0}", genericNameBase + ".compiled"),
700                                         ex);
701                         }
702                 }
703                 
704                 static Assembly ResolveAssemblyHandler(object sender, ResolveEventArgs e)
705                 {
706                         AssemblyName an = new AssemblyName (e.Name);
707                         string dynamic_base = AppDomain.CurrentDomain.SetupInformation.DynamicBase;
708                         string compiled = Path.Combine (dynamic_base, an.Name + ".compiled");
709
710                         if (!File.Exists (compiled))
711                                 return null;
712
713                         PreservationFile pf;
714                         try {
715                                 pf = new PreservationFile (compiled);
716                         } catch (Exception ex) {
717                                 throw new HttpException (
718                                         String.Format ("Failed to read preservation file {0}", an.Name + ".compiled"),
719                                         ex);
720                         }
721                         
722                         Assembly ret = null;
723                         try {
724                                 string asmPath = Path.Combine (dynamic_base, pf.Assembly + ".dll");
725                                 ret = Assembly.LoadFrom (asmPath);
726                         } catch (Exception) {
727                                 // ignore
728                         }
729                         
730                         return ret;
731                 }
732                 
733                 internal static void EnableAssemblyMapping (bool enable)
734                 {
735                         lock (assemblyMappingLock) {
736                                 if (assemblyMappingEnabled == enable)
737                                         return;
738                                 if (enable)
739                                         AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler (ResolveAssemblyHandler);
740                                 else
741                                         AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler (ResolveAssemblyHandler);
742                                 assemblyMappingEnabled = enable;
743                         }
744                 }
745 #endif // #if !TARGET_J2EE
746                 
747                 internal static TraceManager TraceManager {
748                         get {
749                                 return trace_manager;
750                         }
751                 }
752         }
753 }