/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* There is a single global LogManager object that is used to
* maintain a set of shared state about Loggers and log services.
* <p>
* This LogManager object:
* <ul>
* <li> Manages a hierarchical namespace of Logger objects. All
* named Loggers are stored in this namespace.
* <li> Manages a set of logging control properties. These are
* simple key-value pairs that can be used by Handlers and
* other logging objects to configure themselves.
* </ul>
* <p>
* The global LogManager object can be retrieved using LogManager.getLogManager().
* The LogManager object is created during class initialization and
* cannot subsequently be changed.
* <p>
* At startup the LogManager class is located using the
* java.util.logging.manager system property.
* <p>
* By default, the LogManager reads its initial configuration from
* a properties file "lib/logging.properties" in the JRE directory.
* If you edit that property file you can change the default logging
* configuration for all uses of that JRE.
* <p>
* In addition, the LogManager uses two optional system properties that
* allow more control over reading the initial configuration:
* <ul>
* <li>"java.util.logging.config.class"
* <li>"java.util.logging.config.file"
* </ul>
* These two properties may be set via the Preferences API, or as
* command line property definitions to the "java" command, or as
* system property definitions passed to JNI_CreateJavaVM.
* <p>
* If the "java.util.logging.config.class" property is set, then the
* property value is treated as a class name. The given class will be
* loaded, an object will be instantiated, and that object's constructor
* is responsible for reading in the initial configuration. (That object
* may use other system properties to control its configuration.) The
* alternate configuration class can use <tt>readConfiguration(InputStream)</tt>
* to define properties in the LogManager.
* <p>
* If "java.util.logging.config.class" property is <b>not</b> set,
* then the "java.util.logging.config.file" system property can be used
* to specify a properties file (in java.util.Properties format). The
* initial logging configuration will be read from this file.
* <p>
* If neither of these properties is defined then, as described
* above, the LogManager will read its initial configuration from
* a properties file "lib/logging.properties" in the JRE directory.
* <p>
* The properties for loggers and Handlers will have names starting
* with the dot-separated name for the handler or logger.
* <p>
* The global logging properties may include:
* <ul>
* <li>A property "handlers". This defines a whitespace or comma separated
* list of class names for handler classes to load and register as
* handlers on the root Logger (the Logger named ""). Each class
* name must be for a Handler class which has a default constructor.
* Note that these Handlers may be created lazily, when they are
* first used.
*
* <li>A property "<logger>.handlers". This defines a whitespace or
* comma separated list of class names for handlers classes to
* load and register as handlers to the specified logger. Each class
* name must be for a Handler class which has a default constructor.
* Note that these Handlers may be created lazily, when they are
* first used.
*
* <li>A property "<logger>.useParentHandlers". This defines a boolean
* value. By default every logger calls its parent in addition to
* handling the logging message itself, this often result in messages
* being handled by the root logger as well. When setting this property
* to false a Handler needs to be configured for this logger otherwise
* no logging messages are delivered.
*
* <li>A property "config". This property is intended to allow
* arbitrary configuration code to be run. The property defines a
* whitespace or comma separated list of class names. A new instance will be
* created for each named class. The default constructor of each class
* may execute arbitrary code to update the logging configuration, such as
* setting logger levels, adding handlers, adding filters, etc.
* </ul>
* <p>
* Note that all classes loaded during LogManager configuration are
* first searched on the system class path before any user class path.
* That includes the LogManager class, any config classes, and any
* handler classes.
* <p>
* Loggers are organized into a naming hierarchy based on their
* dot separated names. Thus "a.b.c" is a child of "a.b", but
* "a.b1" and a.b2" are peers.
* <p>
* All properties whose names end with ".level" are assumed to define
* log levels for Loggers. Thus "foo.level" defines a log level for
* the logger called "foo" and (recursively) for any of its children
* in the naming hierarchy. Log Levels are applied in the order they
* are defined in the properties file. Thus level settings for child
* nodes in the tree should come after settings for their parents.
* The property name ".level" can be used to set the level for the
* root of the tree.
* <p>
* All methods on the LogManager object are multi-thread safe.
*
* @since 1.4
*/
public class LogManager {
// The global LogManager object
= new PropertyChangeSupport(LogManager.class);
// LoggerContext for system loggers and user loggers
// Have we done the primordial reading of the configuration file?
// (Must be done after a suitable amount of java.lang.System
// initialization has been done)
private volatile boolean readPrimordialConfiguration;
// Have we initialized global (root) handlers yet?
// This gets set to false in readConfiguration
private boolean initializedGlobalHandlers = true;
// True if JVM death is imminent and the exit hook has been called.
private boolean deathImminent;
static {
try {
try {
} catch (ClassNotFoundException ex) {
}
}
}
manager = new LogManager();
}
// Create and retain Logger for the root of the namespace.
// since by design the global manager's userContext and
// systemContext don't have their requiresDefaultLoggers
// flag set - we make sure to add the root logger to
// the global manager's default contexts here.
// Adding the global Logger. Doing so in the Logger.<clinit>
// would deadlock with the LogManager.<clinit>.
// Make sure the global logger will be registered in the
// global manager's default contexts.
// We don't call readConfiguration() here, as we may be running
// very early in the JVM startup sequence. Instead readConfiguration
// will be called lazily in getLogManager().
return null;
}
});
}
// This private class is used as a shutdown hook.
// It does a "reset" to close all open handlers.
private Cleaner() {
/* Set context class loader to null in order to avoid
* keeping a strong reference to an application classloader.
*/
this.setContextClassLoader(null);
}
public void run() {
// This is to ensure the LogManager.<clinit> is completed
// before synchronized block. Otherwise deadlocks are possible.
// If the global handlers haven't been initialized yet, we
// don't want to initialize them just so we can close them!
synchronized (LogManager.this) {
// Note that death is imminent.
deathImminent = true;
initializedGlobalHandlers = true;
}
// Do a reset to close all active handlers.
reset();
}
}
/**
* Protected constructor. This is protected so that container applications
* (such as J2EE containers) can subclass the object. It is non-public as
* it is intended that there only be one LogManager object, whose value is
* retrieved by calling Logmanager.getLogManager.
*/
protected LogManager() {
// Add a shutdown hook to close the global handlers.
try {
} catch (IllegalStateException e) {
// If the VM is already shutting down,
// We do not need to register shutdownHook.
}
}
/**
* Return the global LogManager object.
*/
}
return manager;
}
private void readPrimordialConfiguration() {
if (!readPrimordialConfiguration) {
synchronized (this) {
if (!readPrimordialConfiguration) {
// indication that we're still in the
// bootstrapping phase
return;
}
readPrimordialConfiguration = true;
try {
// Platform loggers begin to delegate to java.util.logging.Logger
return null;
}
});
// System.err.println("Can't read logging configuration:");
// ex.printStackTrace();
}
}
}
}
}
/**
* Adds an event listener to be invoked when the logging
* properties are re-read. Adding multiple instances of
* the same event Listener results in multiple entries
* in the property event listener table.
*
* @param l event listener
* @exception SecurityException if a security manager exists and if
* the caller does not have LoggingPermission("control").
* @exception NullPointerException if the PropertyChangeListener is null.
*/
if (l == null) {
throw new NullPointerException();
}
}
/**
* Removes an event listener for property change events.
* If the same listener instance has been added to the listener table
* through multiple invocations of <CODE>addPropertyChangeListener</CODE>,
* then an equivalent number of
* <CODE>removePropertyChangeListener</CODE> invocations are required to remove
* all instances of that listener from the listener table.
* <P>
* Returns silently if the given listener is not found.
*
* @param l event listener (can be null)
* @exception SecurityException if a security manager exists and if
* the caller does not have LoggingPermission("control").
*/
}
// Returns the LoggerContext for the user code (i.e. application or AppContext).
// Loggers are isolated from each AppContext.
synchronized (javaAwtAccess) {
// AppContext.getAppContext() returns the system AppContext if called
// from a system thread but Logger.getLogger might be called from
// an applet code. Instead, find the AppContext of the applet code
// from the execution stack.
// fall back to thread group seach of AppContext
}
if (javaAwtAccess.isMainAppContext()) {
} else {
// Create a new LoggerContext for the applet.
// The new logger context has its requiresDefaultLoggers
// flag set to true - so that these loggers will be
// lazily added when the context is firt accessed.
context = new LoggerContext(true);
}
}
}
}
}
}
return cxs;
}
// Find or create a specified logger instance. If a logger has
// already been created with the given name it is returned.
// Otherwise a new logger instance is created and registered
// in the LogManager global namespace.
// This method will always return a non-null Logger object.
// Synchronization is not required here. All synchronization for
// adding a new Logger object is handled by addLogger().
//
// This method must delegate to the LogManager implementation to
// add a new Logger or return the one that has been added previously
// as a LogManager subclass may override the addLogger, getLogger,
// readConfiguration, and other methods.
// only allocate the new logger once
do {
// We successfully added the new Logger that we
// created above so return it without refetching.
return newLogger;
}
// We didn't add the new Logger that we created above
// because another thread added a Logger with the same
// name after our null check above and before our call
// to addLogger(). We have to refetch the Logger because
// addLogger() returns a boolean instead of the Logger
// reference itself. However, if the thread that created
// the other Logger is not holding a strong reference to
// the other Logger, then it is possible for the other
// Logger to be GC'ed after we saw it in addLogger() and
// before we can refetch it. If it has been GC'ed then
// we'll just loop around and try again.
}
return result;
}
// Add a system logger in the system context's namespace
// Add the system logger to the LogManager's namespace if not exist
// so that there is only one single logger of the given name.
// System loggers are visible to applications unless a logger of
// the same name has been added.
do {
// First attempt to call addLogger instead of getLogger
// This would avoid potential bug in custom LogManager.getLogger
// implementation that adds a logger if does not exist
// successfully added the new system logger
} else {
}
// LogManager will set the sysLogger's handlers via LogManager.addLogger method.
// if logger already exists but handlers not set
}
return null;
}
});
}
return sysLogger;
}
// LoggerContext maintains the logger namespace per context.
// The default LogManager implementation has one system context and user
// context. The system context is used to maintain the namespace for
// all system loggers and is queried by the system code. If a system logger
// doesn't exist in the user context, it'll also be added to the user context.
// The user context is queried by the user code and all other loggers are
// added in the user context.
static class LoggerContext {
// Table of named Loggers that maps names to Loggers.
// Tree of named Loggers
private final boolean requiresDefaultLoggers;
private LoggerContext() {
this(false);
}
}
// a LogManager subclass may have its own implementation to add and
// get a Logger. So delegate to the LogManager to do the work.
}
// Due to subtle deadlock issues getUserContext() no longer
// calls addLocalLogger(rootLogger);
// Therefore - we need to add the default loggers later on.
// Checks that the context is properly initialized
// This is necessary before calling e.g. find(name)
// or getLoggerNames()
//
private void ensureInitialized() {
if (requiresDefaultLoggers) {
// Ensure that the root and global loggers are set.
}
}
// ensure that this context is properly initialized before
// looking for loggers.
return null;
}
// Hashtable holds stale weak reference
// to a logger which has been GC-ed.
}
return logger;
}
// This method is called before adding a logger to the
// context.
// 'logger' is the context that will be added.
// This method will ensure that the defaults loggers are added
// before adding 'logger'.
//
if (requiresDefaultLoggers) {
}
}
}
}
// Used for lazy addition of root logger and global logger
// to a LoggerContext.
// This check is simple sanity: we do not want that this
// method be called for anything else than Logger.global
// or owner.rootLogger.
// the case where we have a non null logger which is neither
// Logger.global nor manager.rootLogger indicates a serious
// issue - as ensureDefaultLogger should never be called
// with any other loggers than one of these two (or null - if
// e.g manager.rootLogger is not yet initialized)...
return;
}
// Adds the logger if it's not already there.
// It is important to prevent addLocalLogger to
// call ensureAllDefaultLoggers when we're in the process
// off adding one of those default loggers - as this would
// immediately cause a stack overflow.
// Therefore we must pass addDefaultLoggersIfNeeded=false,
// even if requiresDefaultLoggers is true.
addLocalLogger(logger, false);
}
}
// no need to add default loggers if it's not required
}
// Add a logger to this context. This method will only set its level
// and process parent loggers. It doesn't set its handlers.
// addDefaultLoggersIfNeeded serves to break recursion when adding
// default loggers. If we're adding one of the default loggers
// (we're being called from ensureDefaultLogger()) then
// addDefaultLoggersIfNeeded will be false: we don't want to
// call ensureAllDefaultLoggers again.
//
// Note: addDefaultLoggersIfNeeded can also be false when
// requiresDefaultLoggers is false - since calling
// ensureAllDefaultLoggers would have no effect in this case.
if (addDefaultLoggersIfNeeded) {
}
throw new NullPointerException();
}
// It's possible that the Logger was GC'ed after a
// drainLoggerRefQueueBounded() call so allow
// a new one to be registered.
} else {
// We already have a registered logger with the given name.
return false;
}
}
// We're adding a new logger.
// Note that we are creating a weak reference here.
// Apply any initial level defined for the new logger.
}
// Find the new node and its parent.
break;
}
}
}
}
// Walk over the children and tell them we are their new parent.
// new LogNode is ready so tell the LoggerWeakRef about it
return true;
}
// note: all calls to removeLogger are synchronized on LogManager's
// intrinsic lock
}
// ensure that this context is properly initialized before
// returning logger names.
return namedLoggers.keys();
}
// If logger.getUseParentHandlers() returns 'true' and any of the logger's
// parents have levels or handlers defined, make sure they are instantiated.
if (!useParent) {
logger.setUseParentHandlers(false);
}
}
return null;
}
});
int ix = 1;
for (;;) {
if (ix2 < 0) {
break;
}
// Make sure it exists.
}
}
}
// Gets a node in our tree of logger nodes.
// If necessary, create it.
return root;
}
if (ix > 0) {
} else {
name = "";
}
}
}
}
return node;
}
}
// Add a system logger in the system context's namespace as well as
// in the LogManager's namespace if not exist so that there is only
// one single logger of the given name. System loggers are visible
// to applications unless a logger of the same name has been added.
// only allocate the new system logger once
do {
if (addLocalLogger(newLogger)) {
// We successfully added the new Logger that we
// created above so return it without refetching.
} else {
// We didn't add the new Logger that we created above
// because another thread added a Logger with the same
// name after our null check above and before our call
// to addLogger(). We have to refetch the Logger because
// addLogger() returns a boolean instead of the Logger
// reference itself. However, if the thread that created
// the other Logger is not holding a strong reference to
// the other Logger, then it is possible for the other
// Logger to be GC'ed after we saw it in addLogger() and
// before we can refetch it. If it has been GC'ed then
// we'll just loop around and try again.
}
}
return result;
}
}
// Add new per logger handlers.
// We need to raise privilege here. All our decisions will
// be made based on the logging configuration, which can
// only be modified by trusted code.
final String handlersPropertyName)
{
try {
// Check if there is a property defining the
// this handler's level.
if (l != null) {
} else {
// Probably a bad level. Drop through.
}
}
// Add this Handler to the logger
}
}
return null;
}
});
}
// loggerRefQueue holds LoggerWeakRef objects for Logger objects
// that have been GC'ed.
= new ReferenceQueue<>();
// Package-level inner class.
// Helper class for managing WeakReferences to Logger objects.
//
// LogManager.namedLoggers
// - has weak references to all named Loggers
// - namedLoggers keeps the LoggerWeakRef objects for the named
// Loggers around until we can deal with the book keeping for
// the named Logger that is being GC'ed.
// LogManager.LogNode.loggerRef
// - has a weak reference to a named Logger
// - the LogNode will also keep the LoggerWeakRef objects for
// the named Loggers around; currently LogNodes never go away.
// Logger.kids
// - has a weak reference to each direct child Logger; this
// includes anonymous and named Loggers
// - anonymous Loggers are always children of the rootLogger
// which is a strong reference; rootLogger.kids keeps the
// LoggerWeakRef objects for the anonymous Loggers around
// until we can deal with the book keeping.
//
super(logger, loggerRefQueue);
}
// dispose of this LoggerWeakRef object
void dispose() {
// if we have a LogNode, then we were a named Logger
// so clear namedLoggers weak ref to us
}
// this LoggerWeakRef has or had a parent Logger
// the parent Logger is still there so clear the
// parent Logger's weak ref to us
parent.removeChildLogger(this);
}
}
}
// set the node field to the specified value
}
// set the parentRef field to the specified value
}
}
// Package-level method.
// Drain some Logger objects that have been GC'ed.
//
// drainLoggerRefQueueBounded() is called by addLogger() below
// and by Logger.getAnonymousLogger(String) so we'll drain up to
// MAX_ITERATIONS GC'ed Loggers for every Logger we add.
//
// On a WinXP VMware client, a MAX_ITERATIONS value of 400 gives
// us about a 50/50 mix in increased weak ref counts versus
// decreased weak ref counts in the AnonLoggerWeakRefLeak test.
// Here are stats for cleaning up sets of 400 anonymous Loggers:
// - test duration 1 minute
// - sample size of 125 sets of 400
// - average: 1.99 ms
// - minimum: 0.57 ms
// - maximum: 25.3 ms
//
// The same config gives us a better decreased weak ref count
// than increased weak ref count in the LoggerWeakRefLeak test.
// Here are stats for cleaning up sets of 400 named Loggers:
// - test duration 2 minutes
// - sample size of 506 sets of 400
// - average: 0.57 ms
// - minimum: 0.02 ms
// - maximum: 10.9 ms
//
final synchronized void drainLoggerRefQueueBounded() {
for (int i = 0; i < MAX_ITERATIONS; i++) {
if (loggerRefQueue == null) {
// haven't finished loading LogManager yet
break;
}
break;
}
// a Logger object has been GC'ed so clean it up
}
}
/**
* Add a named logger. This does nothing and returns false if a logger
* with the same name is already registered.
* <p>
* The Logger factory methods call this method to register each
* newly created Logger.
* <p>
* The application should retain its own reference to the Logger
* object to avoid it being garbage collected. The LogManager
* may only retain a weak reference.
*
* @param logger the new logger.
* @return true if the argument logger was registered successfully,
* false if a logger of that name already exists.
* @exception NullPointerException if the logger name is null.
*/
throw new NullPointerException();
}
// Do we have a per logger handler too?
// Note: this will add a 200ms penalty
return true;
} else {
return false;
}
}
// Private method to set a level on a logger.
// If necessary, we raise privilege before doing the call.
// There is no security manager, so things are easy.
return;
}
// There is a security manager. Raise privilege before
// calling setLevel.
return null;
}});
}
// Private method to set a parent on a logger.
// If necessary, we raise privilege before doing the setParent call.
// There is no security manager, so things are easy.
return;
}
// There is a security manager. Raise privilege before
// calling setParent.
return null;
}});
}
/**
* Method to find a named logger.
* <p>
* Note that since untrusted code may create loggers with
* arbitrary names this method should not be relied on to
* find Loggers for security sensitive logging.
* It is also important to note that the Logger associated with the
* String {@code name} may be garbage collected at any time if there
* is no strong reference to the Logger. The caller of this method
* must check the return value for null in order to properly handle
* the case where the Logger has been garbage collected.
* <p>
* @param name name of the logger
* @return matching logger or null if none is found
*/
}
/**
* Get an enumeration of known logger names.
* <p>
* Note: Loggers may be added dynamically as new classes are loaded.
* This method only reports on the loggers that are currently registered.
* It is also important to note that this method only returns the name
* of a Logger, not a strong reference to the Logger itself.
* The returned String does nothing to prevent the Logger from being
* garbage collected. In particular, if the returned name is passed
* to {@code LogManager.getLogger()}, then the caller must check the
* return value from {@code LogManager.getLogger()} for null to properly
* handle the case where the Logger has been garbage collected in the
* time since its name was returned by this method.
* <p>
* @return enumeration of logger name strings
*/
return getUserContext().getLoggerNames();
}
/**
* Reinitialize the logging properties and reread the logging configuration.
* <p>
* The same rules are used for locating the configuration properties
* as are used at startup. So normally the logging properties will
* be re-read from the same file that was used at startup.
* <P>
* Any log level definitions in the new configuration file will be
* applied using Logger.setLevel(), if the target Logger exists.
* <p>
* A PropertyChangeEvent will be fired after the properties are read.
*
* @exception SecurityException if a security manager exists and if
* the caller does not have LoggingPermission("control").
* @exception IOException if there are IO problems reading the configuration.
*/
// if a configuration class is specified, load it and use it.
try {
// Instantiate the named class. It is its constructor's
// responsibility to initialize the logging configuration, by
// calling readConfiguration(InputStream) with a suitable stream.
try {
clz.newInstance();
return;
} catch (ClassNotFoundException ex) {
clz.newInstance();
return;
}
// keep going and useful config file.
}
}
throw new Error("Can't find java.home ??");
}
f = new File(f, "logging.properties");
fname = f.getCanonicalPath();
}
try {
} finally {
}
}
}
/**
* Reset the logging configuration.
* <p>
* For all named loggers, the reset operation removes and closes
* all Handlers and (except for the root logger) sets the level
* to null. The root logger's level is set to Level.INFO.
*
* @exception SecurityException if a security manager exists and if
* the caller does not have LoggingPermission("control").
*/
synchronized (this) {
props = new Properties();
// Since we are doing a reset we no longer want to initialize
// the global handlers, if they haven't been initialized yet.
initializedGlobalHandlers = true;
}
while (enum_.hasMoreElements()) {
}
}
}
}
// Private method to reset an individual target logger.
// Close all the Logger's handlers.
logger.removeHandler(h);
try {
h.close();
// Problems closing a handler? Keep going...
}
}
// This is the root logger.
} else {
}
}
// get a list of whitespace separated classnames from a property.
return new String[0];
}
int ix = 0;
break;
}
break;
}
end++;
}
continue;
}
}
}
/**
* Reinitialize the logging properties and reread the logging configuration
* from the given stream, which should be in java.util.Properties format.
* A PropertyChangeEvent will be fired after the properties are read.
* <p>
* Any log level definitions in the new configuration file will be
* applied using Logger.setLevel(), if the target Logger exists.
*
* @param ins stream to read properties from
* @exception SecurityException if a security manager exists and if
* the caller does not have LoggingPermission("control").
* @exception IOException if there are problems reading from the stream.
*/
reset();
// Load the properties
// Instantiate new configuration objects.
try {
clz.newInstance();
// ex.printStackTrace();
}
}
// Set levels on any pre-existing loggers, based on the new properties.
// Notify any interested parties that our properties have changed.
// Note that we need to reinitialize global handles when
// they are first referenced.
synchronized (this) {
initializedGlobalHandlers = false;
}
}
/**
* Get the value of a logging property.
* The method returns null if the property is not found.
* @param name property name
* @return property value
*/
}
// Package private method to get a String property.
// If the property is not defined we return the given
// default value.
return defaultValue;
}
}
// Package private method to get an integer property.
// If the property is not defined or cannot be parsed
// we return the given default value.
return defaultValue;
}
try {
return defaultValue;
}
}
// Package private method to get a boolean property.
// If the property is not defined or cannot be parsed
// we return the given default value.
return defaultValue;
}
return true;
return false;
}
return defaultValue;
}
// Package private method to get a Level property.
// If the property is not defined or cannot be parsed
// we return the given default value.
return defaultValue;
}
return l != null ? l : defaultValue;
}
// Package private method to get a filter property.
// We return an instance of the class named by the "name"
// property. If the property is not defined or has problems
// we return the defaultValue.
try {
}
// We got one of a variety of exceptions in creating the
// class or creating an instance.
// Drop through.
}
// We got an exception. Return the defaultValue.
return defaultValue;
}
// Package private method to get a formatter property.
// We return an instance of the class named by the "name"
// property. If the property is not defined or has problems
// we return the defaultValue.
try {
}
// We got one of a variety of exceptions in creating the
// class or creating an instance.
// Drop through.
}
// We got an exception. Return the defaultValue.
return defaultValue;
}
// Private method to load the global handlers.
// We do the real work lazily, when the global handlers
// are first used.
private synchronized void initializeGlobalHandlers() {
if (initializedGlobalHandlers) {
return;
}
initializedGlobalHandlers = true;
if (deathImminent) {
// Aaargh...
// The VM is shutting down and our exit hook has been called.
// Avoid allocating global handlers.
return;
}
}
void checkPermission() {
}
/**
* Check that the current context is trusted to modify the logging
* configuration. This requires LoggingPermission("control").
* <p>
* If the check fails we throw a SecurityException, otherwise
* we return normally.
*
* @exception SecurityException if a security manager exists and if
* the caller does not have LoggingPermission("control").
*/
}
// Nested class to represent a node in our tree of named loggers.
private static class LogNode {
}
// Recursive method to walk the tree below a node and set
// a new parent logger.
return;
}
} else {
}
}
}
}
// We use a subclass of Logger for the root logger, so
// that we only instantiate the global handlers when they
// are first needed.
private RootLogger() {
super("", null);
}
// Make sure that the global handlers have been instantiated.
}
super.addHandler(h);
}
super.removeHandler(h);
}
return super.getHandlers();
}
}
// Private method to be called when the configuration has
// changed to apply any level settings to any pre-existing loggers.
synchronized private void setLevelsOnExistingLoggers() {
while (enum_.hasMoreElements()) {
// Not a level definition.
continue;
}
continue;
}
if (l == null) {
continue;
}
}
}
}
// Management Support
/**
* String representation of the
* {@link javax.management.ObjectName} for the management interface
* for the logging facility.
*
* @see java.lang.management.PlatformLoggingMXBean
* @see java.util.logging.LoggingMXBean
*
* @since 1.5
*/
= "java.util.logging:type=Logging";
/**
* Returns <tt>LoggingMXBean</tt> for managing loggers.
* An alternative way to manage loggers is through the
* {@link java.lang.management.PlatformLoggingMXBean} interface
* that can be obtained by calling:
* <pre>
* PlatformLoggingMXBean logging = {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
* ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class);
* </pre>
*
* @return a {@link LoggingMXBean} object.
*
* @see java.lang.management.PlatformLoggingMXBean
* @since 1.5
*/
if (loggingMXBean == null) {
loggingMXBean = new Logging();
}
return loggingMXBean;
}
}