KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > logging > Logger


1 /*
2  * @(#)Logger.java 1.46 06/04/12
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8
9 package java.util.logging;
10
11 import java.util.*;
12 import java.security.*;
13 import java.lang.ref.WeakReference JavaDoc;
14
15 /**
16  * A Logger object is used to log messages for a specific
17  * system or application component. Loggers are normally named,
18  * using a hierarchical dot-separated namespace. Logger names
19  * can be arbitrary strings, but they should normally be based on
20  * the package name or class name of the logged component, such
21  * as java.net or javax.swing. In addition it is possible to create
22  * "anonymous" Loggers that are not stored in the Logger namespace.
23  * <p>
24  * Logger objects may be obtained by calls on one of the getLogger
25  * factory methods. These will either create a new Logger or
26  * return a suitable existing Logger.
27  * <p>
28  * Logging messages will be forwarded to registered Handler
29  * objects, which can forward the messages to a variety of
30  * destinations, including consoles, files, OS logs, etc.
31  * <p>
32  * Each Logger keeps track of a "parent" Logger, which is its
33  * nearest existing ancestor in the Logger namespace.
34  * <p>
35  * Each Logger has a "Level" associated with it. This reflects
36  * a minimum Level that this logger cares about. If a Logger's
37  * level is set to <tt>null</tt>, then its effective level is inherited
38  * from its parent, which may in turn obtain it recursively from its
39  * parent, and so on up the tree.
40  * <p>
41  * The log level can be configured based on the properties from the
42  * logging configuration file, as described in the description
43  * of the LogManager class. However it may also be dynamically changed
44  * by calls on the Logger.setLevel method. If a logger's level is
45  * changed the change may also affect child loggers, since any child
46  * logger that has <tt>null</tt> as its level will inherit its
47  * effective level from its parent.
48  * <p>
49  * On each logging call the Logger initially performs a cheap
50  * check of the request level (e.g. SEVERE or FINE) against the
51  * effective log level of the logger. If the request level is
52  * lower than the log level, the logging call returns immediately.
53  * <p>
54  * After passing this initial (cheap) test, the Logger will allocate
55  * a LogRecord to describe the logging message. It will then call a
56  * Filter (if present) to do a more detailed check on whether the
57  * record should be published. If that passes it will then publish
58  * the LogRecord to its output Handlers. By default, loggers also
59  * publish to their parent's Handlers, recursively up the tree.
60  * <p>
61  * Each Logger may have a ResourceBundle name associated with it.
62  * The named bundle will be used for localizing logging messages.
63  * If a Logger does not have its own ResourceBundle name, then
64  * it will inherit the ResourceBundle name from its parent,
65  * recursively up the tree.
66  * <p>
67  * Most of the logger output methods take a "msg" argument. This
68  * msg argument may be either a raw value or a localization key.
69  * During formatting, if the logger has (or inherits) a localization
70  * ResourceBundle and if the ResourceBundle has a mapping for the msg
71  * string, then the msg string is replaced by the localized value.
72  * Otherwise the original msg string is used. Typically, formatters use
73  * java.text.MessageFormat style formatting to format parameters, so
74  * for example a format string "{0} {1}" would format two parameters
75  * as strings.
76  * <p>
77  * When mapping ResourceBundle names to ResourceBundles, the Logger
78  * will first try to use the Thread's ContextClassLoader. If that
79  * is null it will try the SystemClassLoader instead. As a temporary
80  * transition feature in the initial implementation, if the Logger is
81  * unable to locate a ResourceBundle from the ContextClassLoader or
82  * SystemClassLoader the Logger will also search up the class stack
83  * and use successive calling ClassLoaders to try to locate a ResourceBundle.
84  * (This call stack search is to allow containers to transition to
85  * using ContextClassLoaders and is likely to be removed in future
86  * versions.)
87  * <p>
88  * Formatting (including localization) is the responsibility of
89  * the output Handler, which will typically call a Formatter.
90  * <p>
91  * Note that formatting need not occur synchronously. It may be delayed
92  * until a LogRecord is actually written to an external sink.
93  * <p>
94  * The logging methods are grouped in five main categories:
95  * <ul>
96  * <li><p>
97  * There are a set of "log" methods that take a log level, a message
98  * string, and optionally some parameters to the message string.
99  * <li><p>
100  * There are a set of "logp" methods (for "log precise") that are
101  * like the "log" methods, but also take an explicit source class name
102  * and method name.
103  * <li><p>
104  * There are a set of "logrb" method (for "log with resource bundle")
105  * that are like the "logp" method, but also take an explicit resource
106  * bundle name for use in localizing the log message.
107  * <li><p>
108  * There are convenience methods for tracing method entries (the
109  * "entering" methods), method returns (the "exiting" methods) and
110  * throwing exceptions (the "throwing" methods).
111  * <li><p>
112  * Finally, there are a set of convenience methods for use in the
113  * very simplest cases, when a developer simply wants to log a
114  * simple string at a given log level. These methods are named
115  * after the standard Level names ("severe", "warning", "info", etc.)
116  * and take a single argument, a message string.
117  * </ul>
118  * <p>
119  * For the methods that do not take an explicit source name and
120  * method name, the Logging framework will make a "best effort"
121  * to determine which class and method called into the logging method.
122  * However, it is important to realize that this automatically inferred
123  * information may only be approximate (or may even be quite wrong!).
124  * Virtual machines are allowed to do extensive optimizations when
125  * JITing and may entirely remove stack frames, making it impossible
126  * to reliably locate the calling class and method.
127  * <P>
128  * All methods on Logger are multi-thread safe.
129  * <p>
130  * <b>Subclassing Information:</b> Note that a LogManager class may
131  * provide its own implementation of named Loggers for any point in
132  * the namespace. Therefore, any subclasses of Logger (unless they
133  * are implemented in conjunction with a new LogManager class) should
134  * take care to obtain a Logger instance from the LogManager class and
135  * should delegate operations such as "isLoggable" and "log(LogRecord)"
136  * to that instance. Note that in order to intercept all logging
137  * output, subclasses need only override the log(LogRecord) method.
138  * All the other logging methods are implemented as calls on this
139  * log(LogRecord) method.
140  *
141  * @version 1.46, 04/12/06
142  * @since 1.4
143  */

144
145
146 public class Logger {
147     private static final Handler JavaDoc emptyHandlers[] = new Handler JavaDoc[0];
148     private static final int offValue = Level.OFF.intValue();
149     private LogManager JavaDoc manager;
150     private String JavaDoc name;
151     private ArrayList handlers;
152     private String JavaDoc resourceBundleName;
153     private boolean useParentHandlers = true;
154     private Filter JavaDoc filter;
155     private boolean anonymous;
156
157     private ResourceBundle catalog; // Cached resource bundle
158
private String JavaDoc catalogName; // name associated with catalog
159
private Locale catalogLocale; // locale associated with catalog
160

161     // The fields relating to parent-child relationships and levels
162
// are managed under a separate lock, the treeLock.
163
private static Object JavaDoc treeLock = new Object JavaDoc();
164     // We keep weak references from parents to children, but strong
165
// references from children to parents.
166
private Logger JavaDoc parent; // our nearest parent.
167
private ArrayList kids; // WeakReferences to loggers that have us as parent
168
private Level JavaDoc levelObject;
169     private volatile int levelValue; // current effective level value
170

171     /**
172      * The "global" Logger object is provided as a convenience to developers
173      * who are making casual use of the Logging package. Developers
174      * who are making serious use of the logging package (for example
175      * in products) should create and use their own Logger objects,
176      * with appropriate names, so that logging can be controlled on a
177      * suitable per-Logger granularity.
178      * <p>
179      * The global logger is initialized by calling Logger.getLogger("global").
180      */

181     public static final Logger JavaDoc global = new Logger JavaDoc("global");
182
183     /**
184      * Protected method to construct a logger for a named subsystem.
185      * <p>
186      * The logger will be initially configured with a null Level
187      * and with useParentHandlers true.
188      *
189      * @param name A name for the logger. This should
190      * be a dot-separated name and should normally
191      * be based on the package name or class name
192      * of the subsystem, such as java.net
193      * or javax.swing. It may be null for anonymous Loggers.
194      * @param resourceBundleName name of ResourceBundle to be used for localizing
195      * messages for this logger. May be null if none
196      * of the messages require localization.
197      * @throws MissingResourceException if the ResourceBundleName is non-null and
198      * no corresponding resource can be found.
199      */

200     protected Logger(String JavaDoc name, String JavaDoc resourceBundleName) {
201         this.manager = LogManager.getLogManager();
202     if (resourceBundleName != null) {
203         // Note: we may get a MissingResourceException here.
204
setupResourceInfo(resourceBundleName);
205     }
206     this.name = name;
207     levelValue = Level.INFO.intValue();
208     }
209
210     // This constructor is used only to create the global Logger.
211
// It is needed to break a cyclic dependence between the LogManager
212
// and Logger static initializers causing deadlocks.
213
private Logger(String JavaDoc name) {
214         // The manager field is not initialized here.
215
this.name = name;
216     levelValue = Level.INFO.intValue();
217     }
218
219     // It is called from the LogManager.<clinit> to complete
220
// initialization of the global Logger.
221
void setLogManager(LogManager JavaDoc manager) {
222     this.manager = manager;
223     }
224
225     private void checkAccess() throws SecurityException JavaDoc {
226     if (!anonymous) {
227         if (manager == null) {
228                 // Complete initialization of the global Logger.
229
manager = LogManager.getLogManager();
230             }
231         manager.checkAccess();
232     }
233     }
234
235     /**
236      * Find or create a logger for a named subsystem. If a logger has
237      * already been created with the given name it is returned. Otherwise
238      * a new logger is created.
239      * <p>
240      * If a new logger is created its log level will be configured
241      * based on the LogManager configuration and it will configured
242      * to also send logging output to its parent's handlers. It will
243      * be registered in the LogManager global namespace.
244      *
245      * @param name A name for the logger. This should
246      * be a dot-separated name and should normally
247      * be based on the package name or class name
248      * of the subsystem, such as java.net
249      * or javax.swing
250      * @return a suitable Logger
251      * @throws NullPointerException if the name is null.
252      */

253     public static synchronized Logger JavaDoc getLogger(String JavaDoc name) {
254     LogManager JavaDoc manager = LogManager.getLogManager();
255     Logger JavaDoc result = manager.getLogger(name);
256     if (result == null) {
257         result = new Logger JavaDoc(name, null);
258         manager.addLogger(result);
259         result = manager.getLogger(name);
260     }
261     return result;
262     }
263
264     /**
265      * Find or create a logger for a named subsystem. If a logger has
266      * already been created with the given name it is returned. Otherwise
267      * a new logger is created.
268      * <p>
269      * If a new logger is created its log level will be configured
270      * based on the LogManager and it will configured to also send logging
271      * output to its parent loggers Handlers. It will be registered in
272      * the LogManager global namespace.
273      * <p>
274      * If the named Logger already exists and does not yet have a
275      * localization resource bundle then the given resource bundle
276      * name is used. If the named Logger already exists and has
277      * a different resource bundle name then an IllegalArgumentException
278      * is thrown.
279      * <p>
280      * @param name A name for the logger. This should
281      * be a dot-separated name and should normally
282      * be based on the package name or class name
283      * of the subsystem, such as java.net
284      * or javax.swing
285      * @param resourceBundleName name of ResourceBundle to be used for localizing
286      * messages for this logger. May be <CODE>null</CODE> if none of
287      * the messages require localization.
288      * @return a suitable Logger
289      * @throws MissingResourceException if the named ResourceBundle cannot be found.
290      * @throws IllegalArgumentException if the Logger already exists and uses
291      * a different resource bundle name.
292      * @throws NullPointerException if the name is null.
293      */

294     public static synchronized Logger JavaDoc getLogger(String JavaDoc name, String JavaDoc resourceBundleName) {
295     LogManager JavaDoc manager = LogManager.getLogManager();
296     Logger JavaDoc result = manager.getLogger(name);
297     if (result == null) {
298         // Create a new logger.
299
// Note: we may get a MissingResourceException here.
300
result = new Logger JavaDoc(name, resourceBundleName);
301         manager.addLogger(result);
302         result = manager.getLogger(name);
303     }
304     if (result.resourceBundleName == null) {
305         // Note: we may get a MissingResourceException here.
306
result.setupResourceInfo(resourceBundleName);
307     } else if (!result.resourceBundleName.equals(resourceBundleName)) {
308         throw new IllegalArgumentException JavaDoc(result.resourceBundleName +
309                 " != " + resourceBundleName);
310     }
311     return result;
312     }
313
314
315     /**
316      * Create an anonymous Logger. The newly created Logger is not
317      * registered in the LogManager namespace. There will be no
318      * access checks on updates to the logger.
319      * <p>
320      * This factory method is primarily intended for use from applets.
321      * Because the resulting Logger is anonymous it can be kept private
322      * by the creating class. This removes the need for normal security
323      * checks, which in turn allows untrusted applet code to update
324      * the control state of the Logger. For example an applet can do
325      * a setLevel or an addHandler on an anonymous Logger.
326      * <p>
327      * Even although the new logger is anonymous, it is configured
328      * to have the root logger ("") as its parent. This means that
329      * by default it inherits its effective level and handlers
330      * from the root logger.
331      * <p>
332      *
333      * @return a newly created private Logger
334      */

335     public static synchronized Logger JavaDoc getAnonymousLogger() {
336     LogManager JavaDoc manager = LogManager.getLogManager();
337     Logger JavaDoc result = new Logger JavaDoc(null, null);
338     result.anonymous = true;
339     Logger JavaDoc root = manager.getLogger("");
340     result.doSetParent(root);
341     return result;
342     }
343
344     /**
345      * Create an anonymous Logger. The newly created Logger is not
346      * registered in the LogManager namespace. There will be no
347      * access checks on updates to the logger.
348      * <p>
349      * This factory method is primarily intended for use from applets.
350      * Because the resulting Logger is anonymous it can be kept private
351      * by the creating class. This removes the need for normal security
352      * checks, which in turn allows untrusted applet code to update
353      * the control state of the Logger. For example an applet can do
354      * a setLevel or an addHandler on an anonymous Logger.
355      * <p>
356      * Even although the new logger is anonymous, it is configured
357      * to have the root logger ("") as its parent. This means that
358      * by default it inherits its effective level and handlers
359      * from the root logger.
360      * <p>
361      * @param resourceBundleName name of ResourceBundle to be used for localizing
362      * messages for this logger.
363      * May be null if none of the messages require localization.
364      * @return a newly created private Logger
365      * @throws MissingResourceException if the named ResourceBundle cannot be found.
366      */

367     public static synchronized Logger JavaDoc getAnonymousLogger(String JavaDoc resourceBundleName) {
368     LogManager JavaDoc manager = LogManager.getLogManager();
369     Logger JavaDoc result = new Logger JavaDoc(null, resourceBundleName);
370     result.anonymous = true;
371     Logger JavaDoc root = manager.getLogger("");
372     result.doSetParent(root);
373     return result;
374     }
375
376     /**
377      * Retrieve the localization resource bundle for this
378      * logger for the current default locale. Note that if
379      * the result is null, then the Logger will use a resource
380      * bundle inherited from its parent.
381      *
382      * @return localization bundle (may be null)
383      */

384     public ResourceBundle getResourceBundle() {
385     return findResourceBundle(getResourceBundleName());
386     }
387
388     /**
389      * Retrieve the localization resource bundle name for this
390      * logger. Note that if the result is null, then the Logger
391      * will use a resource bundle name inherited from its parent.
392      *
393      * @return localization bundle name (may be null)
394      */

395     public String JavaDoc getResourceBundleName() {
396     return resourceBundleName;
397     }
398
399     /**
400      * Set a filter to control output on this Logger.
401      * <P>
402      * After passing the initial "level" check, the Logger will
403      * call this Filter to check if a log record should really
404      * be published.
405      *
406      * @param newFilter a filter object (may be null)
407      * @exception SecurityException if a security manager exists and if
408      * the caller does not have LoggingPermission("control").
409      */

410     public void setFilter(Filter JavaDoc newFilter) throws SecurityException JavaDoc {
411     checkAccess();
412     filter = newFilter;
413     }
414
415     /**
416      * Get the current filter for this Logger.
417      *
418      * @return a filter object (may be null)
419      */

420     public Filter JavaDoc getFilter() {
421     return filter;
422     }
423
424     /**
425      * Log a LogRecord.
426      * <p>
427      * All the other logging methods in this class call through
428      * this method to actually perform any logging. Subclasses can
429      * override this single method to capture all log activity.
430      *
431      * @param record the LogRecord to be published
432      */

433     public void log(LogRecord JavaDoc record) {
434     if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
435         return;
436     }
437     synchronized (this) {
438         if (filter != null && !filter.isLoggable(record)) {
439             return;
440         }
441     }
442
443     // Post the LogRecord to all our Handlers, and then to
444
// our parents' handlers, all the way up the tree.
445

446     Logger JavaDoc logger = this;
447     while (logger != null) {
448         Handler JavaDoc targets[] = logger.getHandlers();
449
450         if (targets != null) {
451             for (int i = 0; i < targets.length; i++) {
452             targets[i].publish(record);
453         }
454         }
455
456         if (!logger.getUseParentHandlers()) {
457         break;
458         }
459
460         logger = logger.getParent();
461     }
462     }
463
464     // private support method for logging.
465
// We fill in the logger name, resource bundle name, and
466
// resource bundle and then call "void log(LogRecord)".
467
private void doLog(LogRecord JavaDoc lr) {
468     lr.setLoggerName(name);
469     String JavaDoc ebname = getEffectiveResourceBundleName();
470     if (ebname != null) {
471         lr.setResourceBundleName(ebname);
472         lr.setResourceBundle(findResourceBundle(ebname));
473     }
474     log(lr);
475     }
476
477
478     //================================================================
479
// Start of convenience methods WITHOUT className and methodName
480
//================================================================
481

482     /**
483      * Log a message, with no arguments.
484      * <p>
485      * If the logger is currently enabled for the given message
486      * level then the given message is forwarded to all the
487      * registered output Handler objects.
488      * <p>
489      * @param level One of the message level identifiers, e.g. SEVERE
490      * @param msg The string message (or a key in the message catalog)
491      */

492     public void log(Level JavaDoc level, String JavaDoc msg) {
493     if (level.intValue() < levelValue || levelValue == offValue) {
494         return;
495     }
496     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
497     doLog(lr);
498     }
499
500     /**
501      * Log a message, with one object parameter.
502      * <p>
503      * If the logger is currently enabled for the given message
504      * level then a corresponding LogRecord is created and forwarded
505      * to all the registered output Handler objects.
506      * <p>
507      * @param level One of the message level identifiers, e.g. SEVERE
508      * @param msg The string message (or a key in the message catalog)
509      * @param param1 parameter to the message
510      */

511     public void log(Level JavaDoc level, String JavaDoc msg, Object JavaDoc param1) {
512     if (level.intValue() < levelValue || levelValue == offValue) {
513         return;
514     }
515     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
516     Object JavaDoc params[] = { param1 };
517     lr.setParameters(params);
518     doLog(lr);
519     }
520
521     /**
522      * Log a message, with an array of object arguments.
523      * <p>
524      * If the logger is currently enabled for the given message
525      * level then a corresponding LogRecord is created and forwarded
526      * to all the registered output Handler objects.
527      * <p>
528      * @param level One of the message level identifiers, e.g. SEVERE
529      * @param msg The string message (or a key in the message catalog)
530      * @param params array of parameters to the message
531      */

532     public void log(Level JavaDoc level, String JavaDoc msg, Object JavaDoc params[]) {
533     if (level.intValue() < levelValue || levelValue == offValue) {
534         return;
535     }
536     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
537     lr.setParameters(params);
538     doLog(lr);
539     }
540
541     /**
542      * Log a message, with associated Throwable information.
543      * <p>
544      * If the logger is currently enabled for the given message
545      * level then the given arguments are stored in a LogRecord
546      * which is forwarded to all registered output handlers.
547      * <p>
548      * Note that the thrown argument is stored in the LogRecord thrown
549      * property, rather than the LogRecord parameters property. Thus is it
550      * processed specially by output Formatters and is not treated
551      * as a formatting parameter to the LogRecord message property.
552      * <p>
553      * @param level One of the message level identifiers, e.g. SEVERE
554      * @param msg The string message (or a key in the message catalog)
555      * @param thrown Throwable associated with log message.
556      */

557     public void log(Level JavaDoc level, String JavaDoc msg, Throwable JavaDoc thrown) {
558     if (level.intValue() < levelValue || levelValue == offValue) {
559         return;
560     }
561     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
562     lr.setThrown(thrown);
563     doLog(lr);
564     }
565
566     //================================================================
567
// Start of convenience methods WITH className and methodName
568
//================================================================
569

570     /**
571      * Log a message, specifying source class and method,
572      * with no arguments.
573      * <p>
574      * If the logger is currently enabled for the given message
575      * level then the given message is forwarded to all the
576      * registered output Handler objects.
577      * <p>
578      * @param level One of the message level identifiers, e.g. SEVERE
579      * @param sourceClass name of class that issued the logging request
580      * @param sourceMethod name of method that issued the logging request
581      * @param msg The string message (or a key in the message catalog)
582      */

583     public void logp(Level JavaDoc level, String JavaDoc sourceClass, String JavaDoc sourceMethod, String JavaDoc msg) {
584     if (level.intValue() < levelValue || levelValue == offValue) {
585         return;
586     }
587     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
588     lr.setSourceClassName(sourceClass);
589     lr.setSourceMethodName(sourceMethod);
590     doLog(lr);
591     }
592
593     /**
594      * Log a message, specifying source class and method,
595      * with a single object parameter to the log message.
596      * <p>
597      * If the logger is currently enabled for the given message
598      * level then a corresponding LogRecord is created and forwarded
599      * to all the registered output Handler objects.
600      * <p>
601      * @param level One of the message level identifiers, e.g. SEVERE
602      * @param sourceClass name of class that issued the logging request
603      * @param sourceMethod name of method that issued the logging request
604      * @param msg The string message (or a key in the message catalog)
605      * @param param1 Parameter to the log message.
606      */

607     public void logp(Level JavaDoc level, String JavaDoc sourceClass, String JavaDoc sourceMethod,
608                         String JavaDoc msg, Object JavaDoc param1) {
609     if (level.intValue() < levelValue || levelValue == offValue) {
610         return;
611     }
612     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
613     lr.setSourceClassName(sourceClass);
614     lr.setSourceMethodName(sourceMethod);
615     Object JavaDoc params[] = { param1 };
616     lr.setParameters(params);
617     doLog(lr);
618     }
619
620     /**
621      * Log a message, specifying source class and method,
622      * with an array of object arguments.
623      * <p>
624      * If the logger is currently enabled for the given message
625      * level then a corresponding LogRecord is created and forwarded
626      * to all the registered output Handler objects.
627      * <p>
628      * @param level One of the message level identifiers, e.g. SEVERE
629      * @param sourceClass name of class that issued the logging request
630      * @param sourceMethod name of method that issued the logging request
631      * @param msg The string message (or a key in the message catalog)
632      * @param params Array of parameters to the message
633      */

634     public void logp(Level JavaDoc level, String JavaDoc sourceClass, String JavaDoc sourceMethod,
635                         String JavaDoc msg, Object JavaDoc params[]) {
636     if (level.intValue() < levelValue || levelValue == offValue) {
637         return;
638     }
639     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
640     lr.setSourceClassName(sourceClass);
641     lr.setSourceMethodName(sourceMethod);
642     lr.setParameters(params);
643     doLog(lr);
644     }
645
646     /**
647      * Log a message, specifying source class and method,
648      * with associated Throwable information.
649      * <p>
650      * If the logger is currently enabled for the given message
651      * level then the given arguments are stored in a LogRecord
652      * which is forwarded to all registered output handlers.
653      * <p>
654      * Note that the thrown argument is stored in the LogRecord thrown
655      * property, rather than the LogRecord parameters property. Thus is it
656      * processed specially by output Formatters and is not treated
657      * as a formatting parameter to the LogRecord message property.
658      * <p>
659      * @param level One of the message level identifiers, e.g. SEVERE
660      * @param sourceClass name of class that issued the logging request
661      * @param sourceMethod name of method that issued the logging request
662      * @param msg The string message (or a key in the message catalog)
663      * @param thrown Throwable associated with log message.
664      */

665     public void logp(Level JavaDoc level, String JavaDoc sourceClass, String JavaDoc sourceMethod,
666                             String JavaDoc msg, Throwable JavaDoc thrown) {
667     if (level.intValue() < levelValue || levelValue == offValue) {
668         return;
669     }
670     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
671     lr.setSourceClassName(sourceClass);
672     lr.setSourceMethodName(sourceMethod);
673     lr.setThrown(thrown);
674     doLog(lr);
675     }
676
677
678     //=========================================================================
679
// Start of convenience methods WITH className, methodName and bundle name.
680
//=========================================================================
681

682     // Private support method for logging for "logrb" methods.
683
// We fill in the logger name, resource bundle name, and
684
// resource bundle and then call "void log(LogRecord)".
685
private void doLog(LogRecord JavaDoc lr, String JavaDoc rbname) {
686     lr.setLoggerName(name);
687     if (rbname != null) {
688         lr.setResourceBundleName(rbname);
689         lr.setResourceBundle(findResourceBundle(rbname));
690     }
691     log(lr);
692     }
693
694     /**
695      * Log a message, specifying source class, method, and resource bundle name
696      * with no arguments.
697      * <p>
698      * If the logger is currently enabled for the given message
699      * level then the given message is forwarded to all the
700      * registered output Handler objects.
701      * <p>
702      * The msg string is localized using the named resource bundle. If the
703      * resource bundle name is null, or an empty String or invalid
704      * then the msg string is not localized.
705      * <p>
706      * @param level One of the message level identifiers, e.g. SEVERE
707      * @param sourceClass name of class that issued the logging request
708      * @param sourceMethod name of method that issued the logging request
709      * @param bundleName name of resource bundle to localize msg,
710      * can be null
711      * @param msg The string message (or a key in the message catalog)
712      */

713
714     public void logrb(Level JavaDoc level, String JavaDoc sourceClass, String JavaDoc sourceMethod,
715                 String JavaDoc bundleName, String JavaDoc msg) {
716     if (level.intValue() < levelValue || levelValue == offValue) {
717         return;
718     }
719     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
720     lr.setSourceClassName(sourceClass);
721     lr.setSourceMethodName(sourceMethod);
722     doLog(lr, bundleName);
723     }
724
725     /**
726      * Log a message, specifying source class, method, and resource bundle name,
727      * with a single object parameter to the log message.
728      * <p>
729      * If the logger is currently enabled for the given message
730      * level then a corresponding LogRecord is created and forwarded
731      * to all the registered output Handler objects.
732      * <p>
733      * The msg string is localized using the named resource bundle. If the
734      * resource bundle name is null, or an empty String or invalid
735      * then the msg string is not localized.
736      * <p>
737      * @param level One of the message level identifiers, e.g. SEVERE
738      * @param sourceClass name of class that issued the logging request
739      * @param sourceMethod name of method that issued the logging request
740      * @param bundleName name of resource bundle to localize msg,
741      * can be null
742      * @param msg The string message (or a key in the message catalog)
743      * @param param1 Parameter to the log message.
744      */

745     public void logrb(Level JavaDoc level, String JavaDoc sourceClass, String JavaDoc sourceMethod,
746                 String JavaDoc bundleName, String JavaDoc msg, Object JavaDoc param1) {
747     if (level.intValue() < levelValue || levelValue == offValue) {
748         return;
749     }
750     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
751     lr.setSourceClassName(sourceClass);
752     lr.setSourceMethodName(sourceMethod);
753     Object JavaDoc params[] = { param1 };
754     lr.setParameters(params);
755     doLog(lr, bundleName);
756     }
757
758     /**
759      * Log a message, specifying source class, method, and resource bundle name,
760      * with an array of object arguments.
761      * <p>
762      * If the logger is currently enabled for the given message
763      * level then a corresponding LogRecord is created and forwarded
764      * to all the registered output Handler objects.
765      * <p>
766      * The msg string is localized using the named resource bundle. If the
767      * resource bundle name is null, or an empty String or invalid
768      * then the msg string is not localized.
769      * <p>
770      * @param level One of the message level identifiers, e.g. SEVERE
771      * @param sourceClass name of class that issued the logging request
772      * @param sourceMethod name of method that issued the logging request
773      * @param bundleName name of resource bundle to localize msg,
774      * can be null.
775      * @param msg The string message (or a key in the message catalog)
776      * @param params Array of parameters to the message
777      */

778     public void logrb(Level JavaDoc level, String JavaDoc sourceClass, String JavaDoc sourceMethod,
779                 String JavaDoc bundleName, String JavaDoc msg, Object JavaDoc params[]) {
780     if (level.intValue() < levelValue || levelValue == offValue) {
781         return;
782     }
783     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
784     lr.setSourceClassName(sourceClass);
785     lr.setSourceMethodName(sourceMethod);
786     lr.setParameters(params);
787     doLog(lr, bundleName);
788     }
789
790     /**
791      * Log a message, specifying source class, method, and resource bundle name,
792      * with associated Throwable information.
793      * <p>
794      * If the logger is currently enabled for the given message
795      * level then the given arguments are stored in a LogRecord
796      * which is forwarded to all registered output handlers.
797      * <p>
798      * The msg string is localized using the named resource bundle. If the
799      * resource bundle name is null, or an empty String or invalid
800      * then the msg string is not localized.
801      * <p>
802      * Note that the thrown argument is stored in the LogRecord thrown
803      * property, rather than the LogRecord parameters property. Thus is it
804      * processed specially by output Formatters and is not treated
805      * as a formatting parameter to the LogRecord message property.
806      * <p>
807      * @param level One of the message level identifiers, e.g. SEVERE
808      * @param sourceClass name of class that issued the logging request
809      * @param sourceMethod name of method that issued the logging request
810      * @param bundleName name of resource bundle to localize msg,
811      * can be null
812      * @param msg The string message (or a key in the message catalog)
813      * @param thrown Throwable associated with log message.
814      */

815     public void logrb(Level JavaDoc level, String JavaDoc sourceClass, String JavaDoc sourceMethod,
816                     String JavaDoc bundleName, String JavaDoc msg, Throwable JavaDoc thrown) {
817     if (level.intValue() < levelValue || levelValue == offValue) {
818         return;
819     }
820     LogRecord JavaDoc lr = new LogRecord JavaDoc(level, msg);
821     lr.setSourceClassName(sourceClass);
822     lr.setSourceMethodName(sourceMethod);
823     lr.setThrown(thrown);
824     doLog(lr, bundleName);
825     }
826
827
828     //======================================================================
829
// Start of convenience methods for logging method entries and returns.
830
//======================================================================
831

832     /**
833      * Log a method entry.
834      * <p>
835      * This is a convenience method that can be used to log entry
836      * to a method. A LogRecord with message "ENTRY", log level
837      * FINER, and the given sourceMethod and sourceClass is logged.
838      * <p>
839      * @param sourceClass name of class that issued the logging request
840      * @param sourceMethod name of method that is being entered
841      */

842     public void entering(String JavaDoc sourceClass, String JavaDoc sourceMethod) {
843     if (Level.FINER.intValue() < levelValue) {
844         return;
845     }
846     logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
847     }
848
849     /**
850      * Log a method entry, with one parameter.
851      * <p>
852      * This is a convenience method that can be used to log entry
853      * to a method. A LogRecord with message "ENTRY {0}", log level
854      * FINER, and the given sourceMethod, sourceClass, and parameter
855      * is logged.
856      * <p>
857      * @param sourceClass name of class that issued the logging request
858      * @param sourceMethod name of method that is being entered
859      * @param param1 parameter to the method being entered
860      */

861     public void entering(String JavaDoc sourceClass, String JavaDoc sourceMethod, Object JavaDoc param1) {
862     if (Level.FINER.intValue() < levelValue) {
863         return;
864     }
865     Object JavaDoc params[] = { param1 };
866     logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", params);
867     }
868
869     /**
870      * Log a method entry, with an array of parameters.
871      * <p>
872      * This is a convenience method that can be used to log entry
873      * to a method. A LogRecord with message "ENTRY" (followed by a
874      * format {N} indicator for each entry in the parameter array),
875      * log level FINER, and the given sourceMethod, sourceClass, and
876      * parameters is logged.
877      * <p>
878      * @param sourceClass name of class that issued the logging request
879      * @param sourceMethod name of method that is being entered
880      * @param params array of parameters to the method being entered
881      */

882     public void entering(String JavaDoc sourceClass, String JavaDoc sourceMethod, Object JavaDoc params[]) {
883     if (Level.FINER.intValue() < levelValue) {
884         return;
885     }
886     String JavaDoc msg = "ENTRY";
887     if (params == null ) {
888        logp(Level.FINER, sourceClass, sourceMethod, msg);
889        return;
890     }
891     for (int i = 0; i < params.length; i++) {
892         msg = msg + " {" + i + "}";
893     }
894     logp(Level.FINER, sourceClass, sourceMethod, msg, params);
895     }
896
897     /**
898      * Log a method return.
899      * <p>
900      * This is a convenience method that can be used to log returning
901      * from a method. A LogRecord with message "RETURN", log level
902      * FINER, and the given sourceMethod and sourceClass is logged.
903      * <p>
904      * @param sourceClass name of class that issued the logging request
905      * @param sourceMethod name of the method
906      */

907     public void exiting(String JavaDoc sourceClass, String JavaDoc sourceMethod) {