KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > util > log > Logger


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE file.
7  */

8 package org.jivesoftware.util.log;
9
10 /**
11  * The object interacted with by client objects to perform logging.
12  *
13  * @author <a HREF="mailto:peter@apache.org">Peter Donald</a>
14  */

15 public class Logger {
16     ///Separator character use to separate different categories
17
public final static char CATEGORY_SEPARATOR = '.';
18
19     ///The ErrorHandler associated with Logger
20
private final ErrorHandler m_errorHandler;
21
22     ///Logger to inherit logtargets and priorities from
23
private final Logger m_parent;
24
25     ///the fully qualified name of category
26
private final String JavaDoc m_category;
27
28     ///The list of child loggers associated with this logger
29
private Logger[] m_children;
30
31     ///The log-targets this logger writes to
32
private LogTarget[] m_logTargets;
33
34     ///Indicate that logTargets were set with setLogTargets() rather than inherited
35
private boolean m_logTargetsForceSet;
36
37     ///The priority threshold associated with logger
38
private Priority m_priority;
39
40     ///Indicate that priority was set with setPriority() rather than inherited
41
private boolean m_priorityForceSet;
42
43     /**
44      * True means LogEvents will be sent to parents LogTargets
45      * aswell as the ones set for this Logger.
46      */

47     private boolean m_additivity;
48
49     /**
50      * Protected constructor for use inside the logging toolkit.
51      * You should not be using this constructor directly.
52      *
53      * @param errorHandler the ErrorHandler logger uses to log errors
54      * @param category the fully qualified name of category
55      * @param logTargets the LogTargets associated with logger
56      * @param parent the parent logger (used for inheriting from)
57      */

58     Logger(final ErrorHandler errorHandler,
59            final String JavaDoc category,
60            final LogTarget[] logTargets,
61            final Logger parent) {
62         m_errorHandler = errorHandler;
63         m_category = category;
64         m_logTargets = logTargets;
65         m_parent = parent;
66
67         if (null == m_logTargets) {
68             unsetLogTargets();
69         }
70
71         unsetPriority();
72     }
73
74     /**
75      * Determine if messages of priority DEBUG will be logged.
76      *
77      * @return true if DEBUG messages will be logged
78      */

79     public final boolean isDebugEnabled() {
80         return m_priority.isLowerOrEqual(Priority.DEBUG);
81     }
82
83     /**
84      * Log a debug priority event.
85      *
86      * @param message the message
87      * @param throwable the throwable
88      */

89     public final void debug(final String JavaDoc message, final Throwable JavaDoc throwable) {
90         if (isDebugEnabled()) {
91             output(Priority.DEBUG, message, throwable);
92         }
93     }
94
95     /**
96      * Log a debug priority event.
97      *
98      * @param message the message
99      */

100     public final void debug(final String JavaDoc message) {
101         if (isDebugEnabled()) {
102             output(Priority.DEBUG, message, null);
103         }
104     }
105
106     /**
107      * Determine if messages of priority INFO will be logged.
108      *
109      * @return true if INFO messages will be logged
110      */

111     public final boolean isInfoEnabled() {
112         return m_priority.isLowerOrEqual(Priority.INFO);
113     }
114
115     /**
116      * Log a info priority event.
117      *
118      * @param message the message
119      */

120     public final void info(final String JavaDoc message, final Throwable JavaDoc throwable) {
121         if (isInfoEnabled()) {
122             output(Priority.INFO, message, throwable);
123         }
124     }
125
126     /**
127      * Log a info priority event.
128      *
129      * @param message the message
130      */

131     public final void info(final String JavaDoc message) {
132         if (isInfoEnabled()) {
133             output(Priority.INFO, message, null);
134         }
135     }
136
137     /**
138      * Determine if messages of priority WARN will be logged.
139      *
140      * @return true if WARN messages will be logged
141      */

142     public final boolean isWarnEnabled() {
143         return m_priority.isLowerOrEqual(Priority.WARN);
144     }
145
146     /**
147      * Log a warn priority event.
148      *
149      * @param message the message
150      * @param throwable the throwable
151      */

152     public final void warn(final String JavaDoc message, final Throwable JavaDoc throwable) {
153         if (isWarnEnabled()) {
154             output(Priority.WARN, message, throwable);
155         }
156     }
157
158     /**
159      * Log a warn priority event.
160      *
161      * @param message the message
162      */

163     public final void warn(final String JavaDoc message) {
164         if (isWarnEnabled()) {
165             output(Priority.WARN, message, null);
166         }
167     }
168
169     /**
170      * Determine if messages of priority ERROR will be logged.
171      *
172      * @return true if ERROR messages will be logged
173      */

174     public final boolean isErrorEnabled() {
175         return m_priority.isLowerOrEqual(Priority.ERROR);
176     }
177
178     /**
179      * Log a error priority event.
180      *
181      * @param message the message
182      * @param throwable the throwable
183      */

184     public final void error(final String JavaDoc message, final Throwable JavaDoc throwable) {
185         if (isErrorEnabled()) {
186             output(Priority.ERROR, message, throwable);
187         }
188     }
189
190     /**
191      * Log a error priority event.
192      *
193      * @param message the message
194      */

195     public final void error(final String JavaDoc message) {
196         if (isErrorEnabled()) {
197             output(Priority.ERROR, message, null);
198         }
199     }
200
201     /**
202      * Determine if messages of priority FATAL_ERROR will be logged.
203      *
204      * @return true if FATAL_ERROR messages will be logged
205      */

206     public final boolean isFatalErrorEnabled() {
207         return m_priority.isLowerOrEqual(Priority.FATAL_ERROR);
208     }
209
210     /**
211      * Log a fatalError priority event.
212      *
213      * @param message the message
214      * @param throwable the throwable
215      */

216     public final void fatalError(final String JavaDoc message, final Throwable JavaDoc throwable) {
217         if (isFatalErrorEnabled()) {
218             output(Priority.FATAL_ERROR, message, throwable);
219         }
220     }
221
222     /**
223      * Log a fatalError priority event.
224      *
225      * @param message the message
226      */

227     public final void fatalError(final String JavaDoc message) {
228         if (isFatalErrorEnabled()) {
229             output(Priority.FATAL_ERROR, message, null);
230         }
231     }
232
233     /**
234      * Make this logger additive, which means send all log events to parent
235      * loggers LogTargets regardless of whether or not the
236      * LogTargets have been overidden.
237      * <p/>
238      * This is derived from Log4js notion of Additivity.
239      *
240      * @param additivity true to make logger additive, false otherwise
241      */

242     public final void setAdditivity(final boolean additivity) {
243         m_additivity = additivity;
244     }
245
246     /**
247      * Determine if messages of priority will be logged.
248      *
249      * @return true if messages will be logged
250      */

251     public final boolean isPriorityEnabled(final Priority priority) {
252         return m_priority.isLowerOrEqual(priority);
253     }
254
255     /**
256      * Log a event at specific priority with a certain message and throwable.
257      *
258      * @param message the message
259      * @param priority the priority
260      * @param throwable the throwable
261      */

262     public final void log(final Priority priority,
263                           final String JavaDoc message,
264                           final Throwable JavaDoc throwable) {
265         if (m_priority.isLowerOrEqual(priority)) {
266             output(priority, message, throwable);
267         }
268     }
269
270     /**
271      * Log a event at specific priority with a certain message.
272      *
273      * @param message the message
274      * @param priority the priority
275      */

276     public final void log(final Priority priority, final String JavaDoc message) {
277         log(priority, message, null);
278     }
279
280     /**
281      * Set the priority for this logger.
282      *
283      * @param priority the priority
284      */

285     public synchronized void setPriority(final Priority priority) {
286         m_priority = priority;
287         m_priorityForceSet = true;
288         resetChildPriorities(false);
289     }
290
291     /**
292      * Unset the priority of Logger.
293      * (Thus it will use it's parent's priority or DEBUG if no parent.
294      */

295     public synchronized void unsetPriority() {
296         unsetPriority(false);
297     }
298
299     /**
300      * Unset the priority of Logger.
301      * (Thus it will use it's parent's priority or DEBUG if no parent.
302      * If recursive is true unset priorities of all child loggers.
303      *
304      * @param recursive true to unset priority of all child loggers
305      */

306     public synchronized void unsetPriority(final boolean recursive) {
307         if (null != m_parent)
308             m_priority = m_parent.m_priority;
309         else
310             m_priority = Priority.DEBUG;
311
312         m_priorityForceSet = false;
313         resetChildPriorities(recursive);
314     }
315
316     /**
317      * Set the log targets for this logger.
318      *
319      * @param logTargets the Log Targets
320      */

321     public synchronized void setLogTargets(final LogTarget[] logTargets) {
322         m_logTargets = logTargets;
323         setupErrorHandlers();
324         m_logTargetsForceSet = true;
325         resetChildLogTargets(false);
326     }
327
328     /**
329      * Unset the logtargets for this logger.
330      * This logger (and thus all child loggers who don't specify logtargets) will
331      * inherit from the parents LogTargets.
332      */

333     public synchronized void unsetLogTargets() {
334         unsetLogTargets(false);
335     }
336
337     /**
338      * Unset the logtargets for this logger and all child loggers if recursive is set.
339      * The loggers unset (and all child loggers who don't specify logtargets) will
340      * inherit from the parents LogTargets.
341      */

342     public synchronized void unsetLogTargets(final boolean recursive) {
343         if (null != m_parent)
344             m_logTargets = m_parent.safeGetLogTargets();
345         else
346             m_logTargets = null;
347
348         m_logTargetsForceSet = false;
349         resetChildLogTargets(recursive);
350     }
351
352     /**
353      * Get all the child Loggers of current logger.
354      *
355      * @return the child loggers
356      */

357     public synchronized Logger[] getChildren() {
358         if (null == m_children) return new Logger[0];
359
360         final Logger[] children = new Logger[m_children.length];
361
362         for (int i = 0; i < children.length; i++) {
363             children[i] = m_children[i];
364         }
365
366         return children;
367     }
368
369     /**
370      * Create a new child logger.
371      * The category of child logger is [current-category].subcategory
372      *
373      * @param subCategory the subcategory of this logger
374      * @return the new logger
375      * @throws IllegalArgumentException if subCategory has an empty element name
376      */

377     public synchronized Logger getChildLogger(final String JavaDoc subCategory)
378             throws IllegalArgumentException JavaDoc {
379         final int end = subCategory.indexOf(CATEGORY_SEPARATOR);
380
381         String JavaDoc nextCategory = null;
382         String JavaDoc remainder = null;
383
384         if (-1 == end)
385             nextCategory = subCategory;
386         else {
387             if (end == 0) {
388                 throw new IllegalArgumentException JavaDoc("Logger categories MUST not have empty elements");
389             }
390
391             nextCategory = subCategory.substring(0, end);
392             remainder = subCategory.substring(end + 1);
393         }
394
395         //Get FQN for category
396
String JavaDoc category = null;
397         if (m_category.equals(""))
398             category = nextCategory;
399         else {
400             category = m_category + CATEGORY_SEPARATOR + nextCategory;
401         }
402
403         //Check existing children to see if they
404
//contain next Logger for step in category
405
if (null != m_children) {
406             for (int i = 0; i < m_children.length; i++) {
407                 if (m_children[i].m_category.equals(category)) {
408                     if (null == remainder)
409                         return m_children[i];
410                     else
411                         return m_children[i].getChildLogger(remainder);
412                 }
413             }
414         }
415
416         //Create new logger
417
final Logger child = new Logger(m_errorHandler, category, null, this);
418
419         //Add new logger to child list
420
if (null == m_children) {
421             m_children = new Logger[]{child};
422         }
423         else {
424             final Logger[] children = new Logger[m_children.length + 1];
425             System.arraycopy(m_children, 0, children, 0, m_children.length);
426             children[m_children.length] = child;
427             m_children = children;
428         }
429
430         if (null == remainder)
431             return child;
432         else
433             return child.getChildLogger(remainder);
434     }
435
436     /**
437      * Retrieve priority associated with Logger.
438      *
439      * @return the loggers priority
440      * @deprecated This method violates Inversion of Control principle.
441      * It will downgraded to protected access in a future
442      * release. When user needs to check priority it is advised
443      * that they use the is[Priority]Enabled() functions.
444      */

445     public final Priority getPriority() {
446         return m_priority;
447     }
448
449     /**
450      * Retrieve category associated with logger.
451      *
452      * @return the Category
453      * @deprecated This method violates Inversion of Control principle.
454      * If you are relying on its presence then there may be
455      * something wrong with the design of your system
456      */

457     public final String JavaDoc getCategory() {
458         return m_category;
459     }
460
461     /**
462      * Get a copy of log targets for this logger.
463      *
464      * @return the child loggers
465      */

466     public LogTarget[] getLogTargets() {
467         // Jive change - we ignore the deprecated warning above and just return the log targets
468
// since it's a closed system for us anyways
469
return m_logTargets;
470     }
471
472     /**
473      * Internal method to do actual outputting.
474      *
475      * @param priority the priority
476      * @param message the message
477      * @param throwable the throwable
478      */

479     private final void output(final Priority priority,
480                               final String JavaDoc message,
481                               final Throwable JavaDoc throwable) {
482         final LogEvent event = new LogEvent();
483         event.setCategory(m_category);
484 // event.setContextStack( ContextStack.getCurrentContext( false ) );
485
event.setContextMap(ContextMap.getCurrentContext(false));
486
487         if (null != message) {
488             event.setMessage(message);
489         }
490         else {
491             event.setMessage("");
492         }
493
494         event.setThrowable(throwable);
495         event.setPriority(priority);
496
497         //this next line can kill performance. It may be wise to
498
//disable it sometimes and use a more granular approach
499
event.setTime(System.currentTimeMillis());
500
501         output(event);
502     }
503
504     private final void output(final LogEvent event) {
505         //cache a copy of targets for thread safety
506
//It is now possible for another thread
507
//to replace m_logTargets
508
final LogTarget[] targets = m_logTargets;
509
510         if (null == targets) {
511             final String JavaDoc message = "LogTarget is null for category '" + m_category + "'";
512             m_errorHandler.error(message, null, event);
513         }
514         else if (!m_additivity) {
515             fireEvent(event, targets);
516         }
517         else {
518             //If log targets were not inherited, additivity is true
519
//then fire an event to local targets
520
if (m_logTargetsForceSet) {
521                 fireEvent(event, targets);
522             }
523
524             //if we have a parent Logger then send log event to parent
525
if (null != m_parent) {
526                 m_parent.output(event);
527             }
528         }
529     }
530
531     private final void fireEvent(final LogEvent event, final LogTarget[] targets) {
532         for (int i = 0; i < targets.length; i++) {
533             //No need to clone array as addition of a log-target
534
//will result in changin whole array
535
targets[i].processEvent(event);
536         }
537     }
538
539     /**
540      * Update priority of children if any.
541      */

542     private synchronized void resetChildPriorities(final boolean recursive) {
543         if (null == m_children) return;
544
545         final Logger[] children = m_children;
546
547         for (int i = 0; i < children.length; i++) {
548             children[i].resetPriority(recursive);
549         }
550     }
551
552     /**
553      * Update priority of this Logger.
554      * If this loggers priority was manually set then ignore
555      * otherwise get parents priority and update all children's priority.
556      */

557     private synchronized void resetPriority(final boolean recursive) {
558         if (recursive) {
559             m_priorityForceSet = false;
560         }
561         else if (m_priorityForceSet) {
562             return;
563         }
564
565         m_priority = m_parent.m_priority;
566         resetChildPriorities(recursive);
567     }
568
569     /**
570      * Retrieve logtarget array contained in logger.
571      * This method is provided so that child Loggers can access a
572      * copy of parents LogTargets.
573      *
574      * @return the array of LogTargets
575      */

576     private synchronized LogTarget[] safeGetLogTargets() {
577         if (null == m_logTargets) {
578             if (null == m_parent)
579                 return new LogTarget[0];
580             else
581                 return m_parent.safeGetLogTargets();
582         }
583         else {
584             final LogTarget[] logTargets = new LogTarget[m_logTargets.length];
585
586             for (int i = 0; i < logTargets.length; i++) {
587                 logTargets[i] = m_logTargets[i];
588             }
589
590             return logTargets;
591         }
592     }
593
594     /**
595      * Update logTargets of children if any.
596      */

597     private synchronized void resetChildLogTargets(final boolean recursive) {
598         if (null == m_children) return;
599
600         for (int i = 0; i < m_children.length; i++) {
601             m_children[i].resetLogTargets(recursive);
602         }
603     }
604
605     /**
606      * Set ErrorHandlers of LogTargets if necessary.
607      */

608     private synchronized void setupErrorHandlers() {
609         if (null == m_logTargets) return;
610
611         for (int i = 0; i < m_logTargets.length; i++) {
612             final LogTarget target = m_logTargets[i];
613             if (target instanceof ErrorAware) {
614                 ((ErrorAware)target).setErrorHandler(m_errorHandler);
615             }
616         }
617     }
618
619     /**
620      * Update logTarget of this Logger.
621      * If this loggers logTarget was manually set then ignore
622      * otherwise get parents logTarget and update all children's logTarget.
623      */

624     private synchronized void resetLogTargets(final boolean recursive) {
625         if (recursive) {
626             m_logTargetsForceSet = false;
627         }
628         else if (m_logTargetsForceSet) {
629             return;
630         }
631
632         m_logTargets = m_parent.safeGetLogTargets();
633         resetChildLogTargets(recursive);
634     }
635 }
Popular Tags