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

Quick Search    Search Deep

Source code: com/go/trove/log/Log.java


1   /* ====================================================================
2    * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group
3    * ====================================================================
4    * The Tea Software License, Version 1.1
5    *
6    * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7    *
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   * 1. Redistributions of source code must retain the above copyright
13   *    notice, this list of conditions and the following disclaimer.
14   *
15   * 2. Redistributions in binary form must reproduce the above copyright
16   *    notice, this list of conditions and the following disclaimer in
17   *    the documentation and/or other materials provided with the
18   *    distribution.
19   *
20   * 3. The end-user documentation included with the redistribution,
21   *    if any, must include the following acknowledgment:
22   *       "This product includes software developed by the
23   *        Walt Disney Internet Group (http://opensource.go.com/)."
24   *    Alternately, this acknowledgment may appear in the software itself,
25   *    if and wherever such third-party acknowledgments normally appear.
26   *
27   * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28   *    not be used to endorse or promote products derived from this
29   *    software without prior written permission. For written
30   *    permission, please contact opensource@dig.com.
31   *
32   * 5. Products derived from this software may not be called "Tea",
33   *    "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34   *    "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35   *    written permission of the Walt Disney Internet Group.
36   *
37   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40   * DISCLAIMED.  IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
44   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45   * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
46   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48   * ====================================================================
49   *
50   * For more information about Tea, please see http://opensource.go.com/.
51   */
52  
53  package com.go.trove.log;
54  
55  import java.io.*;
56  import java.util.*;
57  import java.lang.ref.WeakReference;
58  
59  /******************************************************************************
60   * General purpose logging class that operates using a hierarchy of Logs and
61   * an event model. All LogEvents are categorized into one of four types: 
62   * debugging, informational, warning and error.
63   *
64   * A log event can be generated by writing to one of the four PrintWriter
65   * fields provided (debug, info, warn and error), or by calling the debug,
66   * info, warn or error methods.
67   *
68   * Logs can have a parent Log, which by default, receives all the events
69   * that the Log generates or receives. If a log is disabled, it will not
70   * generate or propagate events.
71   *
72   * Examples:
73   * <pre>
74   * Log log = new Log("test", null);
75   * log.addLogListener(new LogScribe(new PrintWriter(System.out)));
76   *
77   * log.debug().println("Printing a debugging message");
78   * log.info("System running");
79   *
80   * Syslog.info().println("Creating child log...");
81   * Log child = new Log("child", Syslog.log);
82   * child.warn("This is a system warning...");
83   *
84   * try {
85   *     ...
86   * }
87   * catch (Exception e) {
88   *     child.error(e);
89   * }
90   *
91   * Log saved = new Log("saved", Syslog.log);
92   * File logDir = new File("/logs/");
93   * OutputStream out = new DailyFileLogStream(logDir);
94   * saved.addLogListener(new LogScribe(new PrintWriter(out)));
95   * saved.info("Saved log file initialized");
96   * </pre>
97   *
98   * @author Brian S O'Neill
99   * @version
100  * <!--$$Revision:--> 27 <!-- $-->, <!--$$JustDate:-->  6/28/01 <!-- $-->
101  * @see LogScribe
102  * @see Syslog
103  * @see LogEventParsingWriter
104  * @see DailyFileLogStream
105  */
106 public class Log implements LogListener, Serializable {
107     private static final int ENABLED_MASK = 0x01;
108     private static final int DEBUG_ENABLED_MASK = 0x02;
109     private static final int INFO_ENABLED_MASK = 0x04;
110     private static final int WARN_ENABLED_MASK = 0x08;
111     private static final int ERROR_ENABLED_MASK = 0x10;
112 
113     private final transient PrintWriter mDebug;
114     private final transient PrintWriter mInfo;
115     private final transient PrintWriter mWarn;
116     private final transient PrintWriter mError;
117 
118     private Log mParent;
119     private Collection mChildren = new Vector();
120     private String mName;
121     private String mDescription;
122     private int mEnabledFlags = 0xfffffff;
123     private transient List mListeners = new Vector();
124 
125     /**
126      * Create a new Log that inherits enabled settings from its parent. If no
127      * parent is specified, then the Log is fully enabled. If a parent is
128      * specified, then it is added automatically as a listener to this Log.
129      *
130      * @param name The optional name of this Log.
131      * @param parent The parent Log that will be added as a LogListener to this
132      * Log. If null, then this Log has no parent Log.
133      */
134     public Log(String name, Log parent) {
135         this();
136 
137         if (parent != null) {
138             mParent = parent;
139             parent.mChildren.add(new WeakReference(this));
140             mEnabledFlags = parent.mEnabledFlags;
141             addLogListener(parent);
142         }
143 
144         mName = name;
145         mDescription = name;
146     }
147 
148     private Log() {
149         LogEventParsingWriter writer;
150 
151         writer = new LogEventParsingWriter(this, LogEvent.DEBUG_TYPE, this) {
152             public boolean isEnabled() {
153                 return isDebugEnabled();
154             }
155         };
156         writer.addLogListener(this);
157         mDebug = new PrintWriter(writer, true);
158 
159         writer = new LogEventParsingWriter(this, LogEvent.INFO_TYPE, this) {
160             public boolean isEnabled() {
161                 return isInfoEnabled();
162             }
163         };
164         writer.addLogListener(this);
165         mInfo = new PrintWriter(writer, true);
166 
167         writer = new LogEventParsingWriter(this, LogEvent.WARN_TYPE, this) {
168             public boolean isEnabled() {
169                 return isWarnEnabled();
170             }
171         };
172         writer.addLogListener(this);
173         mWarn = new PrintWriter(writer, true);
174 
175         writer = new LogEventParsingWriter(this, LogEvent.ERROR_TYPE, this) {
176             public boolean isEnabled() {
177                 return isErrorEnabled();
178             }
179         };
180         writer.addLogListener(this);
181         mError = new PrintWriter(writer, true);
182     }
183 
184     /**
185      * adds a listener to the root log, the log with a null parent
186      */
187     public void addRootLogListener(LogListener listener) {
188         if (mParent == null) {
189             addLogListener(listener);
190         }
191         else {
192             mParent.addRootLogListener(listener);
193         }
194     }
195 
196     public void removeRootLogListener(LogListener listener) {
197         mListeners.remove(listener);
198         if (mParent == null) {
199             removeLogListener(listener);
200         }
201         else {
202             mParent.removeRootLogListener(listener);
203         }
204     }
205 
206     public void addLogListener(LogListener listener) {
207         mListeners.add(listener);
208     }
209 
210     public void removeLogListener(LogListener listener) {
211         mListeners.remove(listener);
212     }
213 
214     /**
215      * If this Log is enabled, then dispatch the LogEvent to all of its
216      * listeners as a logged message.
217      */
218     public void logMessage(LogEvent e) {
219         if (isEnabled()) {
220             dispatchLogMessage(e);
221         }
222     }
223 
224     /**
225      * If this Log is enabled, then dispatch the LogEvent to all of its
226      * listeners as a logged exception.
227      */
228     public void logException(LogEvent e) {
229         if (isEnabled()) {
230             dispatchLogException(e);
231         }
232     }
233 
234     private void dispatchLogMessage(LogEvent e) {
235         int size = mListeners.size();
236         try {
237             for (int i=0; i<size; i++) {
238                 ((LogListener)mListeners.get(i)).logMessage(e);
239             }
240         }
241         catch (IndexOutOfBoundsException ex) {
242         }
243     }
244 
245     private void dispatchLogException(LogEvent e) {
246         int size = mListeners.size();
247         try {
248             for (int i=0; i<size; i++) {
249                 ((LogListener)mListeners.get(i)).logException(e);
250             }
251         }
252         catch (IndexOutOfBoundsException ex) {
253         }
254     }
255 
256     /**
257      * Returns a PrintWriter for debug messages.
258      */
259     public PrintWriter debug() {
260         return mDebug;
261     }
262 
263     /**
264      * Simple method for logging a single debugging message.
265      */
266     public synchronized void debug(String s) {
267         if (isEnabled() && isDebugEnabled()) {
268             dispatchLogMessage(new LogEvent(this, LogEvent.DEBUG_TYPE, s));
269         }
270     }
271 
272     /**
273      * Simple method for logging a single debugging exception.
274      */
275     public synchronized void debug(Throwable t) {
276         if (isEnabled() && isDebugEnabled()) {
277             dispatchLogException(new LogEvent(this, LogEvent.DEBUG_TYPE, t));
278         }
279     }
280 
281     /**
282      * Returns a PrintWriter for information messages.
283      */
284     public PrintWriter info() {
285         return mInfo;
286     }
287 
288     /**
289      * Simple method for logging a single information message.
290      */
291     public synchronized void info(String s) {
292         if (isEnabled() && isInfoEnabled()) {
293             dispatchLogMessage(new LogEvent(this, LogEvent.INFO_TYPE, s));
294         }
295     }
296 
297     /**
298      * Simple method for logging a single information exception.
299      */
300     public synchronized void info(Throwable t) {
301         if (isEnabled() && isInfoEnabled()) {
302             dispatchLogException(new LogEvent(this, LogEvent.INFO_TYPE, t));
303         }
304     }
305 
306     /**
307      * Returns a PrintWriter for warning messages.
308      */
309     public PrintWriter warn() {
310         return mWarn;
311     }
312 
313     /**
314      * Simple method for logging a single warning message.
315      */
316     public synchronized void warn(String s) {
317         if (isEnabled() && isWarnEnabled()) {
318             dispatchLogMessage(new LogEvent(this, LogEvent.WARN_TYPE, s));
319         }
320     }
321 
322     /**
323      * Simple method for logging a single warning exception.
324      */
325     public synchronized void warn(Throwable t) {
326         if (isEnabled() && isWarnEnabled()) {
327             dispatchLogException(new LogEvent(this, LogEvent.WARN_TYPE, t));
328         }
329     }
330 
331     /**
332      * Returns a PrintWriter for error messages.
333      */
334     public PrintWriter error() {
335         return mError;
336     }
337 
338     /**
339      * Simple method for logging a single error message.
340      */
341     public synchronized void error(String s) {
342         if (isEnabled() && isErrorEnabled()) {
343             dispatchLogMessage(new LogEvent(this, LogEvent.ERROR_TYPE, s));
344         }
345     }
346 
347     /**
348      * Simple method for logging a single error exception.
349      */
350     public synchronized void error(Throwable t) {
351         if (isEnabled() && isErrorEnabled()) {
352             dispatchLogException(new LogEvent(this, LogEvent.ERROR_TYPE, t));
353         }
354     }
355 
356     /**
357      * Returns a copy of the children Logs.
358      */
359     public Log[] getChildren() {
360         Collection copy;
361 
362         synchronized (mChildren) {
363             copy = new ArrayList(mChildren.size());
364             Iterator it = mChildren.iterator();
365             while (it.hasNext()) {
366                 Log child = (Log)((WeakReference)it.next()).get();
367                 if (child == null) {
368                     it.remove();
369                 }
370                 else {
371                     copy.add(child);
372                 }
373             }
374         }
375 
376         return (Log[])copy.toArray(new Log[copy.size()]);
377     }
378 
379     /**
380      * Returns null if this Log has no name.
381      */
382     public String getName() {
383         return mName;
384     }
385 
386     /**
387      * Returns a brief description of this Log. By default, returns the name.
388      */
389     public String getDescription() {
390         return mDescription;
391     }
392 
393     /**
394      * Set the log's description text.
395      */
396     public void setDescription(String desc) {
397         mDescription = desc;
398     }
399 
400     /**
401      * Returns true if this Log is enabled. If log is disabled, then no log 
402      * events of any kind are generated or propagated to listeners.
403      */
404     public boolean isEnabled() {
405         return isEnabled(ENABLED_MASK);
406     }
407 
408     /**
409      * When this Log is enabled, all parent Logs are also enabled. When this
410      * Log is disabled, parent Logs are unaffected.
411      */
412     public synchronized void setEnabled(boolean enabled) {
413         setEnabled(enabled, ENABLED_MASK);
414         if (enabled) {
415             Log parent;
416             if ((parent = mParent) != null) {
417                 parent.setEnabled(true);
418             }
419         }
420     }
421 
422     /**
423      * Returns true if debug events for this Log are enabled. If debug events
424      * are disabled, then no debug log events are generated, but they can be
425      * propagated to listeners.
426      */
427     public boolean isDebugEnabled() {
428         return isEnabled(DEBUG_ENABLED_MASK);
429     }
430 
431     /**
432      * When debug is enabled, this Log is enabled and all parent Logs are
433      * enabled. Disabling debug only affects this Log's debug state.
434      */
435     public synchronized void setDebugEnabled(boolean enabled) {
436         setEnabled(enabled, DEBUG_ENABLED_MASK);
437         if (enabled) {
438             setEnabled(true);
439         }
440     }
441 
442     /**
443      * Returns true if info events for this Log are enabled. If info events
444      * are disabled, then no info log events are generated, but they can be
445      * propagated to listeners.
446      */
447     public boolean isInfoEnabled() {
448         return isEnabled(INFO_ENABLED_MASK);
449     }
450 
451     /**
452      * When info is enabled, this Log is enabled and all parent Logs are
453      * enabled. Disabling info only affects this Log's info state.
454      */
455     public synchronized void setInfoEnabled(boolean enabled) {
456         setEnabled(enabled, INFO_ENABLED_MASK);
457         if (enabled) {
458             setEnabled(true);
459         }
460     }
461 
462     /**
463      * Returns true if warn events for this Log are enabled. If warn events
464      * are disabled, then no warn log events are generated, but they can be
465      * propagated to listeners.
466      */
467     public boolean isWarnEnabled() {
468         return isEnabled(WARN_ENABLED_MASK);
469     }
470 
471     /**
472      * When warn is enabled, this Log is enabled and all parent Logs are
473      * enabled. Disabling warn only affects this Log's warn state.
474      */
475     public synchronized void setWarnEnabled(boolean enabled) {
476         setEnabled(enabled, WARN_ENABLED_MASK);
477         if (enabled) {
478             setEnabled(true);
479         }
480     }
481 
482     /**
483      * Returns true if error events for this Log are enabled. If error events
484      * are disabled, then no error log events are generated, but they can be
485      * propagated to listeners.
486      */
487     public boolean isErrorEnabled() {
488         return isEnabled(ERROR_ENABLED_MASK);
489     }
490 
491     /**
492      * When error is enabled, this Log is enabled and all parent Logs are
493      * enabled. Disabling error only affects this Log's error state.
494      */
495     public synchronized void setErrorEnabled(boolean enabled) {
496         setEnabled(enabled, ERROR_ENABLED_MASK);
497         if (enabled) {
498             setEnabled(true);
499         }
500     }
501 
502     /**
503      * Understands and applies the following boolean properties. True is the
504      * default value if the value doesn't equal "false", ignoring case.
505      *
506      * <ul>
507      * <li>enabled
508      * <li>debug
509      * <li>info
510      * <li>warn
511      * <li>error
512      * </ul>
513      */
514     public synchronized void applyProperties(Map properties) {
515         if (properties.containsKey("enabled")) {
516             setEnabled(!"false".equalsIgnoreCase
517                        ((String)properties.get("enabled")));
518         }
519 
520         if (properties.containsKey("debug")) {
521             setDebugEnabled(!"false".equalsIgnoreCase
522                             ((String)properties.get("debug")));
523         }
524 
525         if (properties.containsKey("info")) {
526             setInfoEnabled(!"false".equalsIgnoreCase
527                            ((String)properties.get("info")));
528         }
529 
530         if (properties.containsKey("warn")) {
531             setWarnEnabled(!"false".equalsIgnoreCase
532                            ((String)properties.get("warn")));
533         }
534 
535         if (properties.containsKey("error")) {
536             setErrorEnabled(!"false".equalsIgnoreCase
537                             ((String)properties.get("error")));
538         }
539     }
540 
541     /**
542      * Returns a short description of this log.
543      */
544     public String toString() {
545         return "Log[" + getDescription() + "]@" + 
546             Integer.toHexString(hashCode());
547     }
548 
549     private synchronized boolean isEnabled(int mask) {
550         return (mEnabledFlags & mask) == mask;
551     }
552 
553     private synchronized void setEnabled(boolean enabled, int mask) {
554         if (enabled) {
555             mEnabledFlags |= mask;
556         }
557         else {
558             mEnabledFlags &= ~mask;
559         }
560     }
561 }