2008-04-16 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System / System.Diagnostics / TraceListener.cs
1 //
2 // System.Diagnostics.TraceListener.cs
3 //
4 // Authors:
5 //   Jonathan Pryor (jonpryor@vt.edu)
6 //   Atsushi Enomoto (atsushi@ximian.com)
7 //
8 // Comments from John R. Hicks <angryjohn69@nc.rr.com> original implementation 
9 // can be found at: /mcs/docs/apidocs/xml/en/System.Diagnostics
10 //
11 // (C) 2002 Jonathan Pryor
12 // (C) 2007 Novell, Inc.
13 //
14
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 //
35
36 using System;
37 using System.Collections;
38 using System.Collections.Specialized;
39 using System.Runtime.InteropServices;
40 using System.Diagnostics;
41
42 namespace System.Diagnostics {
43
44         public abstract class TraceListener : MarshalByRefObject, IDisposable {
45
46 #if TARGET_JVM
47                 readonly LocalDataStoreSlot _indentLevelStore = System.Threading.Thread.AllocateDataSlot ();
48                 readonly LocalDataStoreSlot _indentSizeStore = System.Threading.Thread.AllocateDataSlot ();
49                 readonly LocalDataStoreSlot _attributesStore = System.Threading.Thread.AllocateDataSlot ();
50                 readonly LocalDataStoreSlot _filterStore = System.Threading.Thread.AllocateDataSlot ();
51                 readonly LocalDataStoreSlot _optionsStore = System.Threading.Thread.AllocateDataSlot ();
52                 
53                 private int indentLevel {
54                         get {
55                                 object o = System.Threading.Thread.GetData (_indentLevelStore);
56                                 if (o == null)
57                                         return 0;
58                                 return (int) o;
59                         }
60                         set { System.Threading.Thread.SetData (_indentLevelStore, value); }
61                 }
62                 
63                 private int indentSize {
64                         get {
65                                 object o = System.Threading.Thread.GetData (_indentSizeStore);
66                                 if (o == null)
67                                         return 4;
68                                 return (int) o;
69                         }
70                         set { System.Threading.Thread.SetData (_indentSizeStore, value); }
71                 }
72
73 #if NET_2_0
74                 private StringDictionary attributes {
75                         get { return (StringDictionary) System.Threading.Thread.GetData (_attributesStore); }
76                         set { System.Threading.Thread.SetData (_attributesStore, value); }
77                 }
78
79                 private TraceFilter filter {
80                         get { return (TraceFilter) System.Threading.Thread.GetData (_filterStore); }
81                         set { System.Threading.Thread.SetData (_filterStore, value); }
82                 }
83
84                 private TraceOptions options {\r
85                         get {\r
86                                 object o = System.Threading.Thread.GetData (_optionsStore);\r
87                                 if (o == null)\r
88                                         return TraceOptions.None;\r
89                                 return (TraceOptions) o;\r
90                         }
91                         set { System.Threading.Thread.SetData (_optionsStore, value); }
92                 }
93 #endif
94 #else
95                 [ThreadStatic]
96                 private int indentLevel = 0;
97
98                 [ThreadStatic]
99                 private int indentSize = 4;
100
101 #if NET_2_0
102                 [ThreadStatic]
103                 private StringDictionary attributes = new StringDictionary ();
104                 [ThreadStatic]
105                 private TraceFilter filter;
106                 [ThreadStatic]
107                 private TraceOptions options;
108 #endif
109 #endif
110
111 #if NET_2_0\r
112                 static readonly string [] empty_array = new string [0];
113 #endif
114
115                 private string name = null;
116                 private bool needIndent = true;
117
118                 protected TraceListener () : this ("")
119                 {
120                 }
121
122                 protected TraceListener (string name)
123                 {
124                         Name = name;
125                 }
126
127                 public int IndentLevel {
128                         get {return indentLevel;}
129                         set {indentLevel = value;}
130                 }
131
132                 public int IndentSize {
133                         get {return indentSize;}
134                         set {indentSize = value;}
135                 }
136
137                 public virtual string Name {
138                         get {return name;}
139                         set {name = value;}
140                 }
141
142                 protected bool NeedIndent {
143                         get {return needIndent;}
144                         set {needIndent = value;}
145                 }
146
147 #if NET_2_0
148                 [MonoLimitation ("This property exists but is never considered.")]
149                 public virtual bool IsThreadSafe {
150                         get { return false; }
151                 }
152 #endif
153
154                 public virtual void Close ()
155                 {
156                         Dispose ();
157                 }
158
159                 public void Dispose ()
160                 {
161                         Dispose (true);
162                         GC.SuppressFinalize (this);
163                 }
164
165                 protected virtual void Dispose (bool disposing)
166                 {
167                 }
168
169                 public virtual void Fail (string message)
170                 {
171                         Fail (message, "");
172                 }
173
174                 public virtual void Fail (string message, string detailMessage)
175                 {
176                         WriteLine ("---- DEBUG ASSERTION FAILED ----");
177                         WriteLine ("---- Assert Short Message ----");
178                         WriteLine (message);
179                         WriteLine ("---- Assert Long Message ----");
180                         WriteLine (detailMessage);
181                         WriteLine ("");
182                 }
183
184                 public virtual void Flush ()
185                 {
186                 }
187
188                 public virtual void Write (object o)
189                 {
190                         Write (o.ToString());
191                 }
192
193                 public abstract void Write (string message);
194
195                 public virtual void Write (object o, string category)
196                 {
197                         Write (o.ToString(), category);
198                 }
199
200                 public virtual void Write (string message, string category)
201                 {
202                         Write (category + ": " + message);
203                 }
204
205                 protected virtual void WriteIndent ()
206                 {
207                         // Must set NeedIndent to false before Write; otherwise, we get endless
208                         // recursion with Write->WriteIndent->Write->WriteIndent...*boom*
209                         NeedIndent = false;
210                         String indent = new String (' ', IndentLevel*IndentSize);
211                         Write (indent);
212                 }
213
214                 public virtual void WriteLine (object o)
215                 {
216                         WriteLine (o.ToString());
217                 }
218
219                 public abstract void WriteLine (string message);
220
221                 public virtual void WriteLine (object o, string category)
222                 {
223                         WriteLine (o.ToString(), category);
224                 }
225
226                 public virtual void WriteLine (string message, string category)
227                 {
228                         WriteLine (category + ": " + message);
229                 }
230
231 #if NET_2_0
232                 internal static string FormatArray (ICollection list, string joiner)
233                 {
234                         string [] arr = new string [list.Count];
235                         int i = 0;
236                         foreach (object o in list)
237                                 arr [i++] = o != null ? o.ToString () : String.Empty;
238                         return String.Join (joiner, arr);
239                 }
240
241                 [ComVisible (false)]
242                 public virtual void TraceData (TraceEventCache eventCache, string source,
243                         TraceEventType eventType, int id, object data)
244                 {
245                         if (Filter != null &&
246                             !Filter.ShouldTrace (eventCache, source, eventType,
247                                                  id, null, null, data, null))
248                                 return;
249
250                         WriteLine (String.Format ("{0} {1}: {2} : {3}", source, eventType, id, data));
251
252                         if (eventCache == null)
253                                 return;
254
255                         if ((TraceOutputOptions & TraceOptions.ProcessId) != 0)
256                                 WriteLine ("    ProcessId=" + eventCache.ProcessId);
257                         if ((TraceOutputOptions & TraceOptions.LogicalOperationStack) != 0)
258                                 WriteLine ("    LogicalOperationStack=" + FormatArray (eventCache.LogicalOperationStack, ", "));
259                         if ((TraceOutputOptions & TraceOptions.ThreadId) != 0)
260                                 WriteLine ("    ThreadId=" + eventCache.ThreadId);
261                         if ((TraceOutputOptions & TraceOptions.DateTime) != 0)
262                                 WriteLine ("    DateTime=" + eventCache.DateTime.ToString ("o"));
263                         if ((TraceOutputOptions & TraceOptions.Timestamp) != 0)
264                                 WriteLine ("    Timestamp=" + eventCache.Timestamp);
265                         if ((TraceOutputOptions & TraceOptions.Callstack) != 0)
266                                 WriteLine ("    Callstack=" + eventCache.Callstack);
267                 }
268
269                 [ComVisible (false)]
270                 public virtual void TraceData (TraceEventCache eventCache, string source,
271                         TraceEventType eventType, int id, params object [] data)
272                 {
273                         if (Filter != null &&
274                             !Filter.ShouldTrace (eventCache, source, eventType,
275                                                  id, null, null, null, data))
276                                 return;
277
278                         TraceData (eventCache, source, eventType, id, FormatArray (data, " "));
279                 }
280
281                 [ComVisible (false)]
282                 public virtual void TraceEvent (TraceEventCache eventCache, string source, TraceEventType eventType, int id)
283                 {
284                         TraceEvent (eventCache, source, eventType, id, null);
285                 }
286
287                 [ComVisible (false)]
288                 public virtual void TraceEvent (TraceEventCache eventCache, string source, TraceEventType eventType,
289                         int id, string message)
290                 {
291                         TraceData (eventCache, source, eventType, id, message);
292                 }
293
294                 [ComVisible (false)]
295                 public virtual void TraceEvent (TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object [] args)
296                 {
297                         TraceEvent (eventCache, source, eventType, id, String.Format (format, args));
298                 }
299
300                 [ComVisible (false)]
301                 public virtual void TraceTransfer (TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
302                 {
303                         TraceEvent (eventCache, source, TraceEventType.Transfer, id, String.Format ("{0}, relatedActivityId={1}", message, relatedActivityId));
304                 }
305
306                 [MonoTODO ("The property exists but the values are not considered")]
307                 protected virtual string [] GetSupportedAttributes ()
308                 {
309                         return empty_array;
310                 }
311
312                 [MonoTODO ("The property exists but the values are not considered")]
313                 public StringDictionary Attributes {
314                         get { return attributes; }
315                 }
316
317                 [ComVisibleAttribute (false)]
318                 public TraceFilter Filter {
319                         get { return filter; }
320                         set { filter = value; }
321                 }
322
323                 [ComVisibleAttribute (false)]
324                 public TraceOptions TraceOutputOptions {
325                         get { return options; }
326                         set { options = value; }
327                 }
328 #endif
329         }
330 }
331