Mercurial > hg > blitz_condensed
comparison src/com/go/trove/log/Log.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3dc0c5604566 |
---|---|
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: 1.1 $-->, <!--$$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 } |