1 /* Logger.java -- a class for logging messages
2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java
.util
.logging
;
41 import java
.util
.List
;
42 import java
.util
.MissingResourceException
;
43 import java
.util
.ResourceBundle
;
46 * A Logger is used for logging information about events. Usually, there
47 * is a seprate logger for each subsystem or component, although there
48 * is a shared instance for components that make only occasional use of
49 * the logging framework.
51 * <p>It is common to name a logger after the name of a corresponding
52 * Java package. Loggers are organized into a hierarchical namespace;
53 * for example, the logger <code>"org.gnu.foo"</code> is the
54 * <em>parent</em> of logger <code>"org.gnu.foo.bar"</code>.
56 * <p>A logger for a named subsystem can be obtained through {@link
57 * java.util.logging.Logger#getLogger(java.lang.String)}. However,
58 * only code which has been granted the permission to control the
59 * logging infrastructure will be allowed to customize that logger.
60 * Untrusted code can obtain a private, anonymous logger through
61 * {@link #getAnonymousLogger()} if it wants to perform any
62 * modifications to the logger.
64 * <p>FIXME: Write more documentation.
66 * @author Sascha Brawer (brawer@acm.org)
71 * A logger provided to applications that make only occasional use
72 * of the logging framework, typically early prototypes. Serious
73 * products are supposed to create and use their own Loggers, so
74 * they can be controlled individually.
76 public static final Logger global
= getLogger("global");
80 * The name of the Logger, or <code>null</code> if the logger is
83 * <p>A previous version of the GNU Classpath implementation granted
84 * untrusted code the permission to control any logger whose name
85 * was null. However, test code revealed that the Sun J2SE 1.4
86 * reference implementation enforces the security control for any
87 * logger that was not created through getAnonymousLogger, even if
88 * it has a null name. Therefore, a separate flag {@link
89 * Logger#anonymous} was introduced.
91 private final String name
;
95 * The name of the resource bundle used for localization.
97 * <p>This variable cannot be declared as <code>final</code>
98 * because its value can change as a result of calling
99 * getLogger(String,String).
101 private String resourceBundleName
;
105 * The resource bundle used for localization.
107 * <p>This variable cannot be declared as <code>final</code>
108 * because its value can change as a result of calling
109 * getLogger(String,String).
111 private ResourceBundle resourceBundle
;
113 private Filter filter
;
115 private final List handlerList
= new java
.util
.ArrayList(4);
116 private Handler
[] handlers
= new Handler
[0];
119 * Indicates whether or not this logger is anonymous. While
120 * a LoggingPermission is required for any modifications to
121 * a normal logger, untrusted code can obtain an anonymous logger
122 * and modify it according to its needs.
124 * <p>A previous version of the GNU Classpath implementation
125 * granted access to every logger whose name was null.
126 * However, test code revealed that the Sun J2SE 1.4 reference
127 * implementation enforces the security control for any logger
128 * that was not created through getAnonymousLogger, even
129 * if it has a null name.
131 private boolean anonymous
;
134 private boolean useParentHandlers
;
138 private Logger parent
;
141 * Constructs a Logger for a subsystem. Most applications do not
142 * need to create new Loggers explicitly; instead, they should call
143 * the static factory methods
144 * {@link #getLogger(java.lang.String,java.lang.String) getLogger}
145 * (with ResourceBundle for localization) or
146 * {@link #getLogger(java.lang.String) getLogger} (without
147 * ResourceBundle), respectively.
149 * @param name the name for the logger, for example "java.awt"
150 * or "com.foo.bar". The name should be based on
151 * the name of the package issuing log records
152 * and consist of dot-separated Java identifiers.
154 * @param resourceBundleName the name of a resource bundle
155 * for localizing messages, or <code>null</code>
156 * to indicate that messages do not need to be localized.
158 * @throws java.util.MissingResourceException if
159 * <code>resourceBundleName</code> is not <code>null</code>
160 * and no such bundle could be located.
162 protected Logger(String name
, String resourceBundleName
)
163 throws MissingResourceException
166 this.resourceBundleName
= resourceBundleName
;
168 if (resourceBundleName
== null)
169 resourceBundle
= null;
171 resourceBundle
= ResourceBundle
.getBundle(resourceBundleName
);
175 /* This is null when the root logger is being constructed,
176 * and the root logger afterwards.
178 parent
= LogManager
.getLogManager().rootLogger
;
180 useParentHandlers
= (parent
!= null);
186 * Finds a registered logger for a subsystem, or creates one in
187 * case no logger has been registered yet.
189 * @param name the name for the logger, for example "java.awt"
190 * or "com.foo.bar". The name should be based on
191 * the name of the package issuing log records
192 * and consist of dot-separated Java identifiers.
194 * @throws IllegalArgumentException if a logger for the subsystem
195 * identified by <code>name</code> has already been created,
196 * but uses a a resource bundle for localizing messages.
198 * @throws NullPointerException if <code>name</code> is
201 * @return a logger for the subsystem specified by <code>name</code>
202 * that does not localize messages.
204 public static Logger
getLogger(String name
)
206 return getLogger(name
, null);
211 * Finds a registered logger for a subsystem, or creates one in case
212 * no logger has been registered yet.
214 * <p>If a logger with the specified name has already been
215 * registered, the behavior depends on the resource bundle that is
216 * currently associated with the existing logger.
218 * <ul><li>If the existing logger uses the same resource bundle as
219 * specified by <code>resourceBundleName</code>, the existing logger
222 * <li>If the existing logger currently does not localize messages,
223 * the existing logger is modified to use the bundle specified by
224 * <code>resourceBundleName</code>. The existing logger is then
225 * returned. Therefore, all subsystems currently using this logger
226 * will produce localized messages from now on.</li>
228 * <li>If the existing logger already has an associated resource
229 * bundle, but a different one than specified by
230 * <code>resourceBundleName</code>, an
231 * <code>IllegalArgumentException</code> is thrown.</li></ul>
233 * @param name the name for the logger, for example "java.awt"
234 * or "org.gnu.foo". The name should be based on
235 * the name of the package issuing log records
236 * and consist of dot-separated Java identifiers.
238 * @param resourceBundleName the name of a resource bundle
239 * for localizing messages, or <code>null</code>
240 * to indicate that messages do not need to be localized.
242 * @return a logger for the subsystem specified by <code>name</code>.
244 * @throws java.util.MissingResourceException if
245 * <code>resourceBundleName</code> is not <code>null</code>
246 * and no such bundle could be located.
248 * @throws IllegalArgumentException if a logger for the subsystem
249 * identified by <code>name</code> has already been created,
250 * but uses a different resource bundle for localizing
253 * @throws NullPointerException if <code>name</code> is
256 public static Logger
getLogger(String name
, String resourceBundleName
)
258 LogManager lm
= LogManager
.getLogManager();
261 /* Throw NullPointerException if name is null. */
264 /* Without synchronized(lm), it could happen that another thread
265 * would create a logger between our calls to getLogger and
266 * addLogger. While addLogger would indicate this by returning
267 * false, we could not be sure that this other logger was still
268 * existing when we called getLogger a second time in order
269 * to retrieve it -- note that LogManager is only allowed to
270 * keep weak references to registered loggers, so Loggers
271 * can be garbage collected at any time in general, and between
272 * our call to addLogger and our second call go getLogger
275 * Of course, we assume here that LogManager.addLogger etc.
276 * are synchronizing on the global LogManager object. There
277 * is a comment in the implementation of LogManager.addLogger
278 * referring to this comment here, so that any change in
279 * the synchronization of LogManager will be reflected here.
283 result
= lm
.getLogger(name
);
286 boolean couldBeAdded
;
288 result
= new Logger(name
, resourceBundleName
);
289 couldBeAdded
= lm
.addLogger(result
);
291 throw new IllegalStateException("cannot register new logger");
295 /* The logger already exists. Make sure it uses
296 * the same resource bundle for localizing messages.
298 String existingBundleName
= result
.getResourceBundleName();
300 /* The Sun J2SE 1.4 reference implementation will return the
301 * registered logger object, even if it does not have a resource
302 * bundle associated with it. However, it seems to change the
303 * resourceBundle of the registered logger to the bundle
304 * whose name was passed to getLogger.
306 if ((existingBundleName
== null) && (resourceBundleName
!= null))
308 /* If ResourceBundle.getBundle throws an exception, the
309 * existing logger will be unchanged. This would be
310 * different if the assignment to resourceBundleName
313 result
.resourceBundle
= ResourceBundle
.getBundle(resourceBundleName
);
314 result
.resourceBundleName
= resourceBundleName
;
318 if ((existingBundleName
!= resourceBundleName
)
319 && ((existingBundleName
== null)
320 || !existingBundleName
.equals(resourceBundleName
)))
322 throw new IllegalArgumentException();
332 * Creates a new, unnamed logger. Unnamed loggers are not
333 * registered in the namespace of the LogManager, and no special
334 * security permission is required for changing their state.
335 * Therefore, untrusted applets are able to modify their private
336 * logger instance obtained through this method.
338 * <p>The parent of the newly created logger will the the root
339 * logger, from which the level threshold and the handlers are
342 public static Logger
getAnonymousLogger()
344 return getAnonymousLogger(null);
349 * Creates a new, unnamed logger. Unnamed loggers are not
350 * registered in the namespace of the LogManager, and no special
351 * security permission is required for changing their state.
352 * Therefore, untrusted applets are able to modify their private
353 * logger instance obtained through this method.
355 * <p>The parent of the newly created logger will the the root
356 * logger, from which the level threshold and the handlers are
359 * @param resourceBundleName the name of a resource bundle
360 * for localizing messages, or <code>null</code>
361 * to indicate that messages do not need to be localized.
363 * @throws java.util.MissingResourceException if
364 * <code>resourceBundleName</code> is not <code>null</code>
365 * and no such bundle could be located.
367 public static Logger
getAnonymousLogger(String resourceBundleName
)
368 throws MissingResourceException
372 result
= new Logger(null, resourceBundleName
);
373 result
.anonymous
= true;
379 * Returns the name of the resource bundle that is being used for
380 * localizing messages.
382 * @return the name of the resource bundle used for localizing messages,
383 * or <code>null</code> if the parent's resource bundle
384 * is used for this purpose.
386 public synchronized String
getResourceBundleName()
388 return resourceBundleName
;
393 * Returns the resource bundle that is being used for localizing
396 * @return the resource bundle used for localizing messages,
397 * or <code>null</code> if the parent's resource bundle
398 * is used for this purpose.
400 public synchronized ResourceBundle
getResourceBundle()
402 return resourceBundle
;
407 * Returns the severity level threshold for this <code>Handler</code>.
408 * All log records with a lower severity level will be discarded;
409 * a log record of the same or a higher level will be published
410 * unless an installed <code>Filter</code> decides to discard it.
412 * @return the severity level below which all log messages will be
413 * discarded, or <code>null</code> if the logger inherits
414 * the threshold from its parent.
416 public synchronized Level
getLevel()
423 * Returns whether or not a message of the specified level
424 * would be logged by this logger.
426 * @throws NullPointerException if <code>level</code>
427 * is <code>null</code>.
429 public synchronized boolean isLoggable(Level level
)
431 if (this.level
!= null)
432 return this.level
.intValue() <= level
.intValue();
435 return parent
.isLoggable(level
);
442 * Sets the severity level threshold for this <code>Handler</code>.
443 * All log records with a lower severity level will be discarded
444 * immediately. A log record of the same or a higher level will be
445 * published unless an installed <code>Filter</code> decides to
448 * @param level the severity level below which all log messages
449 * will be discarded, or <code>null</code> to
450 * indicate that the logger should inherit the
451 * threshold from its parent.
453 * @throws SecurityException if this logger is not anonymous, a
454 * security manager exists, and the caller is not granted
455 * the permission to control the logging infrastructure by
456 * having LoggingPermission("control"). Untrusted code can
457 * obtain an anonymous logger through the static factory method
458 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
460 public synchronized void setLevel(Level level
)
462 /* An application is allowed to control an anonymous logger
463 * without having the permission to control the logging
467 LogManager
.getLogManager().checkAccess();
473 public synchronized Filter
getFilter()
480 * @throws SecurityException if this logger is not anonymous, a
481 * security manager exists, and the caller is not granted
482 * the permission to control the logging infrastructure by
483 * having LoggingPermission("control"). Untrusted code can
484 * obtain an anonymous logger through the static factory method
485 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
487 public synchronized void setFilter(Filter filter
)
488 throws SecurityException
490 /* An application is allowed to control an anonymous logger
491 * without having the permission to control the logging
495 LogManager
.getLogManager().checkAccess();
497 this.filter
= filter
;
504 * Returns the name of this logger.
506 * @return the name of this logger, or <code>null</code> if
507 * the logger is anonymous.
509 public String
getName()
511 /* Note that the name of a logger cannot be changed during
512 * its lifetime, so no synchronization is needed.
519 * Passes a record to registered handlers, provided the record
520 * is considered as loggable both by {@link #isLoggable(Level)}
521 * and a possibly installed custom {@link #setFilter(Filter) filter}.
523 * <p>If the logger has been configured to use parent handlers,
524 * the record will be forwarded to the parent of this logger
525 * in addition to being processed by the handlers registered with
528 * <p>The other logging methods in this class are convenience methods
529 * that merely create a new LogRecord and pass it to this method.
530 * Therefore, subclasses usually just need to override this single
531 * method for customizing the logging behavior.
533 * @param record the log record to be inspected and possibly forwarded.
535 public synchronized void log(LogRecord record
)
537 if (!isLoggable(record
.getLevel()))
540 if ((filter
!= null) && !filter
.isLoggable(record
))
543 /* If no logger name has been set for the log record,
544 * use the name of this logger.
546 if (record
.getLoggerName() == null)
547 record
.setLoggerName(name
);
549 /* Avoid that some other thread is changing the logger hierarchy
550 * while we are traversing it.
552 synchronized (LogManager
.getLogManager())
554 Logger curLogger
= this;
558 /* The Sun J2SE 1.4 reference implementation seems to call the
559 * filter only for the logger whose log method is called,
560 * never for any of its parents. Also, parent loggers publish
561 * log record whatever their level might be. This is pretty
562 * weird, but GNU Classpath tries to be as compatible as
563 * possible to the reference implementation.
565 for (int i
= 0; i
< curLogger
.handlers
.length
; i
++)
566 curLogger
.handlers
[i
].publish(record
);
568 if (curLogger
.getUseParentHandlers() == false)
571 curLogger
= curLogger
.getParent();
573 while (parent
!= null);
578 public void log(Level level
, String message
)
580 if (isLoggable(level
))
581 log(level
, message
, (Object
[]) null);
585 public synchronized void log(Level level
,
589 if (isLoggable(level
))
591 StackTraceElement caller
= getCallerStackFrame();
593 caller
!= null ? caller
.getClassName() : "<unknown>",
594 caller
!= null ? caller
.getMethodName() : "<unknown>",
601 public synchronized void log(Level level
,
605 if (isLoggable(level
))
607 StackTraceElement caller
= getCallerStackFrame();
609 caller
!= null ? caller
.getClassName() : "<unknown>",
610 caller
!= null ? caller
.getMethodName() : "<unknown>",
617 public synchronized void log(Level level
,
621 if (isLoggable(level
))
623 StackTraceElement caller
= getCallerStackFrame();
625 caller
!= null ? caller
.getClassName() : "<unknown>",
626 caller
!= null ? caller
.getMethodName() : "<unknown>",
633 public synchronized void logp(Level level
,
638 logp(level
, sourceClass
, sourceMethod
, message
,
643 public synchronized void logp(Level level
,
649 logp(level
, sourceClass
, sourceMethod
, message
,
650 new Object
[] { param
});
654 private synchronized ResourceBundle
findResourceBundle()
656 if (resourceBundle
!= null)
657 return resourceBundle
;
660 return parent
.findResourceBundle();
666 private synchronized void logImpl(Level level
,
672 LogRecord rec
= new LogRecord(level
, message
);
674 rec
.setResourceBundle(findResourceBundle());
675 rec
.setSourceClassName(sourceClass
);
676 rec
.setSourceMethodName(sourceMethod
);
677 rec
.setParameters(params
);
683 public synchronized void logp(Level level
,
689 logImpl(level
, sourceClass
, sourceMethod
, message
, params
);
693 public synchronized void logp(Level level
,
699 LogRecord rec
= new LogRecord(level
, message
);
701 rec
.setResourceBundle(resourceBundle
);
702 rec
.setSourceClassName(sourceClass
);
703 rec
.setSourceMethodName(sourceMethod
);
704 rec
.setThrown(thrown
);
710 public synchronized void logrb(Level level
,
716 logrb(level
, sourceClass
, sourceMethod
, bundleName
,
717 message
, (Object
[]) null);
721 public synchronized void logrb(Level level
,
728 logrb(level
, sourceClass
, sourceMethod
, bundleName
,
729 message
, new Object
[] { param
});
733 public synchronized void logrb(Level level
,
740 LogRecord rec
= new LogRecord(level
, message
);
742 rec
.setResourceBundleName(bundleName
);
743 rec
.setSourceClassName(sourceClass
);
744 rec
.setSourceMethodName(sourceMethod
);
745 rec
.setParameters(params
);
751 public synchronized void logrb(Level level
,
758 LogRecord rec
= new LogRecord(level
, message
);
760 rec
.setResourceBundleName(bundleName
);
761 rec
.setSourceClassName(sourceClass
);
762 rec
.setSourceMethodName(sourceMethod
);
763 rec
.setThrown(thrown
);
769 public synchronized void entering(String sourceClass
,
772 if (isLoggable(Level
.FINER
))
773 logp(Level
.FINER
, sourceClass
, sourceMethod
, "ENTRY");
777 public synchronized void entering(String sourceClass
,
781 if (isLoggable(Level
.FINER
))
782 logp(Level
.FINER
, sourceClass
, sourceMethod
, "ENTRY {0}", param
);
786 public synchronized void entering(String sourceClass
,
790 if (isLoggable(Level
.FINER
))
792 StringBuffer buf
= new StringBuffer(80);
794 for (int i
= 0; i
< params
.length
; i
++)
801 logp(Level
.FINER
, sourceClass
, sourceMethod
, buf
.toString(), params
);
806 public synchronized void exiting(String sourceClass
,
809 if (isLoggable(Level
.FINER
))
810 logp(Level
.FINER
, sourceClass
, sourceMethod
, "RETURN");
814 public synchronized void exiting(String sourceClass
,
818 if (isLoggable(Level
.FINER
))
819 logp(Level
.FINER
, sourceClass
, sourceMethod
, "RETURN {0}", result
);
823 public synchronized void throwing(String sourceClass
,
827 if (isLoggable(Level
.FINER
))
828 logp(Level
.FINER
, sourceClass
, sourceMethod
, "THROW", thrown
);
833 * Logs a message with severity level SEVERE, indicating a serious
834 * failure that prevents normal program execution. Messages at this
835 * level should be understandable to an inexperienced, non-technical
836 * end user. Ideally, they explain in simple words what actions the
837 * user can take in order to resolve the problem.
841 * @param message the message text, also used as look-up key if the
842 * logger is localizing messages with a resource
843 * bundle. While it is possible to pass
844 * <code>null</code>, this is not recommended, since
845 * a logging message without text is unlikely to be
848 public synchronized void severe(String message
)
850 if (isLoggable(Level
.SEVERE
))
851 log(Level
.SEVERE
, message
);
856 * Logs a message with severity level WARNING, indicating a
857 * potential problem that does not prevent normal program execution.
858 * Messages at this level should be understandable to an
859 * inexperienced, non-technical end user. Ideally, they explain in
860 * simple words what actions the user can take in order to resolve
865 * @param message the message text, also used as look-up key if the
866 * logger is localizing messages with a resource
867 * bundle. While it is possible to pass
868 * <code>null</code>, this is not recommended, since
869 * a logging message without text is unlikely to be
872 public synchronized void warning(String message
)
874 if (isLoggable(Level
.WARNING
))
875 log(Level
.WARNING
, message
);
880 * Logs a message with severity level INFO. {@link Level#INFO} is
881 * intended for purely informational messages that do not indicate
882 * error or warning situations. In the default logging
883 * configuration, INFO messages will be written to the system
884 * console. For this reason, the INFO level should be used only for
885 * messages that are important to end users and system
886 * administrators. Messages at this level should be understandable
887 * to an inexperienced, non-technical user.
889 * @param message the message text, also used as look-up key if the
890 * logger is localizing messages with a resource
891 * bundle. While it is possible to pass
892 * <code>null</code>, this is not recommended, since
893 * a logging message without text is unlikely to be
896 public synchronized void info(String message
)
898 if (isLoggable(Level
.INFO
))
899 log(Level
.INFO
, message
);
904 * Logs a message with severity level CONFIG. {@link Level#CONFIG} is
905 * intended for static configuration messages, for example about the
906 * windowing environment, the operating system version, etc.
908 * @param message the message text, also used as look-up key if the
909 * logger is localizing messages with a resource bundle. While
910 * it is possible to pass <code>null</code>, this is not
911 * recommended, since a logging message without text is unlikely
914 public synchronized void config(String message
)
916 if (isLoggable(Level
.CONFIG
))
917 log(Level
.CONFIG
, message
);
922 * Logs a message with severity level FINE. {@link Level#FINE} is
923 * intended for messages that are relevant for developers using
924 * the component generating log messages. Examples include minor,
925 * recoverable failures, or possible inefficiencies.
927 * @param message the message text, also used as look-up key if the
928 * logger is localizing messages with a resource
929 * bundle. While it is possible to pass
930 * <code>null</code>, this is not recommended, since
931 * a logging message without text is unlikely to be
934 public synchronized void fine(String message
)
936 if (isLoggable(Level
.FINE
))
937 log(Level
.FINE
, message
);
942 * Logs a message with severity level FINER. {@link Level#FINER} is
943 * intended for rather detailed tracing, for example entering a
944 * method, returning from a method, or throwing an exception.
946 * @param message the message text, also used as look-up key if the
947 * logger is localizing messages with a resource
948 * bundle. While it is possible to pass
949 * <code>null</code>, this is not recommended, since
950 * a logging message without text is unlikely to be
953 public synchronized void finer(String message
)
955 if (isLoggable(Level
.FINER
))
956 log(Level
.FINER
, message
);
961 * Logs a message with severity level FINEST. {@link Level#FINEST}
962 * is intended for highly detailed tracing, for example reaching a
963 * certain point inside the body of a method.
965 * @param message the message text, also used as look-up key if the
966 * logger is localizing messages with a resource
967 * bundle. While it is possible to pass
968 * <code>null</code>, this is not recommended, since
969 * a logging message without text is unlikely to be
972 public synchronized void finest(String message
)
974 if (isLoggable(Level
.FINEST
))
975 log(Level
.FINEST
, message
);
980 * Adds a handler to the set of handlers that get notified
981 * when a log record is to be published.
983 * @param handler the handler to be added.
985 * @throws NullPointerException if <code>handler</code>
986 * is <code>null</code>.
988 * @throws SecurityException if this logger is not anonymous, a
989 * security manager exists, and the caller is not granted
990 * the permission to control the logging infrastructure by
991 * having LoggingPermission("control"). Untrusted code can
992 * obtain an anonymous logger through the static factory method
993 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
995 public synchronized void addHandler(Handler handler
)
996 throws SecurityException
998 /* Throw a new NullPointerException if handler is null. */
1001 /* An application is allowed to control an anonymous logger
1002 * without having the permission to control the logging
1006 LogManager
.getLogManager().checkAccess();
1008 if (!handlerList
.contains(handler
))
1010 handlerList
.add(handler
);
1011 handlers
= getHandlers();
1017 * Removes a handler from the set of handlers that get notified
1018 * when a log record is to be published.
1020 * @param handler the handler to be removed.
1022 * @throws SecurityException if this logger is not anonymous, a
1023 * security manager exists, and the caller is not granted the
1024 * permission to control the logging infrastructure by having
1025 * LoggingPermission("control"). Untrusted code can obtain an
1026 * anonymous logger through the static factory method {@link
1027 * #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
1029 * @throws NullPointerException if <code>handler</code>
1030 * is <code>null</code>.
1032 public synchronized void removeHandler(Handler handler
)
1033 throws SecurityException
1035 /* An application is allowed to control an anonymous logger
1036 * without having the permission to control the logging
1040 LogManager
.getLogManager().checkAccess();
1042 /* Throw a new NullPointerException if handler is null. */
1045 handlerList
.remove(handler
);
1046 handlers
= getHandlers();
1051 * Returns the handlers currently registered for this Logger.
1052 * When a log record has been deemed as being loggable,
1053 * it will be passed to all registered handlers for
1054 * publication. In addition, if the logger uses parent handlers
1055 * (see {@link #getUseParentHandlers() getUseParentHandlers}
1056 * and {@link #setUseParentHandlers(boolean) setUseParentHandlers},
1057 * the log record will be passed to the parent's handlers.
1059 public synchronized Handler
[] getHandlers()
1061 /* We cannot return our internal handlers array
1062 * because we do not have any guarantee that the
1063 * caller would not change the array entries.
1065 return (Handler
[]) handlerList
.toArray(new Handler
[handlerList
.size()]);
1070 * Returns whether or not this Logger forwards log records to
1071 * handlers registered for its parent loggers.
1073 * @return <code>false</code> if this Logger sends log records
1074 * merely to Handlers registered with itself;
1075 * <code>true</code> if this Logger sends log records
1076 * not only to Handlers registered with itself, but also
1077 * to those Handlers registered with parent loggers.
1079 public synchronized boolean getUseParentHandlers()
1081 return useParentHandlers
;
1086 * Sets whether or not this Logger forwards log records to
1087 * handlers registered for its parent loggers.
1089 * @param useParentHandlers <code>false</code> to let this
1090 * Logger send log records merely to Handlers registered
1091 * with itself; <code>true</code> to let this Logger
1092 * send log records not only to Handlers registered
1093 * with itself, but also to those Handlers registered with
1096 * @throws SecurityException if this logger is not anonymous, a
1097 * security manager exists, and the caller is not granted
1098 * the permission to control the logging infrastructure by
1099 * having LoggingPermission("control"). Untrusted code can
1100 * obtain an anonymous logger through the static factory method
1101 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
1104 public synchronized void setUseParentHandlers(boolean useParentHandlers
)
1106 /* An application is allowed to control an anonymous logger
1107 * without having the permission to control the logging
1111 LogManager
.getLogManager().checkAccess();
1113 this.useParentHandlers
= useParentHandlers
;
1118 * Returns the parent of this logger. By default, the parent is
1119 * assigned by the LogManager by inspecting the logger's name.
1121 * @return the parent of this logger (as detemined by the LogManager
1122 * by inspecting logger names), the root logger if no other
1123 * logger has a name which is a prefix of this logger's name, or
1124 * <code>null</code> for the root logger.
1126 public synchronized Logger
getParent()
1133 * Sets the parent of this logger. Usually, applications do not
1134 * call this method directly. Instead, the LogManager will ensure
1135 * that the tree of loggers reflects the hierarchical logger
1136 * namespace. Basically, this method should not be public at all,
1137 * but the GNU implementation follows the API specification.
1139 * @throws NullPointerException if <code>parent</code> is
1140 * <code>null</code>.
1142 * @throws SecurityException if this logger is not anonymous, a
1143 * security manager exists, and the caller is not granted
1144 * the permission to control the logging infrastructure by
1145 * having LoggingPermission("control"). Untrusted code can
1146 * obtain an anonymous logger through the static factory method
1147 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
1149 public synchronized void setParent(Logger parent
)
1153 /* Throw a new NullPointerException if parent is null. */
1156 lm
= LogManager
.getLogManager();
1158 if (this == lm
.rootLogger
)
1159 throw new IllegalArgumentException(
1160 "only the root logger can have a null parent");
1162 /* An application is allowed to control an anonymous logger
1163 * without having the permission to control the logging
1167 LogManager
.getLogManager().checkAccess();
1169 this.parent
= parent
;
1173 * Gets the StackTraceElement of the first class that is not this class.
1174 * That should be the initial caller of a logging method.
1175 * @return caller of the initial logging method or null if unknown.
1177 private StackTraceElement
getCallerStackFrame()
1179 Throwable t
= new Throwable();
1180 StackTraceElement
[] stackTrace
= t
.getStackTrace();
1183 // skip to stackentries until this class
1184 while(index
< stackTrace
.length
1185 && !stackTrace
[index
].getClassName().equals(getClass().getName()))
1188 // skip the stackentries of this class
1189 while(index
< stackTrace
.length
1190 && stackTrace
[index
].getClassName().equals(getClass().getName()))
1193 return index
< stackTrace
.length ? stackTrace
[index
] : null;
1197 * Reset and close handlers attached to this logger. This function is package
1198 * private because it must only be avaiable to the LogManager.
1202 for (int i
= 0; i
< handlers
.length
; i
++)
1204 handlers
[i
].close();
1205 handlerList
.remove(handlers
[i
]);
1207 handlers
= getHandlers();