//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
-#if NET_2_0
+
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;
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;
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;
rootGroup.StreamName = streamName;
}
- if (streamName != null)
- Load ();
+ try {
+ if (streamName != null)
+ Load ();
+ } catch (XmlException ex) {
+ throw new ConfigurationErrorsException (ex.Message, ex, streamName, 0);
+ }
}
internal Configuration Parent {
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; }
}
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 {
}
}
- [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;
}
}
rootSectionGroup.Initialize (this, rootGroup);
}
return rootSectionGroup;
- }
+ }
}
public ConfigurationSectionGroupCollection SectionGroups {
- get { return RootSectionGroup.SectionGroups; }
+ get { return RootSectionGroup.SectionGroups; }
}
public ConfigurationSectionCollection Sections {
get { return RootSectionGroup.Sections; }
}
- public ConfigurationSection GetSection (string path)
+ public ConfigurationSection GetSection (string sectionName)
{
- string[] parts = path.Split ('/');
+ string[] parts = sectionName.Split ('/');
if (parts.Length == 1)
return Sections [parts[0]];
return null;
}
- public ConfigurationSectionGroup GetSectionGroup (string path)
+ public ConfigurationSectionGroup GetSectionGroup (string sectionGroupName)
{
- string[] parts = path.Split ('/');
+ string[] parts = sectionGroupName.Split ('/');
ConfigurationSectionGroup group = SectionGroups [parts[0]];
for (int n=1; group != null && n<parts.Length; n++)
group = group.SectionGroups [parts [n]];
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;
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 <location> element.");
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);
section.ConfigHost = system.Host;
parentGroup.AddChild (section);
elementData [section] = sec;
+
+ sec.Initialize (this, section);
}
internal void RemoveConfigInfo (ConfigInfo config)
Save (ConfigurationSaveMode.Modified, false);
}
- public void Save (ConfigurationSaveMode mode)
+ public void Save (ConfigurationSaveMode saveMode)
{
- Save (mode, false);
+ Save (saveMode, false);
}
- public void Save (ConfigurationSaveMode mode, bool forceUpdateAll)
+ public void Save (ConfigurationSaveMode saveMode, bool forceSaveAll)
{
+ if (!forceSaveAll && (saveMode != ConfigurationSaveMode.Full) && !HasValues (saveMode)) {
+ ResetModified ();
+ return;
+ }
+
+ ConfigurationSaveEventHandler saveStart = SaveStart;
+ ConfigurationSaveEventHandler saveEnd = SaveEnd;
+
object ctx = null;
+ Exception saveEx = null;
Stream stream = system.Host.OpenStreamForWrite (streamName, null, ref ctx);
try {
- Save (stream, mode, forceUpdateAll);
+ if (saveStart != null)
+ saveStart (this, new ConfigurationSaveEventArgs (streamName, true, null, ctx));
+
+ Save (stream, saveMode, forceSaveAll);
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));
}
}
SaveAs (filename, ConfigurationSaveMode.Modified, false);
}
- public void SaveAs (string filename, ConfigurationSaveMode mode)
+ public void SaveAs (string filename, ConfigurationSaveMode saveMode)
{
- SaveAs (filename, mode, false);
+ SaveAs (filename, saveMode, false);
}
-
- [MonoTODO ("Detect if file has changed")]
- public void SaveAs (string filename, ConfigurationSaveMode mode, bool forceUpdateAll)
+
+ [MonoInternalNote ("Detect if file has changed")]
+ public void SaveAs (string filename, ConfigurationSaveMode saveMode, bool forceSaveAll)
{
- Save (new FileStream (filename, FileMode.OpenOrCreate, FileAccess.Write), mode, forceUpdateAll);
+ if (!forceSaveAll && (saveMode != ConfigurationSaveMode.Full) && !HasValues (saveMode)) {
+ ResetModified ();
+ return;
+ }
+
+ string dir = Path.GetDirectoryName (Path.GetFullPath (filename));
+ if (!Directory.Exists (dir))
+ Directory.CreateDirectory (dir);
+ Save (new FileStream (filename, FileMode.OpenOrCreate, FileAccess.Write), saveMode, forceSaveAll);
}
void Save (Stream stream, ConfigurationSaveMode mode, bool forceUpdateAll)
SaveData (tw, mode, forceUpdateAll);
tw.WriteEndElement ();
+ ResetModified ();
}
finally {
+ tw.Flush ();
tw.Close ();
}
}
{
rootGroup.WriteRootData (tw, this, mode);
}
+
+ bool HasValues (ConfigurationSaveMode mode)
+ {
+ foreach (ConfigurationLocation loc in Locations) {
+ if (loc.OpenedConfiguration == null)
+ continue;
+ if (loc.OpenedConfiguration.HasValues (mode))
+ return true;
+ }
+
+ return rootGroup.HasValues (this, mode);
+ }
+
+ void ResetModified ()
+ {
+ foreach (ConfigurationLocation loc in Locations) {
+ if (loc.OpenedConfiguration == null)
+ continue;
+ loc.OpenedConfiguration.ResetModified ();
+ }
+
+ rootGroup.ResetModified (this);
+ }
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();
}
+ ResetModified ();
return true;
}
-
- internal void ReadConfigFile (XmlTextReader reader, string fileName)
+ void ReadConfigFile (XmlReader reader, string fileName)
{
reader.MoveToContent ();
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);
}
}
}
-#endif