Merge pull request #364 from directhex/master
[mono.git] / mcs / class / System.Configuration / System.Configuration / SectionGroupInfo.cs
index 2215a4ba44f17df55bcd5b3c2b94dcb1c90d092e..5332ef9bc9bb7a51dcfbf215d2dfb755bf2a1e88 100644 (file)
@@ -31,6 +31,7 @@ using System.Collections;
 using System.Collections.Specialized;
 using System.Xml;
 using System.IO;
+using System.Text;
 
 namespace System.Configuration
 {
@@ -42,7 +43,7 @@ namespace System.Configuration
 
                public SectionGroupInfo ()
                {
-                       TypeName = "System.Configuration.ConfigurationSectionGroup";
+                       Type = typeof (ConfigurationSectionGroup);
                }
                
                public SectionGroupInfo (string groupName, string typeName)
@@ -124,7 +125,7 @@ namespace System.Configuration
                
                public override bool HasConfigContent (Configuration cfg)
                {
-                       if (FileName == cfg.FileName) return true;
+                       if (StreamName == cfg.FileName) return true;
                        foreach (ConfigInfoCollection col in new object[] {Sections, Groups}) {
                                foreach (string key in col) {
                                        ConfigInfo cinfo = col [key];
@@ -135,17 +136,20 @@ namespace System.Configuration
                        return false;
                }
                
-               public override void ReadConfig (Configuration cfg, XmlTextReader reader)
+               public override void ReadConfig (Configuration cfg, string streamName, XmlReader reader)
                {
-                       FileName = cfg.FileName;
+                       StreamName = streamName;
+                       ConfigHost = cfg.ConfigHost;
                        
                        if (reader.LocalName != "configSections")
                        {
                                while (reader.MoveToNextAttribute ()) {
                                        if (reader.Name == "name")
                                                Name = reader.Value;
-                                       else if (reader.Name == "type")
+                                       else if (reader.Name == "type") {
                                                TypeName = reader.Value;
+                                               Type = null;
+                                       }
                                        else
                                                ThrowException ("Unrecognized attribute", reader);
                                }
@@ -194,20 +198,23 @@ namespace System.Configuration
 
                                if (name == "section")
                                        cinfo = new SectionInfo ();
-                               else if (name == "sectionGroup")
+                               else if (name == "sectionGroup") {
                                        cinfo = new SectionGroupInfo ();
-                               else
+                               else
                                        ThrowException ("Unrecognized element: " + reader.Name, reader);
                                        
-                               cinfo.ReadConfig (cfg, reader);
+                               cinfo.ReadConfig (cfg, streamName, reader);
                                ConfigInfo actInfo = Groups [cinfo.Name];
                                if (actInfo == null) actInfo = Sections [cinfo.Name];
                                
                                if (actInfo != null) {
                                        if (actInfo.GetType () != cinfo.GetType ())
                                                ThrowException ("A section or section group named '" + cinfo.Name + "' already exists", reader);
+                                       // Merge all the new data
+                                       actInfo.Merge (cinfo);
+                                       
                                        // Make sure that this section is saved in this configuration file:
-                                       actInfo.FileName = cfg.FileName;
+                                       actInfo.StreamName = streamName;
                                }
                                else
                                        AddChild (cinfo);
@@ -238,13 +245,13 @@ namespace System.Configuration
                        writer.WriteEndElement ();
                }
 
-               private void ReadRemoveSection (XmlTextReader reader)
+               private void ReadRemoveSection (XmlReader reader)
                {
                        if (!reader.MoveToNextAttribute () || reader.Name != "name")
                                ThrowException ("Unrecognized attribute.", reader);
 
                        string removeValue = reader.Value;
-                       if (removeValue == null || removeValue.Length == 0)
+                       if (String.IsNullOrEmpty (removeValue))
                                ThrowException ("Empty name to remove", reader);
 
                        reader.MoveToElement ();
@@ -256,45 +263,116 @@ namespace System.Configuration
                        reader.Skip ();
                }
 
-               public void ReadRootData (XmlTextReader reader, Configuration config)
+               public void ReadRootData (XmlReader reader, Configuration config, bool overrideAllowed)
                {
                        reader.MoveToContent ();
-                       ReadContent (reader, config);
+                       ReadContent (reader, config, overrideAllowed, true);
                }
                
-               public override void ReadData (Configuration config, XmlTextReader reader)
+               public override void ReadData (Configuration config, XmlReader reader, bool overrideAllowed)
                {
                        reader.MoveToContent ();
-                       reader.ReadStartElement ();
-                       ReadContent (reader, config);
-                       reader.MoveToContent ();
-                       reader.ReadEndElement ();
+                       if (!reader.IsEmptyElement) {
+                               reader.ReadStartElement ();
+                               ReadContent (reader, config, overrideAllowed, false);
+                               reader.MoveToContent ();
+                               reader.ReadEndElement ();
+                       } else
+                               reader.Read ();
                }
                
-               void ReadContent (XmlTextReader reader, Configuration config)
+               void ReadContent (XmlReader reader, Configuration config, bool overrideAllowed, bool root)
                {
-                       while (reader.NodeType != XmlNodeType.EndElement) {
+                       while (reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.None) {
                                if (reader.NodeType != XmlNodeType.Element) {
                                        reader.Skip ();
                                        continue;
                                }
+
+                               if (reader.LocalName == "dllmap") {
+                                       reader.Skip ();
+                                       continue;
+                               }
+
                                if (reader.LocalName == "location") {
-                                       Configuration locConfig = new Configuration (config);
+                                       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");
-                                       ConfigurationLocation loc = new ConfigurationLocation (path, locConfig);
-                                       config.Locations.Add (loc);
-                                       ReadData (locConfig, reader);
+                                       if (path != null && path.Length > 0) {
+                                               string xml = reader.ReadOuterXml ();
+                                               string[] pathList = path.Split (',');
+                                               string tpath;
+                                               foreach (string p in pathList) {
+                                                       tpath = p.Trim ();
+                                                       if (config.Locations.Find (tpath) != null)
+                                                               ThrowException ("Sections must only appear once per config file.", reader);
+                                                       
+                                                       ConfigurationLocation loc = new ConfigurationLocation (tpath, 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;
-                               
+                       
+                               ConfigInfo data = GetConfigInfo (reader, this);
                                if (data != null)
-                                       data.ReadData (config, reader);
+                                       data.ReadData (config, reader, overrideAllowed);
                                else
                                        ThrowException ("Unrecognized configuration section <" + reader.LocalName + ">", reader);
                        }
                }
+
+               ConfigInfo GetConfigInfo (XmlReader reader, SectionGroupInfo current)
+               {
+                       ConfigInfo data = null;
+                       if (current.sections != null)
+                               data = current.sections [reader.LocalName];
+                       if (data != null)
+                               return data;
+                       if (current.groups != null)
+                               data = current.groups [reader.LocalName];
+                       if (data != null)
+                               return data;
+                       if (current.groups == null)
+                               return null;
+                       // It might be a section in descendant sectionGroups
+                       foreach (string key in current.groups.AllKeys) {
+                               data = GetConfigInfo (reader, (SectionGroupInfo) current.groups [key]);
+                               if (data != null)
+                                       return data;
+                       }
+                       
+                       // It might be in the root section group
+                       return null;
+               }
+
+               internal override void Merge (ConfigInfo newData)
+               {
+                       SectionGroupInfo data = newData as SectionGroupInfo;
+                       if (data == null)
+                               return;
+                       ConfigInfo actInfo;
+                       if (data.sections != null && data.sections.Count > 0)
+                               foreach (string key in data.sections.AllKeys) {
+                                       actInfo = sections[key];
+                                       if (actInfo != null)
+                                               continue;
+                                       sections.Add (key, data.sections[key]);
+                               }
+                       
+                       if (data.groups != null && data.sections != null && data.sections.Count > 0)
+                               foreach (string key in data.groups.AllKeys) {
+                                       actInfo = groups[key];
+                                       if (actInfo != null)
+                                               continue;
+                                       groups.Add (key, data.groups[key]);
+                               }
+               }
                
                public void WriteRootData (XmlWriter writer, Configuration config, ConfigurationSaveMode mode)
                {
@@ -322,6 +400,11 @@ namespace System.Configuration
        
        internal class ConfigInfoCollection : NameObjectCollectionBase
        {
+               public ConfigInfoCollection ()
+                       : base (StringComparer.Ordinal)
+               {
+               }
+
                public ICollection AllKeys
                {
                        get { return Keys; }