KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > log > Logger


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12  * implied.
13  *
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.log;
18
19 import org.apache.log.util.LoggerListener;
20
21 /**
22  * The object interacted with by client objects to perform logging.
23  *
24  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
25  * @author Peter Donald
26  */

27 public class Logger
28 {
29     private static final Logger[] EMPTY_SET = new Logger[ 0 ];
30
31     /**
32      * Separator character use to separate different categories
33      */

34     public static final char CATEGORY_SEPARATOR = '.';
35
36     // The ErrorHandler associated with Logger
37
private final ErrorHandler m_errorHandler;
38
39     ///The ErrorHandler associated with Logger
40
private final LoggerListener m_loggerListener;
41
42     ///Logger to inherit logtargets and priorities from
43
private final Logger m_parent;
44
45     ///the fully qualified name of category
46
private final String JavaDoc m_category;
47
48     ///The list of child loggers associated with this logger
49
private Logger[] m_children;
50
51     ///The log-targets this logger writes to
52
private LogTarget[] m_logTargets;
53
54     ///Indicate that logTargets were set with setLogTargets() rather than inherited
55
private boolean m_logTargetsForceSet;
56
57     ///The priority threshold associated with logger
58
private Priority m_priority;
59
60     ///Indicate that priority was set with setPriority() rather than inherited
61
private boolean m_priorityForceSet;
62
63     /**
64      * True means LogEvents will be sent to parents LogTargets
65      * aswell as the ones set for this Logger.
66      */

67     private boolean m_additivity;
68
69     /**
70      * Protected constructor for use inside the logging toolkit.
71      * You should not be using this constructor directly.
72      *
73      * @param errorHandler the ErrorHandler logger uses to log errors
74      * @param category the fully qualified name of category
75      * @param logTargets the LogTargets associated with logger
76      * @param parent the parent logger (used for inheriting from)
77      */

78     Logger( final ErrorHandler errorHandler,
79             final LoggerListener loggerListener,
80             final String JavaDoc category,
81             final LogTarget[] logTargets,
82             final Logger parent )
83     {
84         m_errorHandler = errorHandler;
85         m_loggerListener = loggerListener;
86         m_category = category;
87         m_logTargets = logTargets;
88         m_parent = parent;
89
90         if( null == m_logTargets )
91         {
92             unsetLogTargets();
93         }
94
95         unsetPriority();
96     }
97
98     /**
99      * Determine if messages of priority DEBUG will be logged.
100      *
101      * @return true if DEBUG messages will be logged
102      */

103     public final boolean isDebugEnabled()
104     {
105         return m_priority.isLowerOrEqual( Priority.DEBUG );
106     }
107
108     /**
109      * Log a debug priority event.
110      *
111      * @param message the message
112      * @param throwable the throwable
113      */

114     public final void debug( final String JavaDoc message, final Throwable JavaDoc throwable )
115     {
116         if( isDebugEnabled() )
117         {
118             output( Priority.DEBUG, message, throwable );
119         }
120     }
121
122     /**
123      * Log a debug priority event.
124      *
125      * @param message the message
126      */

127     public final void debug( final String JavaDoc message )
128     {
129         if( isDebugEnabled() )
130         {
131             output( Priority.DEBUG, message, null );
132         }
133     }
134
135     /**
136      * Determine if messages of priority INFO will be logged.
137      *
138      * @return true if INFO messages will be logged
139      */

140     public final boolean isInfoEnabled()
141     {
142         return m_priority.isLowerOrEqual( Priority.INFO );
143     }
144
145     /**
146      * Log a info priority event.
147      *
148      * @param message the message
149      * @param throwable the throwable
150      */

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

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

177     public final boolean isWarnEnabled()
178     {
179         return m_priority.isLowerOrEqual( Priority.WARN );
180     }
181
182     /**
183      * Log a warn priority event.
184      *
185      * @param message the message
186      * @param throwable the throwable
187      */

188     public final void warn( final String JavaDoc message, final Throwable JavaDoc throwable )
189     {
190         if( isWarnEnabled() )
191         {
192             output( Priority.WARN, message, throwable );
193         }
194     }
195
196     /**
197      * Log a warn priority event.
198      *
199      * @param message the message
200      */

201     public final void warn( final String JavaDoc message )
202     {
203         if( isWarnEnabled() )
204         {
205             output( Priority.WARN, message, null );
206         }
207     }
208
209     /**
210      * Determine if messages of priority ERROR will be logged.
211      *
212      * @return true if ERROR messages will be logged
213      */

214     public final boolean isErrorEnabled()
215     {
216         return m_priority.isLowerOrEqual( Priority.ERROR );
217     }
218
219     /**
220      * Log a error priority event.
221      *
222      * @param message the message
223      * @param throwable the throwable
224      */

225     public final void error( final String JavaDoc message, final Throwable JavaDoc throwable )
226     {
227         if( isErrorEnabled() )
228         {
229             output( Priority.ERROR, message, throwable );
230         }
231     }
232
233     /**
234      * Log a error priority event.
235      *
236      * @param message the message
237      */

238     public final void error( final String JavaDoc message )
239     {
240         if( isErrorEnabled() )
241         {
242             output( Priority.ERROR, message, null );
243         }
244     }
245
246     /**
247      * Determine if messages of priority FATAL_ERROR will be logged.
248      *
249      * @return true if FATAL_ERROR messages will be logged
250      */

251     public final boolean isFatalErrorEnabled()
252     {
253         return m_priority.isLowerOrEqual( Priority.FATAL_ERROR );
254     }
255
256     /**
257      * Log a fatalError priority event.
258      *
259      * @param message the message
260      * @param throwable the throwable
261      */

262     public final void fatalError( final String JavaDoc message, final Throwable JavaDoc throwable )
263     {
264         if( isFatalErrorEnabled() )
265         {
266             output( Priority.FATAL_ERROR, message, throwable );
267         }
268     }
269
270     /**
271      * Log a fatalError priority event.
272      *
273      * @param message the message
274      */

275     public final void fatalError( final String JavaDoc message )
276     {
277         if( isFatalErrorEnabled() )
278         {
279             output( Priority.FATAL_ERROR, message, null );
280         }
281     }
282
283     /**
284      * Make this logger additive. I.e. Send all log events to parent
285      * loggers LogTargets regardless of whether or not the
286      * LogTargets have been overidden.
287      *
288      * This is derived from Log4js notion of Additivity.
289      *
290      * @param additivity true to make logger additive, false otherwise
291      */

292     public final void setAdditivity( final boolean additivity )
293     {
294         m_additivity = additivity;
295     }
296
297     /**
298      * Determine if messages of priority �will be logged.
299      * @param priority the priority
300      * @return true if messages will be logged
301      */

302     public final boolean isPriorityEnabled( final Priority priority )
303     {
304         return m_priority.isLowerOrEqual( priority );
305     }
306
307     /**
308      * Log a event at specific priority with a certain message and throwable.
309      *
310      * @param priority the priority
311      * @param message the message
312      * @param throwable the throwable
313      */

314     public final void log( final Priority priority,
315                            final String JavaDoc message,
316                            final Throwable JavaDoc throwable )
317     {
318         if( m_priority.isLowerOrEqual( priority ) )
319         {
320             output( priority, message, throwable );
321         }
322     }
323
324     /**
325      * Log a event at specific priority with a certain message.
326      *
327      * @param priority the priority
328      * @param message the message
329      */

330     public final void log( final Priority priority, final String JavaDoc message )
331     {
332         if( m_priority.isLowerOrEqual( priority ) )
333         {
334             log( priority, message, null );
335         }
336     }
337
338     /**
339      * Set the priority for this logger.
340      *
341      * @param priority the priority
342      */

343     public synchronized void setPriority( final Priority priority )
344     {
345         m_priority = priority;
346         m_priorityForceSet = true;
347         resetChildPriorities( false );
348     }
349
350     /**
351      * Unset the priority of Logger.
352      * (Thus it will use it's parent's priority or DEBUG if no parent.
353      */

354     public synchronized void unsetPriority()
355     {
356         unsetPriority( false );
357     }
358
359     /**
360      * Unset the priority of Logger.
361      * (Thus it will use it's parent's priority or DEBUG if no parent.
362      * If recursive is true unset priorities of all child loggers.
363      *
364      * @param recursive true to unset priority of all child loggers
365      */

366     public synchronized void unsetPriority( final boolean recursive )
367     {
368         if( null != m_parent )
369         {
370             m_priority = m_parent.m_priority;
371         }
372         else
373         {
374             m_priority = Priority.DEBUG;
375         }
376
377         m_priorityForceSet = false;
378         resetChildPriorities( recursive );
379     }
380
381     /**
382      * Set the log targets for this logger.
383      *
384      * @param logTargets the Log Targets
385      */

386     public synchronized void setLogTargets( final LogTarget[] logTargets )
387     {
388         if( null != logTargets )
389         {
390             //Make sure that the array passed in does not have any
391
//nulls in it before we actually do the assignment
392
for( int i = 0; i < logTargets.length; i++ )
393             {
394                 if( null == logTargets[ i ] )
395                 {
396                     final String JavaDoc message = "logTargets[ " + i + " ]";
397                     throw new NullPointerException JavaDoc( message );
398                 }
399             }
400         }
401
402         m_logTargets = logTargets;
403
404         setupErrorHandlers();
405         m_logTargetsForceSet = true;
406         resetChildLogTargets( false );
407     }
408
409     /**
410      * Unset the logtargets for this logger.
411      * This logger (and thus all child loggers who don't specify logtargets) will
412      * inherit from the parents LogTargets.
413      */

414     public synchronized void unsetLogTargets()
415     {
416         unsetLogTargets( false );
417     }
418
419     /**
420      * Unset the logtargets for this logger and all child loggers if recursive is set.
421      * The loggers unset (and all child loggers who don't specify logtargets) will
422      * inherit from the parents LogTargets.
423      * @param recursive the recursion policy
424      */

425     public synchronized void unsetLogTargets( final boolean recursive )
426     {
427         if( null != m_parent )
428         {
429             m_logTargets = m_parent.safeGetLogTargets();
430         }
431         else
432         {
433             m_logTargets = null;
434         }
435
436         m_logTargetsForceSet = false;
437         resetChildLogTargets( recursive );
438     }
439
440     /**
441      * Get all the child Loggers of current logger.
442      *
443      * @return the child loggers
444      */

445     public synchronized Logger[] getChildren()
446     {
447         if( null == m_children )
448         {
449             return EMPTY_SET;
450         }
451
452         final Logger[] children = new Logger[ m_children.length ];
453
454         for( int i = 0; i < children.length; i++ )
455         {
456             children[ i ] = m_children[ i ];
457         }
458
459         return children;
460     }
461
462     /**
463      * Create a new child logger.
464      * The category of child logger is [current-category].subcategory
465      *
466      * @param subCategory the subcategory of this logger
467      * @return the new logger
468      * @exception IllegalArgumentException if subCategory has an empty element name
469      */

470     public synchronized Logger getChildLogger( final String JavaDoc subCategory )
471         throws IllegalArgumentException JavaDoc
472     {
473         final int end = subCategory.indexOf( CATEGORY_SEPARATOR );
474
475         String JavaDoc nextCategory = null;
476         String JavaDoc remainder = null;
477
478         if( -1 == end )
479         {
480             nextCategory = subCategory;
481         }
482         else
483         {
484             if( end == 0 )
485             {
486                 throw new IllegalArgumentException JavaDoc( "Logger categories MUST not have empty elements" );
487             }
488
489             nextCategory = subCategory.substring( 0, end );
490             remainder = subCategory.substring( end + 1 );
491         }
492
493         //Get FQN for category
494
String JavaDoc category = null;
495         if( m_category.equals( "" ) )
496         {
497             category = nextCategory;
498         }
499         else
500         {
501             category = m_category + CATEGORY_SEPARATOR + nextCategory;
502         }
503
504         //Check existing children to see if they
505
//contain next Logger for step in category
506
if( null != m_children )
507         {
508             for( int i = 0; i < m_children.length; i++ )
509             {
510                 if( m_children[ i ].m_category.equals( category ) )
511                 {
512                     if( null == remainder )
513                     {
514                         return m_children[ i ];
515                     }
516                     else
517                     {
518                         return m_children[ i ].getChildLogger( remainder );
519                     }
520                 }
521             }
522         }
523
524         //Create new logger
525
final Logger child =
526             new Logger( m_errorHandler, m_loggerListener, category, null, this );
527
528         if( m_additivity )
529         {
530             child.setAdditivity( true );
531         }
532
533         m_loggerListener.loggerCreated( child.m_category, child );
534
535
536         //Add new logger to child list
537
if( null == m_children )
538         {
539             m_children = new Logger[]{child};
540         }
541         else
542         {
543             final Logger[] children = new Logger[ m_children.length + 1 ];
544             System.arraycopy( m_children, 0, children, 0, m_children.length );
545             children[ m_children.length ] = child;
546             m_children = children;
547         }
548
549         if( null == remainder )
550         {
551             return child;
552         }
553         else
554         {
555             return child.getChildLogger( remainder );
556         }
557     }
558
559     /**
560      * Internal method to do actual outputting.
561      *
562      * @param priority the priority
563      * @param message the message
564      * @param throwable the throwable
565      */

566     private final void output( final Priority priority,
567                                final String JavaDoc message,
568                                final Throwable JavaDoc throwable )
569     {
570         final LogEvent event = new LogEvent();
571         event.setCategory( m_category );
572         event.setContextMap( ContextMap.getCurrentContext( false ) );
573
574         if( null != message )
575         {
576             event.setMessage( message );
577         }
578         else
579         {
580             event.setMessage( "" );
581         }
582
583         event.setThrowable( throwable );
584         event.setPriority( priority );
585
586         //this next line can kill performance. It may be wise to
587
//disable it sometimes and use a more granular approach
588
event.setTime( System.currentTimeMillis() );
589
590         output( event );
591     }
592
593     private final void output( final LogEvent event )
594     {
595         //cache a copy of targets for thread safety
596
//It is now possible for another thread
597
//to replace m_logTargets
598
final LogTarget[] targets = m_logTargets;
599
600         if( null == targets )
601         {
602             final String JavaDoc message = "LogTarget is null for category '" + m_category + "'";
603             m_errorHandler.error( message, null, event );
604         }
605         else if( !m_additivity )
606         {
607             fireEvent( event, targets );
608         }
609         else
610         {
611             //If log targets were not inherited, additivity is true
612
//then fire an event to local targets
613
if( m_logTargetsForceSet )
614             {
615                 fireEvent( event, targets );
616             }
617
618             //if we have a parent Logger then send log event to parent
619
if( null != m_parent )
620             {
621                 m_parent.output( event );
622             }
623         }
624     }
625
626     private final void fireEvent( final LogEvent event, final LogTarget[] targets )
627     {
628         for( int i = 0; i < targets.length; i++ )
629         {
630             //No need to clone array as addition of a log-target
631
//will result in changin whole array
632
targets[ i ].processEvent( event );
633         }
634     }
635
636     /**
637      * Update priority of children if any.
638      */

639     private synchronized void resetChildPriorities( final boolean recursive )
640     {
641         if( null == m_children )
642         {
643             return;
644         }
645
646         final Logger[] children = m_children;
647
648         for( int i = 0; i < children.length; i++ )
649         {
650             children[ i ].resetPriority( recursive );
651         }
652     }
653
654     /**
655      * Update priority of this Logger.
656      * If this loggers priority was manually set then ignore
657      * otherwise get parents priority and update all children's priority.
658      *
659      */

660     private synchronized void resetPriority( final boolean recursive )
661     {
662         if( recursive )
663         {
664             m_priorityForceSet = false;
665         }
666         else if( m_priorityForceSet )
667         {
668             return;
669         }
670
671         m_priority = m_parent.m_priority;
672         resetChildPriorities( recursive );
673     }
674
675     /**
676      * Retrieve logtarget array contained in logger.
677      * This method is provided so that child Loggers can access a
678      * copy of parents LogTargets.
679      *
680      * @return the array of LogTargets
681      */

682     private synchronized LogTarget[] safeGetLogTargets()
683     {
684         if( null == m_logTargets )
685         {
686             if( null == m_parent )
687             {
688                 return new LogTarget[ 0 ];
689             }
690             else
691             {
692                 return m_parent.safeGetLogTargets();
693             }
694         }
695         else
696         {
697             final LogTarget[] logTargets = new LogTarget[ m_logTargets.length ];
698             for( int i = 0; i < logTargets.length; i++ )
699             {
700                 logTargets[ i ] = m_logTargets[ i ];
701             }
702
703             return logTargets;
704         }
705     }
706
707     /**
708      * Update logTargets of children if any.
709      */

710     private synchronized void resetChildLogTargets( final boolean recursive )
711     {
712         if( null == m_children )
713         {
714             return;
715         }
716
717         for( int i = 0; i < m_children.length; i++ )
718         {
719             m_children[ i ].resetLogTargets( recursive );
720         }
721     }
722
723     /**
724      * Set ErrorHandlers of LogTargets if necessary.
725      */

726     private synchronized void setupErrorHandlers()
727     {
728         if( null == m_logTargets )
729         {
730             return;
731         }
732
733         for( int i = 0; i < m_logTargets.length; i++ )
734         {
735             final LogTarget target = m_logTargets[ i ];
736             if( target instanceof ErrorAware )
737             {
738                 ( (ErrorAware)target ).setErrorHandler( m_errorHandler );
739             }
740         }
741     }
742
743     /**
744      * Update logTarget of this Logger.
745      * If this loggers logTarget was manually set then ignore
746      * otherwise get parents logTarget and update all children's logTarget.
747      *
748      */

749     private synchronized void resetLogTargets( final boolean recursive )
750     {
751         if( recursive )
752         {
753             m_logTargetsForceSet = false;
754         }
755         else if( m_logTargetsForceSet )
756         {
757             return;
758         }
759
760         m_logTargets = m_parent.safeGetLogTargets();
761         resetChildLogTargets( recursive );
762     }
763 }
764
Popular Tags