Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/mortbay/util/Log.java


1   // ========================================================================
2   // Copyright (c) 1997 MortBay Consulting, Sydney
3   // $Id: Log.java,v 1.12 2003/07/01 09:06:26 gregwilkins Exp $
4   // ========================================================================
5   
6   package org.mortbay.util;
7   
8   import java.util.StringTokenizer;
9   
10  /*-----------------------------------------------------------------------*/
11  /** Log formatted and tagged messages.
12   * Multiple LogSinks instances can be configured, but by default a
13   * System.err sink is created.
14   * <p>
15   * The Log log format is controlled by the LOG_OPTIONS property
16   * supplied to the VM. 
17   * <p>If LOG_OPTIONS is set, then the default output format is controlled
18   * by the option characters in the string:
19   * <PRE>
20   * t Timestamp log output
21   * T Show the log tag name
22   * L Show log label (thread, method and file names).
23   * s Show indication of stack depth
24   * S Stack trace for each output line (VERY VERBOSE)
25   * O Place each log one One line of output
26   * </PRE>
27   *
28   * <p> If the property LOG_CLASSES is set, it is interpreted as a 
29   * semi-colon-separated list of fully-qualified LogSink class names.
30   * An instance of each class, created with a default constructor,
31   * is added to the list of log sinks.
32   * 
33   * Some possibilities for LOG_CLASSES are
34   *  org.mortbay.util.OutputStreamLogSink - log to System.err, a file whose name is
35   * specified in LOG_FILE, and optionally rollover the logs on a daily basis.
36   * See the javadoc for org.mortbay.util.OutputStreamLogSink for information on the
37   * options LOG_DATE_FORMAT, LOG_FILE_BACKUP_FORMAT, LOG_FILE_RETAIN_DAYS,
38   * LOG_FILE_DATE_FORMAT and LOG_TIME_ZONE.
39   *
40   * <p> If the property LOG_CLASSES is missing, a single OutputStreamLogSink is
41   * used to output to System.err.
42   *
43   * <p> As an alternative to the above behavior, you can create LogSinks
44   * in code and add() them to the Log. If you do this before the first
45   * use of the log, the default initialization will be skipped.
46   *
47   * @see org.mortbay.util.OutputStreamLogSink
48   */
49  public class Log 
50  {
51      /*-------------------------------------------------------------------*/
52      public final static String DEBUG= "DEBUG  ";
53      public final static String EVENT= "EVENT  ";
54      public final static String WARN=  "WARN!! ";
55      public final static String ASSERT="ASSERT ";
56      public final static String FAIL=  "FAIL!! ";
57  
58      /*-------------------------------------------------------------------*/
59      public LogSink[] _sinks = null;
60      public String _logOptions=null;
61      private boolean _initialized = false;
62  
63      /*-------------------------------------------------------------------*/
64      private static class Singleton {static final Log __instance = new Log();}
65      
66      /*-------------------------------------------------------------------*/
67      public static Log instance()
68      {
69          return Singleton.__instance;
70      }
71      
72      /*-------------------------------------------------------------------*/
73      /** Default initialization is used the first time we have to log
74       *  unless a sink has been added with add(). _needInit allows us to
75       *  distinguish between initial state and disabled state.
76       */
77      private synchronized void defaultInit() 
78      {
79          if (!_initialized)
80          {
81              _initialized = true;
82              _logOptions=System.getProperty("LOG_OPTIONS",
83                                             Code.getDebug()?"stLT":"tT");
84              String sinkClasses = System.getProperty("LOG_CLASSES",
85                                                      "org.mortbay.util.OutputStreamLogSink");
86              StringTokenizer sinkTokens = new StringTokenizer(sinkClasses, ";");
87                      
88              LogSink sink= null;
89              while (sinkTokens.hasMoreTokens())
90              {
91                  String sinkClassName = sinkTokens.nextToken();
92                        
93                  try
94                  {
95                      Class sinkClass = Loader.loadClass(this.getClass(),sinkClassName);
96                      if (org.mortbay.util.LogSink.class.isAssignableFrom(sinkClass)) {
97                          sink = (LogSink)sinkClass.newInstance();
98                          sink.setOptions(_logOptions);
99                          sink.start();
100                         Singleton.__instance.add(sink);
101                     }
102                     else
103                         // Can't use Code.fail here, that's what we're setting up
104                         System.err.println(sinkClass+" is not a org.mortbay.util.LogSink");
105                 }
106                 catch (Exception e) {
107                     e.printStackTrace();
108                 }
109             }
110         }
111     }
112     
113     /*-------------------------------------------------------------------*/
114     /** Construct the shared instance of Log that decodes the
115      * options setup in the environments properties.
116      */
117     private Log()
118     {}
119 
120 
121 
122     /* ------------------------------------------------------------ */
123     /** Add a Log Sink.
124      * @param logSinkClass The logsink classname or null for the default. 
125      */
126     public synchronized void add(String logSinkClass)
127     {
128         try
129         {
130             if (logSinkClass==null || logSinkClass.length()==0)
131                 logSinkClass="org.mortbay.util.OutputStreamLogSink";
132             Class sinkClass =  Loader.loadClass(this.getClass(),logSinkClass);
133             LogSink sink=(LogSink)sinkClass.newInstance();
134             add(sink);
135         }
136         catch(Exception e)
137         {
138             Code.warning(e);
139             throw new IllegalArgumentException(e.toString());
140         }
141         
142     }
143     
144     /* ------------------------------------------------------------ */
145     /** Add a Log Sink.
146      * @param logSink 
147      */
148     public synchronized void add(LogSink logSink)
149     {
150         if (_sinks==null)
151         {
152             _sinks=new LogSink[1];
153             _sinks[0]=logSink;
154         }
155         else
156         {
157             boolean slotFree = false;
158             for( int i=_sinks.length; i-->0; )
159             {
160                 if( _sinks[i] == null )
161                 {
162                     slotFree = true;
163                     _sinks[i] = logSink;
164                     break;
165                 }
166             }
167 
168             if( !slotFree )
169             {
170                 LogSink[] ns = new LogSink[_sinks.length+1];
171                 for (int i=_sinks.length;i-->0;)
172                     ns[i]=_sinks[i];
173                 ns[_sinks.length]=logSink;
174                 _sinks=ns;
175             }
176         }
177         _initialized = true;
178     }
179     
180     /* ------------------------------------------------------------ */
181     public LogSink[] getLogSinks()
182     {
183         return _sinks;
184     }
185     
186     /* ------------------------------------------------------------ */
187     /** 
188      */
189     public synchronized void deleteStoppedLogSinks()
190     {
191         if (_sinks!=null)
192         {
193             for (int s=_sinks.length;s-->0;)
194             {
195                 if (_sinks[s]==null)
196                     continue;
197                 if (!_sinks[s].isStarted())
198                     _sinks[s]=null;
199             }
200         }
201     }
202     
203     /* ------------------------------------------------------------ */
204     /** No logging.
205      * All log sinks are stopped and removed.
206      */
207     public synchronized void disableLog()
208     {
209         if (_sinks!=null) {
210             for (int s=_sinks.length;s-->0;)
211             {
212                 try{
213                     if (_sinks[s]!=null)
214                         _sinks[s].stop();
215                 }
216                 catch(InterruptedException e)
217                 {
218                     Code.ignore(e);
219                 }
220             }
221             _sinks=null;
222         }
223         _initialized=true;
224     }
225     
226     /*-------------------------------------------------------------------*/
227     public static void message(String tag,
228                                Object msg,
229                                Frame frame)
230     {
231         long time = System.currentTimeMillis();
232         instance().message(tag,msg,frame,time);
233     }
234     
235     /* ------------------------------------------------------------ */
236     /** Log an event.
237      */
238     public static void event(Object message, int stackDepth)
239     {
240         Log.message(Log.EVENT,message,new Frame(stackDepth));
241     }
242     
243     /* ------------------------------------------------------------ */
244     /** Log an event.
245      */
246     public static void event(Object message)
247     {
248         Log.message(Log.EVENT,message,new Frame(1));
249     }
250     
251     /* ------------------------------------------------------------ */
252     /** Log a warning message.
253      * @see org.mortbay.util.Code for warnings of exceptions etc.
254      * @param message the Object to use as a warning message.
255      * @param stackDepth number of levels of stack to ignore.
256      */
257     public static void warning(Object message, int stackDepth)
258     {
259         Log.message(Log.WARN,message,new Frame(stackDepth));
260     }
261     
262     /* ------------------------------------------------------------ */
263     /** Log a warning.
264      * @see org.mortbay.util.Code for warnings of exceptions etc.
265      * @param message the Object to use as a warning message.
266      */
267     public static void warning(Object message)
268     {
269         Log.message(Log.WARN,message,new Frame(1));
270     }
271     
272     /* ------------------------------------------------------------ */
273     /** Log a message.
274      * @param tag Tag for type of log
275      * @param msg The message
276      * @param frame The frame that generated the message.
277      * @param time The time stamp of the message.
278      */
279     public synchronized void message(String tag,
280                                      Object msg,
281                                      Frame frame,
282                                      long time)
283     {
284         if (!_initialized)
285             defaultInit();
286         
287         if (_sinks==null)
288         {
289             System.err.println(time+": "+tag+","+msg+","+frame);
290             return;
291         }
292         
293         boolean logged=false;
294         for (int s=_sinks.length;s-->0;)
295         {
296             if (_sinks[s]==null)
297                 continue;
298             
299             if (_sinks[s].isStarted())
300             {
301                 logged=true;
302                 _sinks[s].log(tag,msg,frame,time);
303             }
304         }
305 
306         if (!logged)
307             System.err.println(time+": "+tag+","+msg+","+frame);
308     }
309     
310     /* ------------------------------------------------------------ */
311     /** Log a message.
312      * @param tag Tag for type of log
313      * @param msg The message
314      */
315     public synchronized void message(String tag,
316                                      String msg)
317     {
318         message(tag,msg,new Frame(1),System.currentTimeMillis());
319     }
320 
321     
322     /*-------------------------------------------------------------------*/
323     public synchronized void setOptions(String logOptions)
324     {
325         _logOptions=logOptions;
326         
327         for (int s=_sinks.length;s-->0;)
328         {
329             if (_sinks[s]==null)
330                 continue;
331             _sinks[s].setOptions(logOptions);
332         }
333     }
334     
335     /* ------------------------------------------------------------ */
336     public String getOptions()
337     {
338         return _logOptions;
339     }
340 }
341