~ifolder-dev/simias/trunk-packaging

« back to all changes in this revision

Viewing changes to src/core/Simias.log4net/src/Appender/.svn/text-base/TextWriterAppender.cs.svn-base

  • Committer: Jorge O. Castro
  • Date: 2007-12-03 06:56:46 UTC
  • Revision ID: jorge@ubuntu.com-20071203065646-mupcnjcwgm5mnhyt
* Remove a bunch of .svn directories we no longer need.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#region Copyright & License
2
 
//
3
 
// Copyright 2001-2005 The Apache Software Foundation
4
 
//
5
 
// Licensed under the Apache License, Version 2.0 (the "License");
6
 
// you may not use this file except in compliance with the License.
7
 
// You may obtain a copy of the License at
8
 
//
9
 
// http://www.apache.org/licenses/LICENSE-2.0
10
 
//
11
 
// Unless required by applicable law or agreed to in writing, software
12
 
// distributed under the License is distributed on an "AS IS" BASIS,
13
 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 
// See the License for the specific language governing permissions and
15
 
// limitations under the License.
16
 
//
17
 
#endregion
18
 
 
19
 
using System;
20
 
using System.IO;
21
 
 
22
 
using log4net.Util;
23
 
using log4net.Layout;
24
 
using log4net.Core;
25
 
 
26
 
namespace log4net.Appender
27
 
{
28
 
        /// <summary>
29
 
        /// Sends logging events to a <see cref="TextWriter"/>.
30
 
        /// </summary>
31
 
        /// <remarks>
32
 
        /// <para>
33
 
        /// An Appender that writes to a <see cref="TextWriter"/>.
34
 
        /// </para>
35
 
        /// <para>
36
 
        /// This appender may be used stand alone if initialized with an appropriate
37
 
        /// writer, however it is typically used as a base class for an appender that
38
 
        /// can open a <see cref="TextWriter"/> to write to.
39
 
        /// </para>
40
 
        /// </remarks>
41
 
        /// <author>Nicko Cadell</author>
42
 
        /// <author>Gert Driesen</author>
43
 
        /// <author>Douglas de la Torre</author>
44
 
        public class TextWriterAppender : AppenderSkeleton
45
 
        {
46
 
                #region Public Instance Constructors
47
 
 
48
 
                /// <summary>
49
 
                /// Initializes a new instance of the <see cref="TextWriterAppender" /> class.
50
 
                /// </summary>
51
 
                /// <remarks>
52
 
                /// <para>
53
 
                /// Default constructor.
54
 
                /// </para>
55
 
                /// </remarks>
56
 
                public TextWriterAppender() 
57
 
                {
58
 
                }
59
 
 
60
 
                /// <summary>
61
 
                /// Initializes a new instance of the <see cref="TextWriterAppender" /> class and
62
 
                /// sets the output destination to a new <see cref="StreamWriter"/> initialized 
63
 
                /// with the specified <see cref="Stream"/>.
64
 
                /// </summary>
65
 
                /// <param name="layout">The layout to use with this appender.</param>
66
 
                /// <param name="os">The <see cref="Stream"/> to output to.</param>
67
 
                /// <remarks>
68
 
                /// <para>
69
 
                /// Obsolete constructor.
70
 
                /// </para>
71
 
                /// </remarks>
72
 
                [Obsolete("Instead use the default constructor and set the Layout & Writer properties")]
73
 
                public TextWriterAppender(ILayout layout, Stream os) : this(layout, new StreamWriter(os))
74
 
                {
75
 
                }
76
 
 
77
 
                /// <summary>
78
 
                /// Initializes a new instance of the <see cref="TextWriterAppender" /> class and sets
79
 
                /// the output destination to the specified <see cref="StreamWriter" />.
80
 
                /// </summary>
81
 
                /// <param name="layout">The layout to use with this appender</param>
82
 
                /// <param name="writer">The <see cref="TextWriter" /> to output to</param>
83
 
                /// <remarks>
84
 
                /// The <see cref="TextWriter" /> must have been previously opened.
85
 
                /// </remarks>
86
 
                /// <remarks>
87
 
                /// <para>
88
 
                /// Obsolete constructor.
89
 
                /// </para>
90
 
                /// </remarks>
91
 
                [Obsolete("Instead use the default constructor and set the Layout & Writer properties")]
92
 
                public TextWriterAppender(ILayout layout, TextWriter writer) 
93
 
                {
94
 
                        Layout = layout;
95
 
                        Writer = writer;
96
 
                }
97
 
 
98
 
                #endregion
99
 
 
100
 
                #region Public Instance Properties
101
 
 
102
 
                /// <summary>
103
 
                /// Gets or set whether the appender will flush at the end 
104
 
                /// of each append operation.
105
 
                /// </summary>
106
 
                /// <value>
107
 
                /// <para>
108
 
                /// The default behavior is to flush at the end of each 
109
 
                /// append operation.
110
 
                /// </para>
111
 
                /// <para>
112
 
                /// If this option is set to <c>false</c>, then the underlying 
113
 
                /// stream can defer persisting the logging event to a later 
114
 
                /// time.
115
 
                /// </para>
116
 
                /// </value>
117
 
                /// <remarks>
118
 
                /// Avoiding the flush operation at the end of each append results in
119
 
                /// a performance gain of 10 to 20 percent. However, there is safety
120
 
                /// trade-off involved in skipping flushing. Indeed, when flushing is
121
 
                /// skipped, then it is likely that the last few log events will not
122
 
                /// be recorded on disk when the application exits. This is a high
123
 
                /// price to pay even for a 20% performance gain.
124
 
                /// </remarks>
125
 
                public bool ImmediateFlush 
126
 
                {
127
 
                        get { return m_immediateFlush; }
128
 
                        set { m_immediateFlush = value; }
129
 
                }
130
 
 
131
 
                /// <summary>
132
 
                /// Sets the <see cref="TextWriter"/> where the log output will go.
133
 
                /// </summary>
134
 
                /// <remarks>
135
 
                /// <para>
136
 
                /// The specified <see cref="TextWriter"/> must be open and writable.
137
 
                /// </para>
138
 
                /// <para>
139
 
                /// The <see cref="TextWriter"/> will be closed when the appender 
140
 
                /// instance is closed.
141
 
                /// </para>
142
 
                /// <para>
143
 
                /// <b>Note:</b> Logging to an unopened <see cref="TextWriter"/> will fail.
144
 
                /// </para>
145
 
                /// </remarks>
146
 
                virtual public TextWriter Writer 
147
 
                {
148
 
                        get { return m_qtw; }
149
 
                        set 
150
 
                        {
151
 
                                lock(this) 
152
 
                                {
153
 
                                        Reset();
154
 
                                        if (value != null)
155
 
                                        {
156
 
                                                m_qtw = new QuietTextWriter(value, ErrorHandler);
157
 
                                                WriteHeader();
158
 
                                        }
159
 
                                }
160
 
                        }
161
 
                }
162
 
 
163
 
                #endregion Public Instance Properties
164
 
 
165
 
                #region Override implementation of AppenderSkeleton
166
 
 
167
 
                /// <summary>
168
 
                /// This method determines if there is a sense in attempting to append.
169
 
                /// </summary>
170
 
                /// <remarks>
171
 
                /// <para>
172
 
                /// This method checked if an output target has been set and if a
173
 
                /// layout has been set. 
174
 
                /// </para>
175
 
                /// </remarks>
176
 
                /// <returns><c>false</c> if any of the preconditions fail.</returns>
177
 
                override protected bool PreAppendCheck() 
178
 
                {
179
 
                        if (!base.PreAppendCheck()) 
180
 
                        {
181
 
                                return false;
182
 
                        }
183
 
 
184
 
                        if (m_qtw == null) 
185
 
                        {
186
 
                                // Allow subclass to lazily create the writer
187
 
                                PrepareWriter();
188
 
 
189
 
                                if (m_qtw == null) 
190
 
                                {
191
 
                                        ErrorHandler.Error("No output stream or file set for the appender named ["+ Name +"].");
192
 
                                        return false;
193
 
                                }
194
 
                        }
195
 
                        if (m_qtw.Closed) 
196
 
                        {
197
 
                                ErrorHandler.Error("Output stream for appender named ["+ Name +"] has been closed.");
198
 
                                return false;
199
 
                        }
200
 
 
201
 
                        return true;
202
 
                }
203
 
 
204
 
                /// <summary>
205
 
                /// This method is called by the <see cref="AppenderSkeleton.DoAppend(LoggingEvent)"/>
206
 
                /// method. 
207
 
                /// </summary>
208
 
                /// <param name="loggingEvent">The event to log.</param>
209
 
                /// <remarks>
210
 
                /// <para>
211
 
                /// Writes a log statement to the output stream if the output stream exists 
212
 
                /// and is writable.  
213
 
                /// </para>
214
 
                /// <para>
215
 
                /// The format of the output will depend on the appender's layout.
216
 
                /// </para>
217
 
                /// </remarks>
218
 
                override protected void Append(LoggingEvent loggingEvent) 
219
 
                {
220
 
                        RenderLoggingEvent(m_qtw, loggingEvent);
221
 
 
222
 
                        if (m_immediateFlush) 
223
 
                        {
224
 
                                m_qtw.Flush();
225
 
                        } 
226
 
                }
227
 
 
228
 
                /// <summary>
229
 
                /// This method is called by the <see cref="AppenderSkeleton.DoAppend(LoggingEvent[])"/>
230
 
                /// method. 
231
 
                /// </summary>
232
 
                /// <param name="loggingEvents">The array of events to log.</param>
233
 
                /// <remarks>
234
 
                /// <para>
235
 
                /// This method writes all the bulk logged events to the output writer
236
 
                /// before flushing the stream.
237
 
                /// </para>
238
 
                /// </remarks>
239
 
                override protected void Append(LoggingEvent[] loggingEvents) 
240
 
                {
241
 
                        foreach(LoggingEvent loggingEvent in loggingEvents)
242
 
                        {
243
 
                                RenderLoggingEvent(m_qtw, loggingEvent);
244
 
                        }
245
 
 
246
 
                        if (m_immediateFlush) 
247
 
                        {
248
 
                                m_qtw.Flush();
249
 
                        } 
250
 
                }
251
 
 
252
 
                /// <summary>
253
 
                /// Close this appender instance. The underlying stream or writer is also closed.
254
 
                /// </summary>
255
 
                /// <remarks>
256
 
                /// Closed appenders cannot be reused.
257
 
                /// </remarks>
258
 
                override protected void OnClose() 
259
 
                {
260
 
                        lock(this)
261
 
                        {
262
 
                                Reset();
263
 
                        }
264
 
                }
265
 
 
266
 
                /// <summary>
267
 
                /// Gets or set the <see cref="IErrorHandler"/> and the underlying 
268
 
                /// <see cref="QuietTextWriter"/>, if any, for this appender. 
269
 
                /// </summary>
270
 
                /// <value>
271
 
                /// The <see cref="IErrorHandler"/> for this appender.
272
 
                /// </value>
273
 
                override public IErrorHandler ErrorHandler
274
 
                {
275
 
                        get { return base.ErrorHandler; }
276
 
                        set
277
 
                        {
278
 
                                lock(this)
279
 
                                {
280
 
                                        if (value == null) 
281
 
                                        {
282
 
                                                LogLog.Warn("TextWriterAppender: You have tried to set a null error-handler.");
283
 
                                        } 
284
 
                                        else 
285
 
                                        {
286
 
                                                base.ErrorHandler = value;
287
 
                                                if (m_qtw != null) 
288
 
                                                {
289
 
                                                        m_qtw.ErrorHandler = value;
290
 
                                                }
291
 
                                        }       
292
 
                                }
293
 
                        }
294
 
                }
295
 
 
296
 
                /// <summary>
297
 
                /// This appender requires a <see cref="Layout"/> to be set.
298
 
                /// </summary>
299
 
                /// <value><c>true</c></value>
300
 
                /// <remarks>
301
 
                /// <para>
302
 
                /// This appender requires a <see cref="Layout"/> to be set.
303
 
                /// </para>
304
 
                /// </remarks>
305
 
                override protected bool RequiresLayout
306
 
                {
307
 
                        get { return true; }
308
 
                }
309
 
 
310
 
                #endregion Override implementation of AppenderSkeleton
311
 
 
312
 
                #region Protected Instance Methods
313
 
 
314
 
                /// <summary>
315
 
                /// Writes the footer and closes the underlying <see cref="TextWriter"/>.
316
 
                /// </summary>
317
 
                /// <remarks>
318
 
                /// <para>
319
 
                /// Writes the footer and closes the underlying <see cref="TextWriter"/>.
320
 
                /// </para>
321
 
                /// </remarks>
322
 
                virtual protected void WriteFooterAndCloseWriter()
323
 
                {
324
 
                        WriteFooter();
325
 
                        CloseWriter();
326
 
                }
327
 
 
328
 
                /// <summary>
329
 
                /// Closes the underlying <see cref="TextWriter"/>.
330
 
                /// </summary>
331
 
                /// <remarks>
332
 
                /// <para>
333
 
                /// Closes the underlying <see cref="TextWriter"/>.
334
 
                /// </para>
335
 
                /// </remarks>
336
 
                virtual protected void CloseWriter() 
337
 
                {
338
 
                        if (m_qtw != null) 
339
 
                        {
340
 
                                try 
341
 
                                {
342
 
                                        m_qtw.Close();
343
 
                                } 
344
 
                                catch(Exception e) 
345
 
                                {
346
 
                                        ErrorHandler.Error("Could not close writer ["+m_qtw+"]", e); 
347
 
                                        // do need to invoke an error handler
348
 
                                        // at this late stage
349
 
                                }
350
 
                        }
351
 
                }
352
 
 
353
 
                /// <summary>
354
 
                /// Clears internal references to the underlying <see cref="TextWriter" /> 
355
 
                /// and other variables.
356
 
                /// </summary>
357
 
                /// <remarks>
358
 
                /// <para>
359
 
                /// Subclasses can override this method for an alternate closing behavior.
360
 
                /// </para>
361
 
                /// </remarks>
362
 
                virtual protected void Reset() 
363
 
                {
364
 
                        WriteFooterAndCloseWriter();
365
 
                        m_qtw = null;
366
 
                }
367
 
 
368
 
                /// <summary>
369
 
                /// Writes a footer as produced by the embedded layout's <see cref="ILayout.Footer"/> property.
370
 
                /// </summary>
371
 
                /// <remarks>
372
 
                /// <para>
373
 
                /// Writes a footer as produced by the embedded layout's <see cref="ILayout.Footer"/> property.
374
 
                /// </para>
375
 
                /// </remarks>
376
 
                virtual protected void WriteFooter() 
377
 
                {
378
 
                        if (Layout != null && m_qtw != null && !m_qtw.Closed) 
379
 
                        {
380
 
                                string f = Layout.Footer;
381
 
                                if (f != null)
382
 
                                {
383
 
                                        m_qtw.Write(f);
384
 
                                }
385
 
                        }
386
 
                }
387
 
 
388
 
                /// <summary>
389
 
                /// Writes a header produced by the embedded layout's <see cref="ILayout.Header"/> property.
390
 
                /// </summary>
391
 
                /// <remarks>
392
 
                /// <para>
393
 
                /// Writes a header produced by the embedded layout's <see cref="ILayout.Header"/> property.
394
 
                /// </para>
395
 
                /// </remarks>
396
 
                virtual protected void WriteHeader() 
397
 
                {
398
 
                        if (Layout != null && m_qtw != null && !m_qtw.Closed) 
399
 
                        {
400
 
                                string h = Layout.Header;
401
 
                                if (h != null)
402
 
                                {
403
 
                                        m_qtw.Write(h);
404
 
                                }
405
 
                        }
406
 
                }
407
 
 
408
 
                /// <summary>
409
 
                /// Called to allow a subclass to lazily initialize the writer
410
 
                /// </summary>
411
 
                /// <remarks>
412
 
                /// <para>
413
 
                /// This method is called when an event is logged and the <see cref="Writer"/> or
414
 
                /// <see cref="QuietWriter"/> have not been set. This allows a subclass to
415
 
                /// attempt to initialize the writer multiple times.
416
 
                /// </para>
417
 
                /// </remarks>
418
 
                virtual protected void PrepareWriter()
419
 
                {
420
 
                }
421
 
 
422
 
                #endregion Protected Instance Methods
423
 
 
424
 
                /// <summary>
425
 
                /// Gets or sets the <see cref="log4net.Util.QuietTextWriter"/> where logging events
426
 
                /// will be written to. 
427
 
                /// </summary>
428
 
                /// <value>
429
 
                /// The <see cref="log4net.Util.QuietTextWriter"/> where logging events are written.
430
 
                /// </value>
431
 
                /// <remarks>
432
 
                /// <para>
433
 
                /// This is the <see cref="log4net.Util.QuietTextWriter"/> where logging events
434
 
                /// will be written to. 
435
 
                /// </para>
436
 
                /// </remarks>
437
 
                protected QuietTextWriter QuietWriter
438
 
                {
439
 
                        get { return m_qtw; }
440
 
                        set { m_qtw = value; }
441
 
                }
442
 
 
443
 
                #region Private Instance Fields
444
 
 
445
 
                /// <summary>
446
 
                /// This is the <see cref="log4net.Util.QuietTextWriter"/> where logging events
447
 
                /// will be written to. 
448
 
                /// </summary>
449
 
                private QuietTextWriter m_qtw;
450
 
 
451
 
                /// <summary>
452
 
                /// Immediate flush means that the underlying <see cref="TextWriter" /> 
453
 
                /// or output stream will be flushed at the end of each append operation.
454
 
                /// </summary>
455
 
                /// <remarks>
456
 
                /// <para>
457
 
                /// Immediate flush is slower but ensures that each append request is 
458
 
                /// actually written. If <see cref="ImmediateFlush"/> is set to
459
 
                /// <c>false</c>, then there is a good chance that the last few
460
 
                /// logging events are not actually persisted if and when the application 
461
 
                /// crashes.
462
 
                /// </para>
463
 
                /// <para>
464
 
                /// The default value is <c>true</c>.
465
 
                /// </para>
466
 
                /// </remarks>
467
 
                private bool m_immediateFlush = true;
468
 
 
469
 
                #endregion Private Instance Fields
470
 
        }
471
 
}