KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > go > trove > log > Log


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 JavaDoc;
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 JavaDoc mName;
121     private String JavaDoc 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 JavaDoc name, Log parent) {
135         this();
136
137         if (parent != null) {
138             mParent = parent;
139             parent.mChildren.add(new WeakReference JavaDoc(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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc)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 JavaDoc getName() {
383         return mName;
384     }
385
386     /**
387      * Returns a brief description of this Log. By default, returns the name.
388      */

389     public String JavaDoc getDescription() {
390         return mDescription;
391     }
392
393     /**
394      * Set the log's description text.
395      */

396     public void setDescription(String JavaDoc 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 JavaDoc)properties.get("enabled")));
518         }
519
520         if (properties.containsKey("debug")) {
521             setDebugEnabled(!"false".equalsIgnoreCase
522                             ((String JavaDoc)properties.get("debug")));
523         }
524
525         if (properties.containsKey("info")) {
526             setInfoEnabled(!"false".equalsIgnoreCase
527                            ((String JavaDoc)properties.get("info")));
528         }
529
530         if (properties.containsKey("warn")) {
531             setWarnEnabled(!"false".equalsIgnoreCase
532                            ((String JavaDoc)properties.get("warn")));
533         }
534
535         if (properties.containsKey("error")) {
536             setErrorEnabled(!"false".equalsIgnoreCase
537                             ((String JavaDoc)properties.get("error")));
538         }
539     }
540
541     /**
542      * Returns a short description of this log.
543      */

544     public String JavaDoc 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 }
562
Popular Tags