-//\r
-// System.Diagnostics.DiagnosticsConfigurationHandler.cs\r
-//\r
-// Comments from John R. Hicks <angryjohn69@nc.rr.com> original implementation \r
-// can be found at: /mcs/docs/apidocs/xml/en/System.Diagnostics\r
-//\r
-// Authors: \r
-// John R. Hicks <angryjohn69@nc.rr.com>\r
-// Jonathan Pryor <jonpryor@vt.edu>\r
-//\r
-// (C) 2002\r
-//\r
-using System;\r
-using System.Collections;\r
-using System.Configuration;\r#if (XML_DEP)
+//
+// System.Diagnostics.DiagnosticsConfigurationHandler.cs
+//
+// Comments from John R. Hicks <angryjohn69@nc.rr.com> original implementation
+// can be found at: /mcs/docs/apidocs/xml/en/System.Diagnostics
+//
+// Authors:
+// John R. Hicks <angryjohn69@nc.rr.com>
+// Jonathan Pryor <jonpryor@vt.edu>
+//
+// (C) 2002, 2005
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Configuration;
+using System.Threading;
+#if (XML_DEP)
using System.Xml;
-#endif\r
-namespace System.Diagnostics\r
-{\r
- internal sealed class DiagnosticsConfiguration\r
- {\r
- private static IDictionary settings = null;\r
-\r
- public static IDictionary Settings {\r
- get {\r
- // TODO: Does anybody know if this is actually thread-safe under .NET?\r
- // I've heard that this construct isn't safe under Java, but it's used\r
- // reasonably often under C++, so I'm not sure about .NET.\r
- if (settings == null) {\r
- lock (typeof(DiagnosticsConfiguration)) {\r
- if (settings == null)\r
- settings = (IDictionary) ConfigurationSettings.GetConfig ("system.diagnostics");\r
- }\r
- }\r
- return settings;\r
- }\r
- }\r
- }\r
-\r#if (XML_DEP)
- public class DiagnosticsConfigurationHandler : IConfigurationSectionHandler\r
- {\r
- delegate void ElementHandler (IDictionary d, XmlNode node);\r
-\r
- IDictionary elementHandlers = new Hashtable ();\r
-\r
- public DiagnosticsConfigurationHandler ()\r
- {\r
- elementHandlers ["assert"] = new ElementHandler (AddAssertNode);\r
- elementHandlers ["switches"] = new ElementHandler (AddSwitchesNode);\r
- elementHandlers ["trace"] = new ElementHandler (AddTraceNode);\r
- }\r
-\r
- public virtual object Create (object parent, object configContext, XmlNode section)\r
- {\r
- IDictionary d;\r
- if (parent == null)\r
- d = new Hashtable (CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);\r
- else\r
- d = (IDictionary) ((ICloneable)parent).Clone();\r
-\r
- foreach (XmlNode child in section.ChildNodes) {\r
- XmlNodeType type = child.NodeType;\r
-\r
- switch (type) {\r
- /* ignore */\r
- case XmlNodeType.Whitespace:\r
- case XmlNodeType.Comment:\r
- continue;\r
- case XmlNodeType.Element:\r
- ElementHandler eh = (ElementHandler) elementHandlers [child.Name];\r
- if (eh != null)\r
- eh (d, child);\r
- else\r
- ThrowUnrecognizedElement (child);\r
- break;\r
- default:\r
- ThrowUnrecognizedElement (child);\r
- break;\r
- }\r
- }\r
-\r
- return d;\r
- }\r
-\r
- // Remarks: Both attribute are optional\r
- private void AddAssertNode (IDictionary d, XmlNode node)\r
- {\r
- XmlAttributeCollection c = node.Attributes;\r
- string assertuienabled = GetAttribute (c, "assertuienabled", false, node);\r
- string logfilename = GetAttribute (c, "logfilename", false, node);\r
- ValidateInvalidAttributes (c, node);\r
- if (assertuienabled != null) {\r
- try {\r
- d ["assertuienabled"] = bool.Parse (assertuienabled);\r
- }\r
- catch (Exception e) {\r
- throw new ConfigurationException ("The `assertuienabled' attribute must be `true' or `false'",\r
- e, node);\r
- }\r
- }\r
-\r
- if (logfilename != null)\r
- d ["logfilename"] = logfilename;\r
-\r
- DefaultTraceListener dtl = (DefaultTraceListener) TraceImpl.Listeners["Default"];\r
- if (dtl != null) {\r
- if (assertuienabled != null)\r
- dtl.AssertUiEnabled = (bool) d ["assertuienabled"];\r
- if (logfilename != null)\r
- dtl.LogFileName = logfilename;\r
- }\r
-\r
- if (node.ChildNodes.Count > 0)\r
- ThrowUnrecognizedElement (node.ChildNodes[0]);\r
- }\r
-\r
- // name attribute is required, value is optional\r
- // Docs do not define "remove" or "clear" elements, but .NET recognizes\r
- // them\r
- private void AddSwitchesNode (IDictionary d, XmlNode node)\r
- {\r
- // There are no attributes on <switch/>\r
- ValidateInvalidAttributes (node.Attributes, node);\r
-\r
- IDictionary newNodes = new Hashtable ();\r
-\r
- foreach (XmlNode child in node.ChildNodes) {\r
- XmlNodeType t = child.NodeType;\r
- if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)\r
- continue;\r
- if (t == XmlNodeType.Element) {\r
- XmlAttributeCollection attributes = child.Attributes;\r
- string name = null;\r
- string value = null;\r
- switch (child.Name) {\r
- case "add":\r
- name = GetAttribute (attributes, "name", true, child);\r
- value = GetAttribute (attributes, "value", false, child);\r
- newNodes[name] = AsString (value);\r
- break;\r
- case "remove":\r
- name = GetAttribute (attributes, "name", true, child);\r
- newNodes.Remove (name);\r
- break;\r
- case "clear":\r
- newNodes.Clear ();\r
- break;\r
- default:\r
- ThrowUnrecognizedElement (child);\r
- break;\r
- }\r
- ValidateInvalidAttributes (attributes, child);\r
- }\r
- else\r
- ThrowUnrecognizedNode (child);\r
- }\r
-\r
- d [node.Name] = newNodes;\r
- }\r
-\r
- private void AddTraceNode (IDictionary d, XmlNode node)\r
- {\r
- AddTraceAttributes (d, node);\r
-\r
- foreach (XmlNode child in node.ChildNodes) {\r
- XmlNodeType t = child.NodeType;\r
- if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)\r
- continue;\r
- if (t == XmlNodeType.Element) {\r
- if (child.Name == "listeners")\r
- AddTraceListeners (child);\r
- else\r
- ThrowUnrecognizedElement (child);\r
- ValidateInvalidAttributes (child.Attributes, child);\r
- }\r
- else\r
- ThrowUnrecognizedNode (child);\r
- }\r
- }\r
-\r
- // all attributes are optional\r
- private void AddTraceAttributes (IDictionary d, XmlNode node)\r
- {\r
- XmlAttributeCollection c = node.Attributes;\r
- string autoflush = GetAttribute (c, "autoflush", false, node);\r
- string indentsize = GetAttribute (c, "indentsize", false, node);\r
- ValidateInvalidAttributes (c, node);\r
- if (autoflush != null) {\r
- try {\r
- bool b = bool.Parse (autoflush);\r
- d ["autoflush"] = b;\r
- TraceImpl.AutoFlush = b;\r
- }\r
- catch (Exception e) {\r
- throw new ConfigurationException ("The `autoflush' attribute must be `true' or `false'",\r
- e, node);\r
- }\r
- }\r
- if (indentsize != null) {\r
- try {\r
- int n = int.Parse (indentsize);\r
- d ["indentsize"] = n;\r
- TraceImpl.IndentSize = n;\r
- }\r
- catch (Exception e) {\r
- throw new ConfigurationException ("The `indentsize' attribute must be an integral value.",\r
- e, node);\r
- }\r
- }\r
- }\r
-\r
- // only defines "add" and "remove", but "clear" also works\r
- // for add, "name" and "type" are required; initializeData is optional\r
- private void AddTraceListeners (XmlNode listenersNode)\r
- {\r
- // There are no attributes on <listeners/>\r
- ValidateInvalidAttributes (listenersNode.Attributes, listenersNode);\r
-\r
- foreach (XmlNode child in listenersNode.ChildNodes) {\r
- XmlNodeType t = child.NodeType;\r
- if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)\r
- continue;\r
- if (t == XmlNodeType.Element) {\r
- XmlAttributeCollection attributes = child.Attributes;\r
- string name = null;\r
- string type = null;\r
- string id = null;\r
- switch (child.Name) {\r
- case "add":\r
- name = GetAttribute (attributes, "name", true, child);\r
- type = GetAttribute (attributes, "type", true, child);\r
- id = GetAttribute (attributes, "initializeData", false, child);\r
- AddTraceListener (name, type, id);\r
- break;\r
- case "remove":\r
- name = GetAttribute (attributes, "name", true, child);\r
- RemoveTraceListener (name);\r
- break;\r
- case "clear":\r
- TraceImpl.Listeners.Clear ();\r
- break;\r
- default:\r
- ThrowUnrecognizedElement (child);\r
- break;\r
- }\r
- ValidateInvalidAttributes (attributes, child);\r
- }\r
- else\r
- ThrowUnrecognizedNode (child);\r
- }\r
- }\r
-\r
- private void AddTraceListener (string name, string type, string initializeData)\r
- {\r
- Type t = Type.GetType (type);\r
- object[] args = null;\r
- if (initializeData == null)\r
- args = new object[]{name};\r
- else\r
- args = new object[]{initializeData, name};\r
- try {\r
- TraceListener l = (TraceListener) Activator.CreateInstance (t, args);\r
- TraceImpl.Listeners.Add (l);\r
- }\r
- catch (Exception e) {\r
- throw new ConfigurationException (\r
- string.Format ("Invalid Type Specified: {0}", type),\r
- e);\r
- }\r
- }\r
-\r
- private void RemoveTraceListener (string name)\r
- {\r
- try {\r
- TraceImpl.Listeners.Remove (name);\r
- }\r
- catch (ArgumentException) {\r
- // The specified listener wasn't in the collection\r
- // Ignore this; .NET does.\r
- }\r
- catch (Exception e) {\r
- throw new ConfigurationException (\r
- string.Format ("Unknown error removing listener: {0}", name),\r
- e);\r
- }\r
- }\r
-\r
- private string GetAttribute (XmlAttributeCollection attrs, string attr, bool required, XmlNode node)\r
- {\r
- XmlAttribute a = attrs[attr];\r
-\r
- string r = null;\r
-\r
- if (a != null) {\r
- r = a.Value;\r
- if (required)\r
- ValidateAttribute (attr, r, node);\r
- attrs.Remove (a);\r
- }\r
- else if (required)\r
- ThrowMissingAttribute (attr, node);\r
-\r
- return r;\r
- }\r
- \r
- private string AsString (string s)\r
- {\r
- return s == null ? string.Empty : s;\r
- }\r
-\r
- private void ValidateAttribute (string attribute, string value, XmlNode node)\r
- {\r
- if (value == null || value.Length == 0)\r
- throw new ConfigurationException (string.Format ("Required attribute `{0}' cannot be empty.", attribute), node);\r
- }\r
-\r
- private void ValidateInvalidAttributes (XmlAttributeCollection c, XmlNode node)\r
- {\r
- if (c.Count != 0)\r
- ThrowUnrecognizedAttribute (c[0].Name, node);\r
- }\r
-\r
- private void ThrowMissingAttribute (string attribute, XmlNode node)\r
- {\r
- throw new ConfigurationException (string.Format ("Missing required attribute `{0}'.", attribute), node);\r
- }\r
-\r
- private void ThrowUnrecognizedNode (XmlNode node)\r
- {\r
- throw new ConfigurationException (\r
- string.Format ("Unrecognized node `{0}'; nodeType={1}", node.Name, node.NodeType),\r
- node);\r
- }\r
-\r
- private void ThrowUnrecognizedElement (XmlNode node)\r
- {\r
- throw new ConfigurationException (\r
- string.Format ("Unrecognized element <{0}/>", node.Name),\r
- node);\r
- }\r
-\r
- private void ThrowUnrecognizedAttribute (string attribute, XmlNode node)\r
- {\r
- throw new ConfigurationException (\r
- string.Format ("Unrecognized attribute `{0}' on element <{1}/>.", attribute, node.Name),\r
- node);\r
- }\r
+#endif
+namespace System.Diagnostics
+{
+ internal sealed class DiagnosticsConfiguration
+ {
+#if NO_LOCK_FREE
+ private static object lock_ = new object();
+#endif
+ private static object settings;
+
+ public static IDictionary Settings {
+ get {
+#if !NO_LOCK_FREE
+ if (settings == null) {
+ object s = ConfigurationSettings.GetConfig ("system.diagnostics");
+ if (s == null)
+ throw new Exception ("INTERNAL configuration error: failed to get configuration 'system.diagnostics'");
+ Thread.MemoryBarrier ();
+ while (Interlocked.CompareExchange (ref settings, s, null) == null) {
+ // do nothing; we're just setting settings.
+ }
+ Thread.MemoryBarrier ();
+ }
+#else
+ lock (lock_) {
+ if (settings == null)
+ settings = ConfigurationSettings.GetConfig ("system.diagnostics");
+ }
+#endif
+ return (IDictionary) settings;
+ }
+ }
}
-#endif\r
-}\r
-\r
+#if (XML_DEP)
+ public class DiagnosticsConfigurationHandler : IConfigurationSectionHandler
+ {
+ delegate void ElementHandler (IDictionary d, XmlNode node);
+
+ IDictionary elementHandlers = new Hashtable ();
+
+ public DiagnosticsConfigurationHandler ()
+ {
+ elementHandlers ["assert"] = new ElementHandler (AddAssertNode);
+ elementHandlers ["switches"] = new ElementHandler (AddSwitchesNode);
+ elementHandlers ["trace"] = new ElementHandler (AddTraceNode);
+#if NET_2_0
+ elementHandlers ["sources"] = new ElementHandler (AddSourcesNode);
+#endif
+ }
+
+ public virtual object Create (object parent, object configContext, XmlNode section)
+ {
+ IDictionary d;
+ if (parent == null)
+ d = new Hashtable (CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
+ else
+ d = (IDictionary) ((ICloneable)parent).Clone();
+
+ foreach (XmlNode child in section.ChildNodes) {
+ XmlNodeType type = child.NodeType;
+
+ switch (type) {
+ /* ignore */
+ case XmlNodeType.Whitespace:
+ case XmlNodeType.Comment:
+ continue;
+ case XmlNodeType.Element:
+ ElementHandler eh = (ElementHandler) elementHandlers [child.Name];
+ if (eh != null)
+ eh (d, child);
+ else
+ ThrowUnrecognizedElement (child);
+ break;
+ default:
+ ThrowUnrecognizedElement (child);
+ break;
+ }
+ }
+
+ return d;
+ }
+
+ // Remarks: Both attribute are optional
+ private void AddAssertNode (IDictionary d, XmlNode node)
+ {
+ XmlAttributeCollection c = node.Attributes;
+ string assertuienabled = GetAttribute (c, "assertuienabled", false, node);
+ string logfilename = GetAttribute (c, "logfilename", false, node);
+ ValidateInvalidAttributes (c, node);
+ if (assertuienabled != null) {
+ try {
+ d ["assertuienabled"] = bool.Parse (assertuienabled);
+ }
+ catch (Exception e) {
+ throw new ConfigurationException ("The `assertuienabled' attribute must be `true' or `false'",
+ e, node);
+ }
+ }
+
+ if (logfilename != null)
+ d ["logfilename"] = logfilename;
+
+ DefaultTraceListener dtl = (DefaultTraceListener) TraceImpl.Listeners["Default"];
+ if (dtl != null) {
+ if (assertuienabled != null)
+ dtl.AssertUiEnabled = (bool) d ["assertuienabled"];
+ if (logfilename != null)
+ dtl.LogFileName = logfilename;
+ }
+
+ if (node.ChildNodes.Count > 0)
+ ThrowUnrecognizedElement (node.ChildNodes[0]);
+ }
+
+ // name and value attributes are required
+ // Docs do not define "remove" or "clear" elements, but .NET recognizes
+ // them
+ private void AddSwitchesNode (IDictionary d, XmlNode node)
+ {
+ // There are no attributes on <switch/>
+ ValidateInvalidAttributes (node.Attributes, node);
+
+ IDictionary newNodes = new Hashtable ();
+
+ foreach (XmlNode child in node.ChildNodes) {
+ XmlNodeType t = child.NodeType;
+ if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)
+ continue;
+ if (t == XmlNodeType.Element) {
+ XmlAttributeCollection attributes = child.Attributes;
+ string name = null;
+ string value = null;
+ switch (child.Name) {
+ case "add":
+ name = GetAttribute (attributes, "name", true, child);
+ value = GetAttribute (attributes, "value", true, child);
+ value = AsString (value); ValidateIntegralValue (name, value);
+ newNodes [name] = value;
+ break;
+ case "remove":
+ name = GetAttribute (attributes, "name", true, child);
+ newNodes.Remove (name);
+ break;
+ case "clear":
+ newNodes.Clear ();
+ break;
+ default:
+ ThrowUnrecognizedElement (child);
+ break;
+ }
+ ValidateInvalidAttributes (attributes, child);
+ }
+ else
+ ThrowUnrecognizedNode (child);
+ }
+
+ d [node.Name] = newNodes;
+ }
+
+ private static int ValidateIntegralValue (string name, string value)
+ {
+ try {
+ return int.Parse (value);
+ } catch {
+ throw new ConfigurationException (string.Format (
+ "Error in '{0}': " +
+ "The value of a switch must be integral", name));
+ }
+ }
+
+ private void AddTraceNode (IDictionary d, XmlNode node)
+ {
+ AddTraceAttributes (d, node);
+
+ foreach (XmlNode child in node.ChildNodes) {
+ XmlNodeType t = child.NodeType;
+ if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)
+ continue;
+ if (t == XmlNodeType.Element) {
+ if (child.Name == "listeners")
+ AddTraceListeners (child);
+ else
+ ThrowUnrecognizedElement (child);
+ ValidateInvalidAttributes (child.Attributes, child);
+ }
+ else
+ ThrowUnrecognizedNode (child);
+ }
+ }
+
+ // all attributes are optional
+ private void AddTraceAttributes (IDictionary d, XmlNode node)
+ {
+ XmlAttributeCollection c = node.Attributes;
+ string autoflush = GetAttribute (c, "autoflush", false, node);
+ string indentsize = GetAttribute (c, "indentsize", false, node);
+ ValidateInvalidAttributes (c, node);
+ if (autoflush != null) {
+ try {
+ bool b = bool.Parse (autoflush);
+ d ["autoflush"] = b;
+ TraceImpl.AutoFlush = b;
+ }
+ catch (Exception e) {
+ throw new ConfigurationException ("The `autoflush' attribute must be `true' or `false'",
+ e, node);
+ }
+ }
+ if (indentsize != null) {
+ try {
+ int n = int.Parse (indentsize);
+ d ["indentsize"] = n;
+ TraceImpl.IndentSize = n;
+ }
+ catch (ConfigurationException e) {
+ throw;
+ }
+ catch (Exception e) {
+ throw new ConfigurationException ("The `indentsize' attribute must be an integral value.",
+ e, node);
+ }
+ }
+ }
+
+#if NET_2_0
+ static readonly Hashtable static_sources = new Hashtable ();
+
+ private void AddSourcesNode (IDictionary d, XmlNode node)
+ {
+ // FIXME: are there valid attributes?
+ ValidateInvalidAttributes (node.Attributes, node);
+ Hashtable sources = d ["sources"] as Hashtable;
+ if (sources == null) {
+ sources = new Hashtable ();
+ d ["sources"] = sources;
+ }
+ // FIXME: here I replace the table with fake static variable.
+ sources = static_sources;
+
+ foreach (XmlNode child in node.ChildNodes) {
+ XmlNodeType t = child.NodeType;
+ if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)
+ continue;
+ if (t == XmlNodeType.Element) {
+ if (child.Name == "source")
+ AddTraceSource (sources, child);
+ else
+ ThrowUnrecognizedElement (child);
+// ValidateInvalidAttributes (child.Attributes, child);
+ }
+ else
+ ThrowUnrecognizedNode (child);
+ }
+ }
+
+ private void AddTraceSource (Hashtable sources, XmlNode node)
+ {
+ string name = null;
+ SourceLevels levels = SourceLevels.Error;
+ StringDictionary atts = new StringDictionary ();
+ foreach (XmlAttribute a in node.Attributes) {
+ switch (a.Name) {
+ case "name":
+ name = a.Value;
+ break;
+ case "switchValue":
+ levels = (SourceLevels) Enum.Parse (typeof (SourceLevels), a.Value);
+ break;
+ default:
+ atts [a.Name] = a.Value;
+ break;
+ }
+ }
+ if (name == null)
+ throw new ConfigurationException ("Mandatory attribute 'name' is missing in 'source' element.");
+
+ // FIXME: it should raise an error for duplicate name sources.
+ if (sources.ContainsKey (name))
+ return;
+
+ TraceSource source = new TraceSource (name, levels);
+ sources.Add (source.Name, source);
+
+ foreach (XmlNode child in node.ChildNodes) {
+ XmlNodeType t = child.NodeType;
+ if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)
+ continue;
+ if (t == XmlNodeType.Element) {
+ if (child.Name == "listeners")
+ AddTraceListeners (child);
+ else
+ ThrowUnrecognizedElement (child);
+ ValidateInvalidAttributes (child.Attributes, child);
+ }
+ else
+ ThrowUnrecognizedNode (child);
+ }
+ }
+#endif
+
+ // only defines "add" and "remove", but "clear" also works
+ // for add, "name" and "type" are required; initializeData is optional
+ private void AddTraceListeners (XmlNode listenersNode)
+ {
+ // There are no attributes on <listeners/>
+ ValidateInvalidAttributes (listenersNode.Attributes, listenersNode);
+
+ foreach (XmlNode child in listenersNode.ChildNodes) {
+ XmlNodeType t = child.NodeType;
+ if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)
+ continue;
+ if (t == XmlNodeType.Element) {
+ XmlAttributeCollection attributes = child.Attributes;
+ string name = null;
+ string type = null;
+ string id = null;
+ switch (child.Name) {
+ case "add":
+ name = GetAttribute (attributes, "name", true, child);
+ type = GetAttribute (attributes, "type", true, child);
+ id = GetAttribute (attributes, "initializeData", false, child);
+ AddTraceListener (name, type, id);
+ break;
+ case "remove":
+ name = GetAttribute (attributes, "name", true, child);
+ RemoveTraceListener (name);
+ break;
+ case "clear":
+ TraceImpl.Listeners.Clear ();
+ break;
+ default:
+ ThrowUnrecognizedElement (child);
+ break;
+ }
+ ValidateInvalidAttributes (attributes, child);
+ }
+ else
+ ThrowUnrecognizedNode (child);
+ }
+ }
+
+ private void AddTraceListener (string name, string type, string initializeData)
+ {
+ Type t = Type.GetType (type);
+ if (t == null)
+ throw new ConfigurationException (string.Format ("Invalid Type Specified: {0}", type));
+
+ object[] args;
+ Type[] types;
+
+ if (initializeData != null) {
+ args = new object[] { initializeData };
+ types = new Type[] { typeof(string) };
+ }
+ else {
+ args = null;
+ types = new Type[0];
+ }
+
+ System.Reflection.ConstructorInfo ctor = t.GetConstructor (types);
+ if (ctor == null)
+ throw new ConfigurationException ("Couldn't find constructor for class " + type);
+
+ TraceListener l = (TraceListener) ctor.Invoke (args);
+ l.Name = name;
+ TraceImpl.Listeners.Add (l);
+ }
+
+ private void RemoveTraceListener (string name)
+ {
+ try {
+ TraceImpl.Listeners.Remove (name);
+ }
+ catch (ArgumentException) {
+ // The specified listener wasn't in the collection
+ // Ignore this; .NET does.
+ }
+ catch (Exception e) {
+ throw new ConfigurationException (
+ string.Format ("Unknown error removing listener: {0}", name),
+ e);
+ }
+ }
+
+ private string GetAttribute (XmlAttributeCollection attrs, string attr, bool required, XmlNode node)
+ {
+ XmlAttribute a = attrs[attr];
+
+ string r = null;
+
+ if (a != null) {
+ r = a.Value;
+ if (required)
+ ValidateAttribute (attr, r, node);
+ attrs.Remove (a);
+ }
+ else if (required)
+ ThrowMissingAttribute (attr, node);
+
+ return r;
+ }
+
+ private string AsString (string s)
+ {
+ return s == null ? string.Empty : s;
+ }
+
+ private void ValidateAttribute (string attribute, string value, XmlNode node)
+ {
+ if (value == null || value.Length == 0)
+ throw new ConfigurationException (string.Format ("Required attribute `{0}' cannot be empty.", attribute), node);
+ }
+
+ private void ValidateInvalidAttributes (XmlAttributeCollection c, XmlNode node)
+ {
+ if (c.Count != 0)
+ ThrowUnrecognizedAttribute (c[0].Name, node);
+ }
+
+ private void ThrowMissingAttribute (string attribute, XmlNode node)
+ {
+ throw new ConfigurationException (string.Format ("Missing required attribute `{0}'.", attribute), node);
+ }
+
+ private void ThrowUnrecognizedNode (XmlNode node)
+ {
+ throw new ConfigurationException (
+ string.Format ("Unrecognized node `{0}'; nodeType={1}", node.Name, node.NodeType),
+ node);
+ }
+
+ private void ThrowUnrecognizedElement (XmlNode node)
+ {
+ throw new ConfigurationException (
+ string.Format ("Unrecognized element <{0}/>", node.Name),
+ node);
+ }
+
+ private void ThrowUnrecognizedAttribute (string attribute, XmlNode node)
+ {
+ throw new ConfigurationException (
+ string.Format ("Unrecognized attribute `{0}' on element <{1}/>.", attribute, node.Name),
+ node);
+ }
+ }
+#endif
+}
+