Merge pull request #4967 from kumpera/profiler-arg-cleanup
[mono.git] / mcs / class / System.Web / System.Web.Configuration_2.0 / WebConfigurationHost.cs
index 9d85f4d00809a7c3c40ef5276a583a410257578d..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;
@@ -34,6 +34,7 @@ using System.IO;
 using System.Security;
 using System.Configuration;
 using System.Configuration.Internal;
+using System.Web.Hosting;
 using System.Web.Util;
 using System.Reflection;
 
@@ -54,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)
                {
@@ -66,13 +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)
+               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)
@@ -80,15 +85,27 @@ namespace System.Web.Configuration
                        File.Delete (streamName);
                }
                
-               public virtual string EncryptSection (string encryptedXml, ProtectedConfigurationProvider protectionProvider,
-                                                     ProtectedConfigurationSection protectedSection)
+               public virtual string EncryptSection (string clearXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedSection)
                {
-                       throw new NotImplementedException ();
+                       if (protectedSection == null)
+                               throw new ArgumentNullException ("protectedSection");
+
+                       return protectedSection.EncryptSection (clearXml, protectionProvider);
                }
                
-               public virtual string GetConfigPathFromLocationSubPath (string configPath, string locatinSubPath)
+               public virtual string GetConfigPathFromLocationSubPath (string configPath, string locationSubPath)
                {
-                       return configPath + "/" + locatinSubPath;
+                       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);
+                       }
+                       
+                       string ret = configPath + "/" + locationSubPath;
+                       if (!String.IsNullOrEmpty (ret) && ret [0] == '/')
+                               return ret.Substring (1);
+                       
+                       return ret;
                }
                
                public virtual Type GetConfigType (string typeName, bool throwOnError)
@@ -121,21 +138,7 @@ namespace System.Web.Configuration
                                string mdir;
 
                                if (map == null)
-#if TARGET_J2EE
-                               {
-                                       // check META-INF/web.config exists
-                                       java.lang.ClassLoader cl = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData ("GH_ContextClassLoader");
-                                       if (cl == null)
-                                               return null;
-                                       java.net.URL url = cl.getResource ("META-INF/web.config");
-                                       if (url == null)
-                                               return null;
-
-                                       return "/META-INF/web.config";
-                               }
-#else
                                        mdir = Path.GetDirectoryName (System.Runtime.InteropServices.RuntimeEnvironment.SystemConfigurationFile);
-#endif
                                else
                                        mdir = Path.GetDirectoryName (map.MachineConfigFilename);
 
@@ -171,7 +174,17 @@ namespace System.Web.Configuration
                {
                        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;
@@ -182,17 +195,14 @@ namespace System.Web.Configuration
                                locationConfigPath = null;
                        } else {
                                int i;
-                               if (locationSubPath == null)
-                               {
+                               if (locationSubPath == null) {
                                        configPath = fullPath;
                                        if (configPath.Length > 1)
                                                configPath = VirtualPathUtility.RemoveTrailingSlash (configPath);
-                               }
-                               else
+                               } else
                                        configPath = locationSubPath;
-
-                               if (configPath == HttpRuntime.AppDomainAppVirtualPath
-                                   || configPath == "/")
+                               
+                               if (configPath == HttpRuntime.AppDomainAppVirtualPath || configPath == "/")
                                        i = -1;
                                else
                                        i = configPath.LastIndexOf ("/");
@@ -213,6 +223,11 @@ 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)
@@ -272,54 +287,31 @@ namespace System.Web.Configuration
                        throw new HttpException ("Invalid virtual directory: " + virtualPath);
                }
 
-               string GetWebConfigFileName (string dir)
+               internal static string GetWebConfigFileName (string dir)
                {
-#if TARGET_J2EE
-                       DirectoryInfo d = GetCaseSensitiveExistingDirectory (new DirectoryInfo (dir));
-                       if (d == null)
-                               return null;
-
-                       FileInfo file = (FileInfo) FindByName ("web.config", d.GetFiles ("W*"));
-                       if (file == null)
-                               file = (FileInfo) FindByName ("web.config", d.GetFiles ("w*"));
-
-                       if (file != null)
-                               return file.FullName;
-#else
-                       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;
-                       }
-#endif
-                       return null;
-               }
-#if TARGET_J2EE
-               static DirectoryInfo GetCaseSensitiveExistingDirectory (DirectoryInfo dir) {
-                       if (dir.Exists)
-                               return dir;
+                       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;
 
-                       DirectoryInfo parent = GetCaseSensitiveExistingDirectory (dir.Parent);
-                       if (parent == null)
-                               return null;
-
-                       return (DirectoryInfo) FindByName (dir.Name, parent.GetDirectories ());
-               }
-               
-               static FileSystemInfo FindByName (string name, FileSystemInfo [] infos)
-               {
-                       for (int i = 0; i < infos.Length; i++) {
-                               if (String.Compare (name, infos [i].Name, StringComparison.OrdinalIgnoreCase) == 0)
-                                       return infos [i];
+                               foreach (string fn in fileNames) {
+                                       file = Path.Combine (appDir, fn);
+                                       if (File.Exists (file))
+                                               return file;
+                               }
                        }
                        return null;
                }
-#endif
                public virtual bool IsAboveApplication (string configPath)
                {
-                       throw new NotImplementedException ();
+                       return !configPath.Contains (HttpRuntime.AppDomainAppPath);
                }
                
                public virtual bool IsConfigRecordRequired (string configPath)
@@ -335,13 +327,34 @@ namespace System.Web.Configuration
                                        return configPath == MachinePath || configPath == MachineWebPath;
                                case ConfigurationAllowDefinition.MachineToWebRoot:
                                case ConfigurationAllowDefinition.MachineToApplication:
-                                       return configPath == MachinePath || configPath == MachineWebPath || configPath == "/" ||
-                                               configPath == HttpRuntime.AppDomainAppVirtualPath;
+                                       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 ();
@@ -355,19 +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);
@@ -381,6 +382,9 @@ 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);
                }
 
@@ -408,7 +412,7 @@ namespace System.Web.Configuration
                }
 
                public virtual object StartMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
-               {
+               {                       
                        throw new NotImplementedException ();
                }
                
@@ -425,14 +429,22 @@ namespace System.Web.Configuration
                                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 {
@@ -482,4 +494,3 @@ namespace System.Web.Configuration
        }
 }
 
-#endif