**** Merged r40732-r40872 from MCS ****
[mono.git] / mcs / class / System / System.Configuration / SectionGroupInfo.cs
1 //
2 // System.Configuration.SectionGroupInfo.cs
3 //
4 // Authors:
5 //      Lluis Sanchez (lluis@novell.com)
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
14 // 
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
17 // 
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 //
26 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
27 //
28 #if NET_2_0 && XML_DEP
29 using System;
30 using System.Collections;
31 using System.Collections.Specialized;
32 using System.Xml;
33 using System.IO;
34
35 namespace System.Configuration
36 {
37         internal class SectionGroupInfo: ConfigInfo
38         {
39                 ConfigInfoCollection sections;
40                 ConfigInfoCollection groups;
41                 static ConfigInfoCollection emptyList = new ConfigInfoCollection ();
42
43                 public SectionGroupInfo ()
44                 {
45                         TypeName = "System.Configuration.ConfigurationSectionGroup";
46                 }
47                 
48                 public SectionGroupInfo (string groupName, string typeName)
49                 {
50                         Name = groupName;
51                         TypeName = typeName;
52                 }
53                 
54                 public void AddChild (ConfigInfo data)
55                 {
56                         data.Parent = this;
57                         if (data is SectionInfo) {
58                                 if (sections == null) sections = new ConfigInfoCollection ();
59                                 sections [data.Name] = data;
60                         }
61                         else {
62                                 if (groups == null) groups = new ConfigInfoCollection ();
63                                 groups [data.Name] = data;
64                         }
65                 }
66                 
67                 public void Clear ()
68                 {
69                         if (sections != null) sections.Clear ();
70                         if (groups != null) groups.Clear ();
71                 }
72                 
73                 public bool HasChild (string name)
74                 {
75                         if (sections != null && sections [name] != null) return true;
76                         return (groups != null && groups [name] != null);
77                 }
78                 
79                 public void RemoveChild (string name)
80                 {
81                         if (sections != null)
82                                 sections.Remove (name);
83                         if (groups != null)
84                                 groups.Remove (name);
85                 }
86                 
87                 public SectionInfo GetChildSection (string name)
88                 {
89                         if (sections != null)
90                                 return sections [name] as SectionInfo;
91                         else
92                                 return null;
93                 }
94                 
95                 public SectionGroupInfo GetChildGroup (string name)
96                 {
97                         if (groups != null)
98                                 return groups [name] as SectionGroupInfo;
99                         else
100                                 return null;
101                 }
102                 
103                 public ConfigInfoCollection Sections
104                 {
105                         get { if (sections == null) return emptyList; else return sections; }
106                 }
107                 
108                 public ConfigInfoCollection Groups
109                 {
110                         get { if (groups == null) return emptyList; else return groups; }
111                 }
112                 
113                 public override bool HasDataContent (Configuration config)
114                 {
115                         foreach (ConfigInfoCollection col in new object[] {Sections, Groups}) {
116                                 foreach (string key in col) {
117                                         ConfigInfo cinfo = col [key];
118                                         if (cinfo.HasDataContent (config))
119                                                 return true;
120                                 }
121                         }
122                         return false;
123                 }
124                 
125                 public override bool HasConfigContent (Configuration cfg)
126                 {
127                         if (FileName == cfg.FileName) return true;
128                         foreach (ConfigInfoCollection col in new object[] {Sections, Groups}) {
129                                 foreach (string key in col) {
130                                         ConfigInfo cinfo = col [key];
131                                         if (cinfo.HasConfigContent (cfg))
132                                                 return true;
133                                 }
134                         }
135                         return false;
136                 }
137                 
138 #if (XML_DEP)
139
140                 public override void ReadConfig (Configuration cfg, XmlTextReader reader)
141                 {
142                         FileName = cfg.FileName;
143                         
144                         if (reader.LocalName != "configSections")
145                         {
146                                 while (reader.MoveToNextAttribute ()) {
147                                         if (reader.Name == "name")
148                                                 Name = reader.Value;
149                                         else if (reader.Name == "type")
150                                                 TypeName = reader.Value;
151                                         else
152                                                 ThrowException ("Unrecognized attribute", reader);
153                                 }
154                                 
155                                 if (Name == null)
156                                         ThrowException ("sectionGroup must have a 'name' attribute", reader);
157         
158                                 if (Name == "location")
159                                         ThrowException ("location is a reserved section name", reader);
160                         }
161                         
162                         if (TypeName == null)
163                                 TypeName = "System.Configuration.ConfigurationSectionGroup";
164                         
165                         if (reader.IsEmptyElement) {
166                                 reader.Skip ();
167                                 return;
168                         }
169                         
170                         reader.ReadStartElement ();
171                         reader.MoveToContent ();
172                         
173                         while (reader.NodeType != XmlNodeType.EndElement)
174                         {
175                                 if (reader.NodeType != XmlNodeType.Element) {
176                                         reader.Skip ();
177                                         continue;
178                                 }
179                                 
180                                 string name = reader.LocalName;
181                                 ConfigInfo cinfo = null;
182                                 
183                                 if (name == "remove") {
184                                         ReadRemoveSection (reader);
185                                         continue;
186                                 }
187
188                                 if (name == "clear") {
189                                         if (reader.HasAttributes)
190                                                 ThrowException ("Unrecognized attribute.", reader);
191
192                                         Clear ();
193                                         reader.Skip ();
194                                         continue;
195                                 }
196
197                                 if (name == "section")
198                                         cinfo = new SectionInfo ();
199                                 else if (name == "sectionGroup")
200                                         cinfo = new SectionGroupInfo ();
201                                 else
202                                         ThrowException ("Unrecognized element: " + reader.Name, reader);
203                                         
204                                 cinfo.ReadConfig (cfg, reader);
205                                 ConfigInfo actInfo = Groups [cinfo.Name];
206                                 if (actInfo == null) actInfo = Sections [cinfo.Name];
207                                 
208                                 if (actInfo != null) {
209                                         if (actInfo.GetType () != cinfo.GetType ())
210                                                 ThrowException ("A section or section group named '" + cinfo.Name + "' already exists", reader);
211                                         // Make sure that this section is saved in this configuration file:
212                                         actInfo.FileName = cfg.FileName;
213                                 }
214                                 else
215                                         AddChild (cinfo);
216                         }
217                         
218                         reader.ReadEndElement ();
219                 }
220                 
221                 public override void WriteConfig (Configuration cfg, XmlWriter writer, ConfigurationUpdateMode mode)
222                 {
223                         if (Name != null) {
224                                 writer.WriteStartElement ("sectionGroup");
225                                 writer.WriteAttributeString ("name", Name);
226                                 if (TypeName != null && TypeName != "" && TypeName != "System.Configuration.ConfigurationSectionGroup")
227                                         writer.WriteAttributeString ("type", TypeName);
228                         }
229                         else
230                                 writer.WriteStartElement ("configSections");
231                         
232                         foreach (ConfigInfoCollection col in new object[] {Sections, Groups}) {
233                                 foreach (string key in col) {
234                                         ConfigInfo cinfo = col [key];
235                                         if (cinfo.HasConfigContent (cfg))
236                                                 cinfo.WriteConfig (cfg, writer, mode);
237                                 }
238                         }
239                         
240                         writer.WriteEndElement ();
241                 }
242
243                 private void ReadRemoveSection (XmlTextReader reader)
244                 {
245                         if (!reader.MoveToNextAttribute () || reader.Name != "name")
246                                 ThrowException ("Unrecognized attribute.", reader);
247
248                         string removeValue = reader.Value;
249                         if (removeValue == null || removeValue.Length == 0)
250                                 ThrowException ("Empty name to remove", reader);
251
252                         reader.MoveToElement ();
253
254                         if (!HasChild (removeValue))
255                                 ThrowException ("No factory for " + removeValue, reader);
256
257                         RemoveChild (removeValue);
258                         reader.Skip ();
259                 }
260
261                 public void ReadRootData (XmlTextReader reader, Configuration config)
262                 {
263                         reader.MoveToContent ();
264                         ReadContent (reader, config);
265                 }
266                 
267                 public override void ReadData (Configuration config, XmlTextReader reader)
268                 {
269                         reader.MoveToContent ();
270                         reader.ReadStartElement ();
271                         ReadContent (reader, config);
272                         reader.MoveToContent ();
273                         reader.ReadEndElement ();
274                 }
275                 
276                 void ReadContent (XmlTextReader reader, Configuration config)
277                 {
278                         while (reader.NodeType != XmlNodeType.EndElement) {
279                                 if (reader.NodeType != XmlNodeType.Element) {
280                                         reader.Skip ();
281                                         continue;
282                                 }
283                                 if (reader.LocalName == "location") {
284                                         Configuration locConfig = new Configuration (config);
285                                         string path = reader.GetAttribute ("path");
286                                         ConfigurationLocation loc = new ConfigurationLocation (path, locConfig);
287                                         config.Locations.Add (loc);
288                                         ReadData (locConfig, reader);
289                                 }
290                                 
291                                 ConfigInfo data = (sections != null) ? (ConfigInfo) sections [reader.LocalName] : (ConfigInfo) null;
292                                 if (data == null) data = (groups != null) ? (ConfigInfo) groups [reader.LocalName] : (ConfigInfo) null;
293                                 
294                                 if (data != null)
295                                         data.ReadData (config, reader);
296                                 else
297                                         ThrowException ("Unrecognized configuration section <" + reader.LocalName + ">", reader);
298                         }
299                 }
300                 
301                 public void WriteRootData (XmlWriter writer, Configuration config, ConfigurationUpdateMode mode)
302                 {
303                         WriteContent (writer, config, mode, false);
304                 }
305                 
306                 public override void WriteData (Configuration config, XmlWriter writer, ConfigurationUpdateMode mode)
307                 {
308                         writer.WriteStartElement (Name);
309                         WriteContent (writer, config, mode, true);
310                         writer.WriteEndElement ();
311                 }
312                 
313                 public void WriteContent (XmlWriter writer, Configuration config, ConfigurationUpdateMode mode, bool writeElem)
314                 {
315                         foreach (ConfigInfoCollection col in new object[] {Sections, Groups}) {
316                                 foreach (string key in col) {
317                                         ConfigInfo cinfo = col [key];
318                                         if (cinfo.HasDataContent (config))
319                                                 cinfo.WriteData (config, writer, mode);
320                                 }
321                         }
322                 }
323 #endif
324         }
325         
326         internal class ConfigInfoCollection : NameObjectCollectionBase
327         {
328                 public ICollection AllKeys
329                 {
330                         get { return Keys; }
331                 }
332                 
333                 public ConfigInfo this [string name]
334                 {
335                         get { return (ConfigInfo) BaseGet (name); }
336                         set { BaseSet (name, value); }
337                 }
338         
339                 public ConfigInfo this [int index]
340                 {
341                         get { return (ConfigInfo) BaseGet (index); }
342                         set { BaseSet (index, value); }
343                 }
344                 
345                 public void Add (string name, ConfigInfo config)
346                 {
347                         BaseAdd (name, config);
348                 }
349                 
350                 public void Clear ()
351                 {
352                         BaseClear ();
353                 }
354                 
355                 public string GetKey (int index)
356                 {
357                         return BaseGetKey (index);
358                 }
359                 
360                 public void Remove (string name)
361                 {
362                         BaseRemove (name);
363                 }
364                 
365                 public void RemoveAt (int index)
366                 {
367                         BaseRemoveAt (index);
368                 }
369         }
370 }
371
372 #endif