importing messaging-2008 branch to trunk.
[mono.git] / mcs / class / System.Web / System.Web / HttpRuntime.cs
1 //
2 // System.Web.HttpRuntime.cs 
3 // 
4 // Author:
5 //      Miguel de Icaza (miguel@novell.com)
6 //
7 //
8 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 //
31 // TODO: Call HttpRequest.CloseInputStream when we finish a request, as we are using the IntPtr stream.
32 //
33 using System.IO;
34 using System.Text;
35 using System.Globalization;
36 using System.Collections;
37 using System.Reflection;
38 using System.Security;
39 using System.Security.Permissions;
40 using System.Web.Caching;
41 using System.Web.Configuration;
42 using System.Web.UI;
43 using System.Web.Util;
44 #if MONOWEB_DEP
45 using Mono.Web.Util;
46 #endif
47 using System.Threading;
48 #if TARGET_J2EE
49 using Mainsoft.Web;
50 #endif
51
52 #if NET_2_0 && !TARGET_JVM
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                 static bool caseInsensitive;
63                 static bool runningOnWindows;
64                 static bool isunc;
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 Exception initialException;
118                 static bool firstRun;
119                 
120 #if NET_2_0
121                 static bool assemblyMappingEnabled;
122                 static object assemblyMappingLock = new object ();
123                 static object appOfflineLock = new object ();
124 #endif
125                 
126 #if ONLY_1_1
127                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
128 #endif
129                 public HttpRuntime ()
130                 {
131
132                 }
133 #endif
134
135                 static HttpRuntime ()
136                 {
137                         PlatformID pid = Environment.OSVersion.Platform;
138                         runningOnWindows = ((int) pid != 128
139 #if NET_2_0
140                                             && pid != PlatformID.Unix && pid != PlatformID.MacOSX
141 #endif
142                         );
143
144                         if (runningOnWindows) {
145                                 caseInsensitive = true;
146                                 isunc = new Uri (AppDomainAppPath).IsUnc;
147                         } else {
148                                 string mono_iomap = Environment.GetEnvironmentVariable ("MONO_IOMAP");
149                                 if (mono_iomap != null) {
150                                         if (mono_iomap == "all")
151                                                 caseInsensitive = true;
152                                         else {
153                                                 string[] parts = mono_iomap.Split (':');
154                                                 foreach (string p in parts) {
155                                                         if (p == "all" || p == "case") {
156                                                                 caseInsensitive = true;
157                                                                 break;
158                                                         }
159                                                 }
160                                         }
161                                 }
162                         }
163                         
164 #if !TARGET_J2EE
165                         firstRun = true;
166 #if NET_2_0
167                         try {
168                                 WebConfigurationManager.Init ();
169 #if MONOWEB_DEP
170                                 SettingsMappingManager.Init ();
171 #endif
172                         } catch (Exception ex) {
173                                 initialException = ex;
174                         }
175 #endif
176
177                         // The classes in whose constructors exceptions may be thrown, should be handled the same way QueueManager
178                         // and TraceManager are below. The constructors themselves MUST NOT throw any exceptions - we MUST be sure
179                         // the objects are created here. The exceptions will be dealt with below, in RealProcessRequest.
180                         queue_manager = new QueueManager ();
181                         if (queue_manager.HasException)
182                                 initialException = queue_manager.InitialException;
183
184                         trace_manager = new TraceManager ();
185                         if (trace_manager.HasException)
186                                         initialException = trace_manager.InitialException;
187
188                         cache = new Cache ();
189                         internalCache = new Cache ();
190                         internalCache.DependencyCache = cache;
191 #endif
192                         do_RealProcessRequest = new WaitCallback (RealProcessRequest);
193                 }
194                 
195 #region AppDomain handling
196                 //
197                 // http://radio.weblogs.com/0105476/stories/2002/07/12/executingAspxPagesWithoutAWebServer.html
198                 //
199                 public static string AppDomainAppId {
200                         [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
201                         get {
202                                 //
203                                 // This value should not change across invocations
204                                 //
205                                 string dirname = (string) AppDomain.CurrentDomain.GetData (".appId");
206                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
207                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
208                                 }
209                                 return dirname;
210                         }
211                 }
212
213                 // Physical directory for the application
214                 public static string AppDomainAppPath {
215                         get {
216                                 string dirname = (string) AppDomain.CurrentDomain.GetData (".appPath");
217                                 if (SecurityManager.SecurityEnabled) {
218                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
219                                 }
220                                 return dirname;
221                         }
222                 }
223
224                 public static string AppDomainAppVirtualPath {
225                         get {
226                                 return (string) AppDomain.CurrentDomain.GetData (".appVPath");
227                         }
228                 }
229
230                 public static string AppDomainId {
231                         [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
232                         get {
233                                 return (string) AppDomain.CurrentDomain.GetData (".domainId");
234                         }
235                 }
236
237                 public static string AspInstallDirectory {
238                         get {
239                                 string dirname = (string) AppDomain.CurrentDomain.GetData (".hostingInstallDir");
240                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
241                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
242                                 }
243                                 return dirname;
244                         }
245                 }
246 #endregion
247
248                 static string _actual_bin_directory;
249                 public static string BinDirectory {
250                         get {
251                                 if (_actual_bin_directory == null) {
252                                         string[] parts = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath.Split (';');
253                                         string mypath = AppDomainAppPath;
254                                         string tmp;
255                                         
256                                         foreach (string p in parts) {
257                                                 tmp = Path.Combine (mypath, p);
258                                                 if (Directory.Exists (tmp)) {
259                                                         _actual_bin_directory = tmp;
260                                                         break;
261                                                 }
262                                         }
263
264                                         if (_actual_bin_directory == null)
265                                                 _actual_bin_directory = Path.Combine (mypath, "bin");
266
267                                         if (_actual_bin_directory [_actual_bin_directory.Length - 1] != Path.DirectorySeparatorChar)
268                                                 _actual_bin_directory += Path.DirectorySeparatorChar;
269                                 }
270                                 
271                                 if (SecurityManager.SecurityEnabled)
272                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, _actual_bin_directory).Demand ();
273
274                                 return _actual_bin_directory;
275                         }
276                 }
277
278                 public static Cache Cache {
279                         get {
280                                 return cache;
281                         }
282                 }
283
284                 internal static Cache InternalCache {
285                         get {
286                                 return internalCache;
287                         }
288                 }
289                 
290                 public static string ClrInstallDirectory {
291                         get {
292                                 string dirname = Path.GetDirectoryName (typeof (Object).Assembly.Location);
293                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
294                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
295                                 }
296                                 return dirname;
297                         }
298                 }
299
300                 public static string CodegenDir {
301                         get {
302                                 string dirname = AppDomain.CurrentDomain.SetupInformation.DynamicBase;
303                                 if (SecurityManager.SecurityEnabled) {
304                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
305                                 }
306                                 return dirname;
307                         }
308                 }
309
310                 public static bool IsOnUNCShare {
311                         [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Low)]
312                         get {
313                                 return isunc;
314                         }
315                 }
316
317                 public static string MachineConfigurationDirectory {
318                         get {
319                                 string dirname = Path.GetDirectoryName (ICalls.GetMachineConfigPath ());
320                                 if ((dirname != null) && (dirname.Length > 0) && SecurityManager.SecurityEnabled) {
321                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dirname).Demand ();
322                                 }
323                                 return dirname;
324                         }
325                 }
326
327                 
328                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
329                 public static void Close ()
330                 {
331                         // Remove all items from cache.
332                 }
333
334                 static void QueuePendingRequests ()
335                 {
336                         HttpWorkerRequest request = queue_manager.GetNextRequest (null);
337                         if (request == null)
338                                 return;
339                         ThreadPool.QueueUserWorkItem (do_RealProcessRequest, request);
340                 }
341
342 #if !TARGET_J2EE
343 #if NET_2_0
344                 static readonly string[] app_offline_files = {"app_offline.htm", "App_Offline.htm", "APP_OFFLINE.HTM"};
345                 static string app_offline_file;
346                 
347                 static bool AppIsOffline (HttpContext context)
348                 {
349                         if (!HttpApplicationFactory.ApplicationDisabled || app_offline_file == null)
350                                 return false;
351
352                         HttpResponse response = context.Response;
353                         response.Clear ();
354                         response.ContentType = "text/html";
355                         response.ExpiresAbsolute = DateTime.UtcNow;
356                         response.StatusCode = 503;
357                         response.TransmitFile (app_offline_file, true);
358                         
359                         context.Request.ReleaseResources ();
360                         context.Response.ReleaseResources ();
361                         HttpContext.Current = null;
362                         
363                         return true;
364                 }
365
366                 static void AppOfflineFileRenamed (object sender, RenamedEventArgs args)
367                 {
368                         AppOfflineFileChanged (sender, args);
369                 }
370
371                 static void AppOfflineFileChanged (object sender, FileSystemEventArgs args)
372                 {
373                         lock (appOfflineLock) {
374                                 bool offline;
375                                 
376                                 switch (args.ChangeType) {
377                                         case WatcherChangeTypes.Created:
378                                         case WatcherChangeTypes.Changed:
379                                                 offline = true;
380                                                 break;
381
382                                         case WatcherChangeTypes.Deleted:
383                                                 offline = false;
384                                                 break;
385
386                                         case WatcherChangeTypes.Renamed:
387                                                 RenamedEventArgs rargs = args as RenamedEventArgs;
388
389                                                 if (rargs != null &&
390                                                     String.Compare (rargs.Name, "app_offline.htm", StringComparison.OrdinalIgnoreCase) == 0)
391                                                         offline = true;
392                                                 else
393                                                         offline = false;
394                                                 break;
395
396                                         default:
397                                                 offline = false;
398                                                 break;
399                                 }
400                                 SetOfflineMode (offline, args.FullPath);
401                         }
402                 }
403
404                 static void SetOfflineMode (bool offline, string filePath)
405                 {
406                         if (!offline) {
407                                 app_offline_file = null;
408                                 if (HttpApplicationFactory.ApplicationDisabled)
409                                         HttpRuntime.UnloadAppDomain ();
410                         } else {
411                                 app_offline_file = filePath;
412                                 HttpApplicationFactory.DisableWatchers ();
413                                 HttpApplicationFactory.ApplicationDisabled = true;
414                                 InternalCache.InvokePrivateCallbacks ();
415                                 HttpApplicationFactory.Dispose ();
416                         }
417                 }
418                 
419                 static void SetupOfflineWatch ()
420                 {
421                         lock (appOfflineLock) {
422                                 FileSystemEventHandler seh = new FileSystemEventHandler (AppOfflineFileChanged);
423                                 RenamedEventHandler reh = new RenamedEventHandler (AppOfflineFileRenamed);
424
425                                 string app_dir = AppDomainAppPath;
426                                 ArrayList watchers = new ArrayList ();
427                                 FileSystemWatcher watcher;
428                                 string offlineFile = null, tmp;
429                                 
430                                 foreach (string f in app_offline_files) {
431                                         watcher = new FileSystemWatcher ();
432                                         watcher.Path = Path.GetDirectoryName (app_dir);
433                                         watcher.Filter = Path.GetFileName (f);
434                                         watcher.NotifyFilter |= NotifyFilters.Size;
435                                         watcher.Deleted += seh;
436                                         watcher.Changed += seh;
437                                         watcher.Created += seh;
438                                         watcher.Renamed += reh;
439                                         watcher.EnableRaisingEvents = true;
440                                         
441                                         watchers.Add (watcher);
442
443                                         tmp = Path.Combine (app_dir, f);
444                                         if (File.Exists (tmp))
445                                                 offlineFile = tmp;
446                                 }
447
448                                 if (offlineFile != null)
449                                         SetOfflineMode (true, offlineFile);
450                         }
451                 }
452 #endif
453 #endif
454                 
455                 static void RealProcessRequest (object o)
456                 {
457 #if TARGET_J2EE
458                         HttpContext context = HttpContext.Current;
459                         if (context == null)
460                                 context = new HttpContext ((HttpWorkerRequest) o);
461                         else
462                                 context.SetWorkerRequest ((HttpWorkerRequest) o);
463 #else
464                         HttpContext context = new HttpContext ((HttpWorkerRequest) o);
465 #endif
466                         HttpContext.Current = context;
467                         bool error = false;
468 #if !TARGET_J2EE
469                         if (firstRun) {
470 #if NET_2_0
471                                 SetupOfflineWatch ();
472 #endif
473                                 firstRun = false;
474                                 if (initialException != null) {
475                                         FinishWithException ((HttpWorkerRequest) o, new HttpException ("Initial exception", initialException));
476                                         error = true;
477                                 }
478                         }
479
480 #if NET_2_0
481                         if (AppIsOffline (context))
482                                 return;
483 #endif
484 #endif
485                         
486                         //
487                         // Get application instance (create or reuse an instance of the correct class)
488                         //
489                         HttpApplication app = null;
490                         if (!error) {
491                                 try {
492                                         app = HttpApplicationFactory.GetApplication (context);
493                                 } catch (Exception e) {
494                                         FinishWithException ((HttpWorkerRequest) o, new HttpException ("", e));
495                                         error = true;
496                                 }
497                         }
498                         
499                         if (error) {
500                                 context.Request.ReleaseResources ();
501                                 context.Response.ReleaseResources ();
502                                 HttpContext.Current = null;
503                         } else {
504                                 context.ApplicationInstance = app;
505
506                                 //
507                                 // Ask application to service the request
508                                 //
509                                 
510 #if TARGET_J2EE
511                                 IHttpAsyncHandler ihah = app;
512                                 if (context.Handler == null)
513                                         ihah.BeginProcessRequest (context, new AsyncCallback (request_processed), context);
514                                 else
515                                         app.Tick ();
516                                 //ihh.ProcessRequest (context);
517                                 IHttpExtendedHandler extHandler = context.Handler as IHttpExtendedHandler;
518                                 if (extHandler != null && !extHandler.IsCompleted)
519                                         return;
520                                 if (context.Error is UnifyRequestException)
521                                         return;
522
523                                 ihah.EndProcessRequest (null);
524 #else
525                                 IHttpHandler ihh = app;
526 //                              IAsyncResult appiar = ihah.BeginProcessRequest (context, new AsyncCallback (request_processed), context);
527 //                              ihah.EndProcessRequest (appiar);
528                                 ihh.ProcessRequest (context);
529 #endif
530
531                                 HttpApplicationFactory.Recycle (app);
532                         }
533                         
534                         QueuePendingRequests ();
535                 }
536                 
537                 //
538                 // ProcessRequest method is executed in the AppDomain of the application
539                 //
540                 // Observations:
541                 //    ProcessRequest does not guarantee that `wr' will be processed synchronously,
542                 //    the request can be queued and processed later.
543                 //
544                 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
545                 public static void ProcessRequest (HttpWorkerRequest wr)
546                 {
547                         if (wr == null)
548                                 throw new ArgumentNullException ("wr");
549                         //
550                         // Queue our request, fetch the next available one from the queue
551                         //
552                         HttpWorkerRequest request = queue_manager.GetNextRequest (wr);
553                         if (request == null)
554                                 return;
555
556                         RealProcessRequest (request);
557                 }
558
559 #if TARGET_J2EE
560                 //
561                 // Callback to be invoked by IHttpAsyncHandler.BeginProcessRequest
562                 //
563                 static void request_processed (IAsyncResult iar)
564                 {
565                         HttpContext context = (HttpContext) iar.AsyncState;
566
567                         context.Request.ReleaseResources ();
568                         context.Response.ReleaseResources ();
569                 }
570 #endif
571                 
572 #if TARGET_JVM
573                 [MonoNotSupported ("UnloadAppDomain is not supported")]
574                 public static void UnloadAppDomain ()
575                 {
576                         throw new NotImplementedException ("UnloadAppDomain is not supported");
577                 }
578 #else
579                 //
580                 // Called when we are shutting down or we need to reload an application
581                 // that has been modified (touch global.asax) 
582                 //
583                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
584                 public static void UnloadAppDomain ()
585                 {
586                         //
587                         // TODO: call ReleaseResources
588                         //
589                         ThreadPool.QueueUserWorkItem (new WaitCallback (ShutdownAppDomain), null);
590                 }
591 #endif
592                 //
593                 // Shuts down the AppDomain
594                 //
595                 static void ShutdownAppDomain (object args)
596                 {
597                         queue_manager.Dispose ();
598                         // This will call Session_End if needed.
599                         InternalCache.InvokePrivateCallbacks ();
600                         // Kill our application.
601                         HttpApplicationFactory.Dispose ();
602                         ThreadPool.QueueUserWorkItem (new WaitCallback (DoUnload), null);
603                 }
604
605                 static void DoUnload (object state)
606                 {
607                         if (Environment.GetEnvironmentVariable ("MONO_ASPNET_NODELETE") == null)
608                                 System.Web.Hosting.ApplicationHost.ClearDynamicBaseDirectory (
609                                         AppDomain.CurrentDomain.SetupInformation.DynamicBase
610                                 );
611 #if TARGET_J2EE
612                         // No unload support for appdomains under Grasshopper
613 #else
614                         AppDomain.Unload (AppDomain.CurrentDomain);
615 #endif
616                 }
617
618                 static string content503 = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" +
619                         "<html><head>\n<title>503 Server Unavailable</title>\n</head><body>\n" +
620                         "<h1>Server Unavailable</h1>\n" +
621                         "</body></html>\n";
622
623                 static void FinishWithException (HttpWorkerRequest wr, HttpException e)
624                 {
625                         int code = e.GetHttpCode ();
626                         wr.SendStatus (code, HttpWorkerRequest.GetStatusDescription (code));
627                         wr.SendUnknownResponseHeader ("Connection", "close");
628                         Encoding enc = Encoding.ASCII;
629                         wr.SendUnknownResponseHeader ("Content-Type", "text/html; charset=" + enc.WebName);
630                         string msg = e.GetHtmlErrorMessage ();
631                         byte [] contentBytes = enc.GetBytes (msg);
632                         wr.SendUnknownResponseHeader ("Content-Length", contentBytes.Length.ToString ());
633                         wr.SendResponseFromMemory (contentBytes, contentBytes.Length);
634                         wr.FlushResponse (true);
635                         wr.CloseConnection ();
636                 }
637
638                 //
639                 // This is called from the QueueManager if a request
640                 // can not be processed (load, no resources, or
641                 // appdomain unload).
642                 //
643                 static internal void FinishUnavailable (HttpWorkerRequest wr)
644                 {
645                         wr.SendStatus (503, "Service unavailable");
646                         wr.SendUnknownResponseHeader ("Connection", "close");
647                         Encoding enc = Encoding.ASCII;
648                         wr.SendUnknownResponseHeader ("Content-Type", "text/html; charset=" + enc.WebName);
649                         byte [] contentBytes = enc.GetBytes (content503);
650                         wr.SendUnknownResponseHeader ("Content-Length", contentBytes.Length.ToString ());
651                         wr.SendResponseFromMemory (contentBytes, contentBytes.Length);
652                         wr.FlushResponse (true);
653                         wr.CloseConnection ();
654                 }
655
656 #if NET_2_0 
657 #if !TARGET_J2EE
658                 static internal void WritePreservationFile (Assembly asm, string genericNameBase)
659                 {
660                         if (asm == null)
661                                 throw new ArgumentNullException ("asm");
662                         if (String.IsNullOrEmpty (genericNameBase))
663                                 throw new ArgumentNullException ("genericNameBase");
664
665                         string compiled = Path.Combine (AppDomain.CurrentDomain.SetupInformation.DynamicBase,
666                                                         genericNameBase + ".compiled");
667                         PreservationFile pf = new PreservationFile ();
668                         try {
669                                 pf.VirtualPath = String.Concat ("/", genericNameBase, "/");
670
671                                 AssemblyName an = asm.GetName ();
672                                 pf.Assembly = an.Name;
673                                 pf.ResultType = BuildResultTypeCode.TopLevelAssembly;
674                                 pf.Save (compiled);
675                         } catch (Exception ex) {
676                                 throw new HttpException (
677                                         String.Format ("Failed to write preservation file {0}", genericNameBase + ".compiled"),
678                                         ex);
679                         }
680                 }
681                 
682                 static Assembly ResolveAssemblyHandler(object sender, ResolveEventArgs e)
683                 {
684                         AssemblyName an = new AssemblyName (e.Name);
685                         string dynamic_base = AppDomain.CurrentDomain.SetupInformation.DynamicBase;
686                         string compiled = Path.Combine (dynamic_base, an.Name + ".compiled");
687
688                         if (!File.Exists (compiled))
689                                 return null;
690
691                         PreservationFile pf;
692                         try {
693                                 pf = new PreservationFile (compiled);
694                         } catch (Exception ex) {
695                                 throw new HttpException (
696                                         String.Format ("Failed to read preservation file {0}", an.Name + ".compiled"),
697                                         ex);
698                         }
699                         
700                         Assembly ret = null;
701                         try {
702                                 string asmPath = Path.Combine (dynamic_base, pf.Assembly + ".dll");
703                                 ret = Assembly.LoadFrom (asmPath);
704                         } catch (Exception) {
705                                 // ignore
706                         }
707                         
708                         return ret;
709                 }
710                 
711                 internal static void EnableAssemblyMapping (bool enable)
712                 {
713                         lock (assemblyMappingLock) {
714                                 if (assemblyMappingEnabled == enable)
715                                         return;
716                                 if (enable)
717                                         AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler (ResolveAssemblyHandler);
718                                 else
719                                         AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler (ResolveAssemblyHandler);
720                         }
721                 }
722 #endif // #if !TARGET_J2EE
723 #endif
724                 internal static bool RunningOnWindows {
725                         get { return runningOnWindows; }
726                 }
727
728                 internal static bool CaseInsensitive {
729                         get { return caseInsensitive; }
730                 }
731
732         
733                 internal static TraceManager TraceManager {
734                         get {
735                                 return trace_manager;
736                         }
737                 }
738         }
739 }