7bb49150b5ef1210361f721d78c6cdcde1c029a8
[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                 private StringDictionary attributes {
74                         get { return (StringDictionary) System.Threading.Thread.GetData (_attributesStore); }
75                         set { System.Threading.Thread.SetData (_attributesStore, value); }
76                 }
77
78 #if !MOBILE
79                 private TraceFilter filter {
80                         get { return (TraceFilter) System.Threading.Thread.GetData (_filterStore); }
81                         set { System.Threading.Thread.SetData (_filterStore, value); }
82                 }
83 #endif
84
85                 private TraceOptions options {
86                         get {
87                                 object o = System.Threading.Thread.GetData (_optionsStore);
88                                 if (o == null)
89                                         return TraceOptions.None;
90                                 return (TraceOptions) o;
91                         }
92                         set { System.Threading.Thread.SetData (_optionsStore, value); }
93                 }
94 #else
95                 [ThreadStatic]
96                 private int indentLevel = 0;
97
98                 [ThreadStatic]
99                 private int indentSize = 4;
100
101                 [ThreadStatic]
102                 private StringDictionary attributes = new StringDictionary ();
103 #if !MOBILE
104                 [ThreadStatic]
105                 private TraceFilter filter;
106 #endif
107                 [ThreadStatic]
108                 private TraceOptions options;
109 #endif
110
111                 private string name;
112                 private bool needIndent = true;
113
114                 protected TraceListener () : this ("")
115                 {
116                 }
117
118                 protected TraceListener (string name)
119                 {
120                         Name = name;
121                 }
122
123                 public int IndentLevel {
124                         get {return indentLevel;}
125                         set {indentLevel = value;}
126                 }
127
128                 public int IndentSize {
129                         get {return indentSize;}
130                         set {indentSize = value;}
131                 }
132
133                 public virtual string Name {
134                         get {return name;}
135                         set {name = value;}
136                 }
137
138                 protected bool NeedIndent {
139                         get {return needIndent;}
140                         set {needIndent = value;}
141                 }
142
143                 [MonoLimitation ("This property exists but is never considered.")]
144                 public virtual bool IsThreadSafe {
145                         get { return false; }
146                 }
147
148                 public virtual void Close ()
149                 {
150                         Dispose ();
151                 }
152
153                 public void Dispose ()
154                 {
155                         Dispose (true);
156                         GC.SuppressFinalize (this);
157                 }
158
159                 protected virtual void Dispose (bool disposing)
160                 {
161                 }
162
163                 public virtual void Fail (string message)
164                 {
165                         Fail (message, null);
166                 }
167
168                 public virtual void Fail (string message, string detailMessage)
169                 {
170                         WriteLine ("---- DEBUG ASSERTION FAILED ----");
171                         WriteLine ("---- Assert Short Message ----");
172                         WriteLine (message);
173                         if (detailMessage != null) {
174                                 WriteLine ("---- Assert Long Message ----");
175                                 WriteLine (detailMessage);
176                         }
177
178                         WriteLine ("");
179                 }
180
181                 public virtual void Flush ()
182                 {
183                 }
184
185                 public virtual void Write (object o)
186                 {
187                         Write (o.ToString());
188                 }
189
190                 public abstract void Write (string message);
191
192                 public virtual void Write (object o, string category)
193                 {
194                         Write (o.ToString(), category);
195                 }
196
197                 public virtual void Write (string message, string category)
198                 {
199                         Write (category + ": " + message);
200                 }
201
202                 protected virtual void WriteIndent ()
203                 {
204                         // Must set NeedIndent to false before Write; otherwise, we get endless
205                         // recursion with Write->WriteIndent->Write->WriteIndent...*boom*
206                         NeedIndent = false;
207                         String indent = new String (' ', IndentLevel*IndentSize);
208                         Write (indent);
209                 }
210
211                 public virtual void WriteLine (object o)
212                 {
213                         WriteLine (o.ToString());
214                 }
215
216                 public abstract void WriteLine (string message);
217
218                 public virtual void WriteLine (object o, string category)
219                 {
220                         WriteLine (o.ToString(), category);
221                 }
222
223                 public virtual void WriteLine (string message, string category)
224                 {
225                         WriteLine (category + ": " + message);
226                 }
227
228                 internal static string FormatArray (ICollection list, string joiner)
229                 {
230                         string [] arr = new string [list.Count];
231                         int i = 0;
232                         foreach (object o in list)
233                                 arr [i++] = o != null ? o.ToString () : String.Empty;
234                         return String.Join (joiner, arr);
235                 }
236
237 #if !MOBILE
238                 [ComVisible (false)]
239                 public virtual void TraceData (TraceEventCache eventCache, string source,
240                         TraceEventType eventType, int id, object data)
241                 {
242                         if (Filter != null &&
243                             !Filter.ShouldTrace (eventCache, source, eventType,
244                                                  id, null, null, data, null))
245                                 return;
246
247                         WriteLine (String.Format ("{0} {1}: {2} : {3}", source, eventType, id, data));
248
249                         if (eventCache == null)
250                                 return;
251
252                         if ((TraceOutputOptions & TraceOptions.ProcessId) != 0)
253                                 WriteLine ("    ProcessId=" + eventCache.ProcessId);
254                         if ((TraceOutputOptions & TraceOptions.LogicalOperationStack) != 0)
255                                 WriteLine ("    LogicalOperationStack=" + FormatArray (eventCache.LogicalOperationStack, ", "));
256                         if ((TraceOutputOptions & TraceOptions.ThreadId) != 0)
257                                 WriteLine ("    ThreadId=" + eventCache.ThreadId);
258                         if ((TraceOutputOptions & TraceOptions.DateTime) != 0)
259                                 WriteLine ("    DateTime=" + eventCache.DateTime.ToString ("o"));
260                         if ((TraceOutputOptions & TraceOptions.Timestamp) != 0)
261                                 WriteLine ("    Timestamp=" + eventCache.Timestamp);
262                         if ((TraceOutputOptions & TraceOptions.Callstack) != 0)
263                                 WriteLine ("    Callstack=" + eventCache.Callstack);
264                 }
265
266                 [ComVisible (false)]
267                 public virtual void TraceData (TraceEventCache eventCache, string source,
268                         TraceEventType eventType, int id, params object [] data)
269                 {
270                         if (Filter != null &&
271                             !Filter.ShouldTrace (eventCache, source, eventType,
272                                                  id, null, null, null, data))
273                                 return;
274
275                         TraceData (eventCache, source, eventType, id, FormatArray (data, " "));
276                 }
277
278                 [ComVisible (false)]
279                 public virtual void TraceEvent (TraceEventCache eventCache, string source, TraceEventType eventType, int id)
280                 {
281                         TraceEvent (eventCache, source, eventType, id, null);
282                 }
283
284                 [ComVisible (false)]
285                 public virtual void TraceEvent (TraceEventCache eventCache, string source, TraceEventType eventType,
286                         int id, string message)
287                 {
288                         TraceData (eventCache, source, eventType, id, message);
289                 }
290
291                 [ComVisible (false)]
292                 public virtual void TraceEvent (TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object [] args)
293                 {
294                         TraceEvent (eventCache, source, eventType, id, String.Format (format, args));
295                 }
296
297                 [ComVisible (false)]
298                 public virtual void TraceTransfer (TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
299                 {
300                         TraceEvent (eventCache, source, TraceEventType.Transfer, id, String.Format ("{0}, relatedActivityId={1}", message, relatedActivityId));
301                 }
302 #endif
303
304                 protected internal virtual string [] GetSupportedAttributes ()
305                 {
306                         return null;
307                 }
308
309                 public StringDictionary Attributes {
310                         get { return attributes; }
311                 }
312
313 #if !MOBILE
314                 [ComVisibleAttribute (false)]
315                 public TraceFilter Filter {
316                         get { return filter; }
317                         set { filter = value; }
318                 }
319 #endif
320
321                 [ComVisibleAttribute (false)]
322                 public TraceOptions TraceOutputOptions {
323                         get { return options; }
324                         set { options = value; }
325                 }
326         }
327 }
328