Merge pull request #5002 from BrzVlad/feature-sgen-modes
[mono.git] / mcs / class / System.Web / System.Web.Configuration_2.0 / WebConfigurationHost.cs
index 2de223f764646d9a82ddc15b13dcf17c6265c1ac..85942d311a41401ea76c73d6ac30d9fde70dd1c4 100644 (file)
@@ -3,6 +3,7 @@
 //
 // Authors:
 //  Lluis Sanchez Gual (lluis@novell.com)
+//  Marek Habersack <mhabersack@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.
 //
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
 //
 
-#if NET_2_0
 
 using System;
+using System.Collections;
 using System.IO;
 using System.Security;
 using System.Configuration;
 using System.Configuration.Internal;
+using System.Web.Hosting;
 using System.Web.Util;
 using System.Reflection;
 
@@ -53,6 +55,8 @@ namespace System.Web.Configuration
                WebConfigurationFileMap map;
                const string MachinePath = ":machine:";
                const string MachineWebPath = ":web:";
+
+               string appVirtualPath;
                
                public virtual object CreateConfigurationContext (string configPath, string locationSubPath)
                {
@@ -65,12 +69,15 @@ namespace System.Web.Configuration
                
                public virtual object CreateDeprecatedConfigContext (string configPath)
                {
-                       throw new NotImplementedException ();
+                       return new HttpConfigurationContext(configPath);
                }
                
                public virtual string DecryptSection (string encryptedXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedSection)
                {
-                       throw new NotImplementedException ();
+                       if (protectedSection == null)
+                               throw new ArgumentNullException ("protectedSection");
+
+                       return protectedSection.EncryptSection (encryptedXml, protectionProvider);
                }
                
                public virtual void DeleteStream (string streamName)
@@ -78,54 +85,32 @@ namespace System.Web.Configuration
                        File.Delete (streamName);
                }
                
-               public virtual string EncryptSection (string encryptedXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedSection)
-               {
-                       throw new NotImplementedException ();
-               }
-               
-               public virtual string GetConfigPathFromLocationSubPath (string configPath, string locatinSubPath)
+               public virtual string EncryptSection (string clearXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedSection)
                {
-                       return configPath + "/" + locatinSubPath;
-               }
-
-               private static string privateBinPath;
+                       if (protectedSection == null)
+                               throw new ArgumentNullException ("protectedSection");
 
-               private static string PrivateBinPath {
-                       get {
-                               if (privateBinPath != null)
-                                       return privateBinPath;
-                               
-                               AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
-                               privateBinPath = Path.Combine(setup.ApplicationBase, setup.PrivateBinPath);
-                               return privateBinPath;
-                       }
+                       return protectedSection.EncryptSection (clearXml, protectionProvider);
                }
                
-               private Type LoadType(string typeName)
+               public virtual string GetConfigPathFromLocationSubPath (string configPath, string locationSubPath)
                {
-                       Type type = Type.GetType (typeName);
-                       if (type != null)
-                               return type;
-
-                       if (!Directory.Exists (PrivateBinPath))
-                               return null;
-                       
-                       string[] binDlls = Directory.GetFiles(PrivateBinPath, "*.dll");
-                       foreach (string s in binDlls) {
-                               Assembly binA = Assembly.LoadFrom (s);
-                               type = binA.GetType (typeName);
-                               if (type == null)
-                                       continue;
-                               
-                               return type;
+                       if (!String.IsNullOrEmpty (locationSubPath) && !String.IsNullOrEmpty (configPath)) {
+                               string relConfigPath = configPath.Length == 1 ? null : configPath.Substring (1) + "/";
+                               if (relConfigPath != null && locationSubPath.StartsWith (relConfigPath, StringComparison.Ordinal))
+                                       locationSubPath = locationSubPath.Substring (relConfigPath.Length);
                        }
                        
-                       return null;
+                       string ret = configPath + "/" + locationSubPath;
+                       if (!String.IsNullOrEmpty (ret) && ret [0] == '/')
+                               return ret.Substring (1);
+                       
+                       return ret;
                }
                
                public virtual Type GetConfigType (string typeName, bool throwOnError)
                {
-                       Type type = LoadType(typeName);
+                       Type type = HttpApplication.LoadType (typeName);
                        if (type == null && throwOnError)
                                throw new ConfigurationErrorsException ("Type not found: '" + typeName + "'");
                        return type;
@@ -136,7 +121,8 @@ namespace System.Web.Configuration
                        return t.AssemblyQualifiedName;
                }
                
-               public virtual void GetRestrictedPermissions (IInternalConfigRecord configRecord, out PermissionSet permissionSet, out bool isHostReady)
+               public virtual void GetRestrictedPermissions (IInternalConfigRecord configRecord, out PermissionSet permissionSet,
+                                                             out bool isHostReady)
                {
                        throw new NotImplementedException ();
                }
@@ -152,11 +138,7 @@ namespace System.Web.Configuration
                                string mdir;
 
                                if (map == null)
-#if TARGET_JVM
-                                       return "/web.config";
-#else
                                        mdir = Path.GetDirectoryName (System.Runtime.InteropServices.RuntimeEnvironment.SystemConfigurationFile);
-#endif
                                else
                                        mdir = Path.GetDirectoryName (map.MachineConfigFilename);
 
@@ -186,36 +168,45 @@ namespace System.Web.Configuration
                {
                }
                
-               public virtual void InitForConfiguration (ref string locationSubPath, out string configPath, out string locationConfigPath, IInternalConfigRoot root, params object[] hostInitConfigurationParams)
+               public virtual void InitForConfiguration (ref string locationSubPath, out string configPath,
+                                                         out string locationConfigPath, IInternalConfigRoot root,
+                                                         params object[] hostInitConfigurationParams)
                {
                        string fullPath = (string) hostInitConfigurationParams [1];
-                       
                        map = (WebConfigurationFileMap) hostInitConfigurationParams [0];
+                       bool inAnotherApp = false;
+
+                       if ((hostInitConfigurationParams.Length > 7)
+                               && (hostInitConfigurationParams[7] is bool))
+                               inAnotherApp = (bool) hostInitConfigurationParams[7];
+
+                       if (inAnotherApp)
+                               appVirtualPath = fullPath;
+                       else
+                               appVirtualPath = HttpRuntime.AppDomainAppVirtualPath;
                        
                        if (locationSubPath == MachineWebPath) {
                                locationSubPath = MachinePath;
                                configPath = MachineWebPath;
                                locationConfigPath = null;
-                       }
-                       else if (locationSubPath == MachinePath) {
+                       } else if (locationSubPath == MachinePath) {
                                locationSubPath = null;
                                configPath = MachinePath;
                                locationConfigPath = null;
-                       }
-                       else {
-                               
+                       } else {
                                int i;
-                               if (locationSubPath == null)
+                               if (locationSubPath == null) {
                                        configPath = fullPath;
-                               else
+                                       if (configPath.Length > 1)
+                                               configPath = VirtualPathUtility.RemoveTrailingSlash (configPath);
+                               } else
                                        configPath = locationSubPath;
-
-                               if (configPath == HttpRuntime.AppDomainAppVirtualPath
-                                   || configPath == "/")
+                               
+                               if (configPath == HttpRuntime.AppDomainAppVirtualPath || configPath == "/")
                                        i = -1;
                                else
                                        i = configPath.LastIndexOf ("/");
-                               
+
                                if (i != -1) {
                                        locationConfigPath = configPath.Substring (i+1);
                                        
@@ -232,18 +223,24 @@ namespace System.Web.Configuration
                
                public string MapPath (string virtualPath)
                {
+                       if (!String.IsNullOrEmpty (virtualPath)) {
+                               if (virtualPath.StartsWith (System.Web.Compilation.BuildManager.FAKE_VIRTUAL_PATH_PREFIX, StringComparison.Ordinal))
+                                       return HttpRuntime.AppDomainAppPath;
+                       }
+                       
                        if (map != null)
                                return MapPathFromMapper (virtualPath);
-                       else if (HttpContext.Current != null
-                                && HttpContext.Current.Request != null)
+                       else if (HttpContext.Current != null && HttpContext.Current.Request != null)
                                return HttpContext.Current.Request.MapPath (virtualPath);
-                       else if (HttpRuntime.AppDomainAppVirtualPath != null && virtualPath.StartsWith (HttpRuntime.AppDomainAppVirtualPath)) {
+                       else if (HttpRuntime.AppDomainAppVirtualPath != null &&
+                                virtualPath.StartsWith (HttpRuntime.AppDomainAppVirtualPath)) {
                                if (virtualPath == HttpRuntime.AppDomainAppVirtualPath)
                                        return HttpRuntime.AppDomainAppPath;
-                               return UrlUtils.Combine (HttpRuntime.AppDomainAppPath, virtualPath.Substring (HttpRuntime.AppDomainAppVirtualPath.Length));
+                               return UrlUtils.Combine (HttpRuntime.AppDomainAppPath,
+                                                        virtualPath.Substring (HttpRuntime.AppDomainAppVirtualPath.Length));
                        }
-                       else
-                               return virtualPath;
+                       
+                       return virtualPath;
                }
                
                public string NormalizeVirtualPath (string virtualPath)
@@ -290,22 +287,31 @@ namespace System.Web.Configuration
                        throw new HttpException ("Invalid virtual directory: " + virtualPath);
                }
 
-               string GetWebConfigFileName (string dir)
+               internal static string GetWebConfigFileName (string dir)
                {
-                       string[] filenames = new string[] {"Web.Config", "Web.config", "web.config" };
+                       AppDomain domain = AppDomain.CurrentDomain;
+                       bool hosted = (domain.GetData (ApplicationHost.MonoHostedDataKey) as string) == "yes";
 
-                       foreach (string fn in filenames) {
-                               string file = Path.Combine (dir, fn);
-                               if (File.Exists (file))
-                                       return file;
-                       }
+                       if (hosted)
+                               return ApplicationHost.FindWebConfig (dir);
+                       else {
+                               Assembly asm = Assembly.GetEntryAssembly () ?? Assembly.GetCallingAssembly ();
+                               string name = Path.GetFileName (asm.Location);
+                               string[] fileNames = new string[] {name + ".config", name + ".Config"};
+                               string appDir = domain.BaseDirectory;
+                               string file;
 
+                               foreach (string fn in fileNames) {
+                                       file = Path.Combine (appDir, fn);
+                                       if (File.Exists (file))
+                                               return file;
+                               }
+                       }
                        return null;
                }
-               
                public virtual bool IsAboveApplication (string configPath)
                {
-                       throw new NotImplementedException ();
+                       return !configPath.Contains (HttpRuntime.AppDomainAppPath);
                }
                
                public virtual bool IsConfigRecordRequired (string configPath)
@@ -313,19 +319,42 @@ namespace System.Web.Configuration
                        throw new NotImplementedException ();
                }
                
-               public virtual bool IsDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition, ConfigurationAllowExeDefinition allowExeDefinition)
+               public virtual bool IsDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
+                                                        ConfigurationAllowExeDefinition allowExeDefinition)
                {
                        switch (allowDefinition) {
                                case ConfigurationAllowDefinition.MachineOnly:
                                        return configPath == MachinePath || configPath == MachineWebPath;
                                case ConfigurationAllowDefinition.MachineToWebRoot:
                                case ConfigurationAllowDefinition.MachineToApplication:
-                                       return configPath == MachinePath || configPath == MachineWebPath || configPath == "/";
+                                       if (String.IsNullOrEmpty (configPath))
+                                               return true;
+                                       string normalized;
+
+                                       if (VirtualPathUtility.IsRooted (configPath))
+                                               normalized = VirtualPathUtility.Normalize (configPath);
+                                       else
+                                               normalized = configPath;
+                                       
+                                       if ((String.Compare (normalized, MachinePath, StringComparison.Ordinal) == 0) ||
+                                               (String.Compare (normalized, MachineWebPath, StringComparison.Ordinal) == 0))
+                                                       return true;
+                               
+                                       if ((String.Compare (normalized, appVirtualPath) != 0))
+                                               return IsApplication (normalized);
+                               
+                                       return true;
                                default:
                                        return true;
                        }
                }
                
+               [MonoTODO("Should return false in case strPath points to the root of an application.")]
+               internal bool IsApplication(string strPath)
+               {
+                       return true;
+               }
+               
                public virtual bool IsFile (string streamName)
                {
                        throw new NotImplementedException ();
@@ -339,18 +368,7 @@ namespace System.Web.Configuration
                public virtual Stream OpenStreamForRead (string streamName)
                {
                        if (!File.Exists (streamName)) {
-#if TARGET_J2EE
-                               if (streamName != null && (streamName.EndsWith ("machine.config") || streamName.EndsWith ("web.config"))) {
-                                       if (streamName.StartsWith ("/"))
-                                               streamName = streamName.Substring (1);
-                                       java.lang.ClassLoader cl = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData ("GH_ContextClassLoader");
-                                       if (cl != null) {
-                                               java.io.InputStream inputStream = cl.getResourceAsStream (streamName);
-                                               return (Stream) vmw.common.IOUtils.getStream (inputStream);
-                                       }
-                               }
-#endif
-                               throw new ConfigurationException ("File '" + streamName + "' not found");
+                               return null;
                        }
                                
                        return new FileStream (streamName, FileMode.Open, FileAccess.Read);
@@ -364,11 +382,15 @@ namespace System.Web.Configuration
 
                public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext)
                {
+                       if (!IsAboveApplication (streamName))
+                               WebConfigurationManager.SuppressAppReload (true);
+
                        return new FileStream (streamName, FileMode.Create, FileAccess.Write);
                }
 
                [MonoTODO ("Not implemented")]
-               public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext, bool assertPermissions)
+               public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext,
+                                                         bool assertPermissions)
                {
                        throw new NotImplementedException ();
                }
@@ -390,7 +412,7 @@ namespace System.Web.Configuration
                }
 
                public virtual object StartMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
-               {
+               {                       
                        throw new NotImplementedException ();
                }
                
@@ -399,20 +421,30 @@ namespace System.Web.Configuration
                        throw new NotImplementedException ();
                }
                
-               public virtual void VerifyDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition, ConfigurationAllowExeDefinition allowExeDefinition, IConfigErrorInfo errorInfo)
+               public virtual void VerifyDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
+                                                            ConfigurationAllowExeDefinition allowExeDefinition,
+                                                            IConfigErrorInfo errorInfo)
                {
                        if (!IsDefinitionAllowed (configPath, allowDefinition, allowExeDefinition))
                                throw new ConfigurationErrorsException ("The section can't be defined in this file (the allowed definition context is '" + allowDefinition + "').", errorInfo.Filename, errorInfo.LineNumber);
                }
                
-               [MonoTODO("Does nothing")]
                public virtual void WriteCompleted (string streamName, bool success, object writeContext)
                {
-               }
-               
-               [MonoTODO("Does nothing")]
+                       WriteCompleted (streamName, success, writeContext, false);
+               }               
+
                public virtual void WriteCompleted (string streamName, bool success, object writeContext, bool assertPermissions)
                {
+                       // There are probably other things to be done here, but for the moment we
+                       // just mark the completed write as one that should not cause application
+                       // reload. Note that it might already be too late for suppression, since the
+                       // FileSystemWatcher monitor might have already delivered the
+                       // notification. If the stream has been open using OpenStreamForWrite then
+                       // we're safe, though.
+
+                       if (!IsAboveApplication (streamName))
+                               WebConfigurationManager.SuppressAppReload (true);
                }
 
                public virtual bool SupportsChangeNotifications {
@@ -462,4 +494,3 @@ namespace System.Web.Configuration
        }
 }
 
-#endif