0N/A/*
6330N/A * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A
0N/Apackage java.util.logging;
0N/A
6330N/Aimport java.lang.ref.WeakReference;
6330N/Aimport java.security.AccessController;
6330N/Aimport java.security.PrivilegedAction;
6330N/Aimport java.util.ArrayList;
6330N/Aimport java.util.Iterator;
6330N/Aimport java.util.Locale;
6330N/Aimport java.util.MissingResourceException;
6330N/Aimport java.util.ResourceBundle;
841N/Aimport java.util.concurrent.CopyOnWriteArrayList;
6338N/Aimport sun.reflect.CallerSensitive;
6338N/Aimport sun.reflect.Reflection;
0N/A
0N/A/**
0N/A * A Logger object is used to log messages for a specific
0N/A * system or application component. Loggers are normally named,
0N/A * using a hierarchical dot-separated namespace. Logger names
0N/A * can be arbitrary strings, but they should normally be based on
0N/A * the package name or class name of the logged component, such
0N/A * as java.net or javax.swing. In addition it is possible to create
0N/A * "anonymous" Loggers that are not stored in the Logger namespace.
0N/A * <p>
0N/A * Logger objects may be obtained by calls on one of the getLogger
0N/A * factory methods. These will either create a new Logger or
2806N/A * return a suitable existing Logger. It is important to note that
2806N/A * the Logger returned by one of the {@code getLogger} factory methods
2806N/A * may be garbage collected at any time if a strong reference to the
2806N/A * Logger is not kept.
0N/A * <p>
0N/A * Logging messages will be forwarded to registered Handler
0N/A * objects, which can forward the messages to a variety of
0N/A * destinations, including consoles, files, OS logs, etc.
0N/A * <p>
0N/A * Each Logger keeps track of a "parent" Logger, which is its
0N/A * nearest existing ancestor in the Logger namespace.
0N/A * <p>
0N/A * Each Logger has a "Level" associated with it. This reflects
0N/A * a minimum Level that this logger cares about. If a Logger's
0N/A * level is set to <tt>null</tt>, then its effective level is inherited
0N/A * from its parent, which may in turn obtain it recursively from its
0N/A * parent, and so on up the tree.
0N/A * <p>
0N/A * The log level can be configured based on the properties from the
0N/A * logging configuration file, as described in the description
0N/A * of the LogManager class. However it may also be dynamically changed
0N/A * by calls on the Logger.setLevel method. If a logger's level is
0N/A * changed the change may also affect child loggers, since any child
0N/A * logger that has <tt>null</tt> as its level will inherit its
0N/A * effective level from its parent.
0N/A * <p>
0N/A * On each logging call the Logger initially performs a cheap
1664N/A * check of the request level (e.g., SEVERE or FINE) against the
0N/A * effective log level of the logger. If the request level is
0N/A * lower than the log level, the logging call returns immediately.
0N/A * <p>
0N/A * After passing this initial (cheap) test, the Logger will allocate
0N/A * a LogRecord to describe the logging message. It will then call a
0N/A * Filter (if present) to do a more detailed check on whether the
0N/A * record should be published. If that passes it will then publish
0N/A * the LogRecord to its output Handlers. By default, loggers also
0N/A * publish to their parent's Handlers, recursively up the tree.
0N/A * <p>
0N/A * Each Logger may have a ResourceBundle name associated with it.
0N/A * The named bundle will be used for localizing logging messages.
0N/A * If a Logger does not have its own ResourceBundle name, then
0N/A * it will inherit the ResourceBundle name from its parent,
0N/A * recursively up the tree.
0N/A * <p>
0N/A * Most of the logger output methods take a "msg" argument. This
0N/A * msg argument may be either a raw value or a localization key.
0N/A * During formatting, if the logger has (or inherits) a localization
0N/A * ResourceBundle and if the ResourceBundle has a mapping for the msg
0N/A * string, then the msg string is replaced by the localized value.
0N/A * Otherwise the original msg string is used. Typically, formatters use
0N/A * java.text.MessageFormat style formatting to format parameters, so
0N/A * for example a format string "{0} {1}" would format two parameters
0N/A * as strings.
0N/A * <p>
0N/A * When mapping ResourceBundle names to ResourceBundles, the Logger
0N/A * will first try to use the Thread's ContextClassLoader. If that
0N/A * is null it will try the SystemClassLoader instead. As a temporary
0N/A * transition feature in the initial implementation, if the Logger is
0N/A * unable to locate a ResourceBundle from the ContextClassLoader or
0N/A * SystemClassLoader the Logger will also search up the class stack
0N/A * and use successive calling ClassLoaders to try to locate a ResourceBundle.
0N/A * (This call stack search is to allow containers to transition to
0N/A * using ContextClassLoaders and is likely to be removed in future
0N/A * versions.)
0N/A * <p>
0N/A * Formatting (including localization) is the responsibility of
0N/A * the output Handler, which will typically call a Formatter.
0N/A * <p>
0N/A * Note that formatting need not occur synchronously. It may be delayed
0N/A * until a LogRecord is actually written to an external sink.
0N/A * <p>
0N/A * The logging methods are grouped in five main categories:
0N/A * <ul>
0N/A * <li><p>
0N/A * There are a set of "log" methods that take a log level, a message
0N/A * string, and optionally some parameters to the message string.
0N/A * <li><p>
0N/A * There are a set of "logp" methods (for "log precise") that are
0N/A * like the "log" methods, but also take an explicit source class name
0N/A * and method name.
0N/A * <li><p>
0N/A * There are a set of "logrb" method (for "log with resource bundle")
0N/A * that are like the "logp" method, but also take an explicit resource
0N/A * bundle name for use in localizing the log message.
0N/A * <li><p>
0N/A * There are convenience methods for tracing method entries (the
0N/A * "entering" methods), method returns (the "exiting" methods) and
0N/A * throwing exceptions (the "throwing" methods).
0N/A * <li><p>
0N/A * Finally, there are a set of convenience methods for use in the
0N/A * very simplest cases, when a developer simply wants to log a
0N/A * simple string at a given log level. These methods are named
0N/A * after the standard Level names ("severe", "warning", "info", etc.)
0N/A * and take a single argument, a message string.
0N/A * </ul>
0N/A * <p>
0N/A * For the methods that do not take an explicit source name and
0N/A * method name, the Logging framework will make a "best effort"
0N/A * to determine which class and method called into the logging method.
0N/A * However, it is important to realize that this automatically inferred
0N/A * information may only be approximate (or may even be quite wrong!).
0N/A * Virtual machines are allowed to do extensive optimizations when
0N/A * JITing and may entirely remove stack frames, making it impossible
0N/A * to reliably locate the calling class and method.
0N/A * <P>
0N/A * All methods on Logger are multi-thread safe.
0N/A * <p>
0N/A * <b>Subclassing Information:</b> Note that a LogManager class may
0N/A * provide its own implementation of named Loggers for any point in
0N/A * the namespace. Therefore, any subclasses of Logger (unless they
0N/A * are implemented in conjunction with a new LogManager class) should
0N/A * take care to obtain a Logger instance from the LogManager class and
0N/A * should delegate operations such as "isLoggable" and "log(LogRecord)"
0N/A * to that instance. Note that in order to intercept all logging
0N/A * output, subclasses need only override the log(LogRecord) method.
0N/A * All the other logging methods are implemented as calls on this
0N/A * log(LogRecord) method.
0N/A *
0N/A * @since 1.4
0N/A */
0N/A
0N/A
0N/Apublic class Logger {
0N/A private static final Handler emptyHandlers[] = new Handler[0];
0N/A private static final int offValue = Level.OFF.intValue();
0N/A private LogManager manager;
0N/A private String name;
841N/A private final CopyOnWriteArrayList<Handler> handlers =
3323N/A new CopyOnWriteArrayList<>();
0N/A private String resourceBundleName;
841N/A private volatile boolean useParentHandlers = true;
841N/A private volatile Filter filter;
0N/A private boolean anonymous;
0N/A
0N/A private ResourceBundle catalog; // Cached resource bundle
0N/A private String catalogName; // name associated with catalog
0N/A private Locale catalogLocale; // locale associated with catalog
0N/A
0N/A // The fields relating to parent-child relationships and levels
0N/A // are managed under a separate lock, the treeLock.
0N/A private static Object treeLock = new Object();
0N/A // We keep weak references from parents to children, but strong
0N/A // references from children to parents.
841N/A private volatile Logger parent; // our nearest parent.
2540N/A private ArrayList<LogManager.LoggerWeakRef> kids; // WeakReferences to loggers that have us as parent
841N/A private volatile Level levelObject;
0N/A private volatile int levelValue; // current effective level value
6394N/A private WeakReference<ClassLoader> callersClassLoaderRef;
0N/A
0N/A /**
0N/A * GLOBAL_LOGGER_NAME is a name for the global logger.
0N/A *
0N/A * @since 1.6
0N/A */
0N/A public static final String GLOBAL_LOGGER_NAME = "global";
0N/A
0N/A /**
0N/A * Return global logger object with the name Logger.GLOBAL_LOGGER_NAME.
0N/A *
0N/A * @return global logger object
0N/A * @since 1.7
0N/A */
0N/A public static final Logger getGlobal() {
0N/A return global;
0N/A }
0N/A
0N/A /**
0N/A * The "global" Logger object is provided as a convenience to developers
0N/A * who are making casual use of the Logging package. Developers
0N/A * who are making serious use of the logging package (for example
0N/A * in products) should create and use their own Logger objects,
0N/A * with appropriate names, so that logging can be controlled on a
2806N/A * suitable per-Logger granularity. Developers also need to keep a
2806N/A * strong reference to their Logger objects to prevent them from
2806N/A * being garbage collected.
0N/A * <p>
0N/A * @deprecated Initialization of this field is prone to deadlocks.
0N/A * The field must be initialized by the Logger class initialization
0N/A * which may cause deadlocks with the LogManager class initialization.
0N/A * In such cases two class initialization wait for each other to complete.
0N/A * The preferred way to get the global logger object is via the call
0N/A * <code>Logger.getGlobal()</code>.
0N/A * For compatibility with old JDK versions where the
0N/A * <code>Logger.getGlobal()</code> is not available use the call
0N/A * <code>Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)</code>
0N/A * or <code>Logger.getLogger("global")</code>.
0N/A */
0N/A @Deprecated
0N/A public static final Logger global = new Logger(GLOBAL_LOGGER_NAME);
0N/A
0N/A /**
0N/A * Protected method to construct a logger for a named subsystem.
0N/A * <p>
0N/A * The logger will be initially configured with a null Level
1664N/A * and with useParentHandlers set to true.
0N/A *
0N/A * @param name A name for the logger. This should
0N/A * be a dot-separated name and should normally
0N/A * be based on the package name or class name
0N/A * of the subsystem, such as java.net
0N/A * or javax.swing. It may be null for anonymous Loggers.
0N/A * @param resourceBundleName name of ResourceBundle to be used for localizing
0N/A * messages for this logger. May be null if none
0N/A * of the messages require localization.
1664N/A * @throws MissingResourceException if the resourceBundleName is non-null and
0N/A * no corresponding resource can be found.
0N/A */
0N/A protected Logger(String name, String resourceBundleName) {
6394N/A this(name, resourceBundleName, null);
6394N/A }
6394N/A
6394N/A Logger(String name, String resourceBundleName, Class<?> caller) {
0N/A this.manager = LogManager.getLogManager();
6394N/A setupResourceInfo(resourceBundleName, caller);
0N/A this.name = name;
0N/A levelValue = Level.INFO.intValue();
0N/A }
0N/A
6394N/A private void setCallersClassLoaderRef(Class<?> caller) {
6394N/A ClassLoader callersClassLoader = ((caller != null)
6394N/A ? caller.getClassLoader()
6394N/A : null);
6394N/A if (callersClassLoader != null) {
6394N/A this.callersClassLoaderRef = new WeakReference(callersClassLoader);
6394N/A }
6394N/A }
6394N/A
6394N/A private ClassLoader getCallersClassLoader() {
6394N/A return (callersClassLoaderRef != null)
6394N/A ? callersClassLoaderRef.get()
6394N/A : null;
6394N/A }
6394N/A
0N/A // This constructor is used only to create the global Logger.
0N/A // It is needed to break a cyclic dependence between the LogManager
0N/A // and Logger static initializers causing deadlocks.
0N/A private Logger(String name) {
0N/A // The manager field is not initialized here.
0N/A this.name = name;
0N/A levelValue = Level.INFO.intValue();
0N/A }
0N/A
0N/A // It is called from the LogManager.<clinit> to complete
0N/A // initialization of the global Logger.
0N/A void setLogManager(LogManager manager) {
0N/A this.manager = manager;
0N/A }
0N/A
5430N/A private void checkPermission() throws SecurityException {
0N/A if (!anonymous) {
0N/A if (manager == null) {
0N/A // Complete initialization of the global Logger.
0N/A manager = LogManager.getLogManager();
0N/A }
5430N/A manager.checkPermission();
0N/A }
0N/A }
0N/A
5720N/A // Until all JDK code converted to call sun.util.logging.PlatformLogger
5720N/A // (see 7054233), we need to determine if Logger.getLogger is to add
5720N/A // a system logger or user logger.
5720N/A //
5720N/A // As an interim solution, if the immediate caller whose caller loader is
5720N/A // null, we assume it's a system logger and add it to the system context.
5731N/A // These system loggers only set the resource bundle to the given
5731N/A // resource bundle name (rather than the default system resource bundle).
6397N/A private static class LoggerHelper {
6397N/A static boolean disableCallerCheck =
6397N/A getBooleanProperty("sun.util.logging.disableCallerCheck");
6397N/A
6397N/A // workaround to turn on the old behavior for resource bundle search
6397N/A static boolean allowStackWalkSearch =
6397N/A getBooleanProperty("jdk.logging.allowStackWalkSearch");
5731N/A private static boolean getBooleanProperty(final String key) {
5731N/A String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
5731N/A public String run() {
5731N/A return System.getProperty(key);
5731N/A }
5731N/A });
5731N/A return Boolean.valueOf(s);
5731N/A }
5731N/A }
5731N/A
6338N/A private static Logger demandLogger(String name, String resourceBundleName, Class<?> caller) {
5720N/A LogManager manager = LogManager.getLogManager();
5720N/A SecurityManager sm = System.getSecurityManager();
6397N/A if (sm != null && !LoggerHelper.disableCallerCheck) {
5720N/A if (caller.getClassLoader() == null) {
5731N/A return manager.demandSystemLogger(name, resourceBundleName);
5720N/A }
5720N/A }
6394N/A return manager.demandLogger(name, resourceBundleName, caller);
6394N/A // ends up calling new Logger(name, resourceBundleName, caller)
6394N/A // iff the logger doesn't exist already
5720N/A }
5720N/A
0N/A /**
0N/A * Find or create a logger for a named subsystem. If a logger has
0N/A * already been created with the given name it is returned. Otherwise
0N/A * a new logger is created.
0N/A * <p>
0N/A * If a new logger is created its log level will be configured
0N/A * based on the LogManager configuration and it will configured
1664N/A * to also send logging output to its parent's Handlers. It will
0N/A * be registered in the LogManager global namespace.
2806N/A * <p>
2806N/A * Note: The LogManager may only retain a weak reference to the newly
2806N/A * created Logger. It is important to understand that a previously
2806N/A * created Logger with the given name may be garbage collected at any
2806N/A * time if there is no strong reference to the Logger. In particular,
2806N/A * this means that two back-to-back calls like
2806N/A * {@code getLogger("MyLogger").log(...)} may use different Logger
2806N/A * objects named "MyLogger" if there is no strong reference to the
2806N/A * Logger named "MyLogger" elsewhere in the program.
0N/A *
0N/A * @param name A name for the logger. This should
0N/A * be a dot-separated name and should normally
0N/A * be based on the package name or class name
0N/A * of the subsystem, such as java.net
0N/A * or javax.swing
0N/A * @return a suitable Logger
0N/A * @throws NullPointerException if the name is null.
0N/A */
4236N/A
4236N/A // Synchronization is not required here. All synchronization for
4236N/A // adding a new Logger object is handled by LogManager.addLogger().
6338N/A @CallerSensitive
4236N/A public static Logger getLogger(String name) {
4236N/A // This method is intentionally not a wrapper around a call
4236N/A // to getLogger(name, resourceBundleName). If it were then
4236N/A // this sequence:
4236N/A //
4236N/A // getLogger("Foo", "resourceBundleForFoo");
4236N/A // getLogger("Foo");
4236N/A //
4236N/A // would throw an IllegalArgumentException in the second call
4236N/A // because the wrapper would result in an attempt to replace
4236N/A // the existing "resourceBundleForFoo" with null.
6338N/A return demandLogger(name, null, Reflection.getCallerClass());
0N/A }
0N/A
0N/A /**
0N/A * Find or create a logger for a named subsystem. If a logger has
0N/A * already been created with the given name it is returned. Otherwise
0N/A * a new logger is created.
0N/A * <p>
0N/A * If a new logger is created its log level will be configured
0N/A * based on the LogManager and it will configured to also send logging
1664N/A * output to its parent's Handlers. It will be registered in
0N/A * the LogManager global namespace.
0N/A * <p>
2806N/A * Note: The LogManager may only retain a weak reference to the newly
2806N/A * created Logger. It is important to understand that a previously
2806N/A * created Logger with the given name may be garbage collected at any
2806N/A * time if there is no strong reference to the Logger. In particular,
2806N/A * this means that two back-to-back calls like
2806N/A * {@code getLogger("MyLogger", ...).log(...)} may use different Logger
2806N/A * objects named "MyLogger" if there is no strong reference to the
2806N/A * Logger named "MyLogger" elsewhere in the program.
2806N/A * <p>
0N/A * If the named Logger already exists and does not yet have a
0N/A * localization resource bundle then the given resource bundle
0N/A * name is used. If the named Logger already exists and has
0N/A * a different resource bundle name then an IllegalArgumentException
0N/A * is thrown.
0N/A * <p>
0N/A * @param name A name for the logger. This should
0N/A * be a dot-separated name and should normally
0N/A * be based on the package name or class name
0N/A * of the subsystem, such as java.net
0N/A * or javax.swing
0N/A * @param resourceBundleName name of ResourceBundle to be used for localizing
0N/A * messages for this logger. May be <CODE>null</CODE> if none of
0N/A * the messages require localization.
0N/A * @return a suitable Logger
1664N/A * @throws MissingResourceException if the resourceBundleName is non-null and
1664N/A * no corresponding resource can be found.
0N/A * @throws IllegalArgumentException if the Logger already exists and uses
0N/A * a different resource bundle name.
0N/A * @throws NullPointerException if the name is null.
0N/A */
4236N/A
4236N/A // Synchronization is not required here. All synchronization for
4236N/A // adding a new Logger object is handled by LogManager.addLogger().
6338N/A @CallerSensitive
4236N/A public static Logger getLogger(String name, String resourceBundleName) {
6394N/A Class<?> callerClass = Reflection.getCallerClass();
6394N/A Logger result = demandLogger(name, resourceBundleName, callerClass);
6394N/A
0N/A if (result.resourceBundleName == null) {
6394N/A // We haven't set a bundle name yet on the Logger, so it's ok to proceed.
6394N/A
6394N/A // We have to set the callers ClassLoader here in case demandLogger
6394N/A // above found a previously created Logger. This can happen, for
6394N/A // example, if Logger.getLogger(name) is called and subsequently
6394N/A // Logger.getLogger(name, resourceBundleName) is called. In this case
6394N/A // we won't necessarily have the correct classloader saved away, so
6394N/A // we need to set it here, too.
6394N/A
0N/A // Note: we may get a MissingResourceException here.
6394N/A result.setupResourceInfo(resourceBundleName, callerClass);
0N/A } else if (!result.resourceBundleName.equals(resourceBundleName)) {
6394N/A // We already had a bundle name on the Logger and we're trying
6394N/A // to change it here which is not allowed.
0N/A throw new IllegalArgumentException(result.resourceBundleName +
0N/A " != " + resourceBundleName);
0N/A }
0N/A return result;
0N/A }
0N/A
5720N/A // package-private
5720N/A // Add a platform logger to the system context.
5720N/A // i.e. caller of sun.util.logging.PlatformLogger.getLogger
5720N/A static Logger getPlatformLogger(String name) {
5720N/A LogManager manager = LogManager.getLogManager();
5720N/A
5720N/A // all loggers in the system context will default to
5720N/A // the system logger's resource bundle
5731N/A Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME);
5720N/A return result;
5720N/A }
0N/A
0N/A /**
0N/A * Create an anonymous Logger. The newly created Logger is not
0N/A * registered in the LogManager namespace. There will be no
0N/A * access checks on updates to the logger.
0N/A * <p>
0N/A * This factory method is primarily intended for use from applets.
0N/A * Because the resulting Logger is anonymous it can be kept private
0N/A * by the creating class. This removes the need for normal security
0N/A * checks, which in turn allows untrusted applet code to update
0N/A * the control state of the Logger. For example an applet can do
0N/A * a setLevel or an addHandler on an anonymous Logger.
0N/A * <p>
0N/A * Even although the new logger is anonymous, it is configured
0N/A * to have the root logger ("") as its parent. This means that
0N/A * by default it inherits its effective level and handlers
0N/A * from the root logger.
0N/A * <p>
0N/A *
0N/A * @return a newly created private Logger
0N/A */
2540N/A public static Logger getAnonymousLogger() {
2540N/A return getAnonymousLogger(null);
0N/A }
0N/A
0N/A /**
0N/A * Create an anonymous Logger. The newly created Logger is not
0N/A * registered in the LogManager namespace. There will be no
0N/A * access checks on updates to the logger.
0N/A * <p>
0N/A * This factory method is primarily intended for use from applets.
0N/A * Because the resulting Logger is anonymous it can be kept private
0N/A * by the creating class. This removes the need for normal security
0N/A * checks, which in turn allows untrusted applet code to update
0N/A * the control state of the Logger. For example an applet can do
0N/A * a setLevel or an addHandler on an anonymous Logger.
0N/A * <p>
0N/A * Even although the new logger is anonymous, it is configured
0N/A * to have the root logger ("") as its parent. This means that
0N/A * by default it inherits its effective level and handlers
0N/A * from the root logger.
0N/A * <p>
0N/A * @param resourceBundleName name of ResourceBundle to be used for localizing
0N/A * messages for this logger.
0N/A * May be null if none of the messages require localization.
0N/A * @return a newly created private Logger
1664N/A * @throws MissingResourceException if the resourceBundleName is non-null and
1664N/A * no corresponding resource can be found.
0N/A */
4236N/A
4236N/A // Synchronization is not required here. All synchronization for
4236N/A // adding a new anonymous Logger object is handled by doSetParent().
6394N/A @CallerSensitive
4236N/A public static Logger getAnonymousLogger(String resourceBundleName) {
0N/A LogManager manager = LogManager.getLogManager();
2540N/A // cleanup some Loggers that have been GC'ed
2540N/A manager.drainLoggerRefQueueBounded();
6394N/A Logger result = new Logger(null, resourceBundleName,
6394N/A Reflection.getCallerClass());
0N/A result.anonymous = true;
0N/A Logger root = manager.getLogger("");
0N/A result.doSetParent(root);
0N/A return result;
0N/A }
0N/A
0N/A /**
0N/A * Retrieve the localization resource bundle for this
0N/A * logger for the current default locale. Note that if
0N/A * the result is null, then the Logger will use a resource
0N/A * bundle inherited from its parent.
0N/A *
0N/A * @return localization bundle (may be null)
0N/A */
0N/A public ResourceBundle getResourceBundle() {
6394N/A return findResourceBundle(getResourceBundleName(), true);
0N/A }
0N/A
0N/A /**
0N/A * Retrieve the localization resource bundle name for this
0N/A * logger. Note that if the result is null, then the Logger
0N/A * will use a resource bundle name inherited from its parent.
0N/A *
0N/A * @return localization bundle name (may be null)
0N/A */
0N/A public String getResourceBundleName() {
0N/A return resourceBundleName;
0N/A }
0N/A
0N/A /**
0N/A * Set a filter to control output on this Logger.
0N/A * <P>
0N/A * After passing the initial "level" check, the Logger will
0N/A * call this Filter to check if a log record should really
0N/A * be published.
0N/A *
0N/A * @param newFilter a filter object (may be null)
0N/A * @exception SecurityException if a security manager exists and if
0N/A * the caller does not have LoggingPermission("control").
0N/A */
841N/A public void setFilter(Filter newFilter) throws SecurityException {
5430N/A checkPermission();
0N/A filter = newFilter;
0N/A }
0N/A
0N/A /**
0N/A * Get the current filter for this Logger.
0N/A *
0N/A * @return a filter object (may be null)
0N/A */
841N/A public Filter getFilter() {
0N/A return filter;
0N/A }
0N/A
0N/A /**
0N/A * Log a LogRecord.
0N/A * <p>
0N/A * All the other logging methods in this class call through
0N/A * this method to actually perform any logging. Subclasses can
0N/A * override this single method to capture all log activity.
0N/A *
0N/A * @param record the LogRecord to be published
0N/A */
0N/A public void log(LogRecord record) {
0N/A if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
841N/A Filter theFilter = filter;
841N/A if (theFilter != null && !theFilter.isLoggable(record)) {
841N/A return;
0N/A }
0N/A
0N/A // Post the LogRecord to all our Handlers, and then to
0N/A // our parents' handlers, all the way up the tree.
0N/A
0N/A Logger logger = this;
0N/A while (logger != null) {
1145N/A for (Handler handler : logger.getHandlers()) {
841N/A handler.publish(record);
0N/A }
0N/A
0N/A if (!logger.getUseParentHandlers()) {
0N/A break;
0N/A }
0N/A
0N/A logger = logger.getParent();
0N/A }
0N/A }
0N/A
0N/A // private support method for logging.
0N/A // We fill in the logger name, resource bundle name, and
0N/A // resource bundle and then call "void log(LogRecord)".
0N/A private void doLog(LogRecord lr) {
0N/A lr.setLoggerName(name);
0N/A String ebname = getEffectiveResourceBundleName();
5720N/A if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) {
0N/A lr.setResourceBundleName(ebname);
6394N/A lr.setResourceBundle(findResourceBundle(ebname, true));
0N/A }
0N/A log(lr);
0N/A }
0N/A
0N/A
0N/A //================================================================
0N/A // Start of convenience methods WITHOUT className and methodName
0N/A //================================================================
0N/A
0N/A /**
0N/A * Log a message, with no arguments.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then the given message is forwarded to all the
0N/A * registered output Handler objects.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param msg The string message (or a key in the message catalog)
0N/A */
0N/A public void log(Level level, String msg) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A doLog(lr);
0N/A }
0N/A
0N/A /**
0N/A * Log a message, with one object parameter.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then a corresponding LogRecord is created and forwarded
0N/A * to all the registered output Handler objects.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param msg The string message (or a key in the message catalog)
0N/A * @param param1 parameter to the message
0N/A */
0N/A public void log(Level level, String msg, Object param1) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A Object params[] = { param1 };
0N/A lr.setParameters(params);
0N/A doLog(lr);
0N/A }
0N/A
0N/A /**
0N/A * Log a message, with an array of object arguments.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then a corresponding LogRecord is created and forwarded
0N/A * to all the registered output Handler objects.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param msg The string message (or a key in the message catalog)
0N/A * @param params array of parameters to the message
0N/A */
0N/A public void log(Level level, String msg, Object params[]) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A lr.setParameters(params);
0N/A doLog(lr);
0N/A }
0N/A
0N/A /**
0N/A * Log a message, with associated Throwable information.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then the given arguments are stored in a LogRecord
0N/A * which is forwarded to all registered output handlers.
0N/A * <p>
0N/A * Note that the thrown argument is stored in the LogRecord thrown
0N/A * property, rather than the LogRecord parameters property. Thus is it
0N/A * processed specially by output Formatters and is not treated
0N/A * as a formatting parameter to the LogRecord message property.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param msg The string message (or a key in the message catalog)
0N/A * @param thrown Throwable associated with log message.
0N/A */
0N/A public void log(Level level, String msg, Throwable thrown) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A lr.setThrown(thrown);
0N/A doLog(lr);
0N/A }
0N/A
0N/A //================================================================
0N/A // Start of convenience methods WITH className and methodName
0N/A //================================================================
0N/A
0N/A /**
0N/A * Log a message, specifying source class and method,
0N/A * with no arguments.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then the given message is forwarded to all the
0N/A * registered output Handler objects.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that issued the logging request
0N/A * @param msg The string message (or a key in the message catalog)
0N/A */
0N/A public void logp(Level level, String sourceClass, String sourceMethod, String msg) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A lr.setSourceClassName(sourceClass);
0N/A lr.setSourceMethodName(sourceMethod);
0N/A doLog(lr);
0N/A }
0N/A
0N/A /**
0N/A * Log a message, specifying source class and method,
0N/A * with a single object parameter to the log message.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then a corresponding LogRecord is created and forwarded
0N/A * to all the registered output Handler objects.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that issued the logging request
0N/A * @param msg The string message (or a key in the message catalog)
0N/A * @param param1 Parameter to the log message.
0N/A */
0N/A public void logp(Level level, String sourceClass, String sourceMethod,
0N/A String msg, Object param1) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A lr.setSourceClassName(sourceClass);
0N/A lr.setSourceMethodName(sourceMethod);
0N/A Object params[] = { param1 };
0N/A lr.setParameters(params);
0N/A doLog(lr);
0N/A }
0N/A
0N/A /**
0N/A * Log a message, specifying source class and method,
0N/A * with an array of object arguments.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then a corresponding LogRecord is created and forwarded
0N/A * to all the registered output Handler objects.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that issued the logging request
0N/A * @param msg The string message (or a key in the message catalog)
0N/A * @param params Array of parameters to the message
0N/A */
0N/A public void logp(Level level, String sourceClass, String sourceMethod,
0N/A String msg, Object params[]) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A lr.setSourceClassName(sourceClass);
0N/A lr.setSourceMethodName(sourceMethod);
0N/A lr.setParameters(params);
0N/A doLog(lr);
0N/A }
0N/A
0N/A /**
0N/A * Log a message, specifying source class and method,
0N/A * with associated Throwable information.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then the given arguments are stored in a LogRecord
0N/A * which is forwarded to all registered output handlers.
0N/A * <p>
0N/A * Note that the thrown argument is stored in the LogRecord thrown
0N/A * property, rather than the LogRecord parameters property. Thus is it
0N/A * processed specially by output Formatters and is not treated
0N/A * as a formatting parameter to the LogRecord message property.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that issued the logging request
0N/A * @param msg The string message (or a key in the message catalog)
0N/A * @param thrown Throwable associated with log message.
0N/A */
0N/A public void logp(Level level, String sourceClass, String sourceMethod,
0N/A String msg, Throwable thrown) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A lr.setSourceClassName(sourceClass);
0N/A lr.setSourceMethodName(sourceMethod);
0N/A lr.setThrown(thrown);
0N/A doLog(lr);
0N/A }
0N/A
0N/A
0N/A //=========================================================================
0N/A // Start of convenience methods WITH className, methodName and bundle name.
0N/A //=========================================================================
0N/A
0N/A // Private support method for logging for "logrb" methods.
0N/A // We fill in the logger name, resource bundle name, and
0N/A // resource bundle and then call "void log(LogRecord)".
0N/A private void doLog(LogRecord lr, String rbname) {
0N/A lr.setLoggerName(name);
0N/A if (rbname != null) {
0N/A lr.setResourceBundleName(rbname);
6394N/A lr.setResourceBundle(findResourceBundle(rbname, false));
0N/A }
0N/A log(lr);
0N/A }
0N/A
0N/A /**
0N/A * Log a message, specifying source class, method, and resource bundle name
0N/A * with no arguments.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then the given message is forwarded to all the
0N/A * registered output Handler objects.
0N/A * <p>
0N/A * The msg string is localized using the named resource bundle. If the
0N/A * resource bundle name is null, or an empty String or invalid
0N/A * then the msg string is not localized.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that issued the logging request
0N/A * @param bundleName name of resource bundle to localize msg,
0N/A * can be null
0N/A * @param msg The string message (or a key in the message catalog)
0N/A */
0N/A public void logrb(Level level, String sourceClass, String sourceMethod,
0N/A String bundleName, String msg) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A lr.setSourceClassName(sourceClass);
0N/A lr.setSourceMethodName(sourceMethod);
0N/A doLog(lr, bundleName);
0N/A }
0N/A
0N/A /**
0N/A * Log a message, specifying source class, method, and resource bundle name,
0N/A * with a single object parameter to the log message.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then a corresponding LogRecord is created and forwarded
0N/A * to all the registered output Handler objects.
0N/A * <p>
0N/A * The msg string is localized using the named resource bundle. If the
0N/A * resource bundle name is null, or an empty String or invalid
0N/A * then the msg string is not localized.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that issued the logging request
0N/A * @param bundleName name of resource bundle to localize msg,
0N/A * can be null
0N/A * @param msg The string message (or a key in the message catalog)
0N/A * @param param1 Parameter to the log message.
0N/A */
0N/A public void logrb(Level level, String sourceClass, String sourceMethod,
0N/A String bundleName, String msg, Object param1) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A lr.setSourceClassName(sourceClass);
0N/A lr.setSourceMethodName(sourceMethod);
0N/A Object params[] = { param1 };
0N/A lr.setParameters(params);
0N/A doLog(lr, bundleName);
0N/A }
0N/A
0N/A /**
0N/A * Log a message, specifying source class, method, and resource bundle name,
0N/A * with an array of object arguments.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then a corresponding LogRecord is created and forwarded
0N/A * to all the registered output Handler objects.
0N/A * <p>
0N/A * The msg string is localized using the named resource bundle. If the
0N/A * resource bundle name is null, or an empty String or invalid
0N/A * then the msg string is not localized.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that issued the logging request
0N/A * @param bundleName name of resource bundle to localize msg,
0N/A * can be null.
0N/A * @param msg The string message (or a key in the message catalog)
0N/A * @param params Array of parameters to the message
0N/A */
0N/A public void logrb(Level level, String sourceClass, String sourceMethod,
0N/A String bundleName, String msg, Object params[]) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A lr.setSourceClassName(sourceClass);
0N/A lr.setSourceMethodName(sourceMethod);
0N/A lr.setParameters(params);
0N/A doLog(lr, bundleName);
0N/A }
0N/A
0N/A /**
0N/A * Log a message, specifying source class, method, and resource bundle name,
0N/A * with associated Throwable information.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then the given arguments are stored in a LogRecord
0N/A * which is forwarded to all registered output handlers.
0N/A * <p>
0N/A * The msg string is localized using the named resource bundle. If the
0N/A * resource bundle name is null, or an empty String or invalid
0N/A * then the msg string is not localized.
0N/A * <p>
0N/A * Note that the thrown argument is stored in the LogRecord thrown
0N/A * property, rather than the LogRecord parameters property. Thus is it
0N/A * processed specially by output Formatters and is not treated
0N/A * as a formatting parameter to the LogRecord message property.
0N/A * <p>
1664N/A * @param level One of the message level identifiers, e.g., SEVERE
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that issued the logging request
0N/A * @param bundleName name of resource bundle to localize msg,
0N/A * can be null
0N/A * @param msg The string message (or a key in the message catalog)
0N/A * @param thrown Throwable associated with log message.
0N/A */
0N/A public void logrb(Level level, String sourceClass, String sourceMethod,
0N/A String bundleName, String msg, Throwable thrown) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(level, msg);
0N/A lr.setSourceClassName(sourceClass);
0N/A lr.setSourceMethodName(sourceMethod);
0N/A lr.setThrown(thrown);
0N/A doLog(lr, bundleName);
0N/A }
0N/A
0N/A
0N/A //======================================================================
0N/A // Start of convenience methods for logging method entries and returns.
0N/A //======================================================================
0N/A
0N/A /**
0N/A * Log a method entry.
0N/A * <p>
0N/A * This is a convenience method that can be used to log entry
0N/A * to a method. A LogRecord with message "ENTRY", log level
0N/A * FINER, and the given sourceMethod and sourceClass is logged.
0N/A * <p>
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that is being entered
0N/A */
0N/A public void entering(String sourceClass, String sourceMethod) {
0N/A if (Level.FINER.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
0N/A }
0N/A
0N/A /**
0N/A * Log a method entry, with one parameter.
0N/A * <p>
0N/A * This is a convenience method that can be used to log entry
0N/A * to a method. A LogRecord with message "ENTRY {0}", log level
0N/A * FINER, and the given sourceMethod, sourceClass, and parameter
0N/A * is logged.
0N/A * <p>
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that is being entered
0N/A * @param param1 parameter to the method being entered
0N/A */
0N/A public void entering(String sourceClass, String sourceMethod, Object param1) {
0N/A if (Level.FINER.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A Object params[] = { param1 };
0N/A logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", params);
0N/A }
0N/A
0N/A /**
0N/A * Log a method entry, with an array of parameters.
0N/A * <p>
0N/A * This is a convenience method that can be used to log entry
0N/A * to a method. A LogRecord with message "ENTRY" (followed by a
0N/A * format {N} indicator for each entry in the parameter array),
0N/A * log level FINER, and the given sourceMethod, sourceClass, and
0N/A * parameters is logged.
0N/A * <p>
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of method that is being entered
0N/A * @param params array of parameters to the method being entered
0N/A */
0N/A public void entering(String sourceClass, String sourceMethod, Object params[]) {
0N/A if (Level.FINER.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A String msg = "ENTRY";
0N/A if (params == null ) {
0N/A logp(Level.FINER, sourceClass, sourceMethod, msg);
0N/A return;
0N/A }
0N/A for (int i = 0; i < params.length; i++) {
0N/A msg = msg + " {" + i + "}";
0N/A }
0N/A logp(Level.FINER, sourceClass, sourceMethod, msg, params);
0N/A }
0N/A
0N/A /**
0N/A * Log a method return.
0N/A * <p>
0N/A * This is a convenience method that can be used to log returning
0N/A * from a method. A LogRecord with message "RETURN", log level
0N/A * FINER, and the given sourceMethod and sourceClass is logged.
0N/A * <p>
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of the method
0N/A */
0N/A public void exiting(String sourceClass, String sourceMethod) {
0N/A if (Level.FINER.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Log a method return, with result object.
0N/A * <p>
0N/A * This is a convenience method that can be used to log returning
0N/A * from a method. A LogRecord with message "RETURN {0}", log level
0N/A * FINER, and the gives sourceMethod, sourceClass, and result
0N/A * object is logged.
0N/A * <p>
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of the method
0N/A * @param result Object that is being returned
0N/A */
0N/A public void exiting(String sourceClass, String sourceMethod, Object result) {
0N/A if (Level.FINER.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A Object params[] = { result };
0N/A logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
0N/A }
0N/A
0N/A /**
0N/A * Log throwing an exception.
0N/A * <p>
0N/A * This is a convenience method to log that a method is
0N/A * terminating by throwing an exception. The logging is done
0N/A * using the FINER level.
0N/A * <p>
0N/A * If the logger is currently enabled for the given message
0N/A * level then the given arguments are stored in a LogRecord
0N/A * which is forwarded to all registered output handlers. The
0N/A * LogRecord's message is set to "THROW".
0N/A * <p>
0N/A * Note that the thrown argument is stored in the LogRecord thrown
0N/A * property, rather than the LogRecord parameters property. Thus is it
0N/A * processed specially by output Formatters and is not treated
0N/A * as a formatting parameter to the LogRecord message property.
0N/A * <p>
0N/A * @param sourceClass name of class that issued the logging request
0N/A * @param sourceMethod name of the method.
0N/A * @param thrown The Throwable that is being thrown.
0N/A */
0N/A public void throwing(String sourceClass, String sourceMethod, Throwable thrown) {
0N/A if (Level.FINER.intValue() < levelValue || levelValue == offValue ) {
0N/A return;
0N/A }
0N/A LogRecord lr = new LogRecord(Level.FINER, "THROW");
0N/A lr.setSourceClassName(sourceClass);
0N/A lr.setSourceMethodName(sourceMethod);
0N/A lr.setThrown(thrown);
0N/A doLog(lr);
0N/A }
0N/A
0N/A //=======================================================================
0N/A // Start of simple convenience methods using level names as method names
0N/A //=======================================================================
0N/A
0N/A /**
0N/A * Log a SEVERE message.
0N/A * <p>
0N/A * If the logger is currently enabled for the SEVERE message
0N/A * level then the given message is forwarded to all the
0N/A * registered output Handler objects.
0N/A * <p>
0N/A * @param msg The string message (or a key in the message catalog)
0N/A */
0N/A public void severe(String msg) {
0N/A if (Level.SEVERE.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A log(Level.SEVERE, msg);
0N/A }
0N/A
0N/A /**
0N/A * Log a WARNING message.
0N/A * <p>
0N/A * If the logger is currently enabled for the WARNING message
0N/A * level then the given message is forwarded to all the
0N/A * registered output Handler objects.
0N/A * <p>
0N/A * @param msg The string message (or a key in the message catalog)
0N/A */
0N/A public void warning(String msg) {
0N/A if (Level.WARNING.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A log(Level.WARNING, msg);
0N/A }
0N/A
0N/A /**
0N/A * Log an INFO message.
0N/A * <p>
0N/A * If the logger is currently enabled for the INFO message
0N/A * level then the given message is forwarded to all the
0N/A * registered output Handler objects.
0N/A * <p>
0N/A * @param msg The string message (or a key in the message catalog)
0N/A */
0N/A public void info(String msg) {
0N/A if (Level.INFO.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A log(Level.INFO, msg);
0N/A }
0N/A
0N/A /**
0N/A * Log a CONFIG message.
0N/A * <p>
0N/A * If the logger is currently enabled for the CONFIG message
0N/A * level then the given message is forwarded to all the
0N/A * registered output Handler objects.
0N/A * <p>
0N/A * @param msg The string message (or a key in the message catalog)
0N/A */
0N/A public void config(String msg) {
0N/A if (Level.CONFIG.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A log(Level.CONFIG, msg);
0N/A }
0N/A
0N/A /**
0N/A * Log a FINE message.
0N/A * <p>
0N/A * If the logger is currently enabled for the FINE message
0N/A * level then the given message is forwarded to all the
0N/A * registered output Handler objects.
0N/A * <p>
0N/A * @param msg The string message (or a key in the message catalog)
0N/A */
0N/A public void fine(String msg) {
0N/A if (Level.FINE.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A log(Level.FINE, msg);
0N/A }
0N/A
0N/A /**
0N/A * Log a FINER message.
0N/A * <p>
0N/A * If the logger is currently enabled for the FINER message
0N/A * level then the given message is forwarded to all the
0N/A * registered output Handler objects.
0N/A * <p>
0N/A * @param msg The string message (or a key in the message catalog)
0N/A */
0N/A public void finer(String msg) {
0N/A if (Level.FINER.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A log(Level.FINER, msg);
0N/A }
0N/A
0N/A /**
0N/A * Log a FINEST message.
0N/A * <p>
0N/A * If the logger is currently enabled for the FINEST message
0N/A * level then the given message is forwarded to all the
0N/A * registered output Handler objects.
0N/A * <p>
0N/A * @param msg The string message (or a key in the message catalog)
0N/A */
0N/A public void finest(String msg) {
0N/A if (Level.FINEST.intValue() < levelValue) {
0N/A return;
0N/A }
0N/A log(Level.FINEST, msg);
0N/A }
0N/A
0N/A //================================================================
0N/A // End of convenience methods
0N/A //================================================================
0N/A
0N/A /**
0N/A * Set the log level specifying which message levels will be
0N/A * logged by this logger. Message levels lower than this
0N/A * value will be discarded. The level value Level.OFF
0N/A * can be used to turn off logging.
0N/A * <p>
0N/A * If the new level is null, it means that this node should
0N/A * inherit its level from its nearest ancestor with a specific
0N/A * (non-null) level value.
0N/A *
0N/A * @param newLevel the new value for the log level (may be null)
0N/A * @exception SecurityException if a security manager exists and if
0N/A * the caller does not have LoggingPermission("control").
0N/A */
0N/A public void setLevel(Level newLevel) throws SecurityException {
5430N/A checkPermission();
0N/A synchronized (treeLock) {
0N/A levelObject = newLevel;
0N/A updateEffectiveLevel();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Get the log Level that has been specified for this Logger.
0N/A * The result may be null, which means that this logger's
0N/A * effective level will be inherited from its parent.
0N/A *
0N/A * @return this Logger's level
0N/A */
0N/A public Level getLevel() {
0N/A return levelObject;
0N/A }
0N/A
0N/A /**
0N/A * Check if a message of the given level would actually be logged
0N/A * by this logger. This check is based on the Loggers effective level,
0N/A * which may be inherited from its parent.
0N/A *
0N/A * @param level a message logging level
0N/A * @return true if the given message level is currently being logged.
0N/A */
0N/A public boolean isLoggable(Level level) {
0N/A if (level.intValue() < levelValue || levelValue == offValue) {
0N/A return false;
0N/A }
0N/A return true;
0N/A }
0N/A
0N/A /**
0N/A * Get the name for this logger.
0N/A * @return logger name. Will be null for anonymous Loggers.
0N/A */
0N/A public String getName() {
0N/A return name;
0N/A }
0N/A
0N/A /**
0N/A * Add a log Handler to receive logging messages.
0N/A * <p>
0N/A * By default, Loggers also send their output to their parent logger.
0N/A * Typically the root Logger is configured with a set of Handlers
0N/A * that essentially act as default handlers for all loggers.
0N/A *
0N/A * @param handler a logging Handler
0N/A * @exception SecurityException if a security manager exists and if
0N/A * the caller does not have LoggingPermission("control").
0N/A */
841N/A public void addHandler(Handler handler) throws SecurityException {
0N/A // Check for null handler
0N/A handler.getClass();
5430N/A checkPermission();
0N/A handlers.add(handler);
0N/A }
0N/A
0N/A /**
0N/A * Remove a log Handler.
0N/A * <P>
0N/A * Returns silently if the given Handler is not found or is null
0N/A *
0N/A * @param handler a logging Handler
0N/A * @exception SecurityException if a security manager exists and if
0N/A * the caller does not have LoggingPermission("control").
0N/A */
841N/A public void removeHandler(Handler handler) throws SecurityException {
5430N/A checkPermission();
0N/A if (handler == null) {
0N/A return;
0N/A }
0N/A handlers.remove(handler);
0N/A }
0N/A
0N/A /**
0N/A * Get the Handlers associated with this logger.
0N/A * <p>
0N/A * @return an array of all registered Handlers
0N/A */
841N/A public Handler[] getHandlers() {
841N/A return handlers.toArray(emptyHandlers);
0N/A }
0N/A
0N/A /**
0N/A * Specify whether or not this logger should send its output
1664N/A * to its parent Logger. This means that any LogRecords will
0N/A * also be written to the parent's Handlers, and potentially
0N/A * to its parent, recursively up the namespace.
0N/A *
0N/A * @param useParentHandlers true if output is to be sent to the
0N/A * logger's parent.
0N/A * @exception SecurityException if a security manager exists and if
0N/A * the caller does not have LoggingPermission("control").
0N/A */
841N/A public void setUseParentHandlers(boolean useParentHandlers) {
5430N/A checkPermission();
0N/A this.useParentHandlers = useParentHandlers;
0N/A }
0N/A
0N/A /**
0N/A * Discover whether or not this logger is sending its output
0N/A * to its parent logger.
0N/A *
0N/A * @return true if output is to be sent to the logger's parent
0N/A */
841N/A public boolean getUseParentHandlers() {
0N/A return useParentHandlers;
0N/A }
0N/A
5720N/A static final String SYSTEM_LOGGER_RB_NAME = "sun.util.logging.resources.logging";
5720N/A
5720N/A private static ResourceBundle findSystemResourceBundle(final Locale locale) {
5720N/A // the resource bundle is in a restricted package
5720N/A return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
5720N/A public ResourceBundle run() {
5720N/A try {
5720N/A return ResourceBundle.getBundle(SYSTEM_LOGGER_RB_NAME,
5731N/A locale,
5731N/A ClassLoader.getSystemClassLoader());
5720N/A } catch (MissingResourceException e) {
5720N/A throw new InternalError(e.toString());
5720N/A }
5720N/A }
5720N/A });
5720N/A }
5720N/A
6330N/A /**
6330N/A * Private utility method to map a resource bundle name to an
6330N/A * actual resource bundle, using a simple one-entry cache.
6330N/A * Returns null for a null name.
6330N/A * May also return null if we can't find the resource bundle and
6330N/A * there is no suitable previous cached value.
6330N/A *
6330N/A * @param name the ResourceBundle to locate
6394N/A * @param userCallersClassLoader if true search using the caller's ClassLoader
6330N/A * @return ResourceBundle specified by name or null if not found
6330N/A */
6394N/A private synchronized ResourceBundle findResourceBundle(String name,
6394N/A boolean useCallersClassLoader) {
6394N/A // For all lookups, we first check the thread context class loader
6394N/A // if it is set. If not, we use the system classloader. If we
6394N/A // still haven't found it we use the callersClassLoaderRef if it
6394N/A // is set and useCallersClassLoader is true. We set
6394N/A // callersClassLoaderRef initially upon creating the logger with a
6394N/A // non-null resource bundle name.
6394N/A
0N/A // Return a null bundle for a null name.
0N/A if (name == null) {
0N/A return null;
0N/A }
0N/A
0N/A Locale currentLocale = Locale.getDefault();
0N/A
0N/A // Normally we should hit on our simple one entry cache.
6330N/A if (catalog != null && currentLocale.equals(catalogLocale)
6330N/A && name.equals(catalogName)) {
0N/A return catalog;
0N/A }
0N/A
5720N/A if (name.equals(SYSTEM_LOGGER_RB_NAME)) {
5720N/A catalog = findSystemResourceBundle(currentLocale);
5720N/A catalogName = name;
5720N/A catalogLocale = currentLocale;
5720N/A return catalog;
5720N/A }
5720N/A
6330N/A // Use the thread's context ClassLoader. If there isn't one, use the
6330N/A // {@linkplain java.lang.ClassLoader#getSystemClassLoader() system ClassLoader}.
0N/A ClassLoader cl = Thread.currentThread().getContextClassLoader();
0N/A if (cl == null) {
0N/A cl = ClassLoader.getSystemClassLoader();
0N/A }
0N/A try {
0N/A catalog = ResourceBundle.getBundle(name, currentLocale, cl);
0N/A catalogName = name;
0N/A catalogLocale = currentLocale;
0N/A return catalog;
0N/A } catch (MissingResourceException ex) {
6394N/A // We can't find the ResourceBundle in the default
6394N/A // ClassLoader. Drop through.
6394N/A }
6394N/A
6394N/A if (useCallersClassLoader) {
6394N/A // Try with the caller's ClassLoader
6394N/A ClassLoader callersClassLoader = getCallersClassLoader();
6397N/A if (callersClassLoader != null && callersClassLoader != cl) {
6397N/A try {
6397N/A catalog = ResourceBundle.getBundle(name, currentLocale,
6397N/A callersClassLoader);
6397N/A catalogName = name;
6397N/A catalogLocale = currentLocale;
6397N/A return catalog;
6397N/A } catch (MissingResourceException ex) {
6397N/A }
6394N/A }
6397N/A }
6394N/A
6397N/A // If -Djdk.logging.allowStackWalkSearch=true is set,
6397N/A // does stack walk to search for the resource bundle
6397N/A if (LoggerHelper.allowStackWalkSearch) {
6397N/A return findResourceBundleFromStack(name, currentLocale, cl);
6394N/A } else {
6330N/A return null;
0N/A }
0N/A }
0N/A
6397N/A /**
6397N/A * This method will fail when running with a VM that enforces caller-sensitive
6397N/A * methods and only allows to get the immediate caller.
6397N/A */
6397N/A @CallerSensitive
6397N/A private synchronized ResourceBundle findResourceBundleFromStack(String name,
6397N/A Locale locale,
6397N/A ClassLoader cl)
6397N/A {
6397N/A for (int ix = 0; ; ix++) {
6397N/A Class<?> clz = sun.reflect.Reflection.getCallerClass(ix);
6397N/A if (clz == null) {
6397N/A break;
6397N/A }
6397N/A ClassLoader cl2 = clz.getClassLoader();
6397N/A if (cl2 == null) {
6397N/A cl2 = ClassLoader.getSystemClassLoader();
6397N/A }
6397N/A if (cl == cl2) {
6397N/A // We've already checked this classloader.
6397N/A continue;
6397N/A }
6397N/A cl = cl2;
6397N/A try {
6397N/A catalog = ResourceBundle.getBundle(name, locale, cl);
6397N/A catalogName = name;
6397N/A catalogLocale = locale;
6397N/A return catalog;
6397N/A } catch (MissingResourceException ex) {
6397N/A }
6397N/A }
6397N/A return null;
6397N/A }
6397N/A
0N/A // Private utility method to initialize our one entry
6394N/A // resource bundle name cache and the callers ClassLoader
0N/A // Note: for consistency reasons, we are careful to check
0N/A // that a suitable ResourceBundle exists before setting the
6394N/A // resourceBundleName field.
6394N/A // Synchronized to prevent races in setting the fields.
6394N/A private synchronized void setupResourceInfo(String name,
6394N/A Class<?> callersClass) {
0N/A if (name == null) {
0N/A return;
0N/A }
6394N/A
6394N/A setCallersClassLoaderRef(callersClass);
6394N/A if (findResourceBundle(name, true) == null) {
0N/A // We've failed to find an expected ResourceBundle.
6394N/A // unset the caller's ClassLoader since we were unable to find the
6394N/A // the bundle using it
6394N/A this.callersClassLoaderRef = null;
6394N/A throw new MissingResourceException("Can't find " + name + " bundle",
6394N/A name, "");
0N/A }
0N/A resourceBundleName = name;
0N/A }
0N/A
0N/A /**
0N/A * Return the parent for this Logger.
0N/A * <p>
0N/A * This method returns the nearest extant parent in the namespace.
0N/A * Thus if a Logger is called "a.b.c.d", and a Logger called "a.b"
0N/A * has been created but no logger "a.b.c" exists, then a call of
0N/A * getParent on the Logger "a.b.c.d" will return the Logger "a.b".
0N/A * <p>
0N/A * The result will be null if it is called on the root Logger
0N/A * in the namespace.
0N/A *
0N/A * @return nearest existing parent Logger
0N/A */
0N/A public Logger getParent() {
841N/A // Note: this used to be synchronized on treeLock. However, this only
841N/A // provided memory semantics, as there was no guarantee that the caller
841N/A // would synchronize on treeLock (in fact, there is no way for external
841N/A // callers to so synchronize). Therefore, we have made parent volatile
841N/A // instead.
841N/A return parent;
0N/A }
0N/A
0N/A /**
0N/A * Set the parent for this Logger. This method is used by
0N/A * the LogManager to update a Logger when the namespace changes.
0N/A * <p>
0N/A * It should not be called from application code.
0N/A * <p>
0N/A * @param parent the new parent logger
0N/A * @exception SecurityException if a security manager exists and if
0N/A * the caller does not have LoggingPermission("control").
0N/A */
0N/A public void setParent(Logger parent) {
0N/A if (parent == null) {
0N/A throw new NullPointerException();
0N/A }
5430N/A manager.checkPermission();
0N/A doSetParent(parent);
0N/A }
0N/A
0N/A // Private method to do the work for parenting a child
0N/A // Logger onto a parent logger.
0N/A private void doSetParent(Logger newParent) {
0N/A
0N/A // System.err.println("doSetParent \"" + getName() + "\" \""
0N/A // + newParent.getName() + "\"");
0N/A
0N/A synchronized (treeLock) {
0N/A
0N/A // Remove ourself from any previous parent.
2540N/A LogManager.LoggerWeakRef ref = null;
0N/A if (parent != null) {
0N/A // assert parent.kids != null;
2540N/A for (Iterator<LogManager.LoggerWeakRef> iter = parent.kids.iterator(); iter.hasNext(); ) {
2540N/A ref = iter.next();
0N/A Logger kid = ref.get();
0N/A if (kid == this) {
2540N/A // ref is used down below to complete the reparenting
0N/A iter.remove();
0N/A break;
2540N/A } else {
2540N/A ref = null;
0N/A }
0N/A }
0N/A // We have now removed ourself from our parents' kids.
0N/A }
0N/A
0N/A // Set our new parent.
0N/A parent = newParent;
0N/A if (parent.kids == null) {
3323N/A parent.kids = new ArrayList<>(2);
0N/A }
2540N/A if (ref == null) {
2540N/A // we didn't have a previous parent
2540N/A ref = manager.new LoggerWeakRef(this);
2540N/A }
3386N/A ref.setParentRef(new WeakReference<Logger>(parent));
2540N/A parent.kids.add(ref);
0N/A
0N/A // As a result of the reparenting, the effective level
0N/A // may have changed for us and our children.
0N/A updateEffectiveLevel();
0N/A
0N/A }
0N/A }
0N/A
2540N/A // Package-level method.
2540N/A // Remove the weak reference for the specified child Logger from the
2540N/A // kid list. We should only be called from LoggerWeakRef.dispose().
2540N/A final void removeChildLogger(LogManager.LoggerWeakRef child) {
2540N/A synchronized (treeLock) {
2540N/A for (Iterator<LogManager.LoggerWeakRef> iter = kids.iterator(); iter.hasNext(); ) {
2540N/A LogManager.LoggerWeakRef ref = iter.next();
2540N/A if (ref == child) {
2540N/A iter.remove();
2540N/A return;
2540N/A }
2540N/A }
2540N/A }
2540N/A }
2540N/A
0N/A // Recalculate the effective level for this node and
0N/A // recursively for our children.
0N/A
0N/A private void updateEffectiveLevel() {
0N/A // assert Thread.holdsLock(treeLock);
0N/A
0N/A // Figure out our current effective level.
0N/A int newLevelValue;
0N/A if (levelObject != null) {
0N/A newLevelValue = levelObject.intValue();
0N/A } else {
0N/A if (parent != null) {
0N/A newLevelValue = parent.levelValue;
0N/A } else {
0N/A // This may happen during initialization.
0N/A newLevelValue = Level.INFO.intValue();
0N/A }
0N/A }
0N/A
0N/A // If our effective value hasn't changed, we're done.
0N/A if (levelValue == newLevelValue) {
0N/A return;
0N/A }
0N/A
0N/A levelValue = newLevelValue;
0N/A
0N/A // System.err.println("effective level: \"" + getName() + "\" := " + level);
0N/A
0N/A // Recursively update the level on each of our kids.
0N/A if (kids != null) {
0N/A for (int i = 0; i < kids.size(); i++) {
2540N/A LogManager.LoggerWeakRef ref = kids.get(i);
0N/A Logger kid = ref.get();
0N/A if (kid != null) {
0N/A kid.updateEffectiveLevel();
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A
0N/A // Private method to get the potentially inherited
0N/A // resource bundle name for this Logger.
0N/A // May return null
0N/A private String getEffectiveResourceBundleName() {
0N/A Logger target = this;
0N/A while (target != null) {
0N/A String rbn = target.getResourceBundleName();
0N/A if (rbn != null) {
0N/A return rbn;
0N/A }
0N/A target = target.getParent();
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A
0N/A}