Merge from the pain train
[official-gcc.git] / libjava / java / util / logging / Logger.java
blob29635558598bcc986bec7f6c01809687a58fab01
1 /* Logger.java -- a class for logging messages
2 Copyright (C) 2002, 2004, 2005 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)
9 any later version.
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
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
24 combination.
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;
45 /**
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)
68 public class Logger
70 /**
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");
79 /**
80 * The name of the Logger, or <code>null</code> if the logger is
81 * anonymous.
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;
94 /**
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;
136 private Level level;
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
165 this.name = name;
166 this.resourceBundleName = resourceBundleName;
168 if (resourceBundleName == null)
169 resourceBundle = null;
170 else
171 resourceBundle = ResourceBundle.getBundle(resourceBundleName);
173 level = null;
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
199 * <code>null</code>.
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
220 * is returned.</li>
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
251 * messages.
253 * @throws NullPointerException if <code>name</code> is
254 * <code>null</code>.
256 public static Logger getLogger(String name, String resourceBundleName)
258 LogManager lm = LogManager.getLogManager();
259 Logger result;
261 /* Throw NullPointerException if name is null. */
262 name.getClass();
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
273 * in particular.
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.
281 synchronized (lm)
283 result = lm.getLogger(name);
284 if (result == null)
286 boolean couldBeAdded;
288 result = new Logger(name, resourceBundleName);
289 couldBeAdded = lm.addLogger(result);
290 if (!couldBeAdded)
291 throw new IllegalStateException("cannot register new logger");
293 else
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
311 * came first.
313 result.resourceBundle = ResourceBundle.getBundle(resourceBundleName);
314 result.resourceBundleName = resourceBundleName;
315 return result;
318 if ((existingBundleName != resourceBundleName)
319 && ((existingBundleName == null)
320 || !existingBundleName.equals(resourceBundleName)))
322 throw new IllegalArgumentException();
327 return result;
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
340 * inherited.
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
357 * inherited.
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
370 Logger result;
372 result = new Logger(null, resourceBundleName);
373 result.anonymous = true;
374 return result;
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
394 * messages.
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()
418 return level;
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();
434 if (parent != null)
435 return parent.isLoggable(level);
436 else
437 return false;
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
446 * discard it.
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
464 * infrastructure.
466 if (!anonymous)
467 LogManager.getLogManager().checkAccess();
469 this.level = level;
473 public synchronized Filter getFilter()
475 return filter;
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
492 * infrastructure.
494 if (!anonymous)
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.
514 return name;
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
526 * this logger.
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()))
538 return;
540 if ((filter != null) && !filter.isLoggable(record))
541 return;
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)
569 break;
571 curLogger = curLogger.getParent();
573 while (parent != null);
578 public void log(Level level, String message)
580 log(level, message, (Object[]) null);
584 public synchronized void log(Level level,
585 String message,
586 Object param)
588 StackTraceElement caller = getCallerStackFrame();
589 logp(level,
590 caller.getClassName(),
591 caller.getMethodName(),
592 message,
593 param);
597 public synchronized void log(Level level,
598 String message,
599 Object[] params)
601 StackTraceElement caller = getCallerStackFrame();
602 logp(level,
603 caller.getClassName(),
604 caller.getMethodName(),
605 message,
606 params);
610 public synchronized void log(Level level,
611 String message,
612 Throwable thrown)
614 StackTraceElement caller = getCallerStackFrame();
615 logp(level,
616 caller.getClassName(),
617 caller.getMethodName(),
618 message,
619 thrown);
623 public synchronized void logp(Level level,
624 String sourceClass,
625 String sourceMethod,
626 String message)
628 logp(level, sourceClass, sourceMethod, message,
629 (Object[]) null);
633 public synchronized void logp(Level level,
634 String sourceClass,
635 String sourceMethod,
636 String message,
637 Object param)
639 logp(level, sourceClass, sourceMethod, message,
640 new Object[] { param });
644 private synchronized ResourceBundle findResourceBundle()
646 if (resourceBundle != null)
647 return resourceBundle;
649 if (parent != null)
650 return parent.findResourceBundle();
652 return null;
656 private synchronized void logImpl(Level level,
657 String sourceClass,
658 String sourceMethod,
659 String message,
660 Object[] params)
662 LogRecord rec = new LogRecord(level, message);
664 rec.setResourceBundle(findResourceBundle());
665 rec.setSourceClassName(sourceClass);
666 rec.setSourceMethodName(sourceMethod);
667 rec.setParameters(params);
669 log(rec);
673 public synchronized void logp(Level level,
674 String sourceClass,
675 String sourceMethod,
676 String message,
677 Object[] params)
679 logImpl(level, sourceClass, sourceMethod, message, params);
683 public synchronized void logp(Level level,
684 String sourceClass,
685 String sourceMethod,
686 String message,
687 Throwable thrown)
689 LogRecord rec = new LogRecord(level, message);
691 rec.setResourceBundle(resourceBundle);
692 rec.setSourceClassName(sourceClass);
693 rec.setSourceMethodName(sourceMethod);
694 rec.setThrown(thrown);
696 log(rec);
700 public synchronized void logrb(Level level,
701 String sourceClass,
702 String sourceMethod,
703 String bundleName,
704 String message)
706 logrb(level, sourceClass, sourceMethod, bundleName,
707 message, (Object[]) null);
711 public synchronized void logrb(Level level,
712 String sourceClass,
713 String sourceMethod,
714 String bundleName,
715 String message,
716 Object param)
718 logrb(level, sourceClass, sourceMethod, bundleName,
719 message, new Object[] { param });
723 public synchronized void logrb(Level level,
724 String sourceClass,
725 String sourceMethod,
726 String bundleName,
727 String message,
728 Object[] params)
730 LogRecord rec = new LogRecord(level, message);
732 rec.setResourceBundleName(bundleName);
733 rec.setSourceClassName(sourceClass);
734 rec.setSourceMethodName(sourceMethod);
735 rec.setParameters(params);
737 log(rec);
741 public synchronized void logrb(Level level,
742 String sourceClass,
743 String sourceMethod,
744 String bundleName,
745 String message,
746 Throwable thrown)
748 LogRecord rec = new LogRecord(level, message);
750 rec.setResourceBundleName(bundleName);
751 rec.setSourceClassName(sourceClass);
752 rec.setSourceMethodName(sourceMethod);
753 rec.setThrown(thrown);
755 log(rec);
759 public synchronized void entering(String sourceClass,
760 String sourceMethod)
762 if (isLoggable(Level.FINER))
763 logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
767 public synchronized void entering(String sourceClass,
768 String sourceMethod,
769 Object param)
771 if (isLoggable(Level.FINER))
772 logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param);
776 public synchronized void entering(String sourceClass,
777 String sourceMethod,
778 Object[] params)
780 if (isLoggable(Level.FINER))
782 StringBuffer buf = new StringBuffer(80);
783 buf.append("ENTRY");
784 for (int i = 0; i < params.length; i++)
786 buf.append(" {");
787 buf.append(i);
788 buf.append('}');
791 logp(Level.FINER, sourceClass, sourceMethod, buf.toString(), params);
796 public synchronized void exiting(String sourceClass,
797 String sourceMethod)
799 if (isLoggable(Level.FINER))
800 logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
804 public synchronized void exiting(String sourceClass,
805 String sourceMethod,
806 Object result)
808 if (isLoggable(Level.FINER))
809 logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
813 public synchronized void throwing(String sourceClass,
814 String sourceMethod,
815 Throwable thrown)
817 if (isLoggable(Level.FINER))
818 logp(Level.FINER, sourceClass, sourceMethod, "THROW", thrown);
823 * Logs a message with severity level SEVERE, indicating a serious
824 * failure that prevents normal program execution. Messages at this
825 * level should be understandable to an inexperienced, non-technical
826 * end user. Ideally, they explain in simple words what actions the
827 * user can take in order to resolve the problem.
829 * @see Level#SEVERE
831 * @param message the message text, also used as look-up key if the
832 * logger is localizing messages with a resource
833 * bundle. While it is possible to pass
834 * <code>null</code>, this is not recommended, since
835 * a logging message without text is unlikely to be
836 * helpful.
838 public synchronized void severe(String message)
840 if (isLoggable(Level.SEVERE))
841 log(Level.SEVERE, message);
846 * Logs a message with severity level WARNING, indicating a
847 * potential problem that does not prevent normal program execution.
848 * Messages at this level should be understandable to an
849 * inexperienced, non-technical end user. Ideally, they explain in
850 * simple words what actions the user can take in order to resolve
851 * the problem.
853 * @see Level#WARNING
855 * @param message the message text, also used as look-up key if the
856 * logger is localizing messages with a resource
857 * bundle. While it is possible to pass
858 * <code>null</code>, this is not recommended, since
859 * a logging message without text is unlikely to be
860 * helpful.
862 public synchronized void warning(String message)
864 if (isLoggable(Level.WARNING))
865 log(Level.WARNING, message);
870 * Logs a message with severity level INFO. {@link Level#INFO} is
871 * intended for purely informational messages that do not indicate
872 * error or warning situations. In the default logging
873 * configuration, INFO messages will be written to the system
874 * console. For this reason, the INFO level should be used only for
875 * messages that are important to end users and system
876 * administrators. Messages at this level should be understandable
877 * to an inexperienced, non-technical user.
879 * @param message the message text, also used as look-up key if the
880 * logger is localizing messages with a resource
881 * bundle. While it is possible to pass
882 * <code>null</code>, this is not recommended, since
883 * a logging message without text is unlikely to be
884 * helpful.
886 public synchronized void info(String message)
888 if (isLoggable(Level.INFO))
889 log(Level.INFO, message);
894 * Logs a message with severity level CONFIG. {@link Level#CONFIG} is
895 * intended for static configuration messages, for example about the
896 * windowing environment, the operating system version, etc.
898 * @param message the message text, also used as look-up key if the
899 * logger is localizing messages with a resource bundle. While
900 * it is possible to pass <code>null</code>, this is not
901 * recommended, since a logging message without text is unlikely
902 * to be helpful.
904 public synchronized void config(String message)
906 if (isLoggable(Level.CONFIG))
907 log(Level.CONFIG, message);
912 * Logs a message with severity level FINE. {@link Level#FINE} is
913 * intended for messages that are relevant for developers using
914 * the component generating log messages. Examples include minor,
915 * recoverable failures, or possible inefficiencies.
917 * @param message the message text, also used as look-up key if the
918 * logger is localizing messages with a resource
919 * bundle. While it is possible to pass
920 * <code>null</code>, this is not recommended, since
921 * a logging message without text is unlikely to be
922 * helpful.
924 public synchronized void fine(String message)
926 if (isLoggable(Level.FINE))
927 log(Level.FINE, message);
932 * Logs a message with severity level FINER. {@link Level#FINER} is
933 * intended for rather detailed tracing, for example entering a
934 * method, returning from a method, or throwing an exception.
936 * @param message the message text, also used as look-up key if the
937 * logger is localizing messages with a resource
938 * bundle. While it is possible to pass
939 * <code>null</code>, this is not recommended, since
940 * a logging message without text is unlikely to be
941 * helpful.
943 public synchronized void finer(String message)
945 if (isLoggable(Level.FINER))
946 log(Level.FINER, message);
951 * Logs a message with severity level FINEST. {@link Level#FINEST}
952 * is intended for highly detailed tracing, for example reaching a
953 * certain point inside the body of a method.
955 * @param message the message text, also used as look-up key if the
956 * logger is localizing messages with a resource
957 * bundle. While it is possible to pass
958 * <code>null</code>, this is not recommended, since
959 * a logging message without text is unlikely to be
960 * helpful.
962 public synchronized void finest(String message)
964 if (isLoggable(Level.FINEST))
965 log(Level.FINEST, message);
970 * Adds a handler to the set of handlers that get notified
971 * when a log record is to be published.
973 * @param handler the handler to be added.
975 * @throws NullPointerException if <code>handler</code>
976 * is <code>null</code>.
978 * @throws SecurityException if this logger is not anonymous, a
979 * security manager exists, and the caller is not granted
980 * the permission to control the logging infrastructure by
981 * having LoggingPermission("control"). Untrusted code can
982 * obtain an anonymous logger through the static factory method
983 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
985 public synchronized void addHandler(Handler handler)
986 throws SecurityException
988 /* Throw a new NullPointerException if handler is null. */
989 handler.getClass();
991 /* An application is allowed to control an anonymous logger
992 * without having the permission to control the logging
993 * infrastructure.
995 if (!anonymous)
996 LogManager.getLogManager().checkAccess();
998 if (!handlerList.contains(handler))
1000 handlerList.add(handler);
1001 handlers = getHandlers();
1007 * Removes a handler from the set of handlers that get notified
1008 * when a log record is to be published.
1010 * @param handler the handler to be removed.
1012 * @throws SecurityException if this logger is not anonymous, a
1013 * security manager exists, and the caller is not granted the
1014 * permission to control the logging infrastructure by having
1015 * LoggingPermission("control"). Untrusted code can obtain an
1016 * anonymous logger through the static factory method {@link
1017 * #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
1019 * @throws NullPointerException if <code>handler</code>
1020 * is <code>null</code>.
1022 public synchronized void removeHandler(Handler handler)
1023 throws SecurityException
1025 /* An application is allowed to control an anonymous logger
1026 * without having the permission to control the logging
1027 * infrastructure.
1029 if (!anonymous)
1030 LogManager.getLogManager().checkAccess();
1032 /* Throw a new NullPointerException if handler is null. */
1033 handler.getClass();
1035 handlerList.remove(handler);
1036 handlers = getHandlers();
1041 * Returns the handlers currently registered for this Logger.
1042 * When a log record has been deemed as being loggable,
1043 * it will be passed to all registered handlers for
1044 * publication. In addition, if the logger uses parent handlers
1045 * (see {@link #getUseParentHandlers() getUseParentHandlers}
1046 * and {@link #setUseParentHandlers(boolean) setUseParentHandlers},
1047 * the log record will be passed to the parent's handlers.
1049 public synchronized Handler[] getHandlers()
1051 /* We cannot return our internal handlers array
1052 * because we do not have any guarantee that the
1053 * caller would not change the array entries.
1055 return (Handler[]) handlerList.toArray(new Handler[handlerList.size()]);
1060 * Returns whether or not this Logger forwards log records to
1061 * handlers registered for its parent loggers.
1063 * @return <code>false</code> if this Logger sends log records
1064 * merely to Handlers registered with itself;
1065 * <code>true</code> if this Logger sends log records
1066 * not only to Handlers registered with itself, but also
1067 * to those Handlers registered with parent loggers.
1069 public synchronized boolean getUseParentHandlers()
1071 return useParentHandlers;
1076 * Sets whether or not this Logger forwards log records to
1077 * handlers registered for its parent loggers.
1079 * @param useParentHandlers <code>false</code> to let this
1080 * Logger send log records merely to Handlers registered
1081 * with itself; <code>true</code> to let this Logger
1082 * send log records not only to Handlers registered
1083 * with itself, but also to those Handlers registered with
1084 * parent loggers.
1086 * @throws SecurityException if this logger is not anonymous, a
1087 * security manager exists, and the caller is not granted
1088 * the permission to control the logging infrastructure by
1089 * having LoggingPermission("control"). Untrusted code can
1090 * obtain an anonymous logger through the static factory method
1091 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
1094 public synchronized void setUseParentHandlers(boolean useParentHandlers)
1096 /* An application is allowed to control an anonymous logger
1097 * without having the permission to control the logging
1098 * infrastructure.
1100 if (!anonymous)
1101 LogManager.getLogManager().checkAccess();
1103 this.useParentHandlers = useParentHandlers;
1108 * Returns the parent of this logger. By default, the parent is
1109 * assigned by the LogManager by inspecting the logger's name.
1111 * @return the parent of this logger (as detemined by the LogManager
1112 * by inspecting logger names), the root logger if no other
1113 * logger has a name which is a prefix of this logger's name, or
1114 * <code>null</code> for the root logger.
1116 public synchronized Logger getParent()
1118 return parent;
1123 * Sets the parent of this logger. Usually, applications do not
1124 * call this method directly. Instead, the LogManager will ensure
1125 * that the tree of loggers reflects the hierarchical logger
1126 * namespace. Basically, this method should not be public at all,
1127 * but the GNU implementation follows the API specification.
1129 * @throws NullPointerException if <code>parent</code> is
1130 * <code>null</code>.
1132 * @throws SecurityException if this logger is not anonymous, a
1133 * security manager exists, and the caller is not granted
1134 * the permission to control the logging infrastructure by
1135 * having LoggingPermission("control"). Untrusted code can
1136 * obtain an anonymous logger through the static factory method
1137 * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
1139 public synchronized void setParent(Logger parent)
1141 LogManager lm;
1143 /* Throw a new NullPointerException if parent is null. */
1144 parent.getClass();
1146 lm = LogManager.getLogManager();
1148 if (this == lm.rootLogger)
1150 if (parent != null)
1151 throw new IllegalArgumentException(
1152 "only the root logger can have a null parent");
1153 this.parent = null;
1154 return;
1157 /* An application is allowed to control an anonymous logger
1158 * without having the permission to control the logging
1159 * infrastructure.
1161 if (!anonymous)
1162 LogManager.getLogManager().checkAccess();
1164 this.parent = parent;
1168 * Gets the StackTraceElement of the first class that is not this class.
1169 * That should be the initial caller of a logging method.
1170 * @return caller of the initial looging method
1172 private native StackTraceElement getCallerStackFrame();