2007-07-21 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.Hosting / ApplicationHost.cs
index 25dab77ee24c83e79789b0a39e81c6dc70eb68c0..0159bbb4fe22253e3e1e36c25dc42189bb579c91 100644 (file)
@@ -1,12 +1,11 @@
 //
-// System.Web.Hosting.ApplicationHost
+// System.Web.Hosting.ApplicationHost.cs 
+// 
+// Author:
+//     Miguel de Icaza (miguel@novell.com)
 //
-// Authors:
-//     Patrik Torstensson (Patrik.Torstensson@labs2.com)
-//     (class signature from Bob Smith <bob@thestuff.net> (C) )
-//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
 //
-
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-using System;
-using System.Collections;
+
 using System.IO;
-using System.Runtime.Remoting;
-using System.Web.Util;
-
-namespace System.Web.Hosting
-{
-       public sealed class ApplicationHost
-       {
-               internal class ConfigInitHelper : MarshalByRefObject
+using System.Security.Permissions;
+using System.Security.Policy;
+
+namespace System.Web.Hosting {
+
+       // CAS - no InheritanceDemand here as the class is sealed
+       [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
+       public sealed class ApplicationHost {
+
+               static string [] types = { "Web.config", "Web.Config", "web.config" };
+
+               private ApplicationHost ()
+               {
+               }
+
+               static string FindWebConfig (string basedir)
                {
-                       internal void InitConfig ()
-                       {
+                       string r = null;
+                               
+                       foreach (string s in types){
+                               r = Path.Combine (basedir, s);
+
+                               if (File.Exists (r))
+                                       return r;
+                       }
+                       // default: return the last one
+                       return r;
+               }
+
+#if NET_2_0
+               static object create_dir = new object ();
+#endif
+
+               internal static bool ClearDynamicBaseDirectory (string directory)
+               {
+                       string[] entries = null;
+                       
+                       try {
+                               entries = Directory.GetDirectories (directory);
+                       } catch {
+                               // ignore
+                       }
+
+                       bool dirEmpty = true;
+                       if (entries != null && entries.Length > 0) {
+                               foreach (string e in entries) {
+                                       if (ClearDynamicBaseDirectory (e)) {
+                                               try {
+                                                       Directory.Delete (e);
+                                               } catch {
+                                                       dirEmpty = false;
+                                               }
+                                       }
+                               }
+                       }
+
+                       try {
+                               entries = Directory.GetFiles (directory);
+                       } catch {
+                               entries = null;
                        }
+
+                       if (entries != null && entries.Length > 0) {
+                               foreach (string e in entries) {
+                                       try {
+                                               File.Delete (e);
+                                       } catch {
+                                               dirEmpty = false;
+                                       }
+                               }
+                       }
+
+                       return dirEmpty;
                }
                
-               private ApplicationHost ()
+               static bool CreateDirectory (string directory)
                {
+#if NET_2_0
+                       lock (create_dir) {
+#endif
+                               if (!Directory.Exists (directory)) {
+                                       Directory.CreateDirectory (directory);
+                                       return false;
+                               } else
+                                       return true;
+#if NET_2_0
+                       }
+#endif
                }
 
-               public static object CreateApplicationHost (Type hostType,
-                                                           string virtualDir,
-                                                           string physicalDir)
+               static string GetBinPath (string physicalDir)
                {
+                       string ret = Path.Combine (physicalDir, "Bin");
+                       if (Directory.Exists (ret))
+                               return ret;
+                       ret = Path.Combine (physicalDir, "bin");
+                       return ret;
+               }
+               
+               //
+               // For further details see `Hosting the ASP.NET runtime'
+               //
+               //    http://www.west-wind.com/presentations/aspnetruntime/aspnetruntime.asp
+               // 
+#if TARGET_JVM
+               [MonoNotSupported ("")]
+#endif
+               [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
+               public static object CreateApplicationHost (Type hostType, string virtualDir, string physicalDir)
+               {
+                       if (physicalDir == null)
+                               throw new NullReferenceException ();
+
+                       // Make sure physicalDir has file system semantics
+                       // and not uri semantics ( '\' and not '/' ).
+                       physicalDir = Path.GetFullPath (physicalDir);
+
                        if (hostType == null)
-                               throw new ArgumentException ("hostType");
+                               throw new ArgumentException ("hostType can't be null");
+
+                       if (virtualDir == null)
+                               throw new ArgumentNullException ("virtualDir");
 
-                       if (virtualDir == null || virtualDir.Length == 0)
-                               throw new ArgumentException ("virtualDir");
+                       Evidence evidence = new Evidence (AppDomain.CurrentDomain.Evidence);
                        
-                       if (physicalDir == null || physicalDir.Length == 0)
-                               throw new ArgumentException ("physicalDir");
+                       //
+                       // Setup
+                       //
+                       AppDomainSetup setup = new AppDomainSetup ();
 
-                       if (physicalDir [physicalDir.Length - 1] != Path.DirectorySeparatorChar)
-                               physicalDir += Path.DirectorySeparatorChar;
+                       setup.ApplicationBase = physicalDir;
+
+                       setup.CachePath = null;
+                       setup.ConfigurationFile = FindWebConfig (physicalDir);
+                       setup.DisallowCodeDownload = true;
+                       string bin_path = GetBinPath (physicalDir);
+                       setup.PrivateBinPath = bin_path;
+                       setup.PrivateBinPathProbe = "*";
+                       setup.ShadowCopyFiles = "true";
+                       setup.ShadowCopyDirectories = bin_path;
 
-                       int nowInt = DateTime.Now.ToString ().GetHashCode ();
-                       string nowHash = nowInt.ToString ("x");
-                       nowInt += physicalDir.GetHashCode ();
-                       string sum = nowInt.ToString ("x");
-                       Hashtable hTable = new Hashtable ();
-                       AppDomainSetup domainSetup = new AppDomainSetup();
-
-                       AppDomainFactory.PopulateDomainBindings (nowHash,
-                                                                sum,
-                                                                sum,
-                                                                physicalDir,
-                                                                virtualDir,
-                                                                domainSetup,
-                                                                hTable);
+                       string dynamic_dir = null;
+                       string user = Environment.UserName;
+                       int tempDirTag = 0;
                        
-                       AppDomain domain = AppDomain.CreateDomain (nowHash, null, domainSetup);
-                       foreach (string key in hTable.Keys)
-                               domain.SetData (key, (string) hTable [key]);
-
-                       domain.SetData (".hostingVirtualPath", virtualDir);
-                       domain.SetData (".hostingInstallDir", ICalls.GetMachineInstallDirectory ());
-                       InitConfigInNewAppDomain (domain);
-                       ObjectHandle o = domain.CreateInstance (hostType.Assembly.FullName,
-                                                               hostType.FullName);
-                       return o.Unwrap();
-               }
+                       for (int i = 0; ; i++){
+                               string d = Path.Combine (Path.GetTempPath (),
+                                       String.Format ("{0}-temp-aspnet-{1:x}", user, i));
+                       
+                               try {
+                                       CreateDirectory (d);
+                                       string stamp = Path.Combine (d, "stamp");
+                                       CreateDirectory (stamp);
+                                       dynamic_dir = d;
+                                       Directory.Delete (stamp);
+                                       tempDirTag = i.GetHashCode ();
+                                       break;
+                               } catch (UnauthorizedAccessException){
+                                       continue;
+                               }
+                       }
+                       // 
+                       // Unique Domain ID
+                       //
+                       string domain_id = (virtualDir.GetHashCode () ^ physicalDir.GetHashCode () ^ tempDirTag).ToString ("x");
 
-               private static void InitConfigInNewAppDomain (AppDomain appDomain)
-               {
-                       Type t = typeof (ConfigInitHelper);
-                       ObjectHandle o = appDomain.CreateInstance (t.Assembly.FullName, t.FullName);
-                       ConfigInitHelper helper = (ConfigInitHelper) o.Unwrap();
-                       helper.InitConfig ();
+                       setup.ApplicationName = domain_id;
+                       setup.DynamicBase = dynamic_dir;
+
+                       string dynamic_base = setup.DynamicBase;
+                       if (CreateDirectory (dynamic_base) && (Environment.GetEnvironmentVariable ("MONO_ASPNET_NODELETE") == null))
+                               ClearDynamicBaseDirectory (dynamic_base);
+
+                       //
+                       // Create app domain
+                       //
+                       AppDomain appdomain;
+                       appdomain = AppDomain.CreateDomain (domain_id, evidence, setup);
+
+                       //
+                       // Populate with the AppDomain data keys expected, Mono only uses a
+                       // few, but third party apps might use others:
+                       //
+                       appdomain.SetData (".appDomain", "*");
+                       int l = physicalDir.Length;
+                       if (physicalDir [l - 1] != Path.DirectorySeparatorChar)
+                               physicalDir += Path.DirectorySeparatorChar;
+                       appdomain.SetData (".appPath", physicalDir);
+                       appdomain.SetData (".appVPath", virtualDir);
+                       appdomain.SetData (".domainId", domain_id);
+                       appdomain.SetData (".hostingVirtualPath", virtualDir);
+                       appdomain.SetData (".hostingInstallDir", Path.GetDirectoryName (typeof (Object).Assembly.CodeBase));
+#if NET_2_0
+                       appdomain.SetData ("DataDirectory", Path.Combine (physicalDir, "App_Data"));
+#endif
+                       return appdomain.CreateInstanceAndUnwrap (hostType.Module.Assembly.FullName, hostType.FullName);
                }
        }
 }
-