Excluded test DefaultType in ToolboxItemAttributeTests.cs under 'TARGET_JVM'
[mono.git] / mcs / class / System / System.Diagnostics / DiagnosticsConfigurationHandler.cs
index 706ce06c4a92956217a4d6eaac52cbe8ad4ff563..8dd3ff9225e2e2b698e88d17e196402228d04b8f 100644 (file)
-//\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
+}
+