SectionGroupInfo rootGroup;
IConfigSystem system;
bool hasFile;
+ string rootNamespace;
string configPath;
string locationConfigPath;
-
- internal Configuration (Configuration parent)
+ string locationSubPath;
+
+ internal Configuration (Configuration parent, string locationSubPath)
{
- Init (parent.system, null, parent);
+ this.parent = parent;
+ this.system = parent.system;
+ this.rootGroup = parent.rootGroup;
+ this.locationSubPath = locationSubPath;
}
internal Configuration (InternalConfigurationSystem system, string locationSubPath)
internal void Init (IConfigSystem system, string configPath, Configuration parent)
{
this.system = system;
+ this.configPath = configPath;
streamName = system.Host.GetStreamName (configPath);
this.parent = parent;
if (parent != null)
rootGroup.StreamName = streamName;
}
- if (configPath != null)
+ if (streamName != null)
Load ();
}
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; }
}
public AppSettingsSection AppSettings {
- get { return Sections ["appSettings"] as AppSettingsSection; }
+ get { return (AppSettingsSection) GetSection ("appSettings"); }
}
public ConnectionStringsSection ConnectionStrings {
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 {
return hasFile;
}
}
+
+ ContextInformation evaluationContext;
+ public ContextInformation EvaluationContext {
+ get {
+ if (evaluationContext == null) {
+ object ctx = system.Host.CreateConfigurationContext (configPath, GetLocationSubPath() );
+ evaluationContext = new ContextInformation (this, ctx);
+ }
+
+
+ return evaluationContext;
+ }
+ }
public ConfigurationLocationCollection Locations {
get {
}
}
+ public bool NamespaceDeclared {
+ get { return rootNamespace != null; }
+ set { rootNamespace = value ? "http://schemas.microsoft.com/.NetConfiguration/v2.0" : null; }
+ }
+
public ConfigurationSectionGroup RootSectionGroup {
get {
if (rootSectionGroup == null) {
rootSectionGroup.Initialize (this, rootGroup);
}
return rootSectionGroup;
- }
+ }
}
public ConfigurationSectionGroupCollection SectionGroups {
- get { return RootSectionGroup.SectionGroups; }
+ get { return RootSectionGroup.SectionGroups; }
}
public ConfigurationSectionCollection Sections {
ConfigurationSection sec = data as ConfigurationSection;
if (sec != null || !createDefaultInstance) return sec;
- object secObj = config.CreateInstance () as ConfigurationSection;
- if (!(secObj is ConfigurationSection))
- sec = new RuntimeOnlySection ();
- else {
- sec = (ConfigurationSection) secObj;
+ object secObj = config.CreateInstance ();
+ sec = secObj as ConfigurationSection;
+ if (sec == null) {
+ DefaultSection ds = new DefaultSection ();
+ ds.SectionHandler = secObj as IConfigurationSectionHandler;
+ sec = ds;
}
-
- ConfigurationSection parentSection = parent != null ? parent.GetSectionInstance (config, true) : null;
- sec.RawXml = data as string;
- sec.Reset (parentSection);
+ sec.Configuration = this;
+
+ 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);
- if (data != null) {
- XmlTextReader r = new XmlTextReader (new StringReader (data as string));
+ string xml = data as string;
+ sec.RawXml = xml;
+ sec.Reset (parentSection);
+
+ if (xml != null && xml == data) {
+ 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;
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 ());
-
- sec.SectionInformation.SetName (name);
- SectionInfo section = new SectionInfo (name, sec.SectionInformation.Type, sec.SectionInformation.AllowLocation, sec.SectionInformation.AllowDefinition, sec.SectionInformation.AllowExeDefinition);
+ SectionInfo section = new SectionInfo (name, sec.SectionInformation);
section.StreamName = streamName;
section.ConfigHost = system.Host;
group.AddChild (section);
section.ConfigHost = system.Host;
parentGroup.AddChild (section);
elementData [section] = sec;
+
+ sec.Initialize (this, section);
}
internal void RemoveConfigInfo (ConfigInfo config)
try {
Save (stream, mode, forceUpdateAll);
system.Host.WriteCompleted (streamName, true, ctx);
- } catch (Exception ex) {
+ } catch (Exception) {
system.Host.WriteCompleted (streamName, false, ctx);
throw;
} finally {
{
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)
{
- Save (new FileStream (filename, FileMode.Open, FileAccess.Write), mode, 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);
}
-
+
void Save (Stream stream, ConfigurationSaveMode mode, bool forceUpdateAll)
{
XmlTextWriter tw = new XmlTextWriter (new StreamWriter (stream));
tw.Formatting = Formatting.Indented;
try {
- tw.WriteStartElement ("configuration");
+ tw.WriteStartDocument ();
+ if (rootNamespace != null)
+ tw.WriteStartElement ("configuration", rootNamespace);
+ else
+ tw.WriteStartElement ("configuration");
if (rootGroup.HasConfigContent (this)) {
rootGroup.WriteConfig (this, tw, mode);
}
bool Load ()
{
- if (streamName == null)
+ if (String.IsNullOrEmpty (streamName))
return true;
-
- Stream stream = system.Host.OpenStreamForRead (streamName);
- XmlTextReader reader = null;
+ Stream stream = null;
+
+ // FIXME: we should remove this kind of hack that
+ // hides the actual error
try {
- reader = new XmlTextReader (stream);
+ stream = system.Host.OpenStreamForRead (streamName);
+ } catch (Exception) {
+ return false;
+ }
+
+ using (XmlTextReader reader = new ConfigXmlTextReader (stream, streamName)) {
ReadConfigFile (reader, streamName);
-/* } catch (ConfigurationException) {
- throw;
- } catch (Exception e) {
- throw new ConfigurationException ("Error reading " + fileName, e);
-*/ } finally {
- if (reader != null)
- reader.Close();
}
return true;
}
-
- internal void ReadConfigFile (XmlTextReader reader, string fileName)
+ void ReadConfigFile (XmlReader 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 ();
rootGroup.ReadRootData (reader, this, true);
}
-
- internal void ReadData (XmlTextReader reader, bool allowOverride)
+
+ internal void ReadData (XmlReader reader, bool allowOverride)
{
- rootGroup.ReadRootData (reader, this, 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 ConfigurationException (text, streamName, li != null ? li.LineNumber : 0);
}
}
}