KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > log > OutputStreamLogSink


1 // ========================================================================
2
// Copyright (c) 1997 MortBay Consulting, Sydney
3
// $Id: OutputStreamLogSink.java,v 1.4 2004/09/19 08:04:57 gregwilkins Exp $
4
// ========================================================================
5

6 package org.mortbay.log;
7
8 import java.io.IOException JavaDoc;
9 import java.io.OutputStream JavaDoc;
10 import java.io.PrintWriter JavaDoc;
11 import java.lang.reflect.Array JavaDoc;
12 import java.lang.reflect.Method JavaDoc;
13 import java.util.TimeZone JavaDoc;
14
15 import org.mortbay.util.ByteArrayISO8859Writer;
16 import org.mortbay.util.DateCache;
17 import org.mortbay.util.MultiException;
18 import org.mortbay.util.RolloverFileOutputStream;
19 import org.mortbay.util.StringBufferWriter;
20 import org.mortbay.util.StringUtil;
21
22
23 /* ------------------------------------------------------------ */
24 /** A Log sink.
25  * This class represents both a concrete or abstract sink of
26  * Log data. The default implementation logs to System.err, but
27  * other output stream or files may be specified.
28  *
29  * Currently this Stream only writes in ISO8859_1 encoding. For
30  * Other encodings use the less efficient WriterLogSink.
31  *
32  * If a logFilename is specified, output is sent to that file.
33  * If the filename contains "yyyy_mm_dd", the log file date format
34  * is used to create the actual filename and the log file is rolled
35  * over at local midnight.
36  * If append is set, existing logfiles are appended to, otherwise
37  * a backup is created with a timestamp.
38  * Dated log files are deleted after retain days.
39  *
40  * <p> If the property LOG_DATE_FORMAT is set, then it is interpreted
41  * as a format string for java.text.SimpleDateFormat and used to
42  * format the log timestamps. Default value: HH:mm:ss.SSS
43  *
44  * <p> If LOG_TIMEZONE is set, it is used to set the timezone of the log date
45  * format, otherwise GMT is used.
46  *
47  * @see org.mortbay.util.Log
48  * @version $Id: OutputStreamLogSink.java,v 1.4 2004/09/19 08:04:57 gregwilkins Exp $
49  * @author Greg Wilkins (gregw)
50  */

51 public class OutputStreamLogSink
52     implements LogSink
53 {
54     /* ------------------------------------------------------------ */
55     private final static String JavaDoc __lineSeparator = System.getProperty("line.separator");
56
57     /*-------------------------------------------------------------------*/
58     private int _retainDays=31;
59     protected DateCache _dateFormat= new DateCache("HH:mm:ss.SSS");
60     protected String JavaDoc _logTimezone;
61
62     /* ------------------------------------------------------------ */
63     protected boolean _logTimeStamps=true;
64     protected boolean _logLabels=true;
65     protected boolean _logTags=true;
66     protected boolean _logStackSize=true;
67     protected boolean _logStackTrace=false;
68     protected boolean _logOneLine=false;
69     protected boolean _suppressStack=false;
70     
71     /*-------------------------------------------------------------------*/
72     private String JavaDoc _filename;
73     private boolean _append=true;
74     protected boolean _flushOn=true;
75     protected int _bufferSize=2048;
76     protected boolean _reopen=false;
77     
78
79     protected transient LogImpl _logImpl=null;
80     protected transient boolean _started;
81     protected transient OutputStream JavaDoc _out;
82     protected transient ByteArrayISO8859Writer _buffer;
83
84     /* ------------------------------------------------------------ */
85     /** Constructor.
86      */

87     public OutputStreamLogSink()
88         throws IOException JavaDoc
89     {
90         _filename=System.getProperty("LOG_FILE");
91         if (_filename==null)
92             _out=LogStream.STDERR_STREAM;
93     }
94         
95     /* ------------------------------------------------------------ */
96     public OutputStreamLogSink(String JavaDoc filename)
97     {
98         _filename=filename;
99     }
100     
101     /* ------------------------------------------------------------ */
102     public String JavaDoc getLogDateFormat()
103     {
104         return _dateFormat.getFormatString();
105     }
106     
107     /* ------------------------------------------------------------ */
108     public void setLogDateFormat(String JavaDoc logDateFormat)
109     {
110         _dateFormat = new DateCache(logDateFormat);
111         if (_logTimezone!=null)
112             _dateFormat.getFormat().setTimeZone(TimeZone.getTimeZone(_logTimezone));
113     }
114
115     
116     /* ------------------------------------------------------------ */
117     /**
118      * @deprecated Use getLogTimeZone()
119      */

120     public String JavaDoc getLogTimezone()
121     {
122         return _logTimezone;
123     }
124     
125     /* ------------------------------------------------------------ */
126     /**
127      * @deprecated Use setLogTimeZone(String)
128      */

129     public void setLogTimezone(String JavaDoc logTimezone)
130     {
131         _logTimezone=logTimezone;
132         if (_dateFormat!=null && _logTimezone!=null)
133             _dateFormat.getFormat().setTimeZone(TimeZone.getTimeZone(_logTimezone));
134     }
135     
136     /* ------------------------------------------------------------ */
137     public String JavaDoc getLogTimeZone()
138     {
139         return _logTimezone;
140     }
141     
142     /* ------------------------------------------------------------ */
143     public void setLogTimeZone(String JavaDoc logTimezone)
144     {
145         _logTimezone=logTimezone;
146         if (_dateFormat!=null && _logTimezone!=null)
147             _dateFormat.getFormat().setTimeZone(TimeZone.getTimeZone(_logTimezone));
148     }
149     
150     /* ------------------------------------------------------------ */
151     public boolean isLogTimeStamps()
152     {
153         return _logTimeStamps;
154     }
155     /* ------------------------------------------------------------ */
156     public void setLogTimeStamps(boolean logTimeStamps)
157     {
158         _logTimeStamps = logTimeStamps;
159     }
160     /* ------------------------------------------------------------ */
161     public boolean isLogLabels()
162     {
163         return _logLabels;
164     }
165     /* ------------------------------------------------------------ */
166     public void setLogLabels(boolean logLabels)
167     {
168         _logLabels = logLabels;
169     }
170     /* ------------------------------------------------------------ */
171     public boolean isLogTags()
172     {
173         return _logTags;
174     }
175     /* ------------------------------------------------------------ */
176     public void setLogTags(boolean logTags)
177     {
178         _logTags = logTags;
179     }
180     /* ------------------------------------------------------------ */
181     public boolean isLogStackSize()
182     {
183         return _logStackSize;
184     }
185     /* ------------------------------------------------------------ */
186     public void setLogStackSize(boolean logStackSize)
187     {
188         _logStackSize = logStackSize;
189     }
190     /* ------------------------------------------------------------ */
191     public boolean isLogStackTrace()
192     {
193         return _logStackTrace;
194     }
195     /* ------------------------------------------------------------ */
196     public void setLogStackTrace(boolean logStackTrace)
197     {
198         _logStackTrace = logStackTrace;
199     }
200     /* ------------------------------------------------------------ */
201     public boolean isLogOneLine()
202     {
203         return _logOneLine;
204     }
205     /* ------------------------------------------------------------ */
206     public void setLogOneLine(boolean logOneLine)
207     {
208         _logOneLine = logOneLine;
209     }
210
211     /* ------------------------------------------------------------ */
212     public boolean isAppend()
213     {
214         return _append;
215     }
216
217     /* ------------------------------------------------------------ */
218     public void setAppend(boolean a)
219     {
220         _append=a;
221     }
222
223     /* ------------------------------------------------------------ */
224     public boolean isSuppressStack()
225     {
226         return _suppressStack;
227     }
228
229     /* ------------------------------------------------------------ */
230     public void setSuppressStack(boolean suppressStack)
231     {
232         _suppressStack = suppressStack;
233     }
234     
235     /* ------------------------------------------------------------ */
236     public synchronized void setOutputStream(OutputStream JavaDoc out)
237     {
238         _reopen=isStarted() && out!=out;
239         _filename=null;
240         if (_buffer!=null)
241             _buffer.resetWriter();
242         _out=out;
243     }
244
245     /* ------------------------------------------------------------ */
246     public OutputStream JavaDoc getOutputStream()
247     {
248         return _out;
249     }
250
251     /* ------------------------------------------------------------ */
252     public synchronized void setFilename(String JavaDoc filename)
253     {
254         if (filename!=null)
255         {
256             filename=filename.trim();
257             if (filename.length()==0)
258                 filename=null;
259         }
260         
261         if (isStarted() && _filename!=null && filename==null)
262             _out=null;
263         
264         _reopen=isStarted() &&
265             ((_filename==null && filename!=null)||
266              (_filename!=null && !_filename.equals(filename)));
267         _filename=filename;
268
269         if (!isStarted() && _filename!=null)
270             _out=null;
271     }
272
273     /* ------------------------------------------------------------ */
274     public String JavaDoc getFilename()
275     {
276         return _filename;
277     }
278     
279     /* ------------------------------------------------------------ */
280     public String JavaDoc getDatedFilename()
281     {
282         if (_filename==null)
283             return null;
284
285         if (_out==null || ! (_out instanceof RolloverFileOutputStream))
286             return null;
287
288         return ((RolloverFileOutputStream)_out).getDatedFilename();
289     }
290     
291     /* ------------------------------------------------------------ */
292     public int getRetainDays()
293     {
294         return _retainDays;
295     }
296
297     /* ------------------------------------------------------------ */
298     public void setRetainDays(int retainDays)
299     {
300         _reopen=isStarted() && _retainDays!=retainDays;
301         _retainDays = retainDays;
302     }
303     
304     /* ------------------------------------------------------------ */
305     /**
306      * @param on If true, log is flushed on every log.
307      */

308     public void setFlushOn(boolean on)
309     {
310         _flushOn=on;
311         if (on && _out!=null)
312         {
313             try{_out.flush();}
314             catch(IOException JavaDoc e){e.printStackTrace();}
315         }
316     }
317     
318     /* ------------------------------------------------------------ */
319     /**
320      * @return true, log is flushed on every log.
321      */

322     public boolean getFlushOn()
323     {
324         return _flushOn;
325     }
326     
327     /* ------------------------------------------------------------ */
328     /** Log a message.
329      * This method formats the log information as a string and calls
330      * log(String). It should only be specialized by a derived
331      * implementation if the format of the logged messages is to be changed.
332      *
333      * @param tag Tag for type of log
334      * @param msg The message
335      * @param frame The frame that generated the message.
336      * @param time The time stamp of the message.
337      */

338     public synchronized void log(String JavaDoc tag,
339                                   Object JavaDoc o,
340                                   Frame frame,
341                                   long time)
342     {
343         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(160);
344         
345         // Log the time stamp
346
if (_logTimeStamps)
347         {
348             buf.append(_dateFormat.format(time));
349             buf.append(' ');
350         }
351             
352             
353         // Log the tag
354
if (_logTags)
355             buf.append(tag);
356         
357         // Log the label
358
if (_logLabels && frame != null)
359         {
360             buf.append(frame.toString());
361         }
362         
363         // Log the stack depth.
364
if (_logStackSize && frame != null)
365         {
366             buf.append(" >");
367             if (frame.getDepth()<10)
368                 buf.append('0');
369             buf.append(Integer.toString(frame.getDepth()));
370             buf.append("> ");
371         }
372         
373         // Determine the indent string for the message and append it
374
// to the buffer. Only put a newline in the buffer if the first
375
// line is not blank
376
String JavaDoc nl=__lineSeparator;
377         
378         if (_logLabels && !_logOneLine && _buffer.size() > 0)
379             buf.append(nl);
380         
381         // Log message
382
formatObject(buf,o);
383         
384         // Add stack frame to message
385
if (_logStackTrace && frame != null)
386         {
387             buf.append(nl);
388             buf.append(frame.getStack());
389         }
390         
391         log(buf.toString());
392     }
393     
394     /* ------------------------------------------------------------ */
395     /** Log a message.
396      * The formatted log string is written to the log sink. The default
397      * implementation writes the message to an outputstream.
398      * @param formattedLog
399      */

400     public synchronized void log(String JavaDoc formattedLog)
401     {
402         if (_reopen || _out==null)
403         {
404             stop();
405             start();
406         }
407         try
408         {
409             _buffer.write(formattedLog);
410             _buffer.write(StringUtil.__LINE_SEPARATOR);
411             if (_flushOn || _buffer.size()>_bufferSize)
412             {
413                 _buffer.writeTo(_out);
414                 _buffer.resetWriter();
415                 _out.flush();
416             }
417         }
418         catch(IOException JavaDoc e){e.printStackTrace();}
419     }
420
421     
422     /* ------------------------------------------------------------ */
423     /** Start a log sink.
424      * The default implementation does nothing
425      */

426     public synchronized void start()
427     {
428         _buffer=new ByteArrayISO8859Writer(_bufferSize);
429         _reopen=false;
430         if (_started)
431             return;
432         
433         if (_out==null && _filename!=null)
434         {
435             try
436             {
437                 RolloverFileOutputStream rfos=
438                     new RolloverFileOutputStream(_filename,_append,_retainDays);
439                 _out=rfos;
440             }
441             catch(IOException JavaDoc e){e.printStackTrace();}
442         }
443
444         if (_out==null)
445             _out=LogStream.STDERR_STREAM;
446         
447         _started=true;
448     }
449     
450     
451     /* ------------------------------------------------------------ */
452     /** Stop a log sink.
453      * An opportunity for subclasses to clean up. The default
454      * implementation does nothing
455      */

456     public synchronized void stop()
457     {
458         _started=false;
459
460         if (_out!=null)
461         {
462             try
463             {
464                 if (_buffer.size()>0)
465                 {
466                     _buffer.writeTo(_out);
467                 }
468                 _out.flush();
469                 _buffer=null;
470             }
471             catch(Exception JavaDoc e){if (_logImpl!=null && _logImpl.getDebug())e.printStackTrace();}
472             Thread.yield();
473         }
474         
475         if (_out!=null && _out!=LogStream.STDERR_STREAM)
476         {
477             try{_out.close();}
478             catch(Exception JavaDoc e){if (_logImpl!=null && _logImpl.getDebug())e.printStackTrace();}
479         }
480
481         if (_filename!=null)
482             _out=null;
483     }
484
485     /* ------------------------------------------------------------ */
486     public boolean isStarted()
487     {
488         return _started;
489     }
490
491     /* (non-Javadoc)
492      * @see org.mortbay.log.LogSink#setLogImpl(org.mortbay.log.LogImpl)
493      */

494     public void setLogImpl(LogImpl impl)
495     {
496         _logImpl=impl;
497     }
498
499     /*-------------------------------------------------------------------*/
500     private static final Class JavaDoc[] __noArgs=new Class JavaDoc[0];
501     private static final String JavaDoc[] __nestedEx =
502         {"getTargetException","getTargetError","getException","getRootCause"};
503
504     /*-------------------------------------------------------------------*/
505     /** Shared static instances, reduces object creation at expense
506      * of lock contention in multi threaded debugging */

507     private static StringBufferWriter __stringBufferWriter = new StringBufferWriter();
508     private static PrintWriter JavaDoc __printWriter = new PrintWriter JavaDoc(__stringBufferWriter);
509
510     /*-------------------------------------------------------------------*/
511     void formatObject(StringBuffer JavaDoc buf,Object JavaDoc o)
512     {
513         int init_size=buf.length();
514         
515         if (o==null)
516             buf.append("null");
517         else if (o.getClass().isArray())
518         {
519             int l=Array.getLength(o);
520             for (int i=0;i<l;i++)
521                 formatObject(buf,Array.get(o,i));
522         }
523         else if (o instanceof Throwable JavaDoc)
524         {
525             Throwable JavaDoc ex = (Throwable JavaDoc) o;
526             buf.append('\n');
527                 
528             if (_suppressStack)
529             {
530                 buf.append(ex.toString());
531                 buf.append("\nNo stack available\n--");
532             }
533             else
534             {
535                 synchronized(__printWriter)
536                 {
537                     __stringBufferWriter.setStringBuffer(buf);
538                     expandThrowable(ex);
539                     __printWriter.flush();
540                 }
541             }
542         }
543         else
544             buf.append(o.toString());
545         
546         int end_size=buf.length();
547         if (_logOneLine)
548         {
549             for (int i=init_size;i<end_size;i++)
550             {
551                 char c=buf.charAt(i);
552                 if (c=='\n')
553                     buf.setCharAt(i,'|');
554                 else if (c=='\r')
555                     buf.setCharAt(i,'<');
556             }
557         }
558     }
559
560     /* ------------------------------------------------------------ */
561     private static void expandThrowable(Throwable JavaDoc ex)
562     {
563         ex.printStackTrace(__printWriter);
564
565         if (ex instanceof MultiException)
566         {
567             MultiException mx = (MultiException)ex;
568             
569             for (int i=0;i<mx.size();i++)
570             {
571                 __printWriter.print("["+i+"]=");
572                 Throwable JavaDoc ex2=mx.getException(i);
573                 expandThrowable(ex2);
574             }
575         }
576         else
577         {
578             for (int i=0;i<__nestedEx.length;i++)
579             {
580                 try
581                 {
582                     Method JavaDoc getTargetException =
583                         ex.getClass().getMethod(__nestedEx[i],__noArgs);
584                     Throwable JavaDoc ex2=(Throwable JavaDoc)getTargetException.invoke(ex,(java.lang.Object JavaDoc[])null);
585                     if (ex2!=null)
586                     {
587                         __printWriter.println(__nestedEx[i]+"():");
588                         expandThrowable(ex2);
589                     }
590                 }
591                 catch(Exception JavaDoc ignore){}
592             }
593         }
594     }
595     
596 };
597
Popular Tags