2 // System.Diagnostics.DiagnosticsConfigurationHandler.cs
\r
4 // Comments from John R. Hicks <angryjohn69@nc.rr.com> original implementation
\r
5 // can be found at: /mcs/docs/apidocs/xml/en/System.Diagnostics
\r
8 // John R. Hicks <angryjohn69@nc.rr.com>
\r
9 // Jonathan Pryor <jonpryor@vt.edu>
\r
14 using System.Collections;
\r
15 using System.Configuration;
\r
18 namespace System.Diagnostics
\r
20 internal sealed class DiagnosticsConfiguration
\r
22 private static IDictionary settings = null;
\r
24 public static IDictionary Settings {
\r
26 // TODO: Does anybody know if this is actually thread-safe under .NET?
\r
27 // I've heard that this construct isn't safe under Java, but it's used
\r
28 // reasonably often under C++, so I'm not sure about .NET.
\r
29 if (settings == null) {
\r
30 lock (typeof(DiagnosticsConfiguration)) {
\r
31 if (settings == null)
\r
32 settings = (IDictionary) ConfigurationSettings.GetConfig ("system.diagnostics");
\r
40 public class DiagnosticsConfigurationHandler : IConfigurationSectionHandler
\r
42 delegate void ElementHandler (IDictionary d, XmlNode node);
\r
44 IDictionary elementHandlers = new Hashtable ();
\r
46 public DiagnosticsConfigurationHandler ()
\r
48 elementHandlers ["assert"] = new ElementHandler (AddAssertNode);
\r
49 elementHandlers ["switches"] = new ElementHandler (AddSwitchesNode);
\r
50 elementHandlers ["trace"] = new ElementHandler (AddTraceNode);
\r
53 public virtual object Create (object parent, object configContext, XmlNode section)
\r
57 d = new Hashtable (CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
\r
59 d = (IDictionary) ((ICloneable)parent).Clone();
\r
61 foreach (XmlNode child in section.ChildNodes) {
\r
62 XmlNodeType type = child.NodeType;
\r
66 case XmlNodeType.Whitespace:
\r
67 case XmlNodeType.Comment:
\r
69 case XmlNodeType.Element:
\r
70 ElementHandler eh = (ElementHandler) elementHandlers [child.Name];
\r
74 ThrowUnrecognizedElement (child);
\r
77 ThrowUnrecognizedElement (child);
\r
85 // Remarks: Both attribute are optional
\r
86 private void AddAssertNode (IDictionary d, XmlNode node)
\r
88 XmlAttributeCollection c = node.Attributes;
\r
89 string assertuienabled = GetAttribute (c, "assertuienabled", false, node);
\r
90 string logfilename = GetAttribute (c, "logfilename", false, node);
\r
91 ValidateInvalidAttributes (c, node);
\r
92 if (assertuienabled != null) {
\r
94 d ["assertuienabled"] = bool.Parse (assertuienabled);
\r
96 catch (Exception e) {
\r
97 throw new ConfigurationException ("The `assertuienabled' attribute must be `true' or `false'",
\r
102 if (logfilename != null)
\r
103 d ["logfilename"] = logfilename;
\r
105 DefaultTraceListener dtl = (DefaultTraceListener) TraceImpl.Listeners["Default"];
\r
107 if (assertuienabled != null)
\r
108 dtl.AssertUiEnabled = (bool) d ["assertuienabled"];
\r
109 if (logfilename != null)
\r
110 dtl.LogFileName = logfilename;
\r
113 if (node.ChildNodes.Count > 0)
\r
114 ThrowUnrecognizedElement (node.ChildNodes[0]);
\r
117 // name attribute is required, value is optional
\r
118 // Docs do not define "remove" or "clear" elements, but .NET recognizes
\r
120 private void AddSwitchesNode (IDictionary d, XmlNode node)
\r
122 // There are no attributes on <switch/>
\r
123 ValidateInvalidAttributes (node.Attributes, node);
\r
125 IDictionary newNodes = new Hashtable ();
\r
127 foreach (XmlNode child in node.ChildNodes) {
\r
128 XmlNodeType t = child.NodeType;
\r
129 if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)
\r
131 if (t == XmlNodeType.Element) {
\r
132 XmlAttributeCollection attributes = child.Attributes;
\r
133 string name = null;
\r
134 string value = null;
\r
135 switch (child.Name) {
\r
137 name = GetAttribute (attributes, "name", true, child);
\r
138 value = GetAttribute (attributes, "value", false, child);
\r
139 newNodes[name] = AsString (value);
\r
142 name = GetAttribute (attributes, "name", true, child);
\r
143 newNodes.Remove (name);
\r
149 ThrowUnrecognizedElement (child);
\r
152 ValidateInvalidAttributes (attributes, child);
\r
155 ThrowUnrecognizedNode (child);
\r
158 d [node.Name] = newNodes;
\r
161 private void AddTraceNode (IDictionary d, XmlNode node)
\r
163 AddTraceAttributes (d, node);
\r
165 foreach (XmlNode child in node.ChildNodes) {
\r
166 XmlNodeType t = child.NodeType;
\r
167 if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)
\r
169 if (t == XmlNodeType.Element) {
\r
170 if (child.Name == "listeners")
\r
171 AddTraceListeners (child);
\r
173 ThrowUnrecognizedElement (child);
\r
174 ValidateInvalidAttributes (child.Attributes, child);
\r
177 ThrowUnrecognizedNode (child);
\r
181 // all attributes are optional
\r
182 private void AddTraceAttributes (IDictionary d, XmlNode node)
\r
184 XmlAttributeCollection c = node.Attributes;
\r
185 string autoflush = GetAttribute (c, "autoflush", false, node);
\r
186 string indentsize = GetAttribute (c, "indentsize", false, node);
\r
187 ValidateInvalidAttributes (c, node);
\r
188 if (autoflush != null) {
\r
190 bool b = bool.Parse (autoflush);
\r
191 d ["autoflush"] = b;
\r
192 TraceImpl.AutoFlush = b;
\r
194 catch (Exception e) {
\r
195 throw new ConfigurationException ("The `autoflush' attribute must be `true' or `false'",
\r
199 if (indentsize != null) {
\r
201 int n = int.Parse (indentsize);
\r
202 d ["indentsize"] = n;
\r
203 TraceImpl.IndentSize = n;
\r
205 catch (Exception e) {
\r
206 throw new ConfigurationException ("The `indentsize' attribute must be an integral value.",
\r
212 // only defines "add" and "remove", but "clear" also works
\r
213 // for add, "name" and "type" are required; initializeData is optional
\r
214 private void AddTraceListeners (XmlNode listenersNode)
\r
216 // There are no attributes on <listeners/>
\r
217 ValidateInvalidAttributes (listenersNode.Attributes, listenersNode);
\r
219 foreach (XmlNode child in listenersNode.ChildNodes) {
\r
220 XmlNodeType t = child.NodeType;
\r
221 if (t == XmlNodeType.Whitespace || t == XmlNodeType.Comment)
\r
223 if (t == XmlNodeType.Element) {
\r
224 XmlAttributeCollection attributes = child.Attributes;
\r
225 string name = null;
\r
226 string type = null;
\r
228 switch (child.Name) {
\r
230 name = GetAttribute (attributes, "name", true, child);
\r
231 type = GetAttribute (attributes, "type", true, child);
\r
232 id = GetAttribute (attributes, "initializeData", false, child);
\r
233 AddTraceListener (name, type, id);
\r
236 name = GetAttribute (attributes, "name", true, child);
\r
237 RemoveTraceListener (name);
\r
240 TraceImpl.Listeners.Clear ();
\r
243 ThrowUnrecognizedElement (child);
\r
246 ValidateInvalidAttributes (attributes, child);
\r
249 ThrowUnrecognizedNode (child);
\r
253 private void AddTraceListener (string name, string type, string initializeData)
\r
255 Type t = Type.GetType (type);
\r
256 object[] args = null;
\r
257 if (initializeData == null)
\r
258 args = new object[]{name};
\r
260 args = new object[]{initializeData, name};
\r
262 TraceListener l = (TraceListener) Activator.CreateInstance (t, args);
\r
263 TraceImpl.Listeners.Add (l);
\r
265 catch (Exception e) {
\r
266 throw new ConfigurationException (
\r
267 string.Format ("Invalid Type Specified: {0}", type),
\r
272 private void RemoveTraceListener (string name)
\r
275 TraceImpl.Listeners.Remove (name);
\r
277 catch (ArgumentException e) {
\r
278 // The specified listener wasn't in the collection
\r
279 // Ignore this; .NET does.
\r
281 catch (Exception e) {
\r
282 throw new ConfigurationException (
\r
283 string.Format ("Unknown error removing listener: {0}", name),
\r
288 private string GetAttribute (XmlAttributeCollection attrs, string attr, bool required, XmlNode node)
\r
290 XmlAttribute a = attrs[attr];
\r
297 ValidateAttribute (attr, r, node);
\r
301 ThrowMissingAttribute (attr, node);
\r
306 private string AsString (string s)
\r
308 return s == null ? string.Empty : s;
\r
311 private void ValidateAttribute (string attribute, string value, XmlNode node)
\r
313 if (value == null || value.Length == 0)
\r
314 throw new ConfigurationException (string.Format ("Required attribute `{0}' cannot be empty.", attribute), node);
\r
317 private void ValidateInvalidAttributes (XmlAttributeCollection c, XmlNode node)
\r
320 ThrowUnrecognizedAttribute (c[0].Name, node);
\r
323 private void ThrowMissingAttribute (string attribute, XmlNode node)
\r
325 throw new ConfigurationException (string.Format ("Missing required attribute `{0}'.", attribute), node);
\r
328 private void ThrowUnrecognizedNode (XmlNode node)
\r
330 throw new ConfigurationException (
\r
331 string.Format ("Unrecognized node `{0}'; nodeType={1}", node.Name, node.NodeType),
\r
335 private void ThrowUnrecognizedElement (XmlNode node)
\r
337 throw new ConfigurationException (
\r
338 string.Format ("Unrecognized element <{0}/>", node.Name),
\r
342 private void ThrowUnrecognizedAttribute (string attribute, XmlNode node)
\r
344 throw new ConfigurationException (
\r
345 string.Format ("Unrecognized attribute `{0}' on element <{1}/>.", attribute, node.Name),
\r