2006-01-26 Chris Toshok <toshok@ximian.com>
authorChris Toshok <toshok@novell.com>
Fri, 27 Jan 2006 02:10:20 +0000 (02:10 -0000)
committerChris Toshok <toshok@novell.com>
Fri, 27 Jan 2006 02:10:20 +0000 (02:10 -0000)
* SectionGroupInfo.cs (ReadContent): handle "location" (seemingly)
correctly.

* InternalConfigurationRoot.cs: misc logical additions.  still
isn't useful.

* ConfigurationManager.cs (OpenExeConfigurationInternal): throw an
exception if both calling_assembly and exePath are null.  Allow
the exePath to be a path to a config file as well, checking to see
if it ends in .config before appending.
(OpenExeConfiguration): stop blindly passing
Assembly.GetCallingAssembly.  I'm assuming this will likely break
.dll.config usage.  need to investigate that (and write more unit
tests.)
(GetSection): call configSystem.GetSection.
(RefreshSection): call configSystem.RefreshSection.
(ChangeConfigurationSystem): modeled after the
ConfigurationSettings System.Web hack - allow
WebConfigurationManager to replace the current
IInternalConfigSystem.

* InternalConfigurationHost.cs (InternalConfigurationHost): make
abstract, and remove all the NotImplenmentedException's.

* ConfigurationElement.cs (DeserializeElement): store off the xml
namespace if there is one.
(SerializeElement): write out the namespace if there was one.

* ClientConfigurationSystem.cs: new class, based on some stack
traces I've seen in tests.  Kinda (well, not *kinda*..) hacky.

* Configuration.cs (NamespaceDeclared): implement.
(Load): don't swallow all exceptions, just the ones raised when we
open the stream for reading.
(ReadConfigFile): handle xmlns.

svn path=/trunk/mcs/; revision=56135

mcs/class/System.Configuration/System.Configuration/ChangeLog
mcs/class/System.Configuration/System.Configuration/ClientConfigurationSystem.cs [new file with mode: 0644]
mcs/class/System.Configuration/System.Configuration/Configuration.cs
mcs/class/System.Configuration/System.Configuration/ConfigurationElement.cs
mcs/class/System.Configuration/System.Configuration/ConfigurationManager.cs
mcs/class/System.Configuration/System.Configuration/InternalConfigurationHost.cs
mcs/class/System.Configuration/System.Configuration/InternalConfigurationRoot.cs
mcs/class/System.Configuration/System.Configuration/SectionGroupInfo.cs

index 7f2f76847bc9680d0465015d1462ea184e24b585..ede9c77d7405c602faa056b62f2c36bd2039d544 100644 (file)
@@ -1,3 +1,41 @@
+2006-01-26  Chris Toshok  <toshok@ximian.com>
+
+       * SectionGroupInfo.cs (ReadContent): handle "location" (seemingly)
+       correctly.
+
+       * InternalConfigurationRoot.cs: misc logical additions.  still
+       isn't useful.
+
+       * ConfigurationManager.cs (OpenExeConfigurationInternal): throw an
+       exception if both calling_assembly and exePath are null.  Allow
+       the exePath to be a path to a config file as well, checking to see
+       if it ends in .config before appending.
+       (OpenExeConfiguration): stop blindly passing
+       Assembly.GetCallingAssembly.  I'm assuming this will likely break
+       .dll.config usage.  need to investigate that (and write more unit
+       tests.)
+       (GetSection): call configSystem.GetSection.
+       (RefreshSection): call configSystem.RefreshSection.
+       (ChangeConfigurationSystem): modeled after the
+       ConfigurationSettings System.Web hack - allow
+       WebConfigurationManager to replace the current
+       IInternalConfigSystem.
+
+       * InternalConfigurationHost.cs (InternalConfigurationHost): make
+       abstract, and remove all the NotImplenmentedException's.
+
+       * ConfigurationElement.cs (DeserializeElement): store off the xml
+       namespace if there is one.
+       (SerializeElement): write out the namespace if there was one.
+
+       * ClientConfigurationSystem.cs: new class, based on some stack
+       traces I've seen in tests.  Kinda (well, not *kinda*..) hacky.
+
+       * Configuration.cs (NamespaceDeclared): implement.
+       (Load): don't swallow all exceptions, just the ones raised when we
+       open the stream for reading.
+       (ReadConfigFile): handle xmlns.
+
 2006-01-25  Chris Toshok  <toshok@ximian.com>
 
        * ConfigInfo.cs (ThrowException): throw a
diff --git a/mcs/class/System.Configuration/System.Configuration/ClientConfigurationSystem.cs b/mcs/class/System.Configuration/System.Configuration/ClientConfigurationSystem.cs
new file mode 100644 (file)
index 0000000..9ebeaf0
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// System.Configuration.ClientConfigurationSystem.cs
+//
+// Authors:
+//  Chris Toshok (toshok@ximian.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// 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) 2006 Novell, Inc (http://www.novell.com)
+//
+
+#if NET_2_0
+
+using System;
+using System.Reflection;
+using System.Configuration.Internal;
+
+namespace System.Configuration {
+
+       internal class ClientConfigurationSystem : IInternalConfigSystem
+       {
+               object IInternalConfigSystem.GetSection (string configKey)
+               {
+                       Assembly a = Assembly.GetEntryAssembly();
+
+                       Configuration cfg = ConfigurationManager.OpenExeConfigurationInternal (ConfigurationUserLevel.None, a, AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
+                       if (cfg == null) return null;
+                       return cfg.GetSection (configKey);
+               }
+
+               void IInternalConfigSystem.RefreshConfig (string sectionName)
+               {
+               }
+
+               /* I'm guessing this means "we support ConfigurationUserLevel.PerUser* files" */
+               bool IInternalConfigSystem.SupportsUserConfig {
+                       get { return true; }
+               }
+       }
+}
+
+#endif
index 91641bdd62844db742bb635dd80933329c6027c3..5b662dfcb277f0cb0c872fb89f87af2d5374d9f6 100644 (file)
@@ -47,6 +47,7 @@ namespace System.Configuration {
                SectionGroupInfo rootGroup;
                IConfigSystem system;
                bool hasFile;
+               string rootNamespace;
                
                string configPath;
                string locationConfigPath;
@@ -176,14 +177,9 @@ namespace System.Configuration {
                        }
                }
 
-               [MonoTODO]
                public bool NamespaceDeclared {
-                       get {
-                               throw new NotImplementedException ();
-                       }
-                       set {
-                               throw new NotImplementedException ();
-                       }
+                       get { return rootNamespace != null; }
+                       set { rootNamespace = value ? "http://schemas.microsoft.com/.NetConfiguration/v2.0" : null; }
                }
 
                public ConfigurationSectionGroup RootSectionGroup {
@@ -365,7 +361,10 @@ namespace System.Configuration {
                        tw.Formatting = Formatting.Indented;
                        try {
                                tw.WriteStartDocument ();
-                               tw.WriteStartElement ("configuration");
+                               if (rootNamespace != null)
+                                       tw.WriteStartElement ("configuration", rootNamespace);
+                               else
+                                       tw.WriteStartElement ("configuration");
                                if (rootGroup.HasConfigContent (this)) {
                                        rootGroup.WriteConfig (this, tw, mode);
                                }
@@ -400,16 +399,21 @@ namespace System.Configuration {
                
                bool Load ()
                {
-                       if (streamName == null)
+                       if (streamName == null || streamName == "")
                                return true;
 
                        XmlTextReader reader = null;
+                       Stream stream = null;
+                       
                        try {
-                               Stream stream = system.Host.OpenStreamForRead (streamName);
-                               reader = new XmlTextReader (stream);
-                               ReadConfigFile (reader, streamName);
+                               stream = system.Host.OpenStreamForRead (streamName);
                        } catch (Exception e) {
                                return false;
+                       }
+
+                       try {
+                               reader = new XmlTextReader (stream);
+                               ReadConfigFile (reader, streamName);
                        } finally {
                                if (reader != null)
                                        reader.Close();
@@ -421,11 +425,21 @@ namespace System.Configuration {
                internal void ReadConfigFile (XmlTextReader reader, string fileName)
                {
                        reader.MoveToContent ();
+
                        if (reader.NodeType != XmlNodeType.Element || reader.Name != "configuration")
                                ThrowException ("Configuration file does not have a valid root element", reader);
 
-                       if (reader.HasAttributes)
-                               ThrowException ("Unrecognized attribute in root element", reader);
+                       if (reader.HasAttributes) {
+                               while (reader.MoveToNextAttribute ()) {
+                                       if (reader.LocalName == "xmlns") {
+                                               rootNamespace = reader.Value;
+                                               continue;
+                                       }
+                                       ThrowException (String.Format ("Unrecognized attribute '{0}' in root element", reader.LocalName), reader);
+                               }
+                       }
+
+                       reader.MoveToElement ();
 
                        if (reader.IsEmptyElement) {
                                reader.Skip ();
index 9fd0cced8a5eeb1543916f854d704cf4b5559f13..4b7aff9b9f82f5878460d23cc4755944335b6a48 100644 (file)
@@ -39,6 +39,7 @@ namespace System.Configuration
        public abstract class ConfigurationElement
        {
                string rawXml;
+               string elementNamespace;
                bool modified;
                ElementMap map;
                ConfigurationPropertyCollection keyProps;
@@ -294,6 +295,9 @@ namespace System.Configuration
                                        else if (reader.LocalName == "lockItem") {
                                                LockItem = (reader.Value.ToLower() == "true");
                                        }
+                                       else if (reader.LocalName == "xmlns") {
+                                               elementNamespace = reader.Value;
+                                       }
                                        else if (!OnDeserializeUnrecognizedAttribute (reader.LocalName, reader.Value))
                                                throw new ConfigurationException ("Unrecognized attribute '" + reader.LocalName + "'.");
 
@@ -440,6 +444,11 @@ namespace System.Configuration
                        
                        bool wroteData = false;
                        
+                       if (elementNamespace != null) {
+                               writer.WriteAttributeString ("xmlns", elementNamespace);
+                               wroteData = true;
+                       }
+
                        foreach (PropertyInformation prop in ElementInformation.Properties)
                        {
                                if (prop.IsElement || prop.ValueOrigin == PropertyValueOrigin.Default)
index 35241f264a7dbbfc75269032c2e1ea0dea588990..181375a30779b8323570559d2b8039ec4aa5908b 100644 (file)
@@ -44,6 +44,8 @@ namespace System.Configuration {
        public static class ConfigurationManager
        {
                static InternalConfigurationFactory configFactory = new InternalConfigurationFactory ();
+               static IInternalConfigSystem configSystem = new ClientConfigurationSystem ();
+               static object lockobj = new object ();
 
                [MonoTODO ("Evidence and version still needs work")]
                static string GetAssemblyInfo (Assembly a)
@@ -77,8 +79,11 @@ namespace System.Configuration {
                        return Path.Combine (String.Format ("{0}_{1}", app_name, evidence_str), version);
                }
 
-               static Configuration OpenExeConfigurationInternal (ConfigurationUserLevel userLevel, Assembly calling_assembly, string exePath)
+               internal static Configuration OpenExeConfigurationInternal (ConfigurationUserLevel userLevel, Assembly calling_assembly, string exePath)
                {
+                       if (calling_assembly == null && exePath == null)
+                               throw new ArgumentException ("exePath must be specified when not running inside a stand alone exe.");
+
                        ExeConfigurationFileMap map = new ExeConfigurationFileMap ();
 
                        /* Roaming and RoamingAndLocal should be different
@@ -91,13 +96,16 @@ namespace System.Configuration {
                        switch (userLevel) {
                        case ConfigurationUserLevel.None:
                                if (exePath == null)
-                                       exePath = Assembly.GetCallingAssembly ().Location;
+                                       exePath = calling_assembly.Location;
                                else if (!File.Exists (exePath))
                                        exePath = "";
 
-                               if (exePath != "")
-                                       map.ExeConfigFilename = exePath + ".config";
-
+                               if (exePath != "") {
+                                       if (!exePath.EndsWith (".config"))
+                                               map.ExeConfigFilename = exePath + ".config";
+                                       else
+                                               map.ExeConfigFilename = exePath;
+                               }
                                break;
                        case ConfigurationUserLevel.PerUserRoaming:
                                map.RoamingUserConfigFilename = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData), GetAssemblyInfo(calling_assembly));
@@ -115,12 +123,12 @@ namespace System.Configuration {
 
                public static Configuration OpenExeConfiguration (ConfigurationUserLevel userLevel)
                {
-                       return OpenExeConfigurationInternal (userLevel, Assembly.GetCallingAssembly (), Assembly.GetCallingAssembly ().Location);
+                       return OpenExeConfigurationInternal (userLevel, Assembly.GetEntryAssembly (), null);
                }
                
                public static Configuration OpenExeConfiguration (string exePath)
                {
-                       return OpenExeConfigurationInternal (ConfigurationUserLevel.None, Assembly.GetCallingAssembly (), exePath);
+                       return OpenExeConfigurationInternal (ConfigurationUserLevel.None, null, exePath);
                }
 
                [MonoTODO ("userLevel")]
@@ -144,24 +152,14 @@ namespace System.Configuration {
                        get { return configFactory; }
                }
 
-               [MonoTODO ("this assembly stuff is probably wrong")]
                public static object GetSection (string sectionName)
                {
-                       Assembly a = Assembly.GetEntryAssembly ();
-                       if (a == null)
-                               a = Assembly.GetCallingAssembly ();
-                       Configuration cfg = OpenExeConfigurationInternal (ConfigurationUserLevel.None,
-                                                                         a, a.Location);
-
-                       if (cfg == null)
-                               return null;
-
-                       return cfg.GetSection (sectionName);
+                       return configSystem.GetSection (sectionName);
                }
 
-               [MonoTODO]
                public static void RefreshSection (string sectionName)
                {
+                       configSystem.RefreshConfig (sectionName);
                }
 
                public static NameValueCollection AppSettings {
@@ -175,10 +173,22 @@ namespace System.Configuration {
                public static ConnectionStringSettingsCollection ConnectionStrings {
                        get {
                                ConnectionStringsSection connectionStrings = (ConnectionStringsSection) GetSection ("connectionStrings");
-
                                return connectionStrings.ConnectionStrings;
                        }
                }
+
+               /* invoked from System.Web */
+               static IInternalConfigSystem ChangeConfigurationSystem (IInternalConfigSystem newSystem)
+               {
+                       if (newSystem == null)
+                               throw new ArgumentNullException ("newSystem");
+
+                       lock (lockobj) {
+                               IInternalConfigSystem old = configSystem;
+                               configSystem = newSystem;
+                               return old;
+                       }
+               }
        }
 }
 
index 94bf85c68746720f26cd59cb94deef194c09fd55..3b1235b2fd3766eb70175adc9be6a19bb74703c3 100644 (file)
@@ -35,7 +35,7 @@ using System.Configuration.Internal;
 
 namespace System.Configuration
 {
-       class InternalConfigurationHost: IInternalConfigHost
+       abstract class InternalConfigurationHost: IInternalConfigHost
        {
                public virtual object CreateConfigurationContext (string configPath, string locationSubPath)
                {
@@ -85,14 +85,14 @@ namespace System.Configuration
                        throw new NotImplementedException ();
                }
                
-               public virtual string GetStreamName (string configPath)
-               {
-                       throw new NotImplementedException ();
-               }
+               public abstract string GetStreamName (string configPath);
+               public abstract void Init (IInternalConfigRoot root, params object[] hostInitParams);
+               public abstract void InitForConfiguration (ref string locationSubPath, out string configPath, out string locationConfigPath, IInternalConfigRoot root, params object[] hostInitConfigurationParams);
                
+               [MonoTODO ("remote config")]
                public virtual string GetStreamNameForConfigSource (string streamName, string configSource)
                {
-                       throw new NotImplementedException ();
+                       throw new NotSupportedException ("mono does not support remote configuration");
                }
                
                public virtual object GetStreamVersion (string streamName)
@@ -105,15 +105,6 @@ namespace System.Configuration
                        throw new NotImplementedException ();
                }
                
-               public virtual void Init (IInternalConfigRoot root, params object[] hostInitParams)
-               {
-               }
-               
-               public virtual void InitForConfiguration (ref string locationSubPath, out string configPath, out string locationConfigPath, IInternalConfigRoot root, params object[] hostInitConfigurationParams)
-               {
-                       throw new NotImplementedException ();
-               }
-               
                public virtual bool IsAboveApplication (string configPath)
                {
                        throw new NotImplementedException ();
index bfa3b583ddfcc45807de956437e660eaac30c2f3..d51b5fd81a20588409703d8ee09410a93f32a0a7 100644 (file)
@@ -36,6 +36,14 @@ namespace System.Configuration
 {
        class InternalConfigurationRoot: IInternalConfigRoot
        {
+               IInternalConfigHost host;
+               bool isDesignTime;
+
+               public InternalConfigurationRoot ()
+               {
+               }
+
+               [MonoTODO]
                public IInternalConfigRecord GetConfigRecord (string configPath)
                {
                        throw new NotImplementedException ();
@@ -43,35 +51,39 @@ namespace System.Configuration
                
                public object GetSection (string section, string configPath)
                {
-                       throw new NotImplementedException ();
+                       IInternalConfigRecord rec = GetConfigRecord (configPath);
+                       return rec.GetSection (section);
                }
-               
+
+               [MonoTODO]
                public string GetUniqueConfigPath (string configPath)
                {
-                       throw new NotImplementedException ();
+                       return configPath;
                }
-               
+
+               [MonoTODO]
                public IInternalConfigRecord GetUniqueConfigRecord (string configPath)
                {
-                       throw new NotImplementedException ();
+                       return GetConfigRecord (GetUniqueConfigPath (configPath));
                }
                
                public void Init (IInternalConfigHost host, bool isDesignTime)
                {
+                       this.host = host;
+                       this.isDesignTime = isDesignTime;
                }
-               
+
+               [MonoTODO]
                public void RemoveConfig (string configPath)
                {
+                       host.DeleteStream (configPath);
+
                        if (ConfigRemoved != null)
                                ConfigRemoved (this, new InternalConfigEventArgs (configPath));
-                               
-                       throw new NotImplementedException ();
                }
                
                public bool IsDesignTime {
-                       get {
-                               throw new NotImplementedException ();
-                       }
+                       get { return isDesignTime; }
                }
 
                public event InternalConfigEventHandler ConfigChanged;
index b93f59dd5ca2406860bcde701c769ec0373cf682..011276070f4a396a6b05784e9106d7f0d0935126 100644 (file)
@@ -263,19 +263,19 @@ namespace System.Configuration
                public void ReadRootData (XmlTextReader reader, Configuration config, bool overrideAllowed)
                {
                        reader.MoveToContent ();
-                       ReadContent (reader, config, overrideAllowed);
+                       ReadContent (reader, config, overrideAllowed, true);
                }
                
                public override void ReadData (Configuration config, XmlTextReader reader, bool overrideAllowed)
                {
                        reader.MoveToContent ();
                        reader.ReadStartElement ();
-                       ReadContent (reader, config, overrideAllowed);
+                       ReadContent (reader, config, overrideAllowed, false);
                        reader.MoveToContent ();
                        reader.ReadEndElement ();
                }
                
-               void ReadContent (XmlTextReader reader, Configuration config, bool overrideAllowed)
+               void ReadContent (XmlTextReader reader, Configuration config, bool overrideAllowed, bool root)
                {
                        StringBuilder spacing = new StringBuilder ();
                        while (reader.NodeType != XmlNodeType.EndElement) {
@@ -286,8 +286,26 @@ namespace System.Configuration
                                        continue;
                                }
                                
-                               if (reader.LocalName == "location")
-                                       ThrowException ("<location> elements are only allowed in <configuration> elements.", reader);
+                               if (reader.LocalName == "location") {
+                                       if (!root)
+                                               ThrowException ("<location> elements are only allowed in <configuration> elements.", reader);
+
+                                       string allowOverrideAttr = reader.GetAttribute ("allowOverride");
+                                       bool allowOverride = allowOverrideAttr == null || allowOverrideAttr.Length == 0 || bool.Parse (allowOverrideAttr);
+                                       string path = reader.GetAttribute ("path");
+                                       if (path != null && path.Length > 0) {
+                                               string xml = reader.ReadOuterXml ();
+                                               string[] pathList = path.Split (',');
+                                               foreach (string p in pathList) {
+                                                       ConfigurationLocation loc = new ConfigurationLocation (p.Trim (), xml, config, allowOverride);
+                                                       config.Locations.Add (loc);
+                                               }
+                                       } else {
+                                               ReadData (config, reader, allowOverride);
+                                       }
+                                       continue;
+                               }
+
                                
                                ConfigInfo data = (sections != null) ? (ConfigInfo) sections [reader.LocalName] : (ConfigInfo) null;
                                if (data == null) data = (groups != null) ? (ConfigInfo) groups [reader.LocalName] : (ConfigInfo) null;