1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/emul/compact/src/main/java/java/util/logging/Logger.java Sat Sep 07 13:51:24 2013 +0200
1.3 @@ -0,0 +1,1530 @@
1.4 +/*
1.5 + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +
1.30 +package java.util.logging;
1.31 +
1.32 +import java.util.*;
1.33 +import java.util.concurrent.CopyOnWriteArrayList;
1.34 +import java.security.*;
1.35 +import java.lang.ref.WeakReference;
1.36 +
1.37 +/**
1.38 + * A Logger object is used to log messages for a specific
1.39 + * system or application component. Loggers are normally named,
1.40 + * using a hierarchical dot-separated namespace. Logger names
1.41 + * can be arbitrary strings, but they should normally be based on
1.42 + * the package name or class name of the logged component, such
1.43 + * as java.net or javax.swing. In addition it is possible to create
1.44 + * "anonymous" Loggers that are not stored in the Logger namespace.
1.45 + * <p>
1.46 + * Logger objects may be obtained by calls on one of the getLogger
1.47 + * factory methods. These will either create a new Logger or
1.48 + * return a suitable existing Logger. It is important to note that
1.49 + * the Logger returned by one of the {@code getLogger} factory methods
1.50 + * may be garbage collected at any time if a strong reference to the
1.51 + * Logger is not kept.
1.52 + * <p>
1.53 + * Logging messages will be forwarded to registered Handler
1.54 + * objects, which can forward the messages to a variety of
1.55 + * destinations, including consoles, files, OS logs, etc.
1.56 + * <p>
1.57 + * Each Logger keeps track of a "parent" Logger, which is its
1.58 + * nearest existing ancestor in the Logger namespace.
1.59 + * <p>
1.60 + * Each Logger has a "Level" associated with it. This reflects
1.61 + * a minimum Level that this logger cares about. If a Logger's
1.62 + * level is set to <tt>null</tt>, then its effective level is inherited
1.63 + * from its parent, which may in turn obtain it recursively from its
1.64 + * parent, and so on up the tree.
1.65 + * <p>
1.66 + * The log level can be configured based on the properties from the
1.67 + * logging configuration file, as described in the description
1.68 + * of the LogManager class. However it may also be dynamically changed
1.69 + * by calls on the Logger.setLevel method. If a logger's level is
1.70 + * changed the change may also affect child loggers, since any child
1.71 + * logger that has <tt>null</tt> as its level will inherit its
1.72 + * effective level from its parent.
1.73 + * <p>
1.74 + * On each logging call the Logger initially performs a cheap
1.75 + * check of the request level (e.g., SEVERE or FINE) against the
1.76 + * effective log level of the logger. If the request level is
1.77 + * lower than the log level, the logging call returns immediately.
1.78 + * <p>
1.79 + * After passing this initial (cheap) test, the Logger will allocate
1.80 + * a LogRecord to describe the logging message. It will then call a
1.81 + * Filter (if present) to do a more detailed check on whether the
1.82 + * record should be published. If that passes it will then publish
1.83 + * the LogRecord to its output Handlers. By default, loggers also
1.84 + * publish to their parent's Handlers, recursively up the tree.
1.85 + * <p>
1.86 + * Each Logger may have a ResourceBundle name associated with it.
1.87 + * The named bundle will be used for localizing logging messages.
1.88 + * If a Logger does not have its own ResourceBundle name, then
1.89 + * it will inherit the ResourceBundle name from its parent,
1.90 + * recursively up the tree.
1.91 + * <p>
1.92 + * Most of the logger output methods take a "msg" argument. This
1.93 + * msg argument may be either a raw value or a localization key.
1.94 + * During formatting, if the logger has (or inherits) a localization
1.95 + * ResourceBundle and if the ResourceBundle has a mapping for the msg
1.96 + * string, then the msg string is replaced by the localized value.
1.97 + * Otherwise the original msg string is used. Typically, formatters use
1.98 + * java.text.MessageFormat style formatting to format parameters, so
1.99 + * for example a format string "{0} {1}" would format two parameters
1.100 + * as strings.
1.101 + * <p>
1.102 + * When mapping ResourceBundle names to ResourceBundles, the Logger
1.103 + * will first try to use the Thread's ContextClassLoader. If that
1.104 + * is null it will try the SystemClassLoader instead. As a temporary
1.105 + * transition feature in the initial implementation, if the Logger is
1.106 + * unable to locate a ResourceBundle from the ContextClassLoader or
1.107 + * SystemClassLoader the Logger will also search up the class stack
1.108 + * and use successive calling ClassLoaders to try to locate a ResourceBundle.
1.109 + * (This call stack search is to allow containers to transition to
1.110 + * using ContextClassLoaders and is likely to be removed in future
1.111 + * versions.)
1.112 + * <p>
1.113 + * Formatting (including localization) is the responsibility of
1.114 + * the output Handler, which will typically call a Formatter.
1.115 + * <p>
1.116 + * Note that formatting need not occur synchronously. It may be delayed
1.117 + * until a LogRecord is actually written to an external sink.
1.118 + * <p>
1.119 + * The logging methods are grouped in five main categories:
1.120 + * <ul>
1.121 + * <li><p>
1.122 + * There are a set of "log" methods that take a log level, a message
1.123 + * string, and optionally some parameters to the message string.
1.124 + * <li><p>
1.125 + * There are a set of "logp" methods (for "log precise") that are
1.126 + * like the "log" methods, but also take an explicit source class name
1.127 + * and method name.
1.128 + * <li><p>
1.129 + * There are a set of "logrb" method (for "log with resource bundle")
1.130 + * that are like the "logp" method, but also take an explicit resource
1.131 + * bundle name for use in localizing the log message.
1.132 + * <li><p>
1.133 + * There are convenience methods for tracing method entries (the
1.134 + * "entering" methods), method returns (the "exiting" methods) and
1.135 + * throwing exceptions (the "throwing" methods).
1.136 + * <li><p>
1.137 + * Finally, there are a set of convenience methods for use in the
1.138 + * very simplest cases, when a developer simply wants to log a
1.139 + * simple string at a given log level. These methods are named
1.140 + * after the standard Level names ("severe", "warning", "info", etc.)
1.141 + * and take a single argument, a message string.
1.142 + * </ul>
1.143 + * <p>
1.144 + * For the methods that do not take an explicit source name and
1.145 + * method name, the Logging framework will make a "best effort"
1.146 + * to determine which class and method called into the logging method.
1.147 + * However, it is important to realize that this automatically inferred
1.148 + * information may only be approximate (or may even be quite wrong!).
1.149 + * Virtual machines are allowed to do extensive optimizations when
1.150 + * JITing and may entirely remove stack frames, making it impossible
1.151 + * to reliably locate the calling class and method.
1.152 + * <P>
1.153 + * All methods on Logger are multi-thread safe.
1.154 + * <p>
1.155 + * <b>Subclassing Information:</b> Note that a LogManager class may
1.156 + * provide its own implementation of named Loggers for any point in
1.157 + * the namespace. Therefore, any subclasses of Logger (unless they
1.158 + * are implemented in conjunction with a new LogManager class) should
1.159 + * take care to obtain a Logger instance from the LogManager class and
1.160 + * should delegate operations such as "isLoggable" and "log(LogRecord)"
1.161 + * to that instance. Note that in order to intercept all logging
1.162 + * output, subclasses need only override the log(LogRecord) method.
1.163 + * All the other logging methods are implemented as calls on this
1.164 + * log(LogRecord) method.
1.165 + *
1.166 + * @since 1.4
1.167 + */
1.168 +
1.169 +
1.170 +public class Logger {
1.171 + private static final Handler emptyHandlers[] = new Handler[0];
1.172 + private static final int offValue = Level.OFF.intValue();
1.173 + private LogManager manager;
1.174 + private String name;
1.175 + private final CopyOnWriteArrayList<Handler> handlers =
1.176 + new CopyOnWriteArrayList<>();
1.177 + private String resourceBundleName;
1.178 + private volatile boolean useParentHandlers = true;
1.179 + private volatile Filter filter;
1.180 + private boolean anonymous;
1.181 +
1.182 + private ResourceBundle catalog; // Cached resource bundle
1.183 + private String catalogName; // name associated with catalog
1.184 + private Locale catalogLocale; // locale associated with catalog
1.185 +
1.186 + // The fields relating to parent-child relationships and levels
1.187 + // are managed under a separate lock, the treeLock.
1.188 + private static Object treeLock = new Object();
1.189 + // We keep weak references from parents to children, but strong
1.190 + // references from children to parents.
1.191 + private volatile Logger parent; // our nearest parent.
1.192 + private ArrayList<LogManager.LoggerWeakRef> kids; // WeakReferences to loggers that have us as parent
1.193 + private volatile Level levelObject;
1.194 + private volatile int levelValue; // current effective level value
1.195 +
1.196 + /**
1.197 + * GLOBAL_LOGGER_NAME is a name for the global logger.
1.198 + *
1.199 + * @since 1.6
1.200 + */
1.201 + public static final String GLOBAL_LOGGER_NAME = "global";
1.202 +
1.203 + /**
1.204 + * Return global logger object with the name Logger.GLOBAL_LOGGER_NAME.
1.205 + *
1.206 + * @return global logger object
1.207 + * @since 1.7
1.208 + */
1.209 + public static final Logger getGlobal() {
1.210 + return global;
1.211 + }
1.212 +
1.213 + /**
1.214 + * The "global" Logger object is provided as a convenience to developers
1.215 + * who are making casual use of the Logging package. Developers
1.216 + * who are making serious use of the logging package (for example
1.217 + * in products) should create and use their own Logger objects,
1.218 + * with appropriate names, so that logging can be controlled on a
1.219 + * suitable per-Logger granularity. Developers also need to keep a
1.220 + * strong reference to their Logger objects to prevent them from
1.221 + * being garbage collected.
1.222 + * <p>
1.223 + * @deprecated Initialization of this field is prone to deadlocks.
1.224 + * The field must be initialized by the Logger class initialization
1.225 + * which may cause deadlocks with the LogManager class initialization.
1.226 + * In such cases two class initialization wait for each other to complete.
1.227 + * The preferred way to get the global logger object is via the call
1.228 + * <code>Logger.getGlobal()</code>.
1.229 + * For compatibility with old JDK versions where the
1.230 + * <code>Logger.getGlobal()</code> is not available use the call
1.231 + * <code>Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)</code>
1.232 + * or <code>Logger.getLogger("global")</code>.
1.233 + */
1.234 + @Deprecated
1.235 + public static final Logger global = new Logger(GLOBAL_LOGGER_NAME);
1.236 +
1.237 + /**
1.238 + * Protected method to construct a logger for a named subsystem.
1.239 + * <p>
1.240 + * The logger will be initially configured with a null Level
1.241 + * and with useParentHandlers set to true.
1.242 + *
1.243 + * @param name A name for the logger. This should
1.244 + * be a dot-separated name and should normally
1.245 + * be based on the package name or class name
1.246 + * of the subsystem, such as java.net
1.247 + * or javax.swing. It may be null for anonymous Loggers.
1.248 + * @param resourceBundleName name of ResourceBundle to be used for localizing
1.249 + * messages for this logger. May be null if none
1.250 + * of the messages require localization.
1.251 + * @throws MissingResourceException if the resourceBundleName is non-null and
1.252 + * no corresponding resource can be found.
1.253 + */
1.254 + protected Logger(String name, String resourceBundleName) {
1.255 + this.manager = LogManager.getLogManager();
1.256 + if (resourceBundleName != null) {
1.257 + // Note: we may get a MissingResourceException here.
1.258 + setupResourceInfo(resourceBundleName);
1.259 + }
1.260 + this.name = name;
1.261 + levelValue = Level.INFO.intValue();
1.262 + }
1.263 +
1.264 + // This constructor is used only to create the global Logger.
1.265 + // It is needed to break a cyclic dependence between the LogManager
1.266 + // and Logger static initializers causing deadlocks.
1.267 + private Logger(String name) {
1.268 + // The manager field is not initialized here.
1.269 + this.name = name;
1.270 + levelValue = Level.INFO.intValue();
1.271 + }
1.272 +
1.273 + // It is called from the LogManager.<clinit> to complete
1.274 + // initialization of the global Logger.
1.275 + void setLogManager(LogManager manager) {
1.276 + this.manager = manager;
1.277 + }
1.278 +
1.279 + private void checkAccess() throws SecurityException {
1.280 + if (!anonymous) {
1.281 + if (manager == null) {
1.282 + // Complete initialization of the global Logger.
1.283 + manager = LogManager.getLogManager();
1.284 + }
1.285 + manager.checkAccess();
1.286 + }
1.287 + }
1.288 +
1.289 + /**
1.290 + * Find or create a logger for a named subsystem. If a logger has
1.291 + * already been created with the given name it is returned. Otherwise
1.292 + * a new logger is created.
1.293 + * <p>
1.294 + * If a new logger is created its log level will be configured
1.295 + * based on the LogManager configuration and it will configured
1.296 + * to also send logging output to its parent's Handlers. It will
1.297 + * be registered in the LogManager global namespace.
1.298 + * <p>
1.299 + * Note: The LogManager may only retain a weak reference to the newly
1.300 + * created Logger. It is important to understand that a previously
1.301 + * created Logger with the given name may be garbage collected at any
1.302 + * time if there is no strong reference to the Logger. In particular,
1.303 + * this means that two back-to-back calls like
1.304 + * {@code getLogger("MyLogger").log(...)} may use different Logger
1.305 + * objects named "MyLogger" if there is no strong reference to the
1.306 + * Logger named "MyLogger" elsewhere in the program.
1.307 + *
1.308 + * @param name A name for the logger. This should
1.309 + * be a dot-separated name and should normally
1.310 + * be based on the package name or class name
1.311 + * of the subsystem, such as java.net
1.312 + * or javax.swing
1.313 + * @return a suitable Logger
1.314 + * @throws NullPointerException if the name is null.
1.315 + */
1.316 +
1.317 + // Synchronization is not required here. All synchronization for
1.318 + // adding a new Logger object is handled by LogManager.addLogger().
1.319 + public static Logger getLogger(String name) {
1.320 + // This method is intentionally not a wrapper around a call
1.321 + // to getLogger(name, resourceBundleName). If it were then
1.322 + // this sequence:
1.323 + //
1.324 + // getLogger("Foo", "resourceBundleForFoo");
1.325 + // getLogger("Foo");
1.326 + //
1.327 + // would throw an IllegalArgumentException in the second call
1.328 + // because the wrapper would result in an attempt to replace
1.329 + // the existing "resourceBundleForFoo" with null.
1.330 + LogManager manager = LogManager.getLogManager();
1.331 + return manager.demandLogger(name);
1.332 + }
1.333 +
1.334 + /**
1.335 + * Find or create a logger for a named subsystem. If a logger has
1.336 + * already been created with the given name it is returned. Otherwise
1.337 + * a new logger is created.
1.338 + * <p>
1.339 + * If a new logger is created its log level will be configured
1.340 + * based on the LogManager and it will configured to also send logging
1.341 + * output to its parent's Handlers. It will be registered in
1.342 + * the LogManager global namespace.
1.343 + * <p>
1.344 + * Note: The LogManager may only retain a weak reference to the newly
1.345 + * created Logger. It is important to understand that a previously
1.346 + * created Logger with the given name may be garbage collected at any
1.347 + * time if there is no strong reference to the Logger. In particular,
1.348 + * this means that two back-to-back calls like
1.349 + * {@code getLogger("MyLogger", ...).log(...)} may use different Logger
1.350 + * objects named "MyLogger" if there is no strong reference to the
1.351 + * Logger named "MyLogger" elsewhere in the program.
1.352 + * <p>
1.353 + * If the named Logger already exists and does not yet have a
1.354 + * localization resource bundle then the given resource bundle
1.355 + * name is used. If the named Logger already exists and has
1.356 + * a different resource bundle name then an IllegalArgumentException
1.357 + * is thrown.
1.358 + * <p>
1.359 + * @param name A name for the logger. This should
1.360 + * be a dot-separated name and should normally
1.361 + * be based on the package name or class name
1.362 + * of the subsystem, such as java.net
1.363 + * or javax.swing
1.364 + * @param resourceBundleName name of ResourceBundle to be used for localizing
1.365 + * messages for this logger. May be <CODE>null</CODE> if none of
1.366 + * the messages require localization.
1.367 + * @return a suitable Logger
1.368 + * @throws MissingResourceException if the resourceBundleName is non-null and
1.369 + * no corresponding resource can be found.
1.370 + * @throws IllegalArgumentException if the Logger already exists and uses
1.371 + * a different resource bundle name.
1.372 + * @throws NullPointerException if the name is null.
1.373 + */
1.374 +
1.375 + // Synchronization is not required here. All synchronization for
1.376 + // adding a new Logger object is handled by LogManager.addLogger().
1.377 + public static Logger getLogger(String name, String resourceBundleName) {
1.378 + LogManager manager = LogManager.getLogManager();
1.379 + Logger result = manager.demandLogger(name);
1.380 + if (result.resourceBundleName == null) {
1.381 + // Note: we may get a MissingResourceException here.
1.382 + result.setupResourceInfo(resourceBundleName);
1.383 + } else if (!result.resourceBundleName.equals(resourceBundleName)) {
1.384 + throw new IllegalArgumentException(result.resourceBundleName +
1.385 + " != " + resourceBundleName);
1.386 + }
1.387 + return result;
1.388 + }
1.389 +
1.390 +
1.391 + /**
1.392 + * Create an anonymous Logger. The newly created Logger is not
1.393 + * registered in the LogManager namespace. There will be no
1.394 + * access checks on updates to the logger.
1.395 + * <p>
1.396 + * This factory method is primarily intended for use from applets.
1.397 + * Because the resulting Logger is anonymous it can be kept private
1.398 + * by the creating class. This removes the need for normal security
1.399 + * checks, which in turn allows untrusted applet code to update
1.400 + * the control state of the Logger. For example an applet can do
1.401 + * a setLevel or an addHandler on an anonymous Logger.
1.402 + * <p>
1.403 + * Even although the new logger is anonymous, it is configured
1.404 + * to have the root logger ("") as its parent. This means that
1.405 + * by default it inherits its effective level and handlers
1.406 + * from the root logger.
1.407 + * <p>
1.408 + *
1.409 + * @return a newly created private Logger
1.410 + */
1.411 + public static Logger getAnonymousLogger() {
1.412 + return getAnonymousLogger(null);
1.413 + }
1.414 +
1.415 + /**
1.416 + * Create an anonymous Logger. The newly created Logger is not
1.417 + * registered in the LogManager namespace. There will be no
1.418 + * access checks on updates to the logger.
1.419 + * <p>
1.420 + * This factory method is primarily intended for use from applets.
1.421 + * Because the resulting Logger is anonymous it can be kept private
1.422 + * by the creating class. This removes the need for normal security
1.423 + * checks, which in turn allows untrusted applet code to update
1.424 + * the control state of the Logger. For example an applet can do
1.425 + * a setLevel or an addHandler on an anonymous Logger.
1.426 + * <p>
1.427 + * Even although the new logger is anonymous, it is configured
1.428 + * to have the root logger ("") as its parent. This means that
1.429 + * by default it inherits its effective level and handlers
1.430 + * from the root logger.
1.431 + * <p>
1.432 + * @param resourceBundleName name of ResourceBundle to be used for localizing
1.433 + * messages for this logger.
1.434 + * May be null if none of the messages require localization.
1.435 + * @return a newly created private Logger
1.436 + * @throws MissingResourceException if the resourceBundleName is non-null and
1.437 + * no corresponding resource can be found.
1.438 + */
1.439 +
1.440 + // Synchronization is not required here. All synchronization for
1.441 + // adding a new anonymous Logger object is handled by doSetParent().
1.442 + public static Logger getAnonymousLogger(String resourceBundleName) {
1.443 + LogManager manager = LogManager.getLogManager();
1.444 + // cleanup some Loggers that have been GC'ed
1.445 + manager.drainLoggerRefQueueBounded();
1.446 + Logger result = new Logger(null, resourceBundleName);
1.447 + result.anonymous = true;
1.448 + Logger root = manager.getLogger("");
1.449 + result.doSetParent(root);
1.450 + return result;
1.451 + }
1.452 +
1.453 + /**
1.454 + * Retrieve the localization resource bundle for this
1.455 + * logger for the current default locale. Note that if
1.456 + * the result is null, then the Logger will use a resource
1.457 + * bundle inherited from its parent.
1.458 + *
1.459 + * @return localization bundle (may be null)
1.460 + */
1.461 + public ResourceBundle getResourceBundle() {
1.462 + return findResourceBundle(getResourceBundleName());
1.463 + }
1.464 +
1.465 + /**
1.466 + * Retrieve the localization resource bundle name for this
1.467 + * logger. Note that if the result is null, then the Logger
1.468 + * will use a resource bundle name inherited from its parent.
1.469 + *
1.470 + * @return localization bundle name (may be null)
1.471 + */
1.472 + public String getResourceBundleName() {
1.473 + return resourceBundleName;
1.474 + }
1.475 +
1.476 + /**
1.477 + * Set a filter to control output on this Logger.
1.478 + * <P>
1.479 + * After passing the initial "level" check, the Logger will
1.480 + * call this Filter to check if a log record should really
1.481 + * be published.
1.482 + *
1.483 + * @param newFilter a filter object (may be null)
1.484 + * @exception SecurityException if a security manager exists and if
1.485 + * the caller does not have LoggingPermission("control").
1.486 + */
1.487 + public void setFilter(Filter newFilter) throws SecurityException {
1.488 + checkAccess();
1.489 + filter = newFilter;
1.490 + }
1.491 +
1.492 + /**
1.493 + * Get the current filter for this Logger.
1.494 + *
1.495 + * @return a filter object (may be null)
1.496 + */
1.497 + public Filter getFilter() {
1.498 + return filter;
1.499 + }
1.500 +
1.501 + /**
1.502 + * Log a LogRecord.
1.503 + * <p>
1.504 + * All the other logging methods in this class call through
1.505 + * this method to actually perform any logging. Subclasses can
1.506 + * override this single method to capture all log activity.
1.507 + *
1.508 + * @param record the LogRecord to be published
1.509 + */
1.510 + public void log(LogRecord record) {
1.511 + if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
1.512 + return;
1.513 + }
1.514 + Filter theFilter = filter;
1.515 + if (theFilter != null && !theFilter.isLoggable(record)) {
1.516 + return;
1.517 + }
1.518 +
1.519 + // Post the LogRecord to all our Handlers, and then to
1.520 + // our parents' handlers, all the way up the tree.
1.521 +
1.522 + Logger logger = this;
1.523 + while (logger != null) {
1.524 + for (Handler handler : logger.getHandlers()) {
1.525 + handler.publish(record);
1.526 + }
1.527 +
1.528 + if (!logger.getUseParentHandlers()) {
1.529 + break;
1.530 + }
1.531 +
1.532 + logger = logger.getParent();
1.533 + }
1.534 + }
1.535 +
1.536 + // private support method for logging.
1.537 + // We fill in the logger name, resource bundle name, and
1.538 + // resource bundle and then call "void log(LogRecord)".
1.539 + private void doLog(LogRecord lr) {
1.540 + lr.setLoggerName(name);
1.541 + String ebname = getEffectiveResourceBundleName();
1.542 + if (ebname != null) {
1.543 + lr.setResourceBundleName(ebname);
1.544 + lr.setResourceBundle(findResourceBundle(ebname));
1.545 + }
1.546 + log(lr);
1.547 + }
1.548 +
1.549 +
1.550 + //================================================================
1.551 + // Start of convenience methods WITHOUT className and methodName
1.552 + //================================================================
1.553 +
1.554 + /**
1.555 + * Log a message, with no arguments.
1.556 + * <p>
1.557 + * If the logger is currently enabled for the given message
1.558 + * level then the given message is forwarded to all the
1.559 + * registered output Handler objects.
1.560 + * <p>
1.561 + * @param level One of the message level identifiers, e.g., SEVERE
1.562 + * @param msg The string message (or a key in the message catalog)
1.563 + */
1.564 + public void log(Level level, String msg) {
1.565 + if (level.intValue() < levelValue || levelValue == offValue) {
1.566 + return;
1.567 + }
1.568 + LogRecord lr = new LogRecord(level, msg);
1.569 + doLog(lr);
1.570 + }
1.571 +
1.572 + /**
1.573 + * Log a message, with one object parameter.
1.574 + * <p>
1.575 + * If the logger is currently enabled for the given message
1.576 + * level then a corresponding LogRecord is created and forwarded
1.577 + * to all the registered output Handler objects.
1.578 + * <p>
1.579 + * @param level One of the message level identifiers, e.g., SEVERE
1.580 + * @param msg The string message (or a key in the message catalog)
1.581 + * @param param1 parameter to the message
1.582 + */
1.583 + public void log(Level level, String msg, Object param1) {
1.584 + if (level.intValue() < levelValue || levelValue == offValue) {
1.585 + return;
1.586 + }
1.587 + LogRecord lr = new LogRecord(level, msg);
1.588 + Object params[] = { param1 };
1.589 + lr.setParameters(params);
1.590 + doLog(lr);
1.591 + }
1.592 +
1.593 + /**
1.594 + * Log a message, with an array of object arguments.
1.595 + * <p>
1.596 + * If the logger is currently enabled for the given message
1.597 + * level then a corresponding LogRecord is created and forwarded
1.598 + * to all the registered output Handler objects.
1.599 + * <p>
1.600 + * @param level One of the message level identifiers, e.g., SEVERE
1.601 + * @param msg The string message (or a key in the message catalog)
1.602 + * @param params array of parameters to the message
1.603 + */
1.604 + public void log(Level level, String msg, Object params[]) {
1.605 + if (level.intValue() < levelValue || levelValue == offValue) {
1.606 + return;
1.607 + }
1.608 + LogRecord lr = new LogRecord(level, msg);
1.609 + lr.setParameters(params);
1.610 + doLog(lr);
1.611 + }
1.612 +
1.613 + /**
1.614 + * Log a message, with associated Throwable information.
1.615 + * <p>
1.616 + * If the logger is currently enabled for the given message
1.617 + * level then the given arguments are stored in a LogRecord
1.618 + * which is forwarded to all registered output handlers.
1.619 + * <p>
1.620 + * Note that the thrown argument is stored in the LogRecord thrown
1.621 + * property, rather than the LogRecord parameters property. Thus is it
1.622 + * processed specially by output Formatters and is not treated
1.623 + * as a formatting parameter to the LogRecord message property.
1.624 + * <p>
1.625 + * @param level One of the message level identifiers, e.g., SEVERE
1.626 + * @param msg The string message (or a key in the message catalog)
1.627 + * @param thrown Throwable associated with log message.
1.628 + */
1.629 + public void log(Level level, String msg, Throwable thrown) {
1.630 + if (level.intValue() < levelValue || levelValue == offValue) {
1.631 + return;
1.632 + }
1.633 + LogRecord lr = new LogRecord(level, msg);
1.634 + lr.setThrown(thrown);
1.635 + doLog(lr);
1.636 + }
1.637 +
1.638 + //================================================================
1.639 + // Start of convenience methods WITH className and methodName
1.640 + //================================================================
1.641 +
1.642 + /**
1.643 + * Log a message, specifying source class and method,
1.644 + * with no arguments.
1.645 + * <p>
1.646 + * If the logger is currently enabled for the given message
1.647 + * level then the given message is forwarded to all the
1.648 + * registered output Handler objects.
1.649 + * <p>
1.650 + * @param level One of the message level identifiers, e.g., SEVERE
1.651 + * @param sourceClass name of class that issued the logging request
1.652 + * @param sourceMethod name of method that issued the logging request
1.653 + * @param msg The string message (or a key in the message catalog)
1.654 + */
1.655 + public void logp(Level level, String sourceClass, String sourceMethod, String msg) {
1.656 + if (level.intValue() < levelValue || levelValue == offValue) {
1.657 + return;
1.658 + }
1.659 + LogRecord lr = new LogRecord(level, msg);
1.660 + lr.setSourceClassName(sourceClass);
1.661 + lr.setSourceMethodName(sourceMethod);
1.662 + doLog(lr);
1.663 + }
1.664 +
1.665 + /**
1.666 + * Log a message, specifying source class and method,
1.667 + * with a single object parameter to the log message.
1.668 + * <p>
1.669 + * If the logger is currently enabled for the given message
1.670 + * level then a corresponding LogRecord is created and forwarded
1.671 + * to all the registered output Handler objects.
1.672 + * <p>
1.673 + * @param level One of the message level identifiers, e.g., SEVERE
1.674 + * @param sourceClass name of class that issued the logging request
1.675 + * @param sourceMethod name of method that issued the logging request
1.676 + * @param msg The string message (or a key in the message catalog)
1.677 + * @param param1 Parameter to the log message.
1.678 + */
1.679 + public void logp(Level level, String sourceClass, String sourceMethod,
1.680 + String msg, Object param1) {
1.681 + if (level.intValue() < levelValue || levelValue == offValue) {
1.682 + return;
1.683 + }
1.684 + LogRecord lr = new LogRecord(level, msg);
1.685 + lr.setSourceClassName(sourceClass);
1.686 + lr.setSourceMethodName(sourceMethod);
1.687 + Object params[] = { param1 };
1.688 + lr.setParameters(params);
1.689 + doLog(lr);
1.690 + }
1.691 +
1.692 + /**
1.693 + * Log a message, specifying source class and method,
1.694 + * with an array of object arguments.
1.695 + * <p>
1.696 + * If the logger is currently enabled for the given message
1.697 + * level then a corresponding LogRecord is created and forwarded
1.698 + * to all the registered output Handler objects.
1.699 + * <p>
1.700 + * @param level One of the message level identifiers, e.g., SEVERE
1.701 + * @param sourceClass name of class that issued the logging request
1.702 + * @param sourceMethod name of method that issued the logging request
1.703 + * @param msg The string message (or a key in the message catalog)
1.704 + * @param params Array of parameters to the message
1.705 + */
1.706 + public void logp(Level level, String sourceClass, String sourceMethod,
1.707 + String msg, Object params[]) {
1.708 + if (level.intValue() < levelValue || levelValue == offValue) {
1.709 + return;
1.710 + }
1.711 + LogRecord lr = new LogRecord(level, msg);
1.712 + lr.setSourceClassName(sourceClass);
1.713 + lr.setSourceMethodName(sourceMethod);
1.714 + lr.setParameters(params);
1.715 + doLog(lr);
1.716 + }
1.717 +
1.718 + /**
1.719 + * Log a message, specifying source class and method,
1.720 + * with associated Throwable information.
1.721 + * <p>
1.722 + * If the logger is currently enabled for the given message
1.723 + * level then the given arguments are stored in a LogRecord
1.724 + * which is forwarded to all registered output handlers.
1.725 + * <p>
1.726 + * Note that the thrown argument is stored in the LogRecord thrown
1.727 + * property, rather than the LogRecord parameters property. Thus is it
1.728 + * processed specially by output Formatters and is not treated
1.729 + * as a formatting parameter to the LogRecord message property.
1.730 + * <p>
1.731 + * @param level One of the message level identifiers, e.g., SEVERE
1.732 + * @param sourceClass name of class that issued the logging request
1.733 + * @param sourceMethod name of method that issued the logging request
1.734 + * @param msg The string message (or a key in the message catalog)
1.735 + * @param thrown Throwable associated with log message.
1.736 + */
1.737 + public void logp(Level level, String sourceClass, String sourceMethod,
1.738 + String msg, Throwable thrown) {
1.739 + if (level.intValue() < levelValue || levelValue == offValue) {
1.740 + return;
1.741 + }
1.742 + LogRecord lr = new LogRecord(level, msg);
1.743 + lr.setSourceClassName(sourceClass);
1.744 + lr.setSourceMethodName(sourceMethod);
1.745 + lr.setThrown(thrown);
1.746 + doLog(lr);
1.747 + }
1.748 +
1.749 +
1.750 + //=========================================================================
1.751 + // Start of convenience methods WITH className, methodName and bundle name.
1.752 + //=========================================================================
1.753 +
1.754 + // Private support method for logging for "logrb" methods.
1.755 + // We fill in the logger name, resource bundle name, and
1.756 + // resource bundle and then call "void log(LogRecord)".
1.757 + private void doLog(LogRecord lr, String rbname) {
1.758 + lr.setLoggerName(name);
1.759 + if (rbname != null) {
1.760 + lr.setResourceBundleName(rbname);
1.761 + lr.setResourceBundle(findResourceBundle(rbname));
1.762 + }
1.763 + log(lr);
1.764 + }
1.765 +
1.766 + /**
1.767 + * Log a message, specifying source class, method, and resource bundle name
1.768 + * with no arguments.
1.769 + * <p>
1.770 + * If the logger is currently enabled for the given message
1.771 + * level then the given message is forwarded to all the
1.772 + * registered output Handler objects.
1.773 + * <p>
1.774 + * The msg string is localized using the named resource bundle. If the
1.775 + * resource bundle name is null, or an empty String or invalid
1.776 + * then the msg string is not localized.
1.777 + * <p>
1.778 + * @param level One of the message level identifiers, e.g., SEVERE
1.779 + * @param sourceClass name of class that issued the logging request
1.780 + * @param sourceMethod name of method that issued the logging request
1.781 + * @param bundleName name of resource bundle to localize msg,
1.782 + * can be null
1.783 + * @param msg The string message (or a key in the message catalog)
1.784 + */
1.785 +
1.786 + public void logrb(Level level, String sourceClass, String sourceMethod,
1.787 + String bundleName, String msg) {
1.788 + if (level.intValue() < levelValue || levelValue == offValue) {
1.789 + return;
1.790 + }
1.791 + LogRecord lr = new LogRecord(level, msg);
1.792 + lr.setSourceClassName(sourceClass);
1.793 + lr.setSourceMethodName(sourceMethod);
1.794 + doLog(lr, bundleName);
1.795 + }
1.796 +
1.797 + /**
1.798 + * Log a message, specifying source class, method, and resource bundle name,
1.799 + * with a single object parameter to the log message.
1.800 + * <p>
1.801 + * If the logger is currently enabled for the given message
1.802 + * level then a corresponding LogRecord is created and forwarded
1.803 + * to all the registered output Handler objects.
1.804 + * <p>
1.805 + * The msg string is localized using the named resource bundle. If the
1.806 + * resource bundle name is null, or an empty String or invalid
1.807 + * then the msg string is not localized.
1.808 + * <p>
1.809 + * @param level One of the message level identifiers, e.g., SEVERE
1.810 + * @param sourceClass name of class that issued the logging request
1.811 + * @param sourceMethod name of method that issued the logging request
1.812 + * @param bundleName name of resource bundle to localize msg,
1.813 + * can be null
1.814 + * @param msg The string message (or a key in the message catalog)
1.815 + * @param param1 Parameter to the log message.
1.816 + */
1.817 + public void logrb(Level level, String sourceClass, String sourceMethod,
1.818 + String bundleName, String msg, Object param1) {
1.819 + if (level.intValue() < levelValue || levelValue == offValue) {
1.820 + return;
1.821 + }
1.822 + LogRecord lr = new LogRecord(level, msg);
1.823 + lr.setSourceClassName(sourceClass);
1.824 + lr.setSourceMethodName(sourceMethod);
1.825 + Object params[] = { param1 };
1.826 + lr.setParameters(params);
1.827 + doLog(lr, bundleName);
1.828 + }
1.829 +
1.830 + /**
1.831 + * Log a message, specifying source class, method, and resource bundle name,
1.832 + * with an array of object arguments.
1.833 + * <p>
1.834 + * If the logger is currently enabled for the given message
1.835 + * level then a corresponding LogRecord is created and forwarded
1.836 + * to all the registered output Handler objects.
1.837 + * <p>
1.838 + * The msg string is localized using the named resource bundle. If the
1.839 + * resource bundle name is null, or an empty String or invalid
1.840 + * then the msg string is not localized.
1.841 + * <p>
1.842 + * @param level One of the message level identifiers, e.g., SEVERE
1.843 + * @param sourceClass name of class that issued the logging request
1.844 + * @param sourceMethod name of method that issued the logging request
1.845 + * @param bundleName name of resource bundle to localize msg,
1.846 + * can be null.
1.847 + * @param msg The string message (or a key in the message catalog)
1.848 + * @param params Array of parameters to the message
1.849 + */
1.850 + public void logrb(Level level, String sourceClass, String sourceMethod,
1.851 + String bundleName, String msg, Object params[]) {
1.852 + if (level.intValue() < levelValue || levelValue == offValue) {
1.853 + return;
1.854 + }
1.855 + LogRecord lr = new LogRecord(level, msg);
1.856 + lr.setSourceClassName(sourceClass);
1.857 + lr.setSourceMethodName(sourceMethod);
1.858 + lr.setParameters(params);
1.859 + doLog(lr, bundleName);
1.860 + }
1.861 +
1.862 + /**
1.863 + * Log a message, specifying source class, method, and resource bundle name,
1.864 + * with associated Throwable information.
1.865 + * <p>
1.866 + * If the logger is currently enabled for the given message
1.867 + * level then the given arguments are stored in a LogRecord
1.868 + * which is forwarded to all registered output handlers.
1.869 + * <p>
1.870 + * The msg string is localized using the named resource bundle. If the
1.871 + * resource bundle name is null, or an empty String or invalid
1.872 + * then the msg string is not localized.
1.873 + * <p>
1.874 + * Note that the thrown argument is stored in the LogRecord thrown
1.875 + * property, rather than the LogRecord parameters property. Thus is it
1.876 + * processed specially by output Formatters and is not treated
1.877 + * as a formatting parameter to the LogRecord message property.
1.878 + * <p>
1.879 + * @param level One of the message level identifiers, e.g., SEVERE
1.880 + * @param sourceClass name of class that issued the logging request
1.881 + * @param sourceMethod name of method that issued the logging request
1.882 + * @param bundleName name of resource bundle to localize msg,
1.883 + * can be null
1.884 + * @param msg The string message (or a key in the message catalog)
1.885 + * @param thrown Throwable associated with log message.
1.886 + */
1.887 + public void logrb(Level level, String sourceClass, String sourceMethod,
1.888 + String bundleName, String msg, Throwable thrown) {
1.889 + if (level.intValue() < levelValue || levelValue == offValue) {
1.890 + return;
1.891 + }
1.892 + LogRecord lr = new LogRecord(level, msg);
1.893 + lr.setSourceClassName(sourceClass);
1.894 + lr.setSourceMethodName(sourceMethod);
1.895 + lr.setThrown(thrown);
1.896 + doLog(lr, bundleName);
1.897 + }
1.898 +
1.899 +
1.900 + //======================================================================
1.901 + // Start of convenience methods for logging method entries and returns.
1.902 + //======================================================================
1.903 +
1.904 + /**
1.905 + * Log a method entry.
1.906 + * <p>
1.907 + * This is a convenience method that can be used to log entry
1.908 + * to a method. A LogRecord with message "ENTRY", log level
1.909 + * FINER, and the given sourceMethod and sourceClass is logged.
1.910 + * <p>
1.911 + * @param sourceClass name of class that issued the logging request
1.912 + * @param sourceMethod name of method that is being entered
1.913 + */
1.914 + public void entering(String sourceClass, String sourceMethod) {
1.915 + if (Level.FINER.intValue() < levelValue) {
1.916 + return;
1.917 + }
1.918 + logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
1.919 + }
1.920 +
1.921 + /**
1.922 + * Log a method entry, with one parameter.
1.923 + * <p>
1.924 + * This is a convenience method that can be used to log entry
1.925 + * to a method. A LogRecord with message "ENTRY {0}", log level
1.926 + * FINER, and the given sourceMethod, sourceClass, and parameter
1.927 + * is logged.
1.928 + * <p>
1.929 + * @param sourceClass name of class that issued the logging request
1.930 + * @param sourceMethod name of method that is being entered
1.931 + * @param param1 parameter to the method being entered
1.932 + */
1.933 + public void entering(String sourceClass, String sourceMethod, Object param1) {
1.934 + if (Level.FINER.intValue() < levelValue) {
1.935 + return;
1.936 + }
1.937 + Object params[] = { param1 };
1.938 + logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", params);
1.939 + }
1.940 +
1.941 + /**
1.942 + * Log a method entry, with an array of parameters.
1.943 + * <p>
1.944 + * This is a convenience method that can be used to log entry
1.945 + * to a method. A LogRecord with message "ENTRY" (followed by a
1.946 + * format {N} indicator for each entry in the parameter array),
1.947 + * log level FINER, and the given sourceMethod, sourceClass, and
1.948 + * parameters is logged.
1.949 + * <p>
1.950 + * @param sourceClass name of class that issued the logging request
1.951 + * @param sourceMethod name of method that is being entered
1.952 + * @param params array of parameters to the method being entered
1.953 + */
1.954 + public void entering(String sourceClass, String sourceMethod, Object params[]) {
1.955 + if (Level.FINER.intValue() < levelValue) {
1.956 + return;
1.957 + }
1.958 + String msg = "ENTRY";
1.959 + if (params == null ) {
1.960 + logp(Level.FINER, sourceClass, sourceMethod, msg);
1.961 + return;
1.962 + }
1.963 + for (int i = 0; i < params.length; i++) {
1.964 + msg = msg + " {" + i + "}";
1.965 + }
1.966 + logp(Level.FINER, sourceClass, sourceMethod, msg, params);
1.967 + }
1.968 +
1.969 + /**
1.970 + * Log a method return.
1.971 + * <p>
1.972 + * This is a convenience method that can be used to log returning
1.973 + * from a method. A LogRecord with message "RETURN", log level
1.974 + * FINER, and the given sourceMethod and sourceClass is logged.
1.975 + * <p>
1.976 + * @param sourceClass name of class that issued the logging request
1.977 + * @param sourceMethod name of the method
1.978 + */
1.979 + public void exiting(String sourceClass, String sourceMethod) {
1.980 + if (Level.FINER.intValue() < levelValue) {
1.981 + return;
1.982 + }
1.983 + logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
1.984 + }
1.985 +
1.986 +
1.987 + /**
1.988 + * Log a method return, with result object.
1.989 + * <p>
1.990 + * This is a convenience method that can be used to log returning
1.991 + * from a method. A LogRecord with message "RETURN {0}", log level
1.992 + * FINER, and the gives sourceMethod, sourceClass, and result
1.993 + * object is logged.
1.994 + * <p>
1.995 + * @param sourceClass name of class that issued the logging request
1.996 + * @param sourceMethod name of the method
1.997 + * @param result Object that is being returned
1.998 + */
1.999 + public void exiting(String sourceClass, String sourceMethod, Object result) {
1.1000 + if (Level.FINER.intValue() < levelValue) {
1.1001 + return;
1.1002 + }
1.1003 + Object params[] = { result };
1.1004 + logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
1.1005 + }
1.1006 +
1.1007 + /**
1.1008 + * Log throwing an exception.
1.1009 + * <p>
1.1010 + * This is a convenience method to log that a method is
1.1011 + * terminating by throwing an exception. The logging is done
1.1012 + * using the FINER level.
1.1013 + * <p>
1.1014 + * If the logger is currently enabled for the given message
1.1015 + * level then the given arguments are stored in a LogRecord
1.1016 + * which is forwarded to all registered output handlers. The
1.1017 + * LogRecord's message is set to "THROW".
1.1018 + * <p>
1.1019 + * Note that the thrown argument is stored in the LogRecord thrown
1.1020 + * property, rather than the LogRecord parameters property. Thus is it
1.1021 + * processed specially by output Formatters and is not treated
1.1022 + * as a formatting parameter to the LogRecord message property.
1.1023 + * <p>
1.1024 + * @param sourceClass name of class that issued the logging request
1.1025 + * @param sourceMethod name of the method.
1.1026 + * @param thrown The Throwable that is being thrown.
1.1027 + */
1.1028 + public void throwing(String sourceClass, String sourceMethod, Throwable thrown) {
1.1029 + if (Level.FINER.intValue() < levelValue || levelValue == offValue ) {
1.1030 + return;
1.1031 + }
1.1032 + LogRecord lr = new LogRecord(Level.FINER, "THROW");
1.1033 + lr.setSourceClassName(sourceClass);
1.1034 + lr.setSourceMethodName(sourceMethod);
1.1035 + lr.setThrown(thrown);
1.1036 + doLog(lr);
1.1037 + }
1.1038 +
1.1039 + //=======================================================================
1.1040 + // Start of simple convenience methods using level names as method names
1.1041 + //=======================================================================
1.1042 +
1.1043 + /**
1.1044 + * Log a SEVERE message.
1.1045 + * <p>
1.1046 + * If the logger is currently enabled for the SEVERE message
1.1047 + * level then the given message is forwarded to all the
1.1048 + * registered output Handler objects.
1.1049 + * <p>
1.1050 + * @param msg The string message (or a key in the message catalog)
1.1051 + */
1.1052 + public void severe(String msg) {
1.1053 + if (Level.SEVERE.intValue() < levelValue) {
1.1054 + return;
1.1055 + }
1.1056 + log(Level.SEVERE, msg);
1.1057 + }
1.1058 +
1.1059 + /**
1.1060 + * Log a WARNING message.
1.1061 + * <p>
1.1062 + * If the logger is currently enabled for the WARNING message
1.1063 + * level then the given message is forwarded to all the
1.1064 + * registered output Handler objects.
1.1065 + * <p>
1.1066 + * @param msg The string message (or a key in the message catalog)
1.1067 + */
1.1068 + public void warning(String msg) {
1.1069 + if (Level.WARNING.intValue() < levelValue) {
1.1070 + return;
1.1071 + }
1.1072 + log(Level.WARNING, msg);
1.1073 + }
1.1074 +
1.1075 + /**
1.1076 + * Log an INFO message.
1.1077 + * <p>
1.1078 + * If the logger is currently enabled for the INFO message
1.1079 + * level then the given message is forwarded to all the
1.1080 + * registered output Handler objects.
1.1081 + * <p>
1.1082 + * @param msg The string message (or a key in the message catalog)
1.1083 + */
1.1084 + public void info(String msg) {
1.1085 + if (Level.INFO.intValue() < levelValue) {
1.1086 + return;
1.1087 + }
1.1088 + log(Level.INFO, msg);
1.1089 + }
1.1090 +
1.1091 + /**
1.1092 + * Log a CONFIG message.
1.1093 + * <p>
1.1094 + * If the logger is currently enabled for the CONFIG message
1.1095 + * level then the given message is forwarded to all the
1.1096 + * registered output Handler objects.
1.1097 + * <p>
1.1098 + * @param msg The string message (or a key in the message catalog)
1.1099 + */
1.1100 + public void config(String msg) {
1.1101 + if (Level.CONFIG.intValue() < levelValue) {
1.1102 + return;
1.1103 + }
1.1104 + log(Level.CONFIG, msg);
1.1105 + }
1.1106 +
1.1107 + /**
1.1108 + * Log a FINE message.
1.1109 + * <p>
1.1110 + * If the logger is currently enabled for the FINE message
1.1111 + * level then the given message is forwarded to all the
1.1112 + * registered output Handler objects.
1.1113 + * <p>
1.1114 + * @param msg The string message (or a key in the message catalog)
1.1115 + */
1.1116 + public void fine(String msg) {
1.1117 + if (Level.FINE.intValue() < levelValue) {
1.1118 + return;
1.1119 + }
1.1120 + log(Level.FINE, msg);
1.1121 + }
1.1122 +
1.1123 + /**
1.1124 + * Log a FINER message.
1.1125 + * <p>
1.1126 + * If the logger is currently enabled for the FINER message
1.1127 + * level then the given message is forwarded to all the
1.1128 + * registered output Handler objects.
1.1129 + * <p>
1.1130 + * @param msg The string message (or a key in the message catalog)
1.1131 + */
1.1132 + public void finer(String msg) {
1.1133 + if (Level.FINER.intValue() < levelValue) {
1.1134 + return;
1.1135 + }
1.1136 + log(Level.FINER, msg);
1.1137 + }
1.1138 +
1.1139 + /**
1.1140 + * Log a FINEST message.
1.1141 + * <p>
1.1142 + * If the logger is currently enabled for the FINEST message
1.1143 + * level then the given message is forwarded to all the
1.1144 + * registered output Handler objects.
1.1145 + * <p>
1.1146 + * @param msg The string message (or a key in the message catalog)
1.1147 + */
1.1148 + public void finest(String msg) {
1.1149 + if (Level.FINEST.intValue() < levelValue) {
1.1150 + return;
1.1151 + }
1.1152 + log(Level.FINEST, msg);
1.1153 + }
1.1154 +
1.1155 + //================================================================
1.1156 + // End of convenience methods
1.1157 + //================================================================
1.1158 +
1.1159 + /**
1.1160 + * Set the log level specifying which message levels will be
1.1161 + * logged by this logger. Message levels lower than this
1.1162 + * value will be discarded. The level value Level.OFF
1.1163 + * can be used to turn off logging.
1.1164 + * <p>
1.1165 + * If the new level is null, it means that this node should
1.1166 + * inherit its level from its nearest ancestor with a specific
1.1167 + * (non-null) level value.
1.1168 + *
1.1169 + * @param newLevel the new value for the log level (may be null)
1.1170 + * @exception SecurityException if a security manager exists and if
1.1171 + * the caller does not have LoggingPermission("control").
1.1172 + */
1.1173 + public void setLevel(Level newLevel) throws SecurityException {
1.1174 + checkAccess();
1.1175 + synchronized (treeLock) {
1.1176 + levelObject = newLevel;
1.1177 + updateEffectiveLevel();
1.1178 + }
1.1179 + }
1.1180 +
1.1181 + /**
1.1182 + * Get the log Level that has been specified for this Logger.
1.1183 + * The result may be null, which means that this logger's
1.1184 + * effective level will be inherited from its parent.
1.1185 + *
1.1186 + * @return this Logger's level
1.1187 + */
1.1188 + public Level getLevel() {
1.1189 + return levelObject;
1.1190 + }
1.1191 +
1.1192 + /**
1.1193 + * Check if a message of the given level would actually be logged
1.1194 + * by this logger. This check is based on the Loggers effective level,
1.1195 + * which may be inherited from its parent.
1.1196 + *
1.1197 + * @param level a message logging level
1.1198 + * @return true if the given message level is currently being logged.
1.1199 + */
1.1200 + public boolean isLoggable(Level level) {
1.1201 + if (level.intValue() < levelValue || levelValue == offValue) {
1.1202 + return false;
1.1203 + }
1.1204 + return true;
1.1205 + }
1.1206 +
1.1207 + /**
1.1208 + * Get the name for this logger.
1.1209 + * @return logger name. Will be null for anonymous Loggers.
1.1210 + */
1.1211 + public String getName() {
1.1212 + return name;
1.1213 + }
1.1214 +
1.1215 + /**
1.1216 + * Add a log Handler to receive logging messages.
1.1217 + * <p>
1.1218 + * By default, Loggers also send their output to their parent logger.
1.1219 + * Typically the root Logger is configured with a set of Handlers
1.1220 + * that essentially act as default handlers for all loggers.
1.1221 + *
1.1222 + * @param handler a logging Handler
1.1223 + * @exception SecurityException if a security manager exists and if
1.1224 + * the caller does not have LoggingPermission("control").
1.1225 + */
1.1226 + public void addHandler(Handler handler) throws SecurityException {
1.1227 + // Check for null handler
1.1228 + handler.getClass();
1.1229 + checkAccess();
1.1230 + handlers.add(handler);
1.1231 + }
1.1232 +
1.1233 + /**
1.1234 + * Remove a log Handler.
1.1235 + * <P>
1.1236 + * Returns silently if the given Handler is not found or is null
1.1237 + *
1.1238 + * @param handler a logging Handler
1.1239 + * @exception SecurityException if a security manager exists and if
1.1240 + * the caller does not have LoggingPermission("control").
1.1241 + */
1.1242 + public void removeHandler(Handler handler) throws SecurityException {
1.1243 + checkAccess();
1.1244 + if (handler == null) {
1.1245 + return;
1.1246 + }
1.1247 + handlers.remove(handler);
1.1248 + }
1.1249 +
1.1250 + /**
1.1251 + * Get the Handlers associated with this logger.
1.1252 + * <p>
1.1253 + * @return an array of all registered Handlers
1.1254 + */
1.1255 + public Handler[] getHandlers() {
1.1256 + return handlers.toArray(emptyHandlers);
1.1257 + }
1.1258 +
1.1259 + /**
1.1260 + * Specify whether or not this logger should send its output
1.1261 + * to its parent Logger. This means that any LogRecords will
1.1262 + * also be written to the parent's Handlers, and potentially
1.1263 + * to its parent, recursively up the namespace.
1.1264 + *
1.1265 + * @param useParentHandlers true if output is to be sent to the
1.1266 + * logger's parent.
1.1267 + * @exception SecurityException if a security manager exists and if
1.1268 + * the caller does not have LoggingPermission("control").
1.1269 + */
1.1270 + public void setUseParentHandlers(boolean useParentHandlers) {
1.1271 + checkAccess();
1.1272 + this.useParentHandlers = useParentHandlers;
1.1273 + }
1.1274 +
1.1275 + /**
1.1276 + * Discover whether or not this logger is sending its output
1.1277 + * to its parent logger.
1.1278 + *
1.1279 + * @return true if output is to be sent to the logger's parent
1.1280 + */
1.1281 + public boolean getUseParentHandlers() {
1.1282 + return useParentHandlers;
1.1283 + }
1.1284 +
1.1285 + // Private utility method to map a resource bundle name to an
1.1286 + // actual resource bundle, using a simple one-entry cache.
1.1287 + // Returns null for a null name.
1.1288 + // May also return null if we can't find the resource bundle and
1.1289 + // there is no suitable previous cached value.
1.1290 +
1.1291 + private synchronized ResourceBundle findResourceBundle(String name) {
1.1292 + // Return a null bundle for a null name.
1.1293 + if (name == null) {
1.1294 + return null;
1.1295 + }
1.1296 +
1.1297 + Locale currentLocale = Locale.getDefault();
1.1298 +
1.1299 + // Normally we should hit on our simple one entry cache.
1.1300 + if (catalog != null && currentLocale == catalogLocale
1.1301 + && name == catalogName) {
1.1302 + return catalog;
1.1303 + }
1.1304 +
1.1305 + // Use the thread's context ClassLoader. If there isn't one,
1.1306 + // use the SystemClassloader.
1.1307 + ClassLoader cl = Thread.currentThread().getContextClassLoader();
1.1308 + if (cl == null) {
1.1309 + cl = ClassLoader.getSystemClassLoader();
1.1310 + }
1.1311 + try {
1.1312 + catalog = ResourceBundle.getBundle(name, currentLocale, cl);
1.1313 + catalogName = name;
1.1314 + catalogLocale = currentLocale;
1.1315 + return catalog;
1.1316 + } catch (MissingResourceException ex) {
1.1317 + // Woops. We can't find the ResourceBundle in the default
1.1318 + // ClassLoader. Drop through.
1.1319 + }
1.1320 +
1.1321 +
1.1322 + // Fall back to searching up the call stack and trying each
1.1323 + // calling ClassLoader.
1.1324 + for (int ix = 0; ; ix++) {
1.1325 + Class clz = sun.reflect.Reflection.getCallerClass(ix);
1.1326 + if (clz == null) {
1.1327 + break;
1.1328 + }
1.1329 + ClassLoader cl2 = clz.getClassLoader();
1.1330 + if (cl2 == null) {
1.1331 + cl2 = ClassLoader.getSystemClassLoader();
1.1332 + }
1.1333 + if (cl == cl2) {
1.1334 + // We've already checked this classloader.
1.1335 + continue;
1.1336 + }
1.1337 + cl = cl2;
1.1338 + try {
1.1339 + catalog = ResourceBundle.getBundle(name, currentLocale, cl);
1.1340 + catalogName = name;
1.1341 + catalogLocale = currentLocale;
1.1342 + return catalog;
1.1343 + } catch (MissingResourceException ex) {
1.1344 + // Ok, this one didn't work either.
1.1345 + // Drop through, and try the next one.
1.1346 + }
1.1347 + }
1.1348 +
1.1349 + if (name.equals(catalogName)) {
1.1350 + // Return the previous cached value for that name.
1.1351 + // This may be null.
1.1352 + return catalog;
1.1353 + }
1.1354 + // Sorry, we're out of luck.
1.1355 + return null;
1.1356 + }
1.1357 +
1.1358 + // Private utility method to initialize our one entry
1.1359 + // resource bundle cache.
1.1360 + // Note: for consistency reasons, we are careful to check
1.1361 + // that a suitable ResourceBundle exists before setting the
1.1362 + // ResourceBundleName.
1.1363 + private synchronized void setupResourceInfo(String name) {
1.1364 + if (name == null) {
1.1365 + return;
1.1366 + }
1.1367 + ResourceBundle rb = findResourceBundle(name);
1.1368 + if (rb == null) {
1.1369 + // We've failed to find an expected ResourceBundle.
1.1370 + throw new MissingResourceException("Can't find " + name + " bundle", name, "");
1.1371 + }
1.1372 + resourceBundleName = name;
1.1373 + }
1.1374 +
1.1375 + /**
1.1376 + * Return the parent for this Logger.
1.1377 + * <p>
1.1378 + * This method returns the nearest extant parent in the namespace.
1.1379 + * Thus if a Logger is called "a.b.c.d", and a Logger called "a.b"
1.1380 + * has been created but no logger "a.b.c" exists, then a call of
1.1381 + * getParent on the Logger "a.b.c.d" will return the Logger "a.b".
1.1382 + * <p>
1.1383 + * The result will be null if it is called on the root Logger
1.1384 + * in the namespace.
1.1385 + *
1.1386 + * @return nearest existing parent Logger
1.1387 + */
1.1388 + public Logger getParent() {
1.1389 + // Note: this used to be synchronized on treeLock. However, this only
1.1390 + // provided memory semantics, as there was no guarantee that the caller
1.1391 + // would synchronize on treeLock (in fact, there is no way for external
1.1392 + // callers to so synchronize). Therefore, we have made parent volatile
1.1393 + // instead.
1.1394 + return parent;
1.1395 + }
1.1396 +
1.1397 + /**
1.1398 + * Set the parent for this Logger. This method is used by
1.1399 + * the LogManager to update a Logger when the namespace changes.
1.1400 + * <p>
1.1401 + * It should not be called from application code.
1.1402 + * <p>
1.1403 + * @param parent the new parent logger
1.1404 + * @exception SecurityException if a security manager exists and if
1.1405 + * the caller does not have LoggingPermission("control").
1.1406 + */
1.1407 + public void setParent(Logger parent) {
1.1408 + if (parent == null) {
1.1409 + throw new NullPointerException();
1.1410 + }
1.1411 + manager.checkAccess();
1.1412 + doSetParent(parent);
1.1413 + }
1.1414 +
1.1415 + // Private method to do the work for parenting a child
1.1416 + // Logger onto a parent logger.
1.1417 + private void doSetParent(Logger newParent) {
1.1418 +
1.1419 + // System.err.println("doSetParent \"" + getName() + "\" \""
1.1420 + // + newParent.getName() + "\"");
1.1421 +
1.1422 + synchronized (treeLock) {
1.1423 +
1.1424 + // Remove ourself from any previous parent.
1.1425 + LogManager.LoggerWeakRef ref = null;
1.1426 + if (parent != null) {
1.1427 + // assert parent.kids != null;
1.1428 + for (Iterator<LogManager.LoggerWeakRef> iter = parent.kids.iterator(); iter.hasNext(); ) {
1.1429 + ref = iter.next();
1.1430 + Logger kid = ref.get();
1.1431 + if (kid == this) {
1.1432 + // ref is used down below to complete the reparenting
1.1433 + iter.remove();
1.1434 + break;
1.1435 + } else {
1.1436 + ref = null;
1.1437 + }
1.1438 + }
1.1439 + // We have now removed ourself from our parents' kids.
1.1440 + }
1.1441 +
1.1442 + // Set our new parent.
1.1443 + parent = newParent;
1.1444 + if (parent.kids == null) {
1.1445 + parent.kids = new ArrayList<>(2);
1.1446 + }
1.1447 + if (ref == null) {
1.1448 + // we didn't have a previous parent
1.1449 + ref = manager.new LoggerWeakRef(this);
1.1450 + }
1.1451 + ref.setParentRef(new WeakReference<Logger>(parent));
1.1452 + parent.kids.add(ref);
1.1453 +
1.1454 + // As a result of the reparenting, the effective level
1.1455 + // may have changed for us and our children.
1.1456 + updateEffectiveLevel();
1.1457 +
1.1458 + }
1.1459 + }
1.1460 +
1.1461 + // Package-level method.
1.1462 + // Remove the weak reference for the specified child Logger from the
1.1463 + // kid list. We should only be called from LoggerWeakRef.dispose().
1.1464 + final void removeChildLogger(LogManager.LoggerWeakRef child) {
1.1465 + synchronized (treeLock) {
1.1466 + for (Iterator<LogManager.LoggerWeakRef> iter = kids.iterator(); iter.hasNext(); ) {
1.1467 + LogManager.LoggerWeakRef ref = iter.next();
1.1468 + if (ref == child) {
1.1469 + iter.remove();
1.1470 + return;
1.1471 + }
1.1472 + }
1.1473 + }
1.1474 + }
1.1475 +
1.1476 + // Recalculate the effective level for this node and
1.1477 + // recursively for our children.
1.1478 +
1.1479 + private void updateEffectiveLevel() {
1.1480 + // assert Thread.holdsLock(treeLock);
1.1481 +
1.1482 + // Figure out our current effective level.
1.1483 + int newLevelValue;
1.1484 + if (levelObject != null) {
1.1485 + newLevelValue = levelObject.intValue();
1.1486 + } else {
1.1487 + if (parent != null) {
1.1488 + newLevelValue = parent.levelValue;
1.1489 + } else {
1.1490 + // This may happen during initialization.
1.1491 + newLevelValue = Level.INFO.intValue();
1.1492 + }
1.1493 + }
1.1494 +
1.1495 + // If our effective value hasn't changed, we're done.
1.1496 + if (levelValue == newLevelValue) {
1.1497 + return;
1.1498 + }
1.1499 +
1.1500 + levelValue = newLevelValue;
1.1501 +
1.1502 + // System.err.println("effective level: \"" + getName() + "\" := " + level);
1.1503 +
1.1504 + // Recursively update the level on each of our kids.
1.1505 + if (kids != null) {
1.1506 + for (int i = 0; i < kids.size(); i++) {
1.1507 + LogManager.LoggerWeakRef ref = kids.get(i);
1.1508 + Logger kid = ref.get();
1.1509 + if (kid != null) {
1.1510 + kid.updateEffectiveLevel();
1.1511 + }
1.1512 + }
1.1513 + }
1.1514 + }
1.1515 +
1.1516 +
1.1517 + // Private method to get the potentially inherited
1.1518 + // resource bundle name for this Logger.
1.1519 + // May return null
1.1520 + private String getEffectiveResourceBundleName() {
1.1521 + Logger target = this;
1.1522 + while (target != null) {
1.1523 + String rbn = target.getResourceBundleName();
1.1524 + if (rbn != null) {
1.1525 + return rbn;
1.1526 + }
1.1527 + target = target.getParent();
1.1528 + }
1.1529 + return null;
1.1530 + }
1.1531 +
1.1532 +
1.1533 +}