X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Configuration%2FSystem.Configuration%2FConfiguration.cs;h=a3f8dc924f43c9c479e4b3fd578cc0e5025d0ddd;hb=9f3ef8e4bac11601a2cf2670cbab337e6276103b;hp=19d71b61434779b30576617bbb2e38852950d701;hpb=d49951ccf584ba637afb1dab7fff714478e3174d;p=mono.git diff --git a/mcs/class/System.Configuration/System.Configuration/Configuration.cs b/mcs/class/System.Configuration/System.Configuration/Configuration.cs index 19d71b61434..a3f8dc924f4 100644 --- a/mcs/class/System.Configuration/System.Configuration/Configuration.cs +++ b/mcs/class/System.Configuration/System.Configuration/Configuration.cs @@ -30,15 +30,28 @@ using System; using System.Collections; using System.Collections.Specialized; +using System.Configuration.Internal; +using System.ComponentModel; using System.Reflection; using System.Xml; using System.IO; -using System.Configuration.Internal; namespace System.Configuration { - public sealed class Configuration + // For configuration document, use this XmlDocument instead of the standard one. This ignores xmlns attribute for MS. + internal class ConfigurationXmlDocument : XmlDocument { + public override XmlElement CreateElement (string prefix, string localName, string namespaceURI) + { + if (namespaceURI == "http://schemas.microsoft.com/.NetConfiguration/v2.0") + return base.CreateElement (String.Empty, localName, String.Empty); + else + return base.CreateElement (prefix, localName, namespaceURI); + } + } + + public sealed class Configuration + { Configuration parent; Hashtable elementData = new Hashtable (); string streamName; @@ -51,19 +64,25 @@ namespace System.Configuration { string configPath; string locationConfigPath; - - internal Configuration (Configuration parent) + string locationSubPath; + + internal static event ConfigurationSaveEventHandler SaveStart; + internal static event ConfigurationSaveEventHandler SaveEnd; + + internal Configuration (Configuration parent, string locationSubPath) { this.parent = parent; this.system = parent.system; this.rootGroup = parent.rootGroup; + this.locationSubPath = locationSubPath; + this.configPath = parent.ConfigPath; } internal Configuration (InternalConfigurationSystem system, string locationSubPath) { hasFile = true; this.system = system; - + system.InitForConfiguration (ref locationSubPath, out configPath, out locationConfigPath); Configuration parent = null; @@ -79,18 +98,21 @@ namespace System.Configuration { internal Configuration FindLocationConfiguration (string relativePath, Configuration defaultConfiguration) { - ConfigurationLocation loc = Locations.Find (relativePath); - Configuration parentConfig = defaultConfiguration; - - if (LocationConfigPath != null) { + + if (!String.IsNullOrEmpty (LocationConfigPath)) { Configuration parentFile = GetParentWithFile (); if (parentFile != null) { - string parentRelativePath = system.Host.GetConfigPathFromLocationSubPath (LocationConfigPath, relativePath); + string parentRelativePath = system.Host.GetConfigPathFromLocationSubPath (configPath, relativePath); parentConfig = parentFile.FindLocationConfiguration (parentRelativePath, defaultConfiguration); } } + string relConfigPath = configPath.Substring (1) + "/"; + if (relativePath.StartsWith (relConfigPath, StringComparison.Ordinal)) + relativePath = relativePath.Substring (relConfigPath.Length); + + ConfigurationLocation loc = Locations.FindBest (relativePath); if (loc == null) return parentConfig; @@ -140,6 +162,19 @@ namespace System.Configuration { get { return locationConfigPath; } } + internal string GetLocationSubPath () + { + Configuration confg = parent; + string path = null; + while (confg != null) { + path = confg.locationSubPath; + if (!String.IsNullOrEmpty (path)) + return path; + confg = confg.parent; + } + return path; + } + internal string ConfigPath { get { return configPath; } } @@ -152,8 +187,15 @@ namespace System.Configuration { get { return (ConnectionStringsSection) GetSection ("connectionStrings"); } } + // MSDN: If the value for this FilePath property represents a merged view and + // no actual file exists for the application, the path to the parent configuration + // file is returned. public string FilePath { - get { return streamName; } + get { + if (streamName == null && parent != null) + return parent.FilePath; + return streamName; + } } public bool HasFile { @@ -162,12 +204,15 @@ namespace System.Configuration { } } - [MonoTODO ("HostingContext")] ContextInformation evaluationContext; public ContextInformation EvaluationContext { get { - if (evaluationContext == null) - evaluationContext = new ContextInformation (this, null /* XXX */); + if (evaluationContext == null) { + object ctx = system.Host.CreateConfigurationContext (configPath, GetLocationSubPath() ); + evaluationContext = new ContextInformation (this, ctx); + } + + return evaluationContext; } } @@ -191,11 +236,11 @@ namespace System.Configuration { rootSectionGroup.Initialize (this, rootGroup); } return rootSectionGroup; - } + } } public ConfigurationSectionGroupCollection SectionGroups { - get { return RootSectionGroup.SectionGroups; } + get { return RootSectionGroup.SectionGroups; } } public ConfigurationSectionCollection Sections { @@ -240,19 +285,28 @@ namespace System.Configuration { ds.SectionHandler = secObj as IConfigurationSectionHandler; sec = ds; } + sec.Configuration = this; - ConfigurationSection parentSection = parent != null ? parent.GetSectionInstance (config, true) : null; + ConfigurationSection parentSection = null; + if (parent != null) { + parentSection = parent.GetSectionInstance (config, true); + sec.SectionInformation.SetParentSection (parentSection); + } + sec.SectionInformation.ConfigFilePath = FilePath; + sec.ConfigContext = system.Host.CreateDeprecatedConfigContext(configPath); + string xml = data as string; - if (xml == null && parentSection != null) - xml = parentSection.RawXml; sec.RawXml = xml; sec.Reset (parentSection); - if (xml != null && xml == data) { - XmlTextReader r = new XmlTextReader (new StringReader (xml)); + if (xml != null) { + XmlTextReader r = new ConfigXmlTextReader (new StringReader (xml), FilePath); sec.DeserializeSection (r); r.Close (); + + if (!String.IsNullOrEmpty (sec.SectionInformation.ConfigSource) && !String.IsNullOrEmpty (FilePath)) + sec.DeserializeConfigSource (Path.GetDirectoryName (FilePath)); } elementData [config] = sec; @@ -284,7 +338,7 @@ namespace System.Configuration { internal void CreateSection (SectionGroupInfo group, string name, ConfigurationSection sec) { if (group.HasChild (name)) - throw new ConfigurationException ("Cannot add a ConfigurationSection. A section or section group already exists with the name '" + name + "'"); + throw new ConfigurationErrorsException ("Cannot add a ConfigurationSection. A section or section group already exists with the name '" + name + "'"); if (!HasFile && !sec.SectionInformation.AllowLocation) throw new ConfigurationErrorsException ("The configuration section <" + name + "> cannot be defined inside a element."); @@ -293,20 +347,21 @@ namespace System.Configuration { object ctx = sec.SectionInformation.AllowExeDefinition != ConfigurationAllowExeDefinition.MachineToApplication ? (object) sec.SectionInformation.AllowExeDefinition : (object) sec.SectionInformation.AllowDefinition; throw new ConfigurationErrorsException ("The section <" + name + "> can't be defined in this configuration file (the allowed definition context is '" + ctx + "')."); } - + if (sec.SectionInformation.Type == null) sec.SectionInformation.Type = system.Host.GetConfigTypeName (sec.GetType ()); - + SectionInfo section = new SectionInfo (name, sec.SectionInformation); section.StreamName = streamName; section.ConfigHost = system.Host; group.AddChild (section); elementData [section] = sec; + sec.Configuration = this; } internal void CreateSectionGroup (SectionGroupInfo parentGroup, string name, ConfigurationSectionGroup sec) { - if (parentGroup.HasChild (name)) throw new ConfigurationException ("Cannot add a ConfigurationSectionGroup. A section or section group already exists with the name '" + name + "'"); + if (parentGroup.HasChild (name)) throw new ConfigurationErrorsException ("Cannot add a ConfigurationSectionGroup. A section or section group already exists with the name '" + name + "'"); if (sec.Type == null) sec.Type = system.Host.GetConfigTypeName (sec.GetType ()); sec.SetName (name); @@ -315,6 +370,8 @@ namespace System.Configuration { section.ConfigHost = system.Host; parentGroup.AddChild (section); elementData [section] = sec; + + sec.Initialize (this, section); } internal void RemoveConfigInfo (ConfigInfo config) @@ -334,16 +391,26 @@ namespace System.Configuration { public void Save (ConfigurationSaveMode mode, bool forceUpdateAll) { + ConfigurationSaveEventHandler saveStart = SaveStart; + ConfigurationSaveEventHandler saveEnd = SaveEnd; + object ctx = null; + Exception saveEx = null; Stream stream = system.Host.OpenStreamForWrite (streamName, null, ref ctx); try { + if (saveStart != null) + saveStart (this, new ConfigurationSaveEventArgs (streamName, true, null, ctx)); + Save (stream, mode, forceUpdateAll); system.Host.WriteCompleted (streamName, true, ctx); } catch (Exception ex) { + saveEx = ex; system.Host.WriteCompleted (streamName, false, ctx); throw; } finally { stream.Close (); + if (saveEnd != null) + saveEnd (this, new ConfigurationSaveEventArgs (streamName, false, saveEx, ctx)); } } @@ -356,10 +423,13 @@ namespace System.Configuration { { SaveAs (filename, mode, false); } - - [MonoTODO ("Detect if file has changed")] + + [MonoInternalNote ("Detect if file has changed")] public void SaveAs (string filename, ConfigurationSaveMode mode, bool forceUpdateAll) { + string dir = Path.GetDirectoryName (Path.GetFullPath (filename)); + if (!Directory.Exists (dir)) + Directory.CreateDirectory (dir); Save (new FileStream (filename, FileMode.OpenOrCreate, FileAccess.Write), mode, forceUpdateAll); } @@ -396,6 +466,7 @@ namespace System.Configuration { tw.WriteEndElement (); } finally { + tw.Flush (); tw.Close (); } } @@ -407,30 +478,25 @@ namespace System.Configuration { bool Load () { - if (streamName == null || streamName == "") + if (String.IsNullOrEmpty (streamName)) return true; - XmlTextReader reader = null; Stream stream = null; - try { stream = system.Host.OpenStreamForRead (streamName); - } catch (Exception e) { + if (stream == null) + return false; + } catch { return false; } - try { - reader = new XmlTextReader (stream); + using (XmlTextReader reader = new ConfigXmlTextReader (stream, streamName)) { ReadConfigFile (reader, streamName); - } finally { - if (reader != null) - reader.Close(); } return true; } - - internal void ReadConfigFile (XmlTextReader reader, string fileName) + void ReadConfigFile (XmlReader reader, string fileName) { reader.MoveToContent (); @@ -466,16 +532,17 @@ namespace System.Configuration { rootGroup.ReadRootData (reader, this, true); } - - internal void ReadData (XmlTextReader reader, bool allowOverride) + + internal void ReadData (XmlReader reader, bool allowOverride) { rootGroup.ReadData (this, reader, allowOverride); } - private void ThrowException (string text, XmlTextReader reader) + private void ThrowException (string text, XmlReader reader) { - throw new ConfigurationException (text, streamName, reader.LineNumber); + IXmlLineInfo li = reader as IXmlLineInfo; + throw new ConfigurationErrorsException (text, streamName, li != null ? li.LineNumber : 0); } } }