blob: 7e5c9cd5a7932ff2e14c9e80a2b62aaf0d8cfca8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.util.logging;
// BEGIN android-note
// this file contains cleaned up documentation and style for contribution
// upstream
// END android-note
import org.apache.harmony.logging.internal.nls.Messages;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Loggers are used to log records to certain outputs, including file, console,
* etc. They use various handlers to actually do the output-dependent
* operations.
* <p>
* Client applications can get named loggers by calling the {@code getLogger}
* methods. They can also get anonymous loggers by calling the
* {@code getAnonymousLogger} methods. Named loggers are organized in a
* namespace hierarchy managed by a log manager. The naming convention is
* usually the same as java package's naming convention, that is using
* dot-separated strings. Anonymous loggers do not belong to any namespace.
* <p>
* Loggers "inherit" log level setting from their parent if their own level is
* set to {@code null}. This is also true for the resource bundle. The logger's
* resource bundle is used to localize the log messages if no resource bundle
* name is given when a log method is called. If {@code getUseParentHandlers()}
* returns {@code true}, loggers also inherit their parent's handlers. In this
* context, "inherit" only means that "behavior" is inherited. The internal
* field values will not change, for example, {@code getLevel()} still returns
* {@code null}.
* <p>
* When loading a given resource bundle, the logger first tries to use the
* context classloader. If that fails, it tries the system classloader. And if
* that still fails, it searches up the class stack and uses each class's
* classloader to try to locate the resource bundle.
* <p>
* Some log methods accept log requests that do not specify the source class and
* source method. In these cases, the logging framework will automatically infer
* the calling class and method, but this is not guaranteed to be accurate.
* <p>
* Once a {@code LogRecord} object has been passed into the logging framework,
* it is owned by the logging framework and the client applications should not
* use it any longer.
* <p>
* All methods of this class are thread-safe.
*
* @see LogManager
*/
public class Logger {
/** The global logger is provided as convenience for casual use. */
public final static Logger global = new Logger("global", null); //$NON-NLS-1$
/** The name of this logger. */
private volatile String name;
/** The parent logger of this logger. */
Logger parent;
/** The logging level of this logger, or null if none is set. */
volatile Level levelObjVal;
/**
* The effective logging level of this logger. In order of preference this
* is the first applicable of:
* <ol>
* <li>the int value of this logger's {@link #levelObjVal}
* <li>the logging level of the parent
* <li>the default level ({@link Level#INFO})
* </ol>
*/
volatile int levelIntVal = Level.INFO.intValue();
/** The filter. */
private Filter filter;
/**
* The resource bundle used to localize logging messages. If null, no
* localization will be performed.
*/
private String resBundleName;
/** The loaded resource bundle according to the specified name. */
private ResourceBundle resBundle;
/**
* The handlers attached to this logger. Lazily initialized in {@link
* #initHandlers()}.
*/
private List<Handler> handlers;
/** True to notify the parent's handlers of each log message. */
private boolean notifyParentHandlers = true;
/**
* Indicates whether this logger is named. Only {@link #getAnonymousLogger
* anonymous loggers} are unnamed.
*/
private boolean isNamed = true;
/**
* Child loggers. Should be accessed only while synchronized on {@code
* LogManager.getLogManager()}.
*/
final List<Logger> children = new ArrayList<Logger>();
private LogManager manager;
private volatile boolean handlerInited;
/**
* Constructs a {@code Logger} object with the supplied name and resource
* bundle name; {@code notifiyParentHandlers} is set to {@code true}.
* <p>
* Notice : Loggers use a naming hierarchy. Thus "z.x.y" is a child of "z.x".
*
* @param name
* the name of this logger, may be {@code null} for anonymous
* loggers.
* @param resourceBundleName
* the name of the resource bundle used to localize logging
* messages, may be {@code null}.
* @throws MissingResourceException
* if the specified resource bundle can not be loaded.
*/
protected Logger(String name, String resourceBundleName) {
// try to load the specified resource bundle first
if (resourceBundleName == null) {
this.resBundleName = null;
this.resBundle = null;
} else {
this.resBundle = loadResourceBundle(resourceBundleName);
this.resBundleName = resourceBundleName;
}
this.name = name;
}
/**
* Load the specified resource bundle, use privileged code.
*
* @param resourceBundleName
* the name of the resource bundle to load, cannot be {@code null}.
* @return the loaded resource bundle.
* @throws MissingResourceException
* if the specified resource bundle can not be loaded.
*/
static ResourceBundle loadResourceBundle(String resourceBundleName) {
// try context class loader to load the resource
ClassLoader cl = AccessController
.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
if (cl != null) {
try {
return ResourceBundle.getBundle(resourceBundleName, Locale
.getDefault(), cl);
} catch (MissingResourceException e) {
// Failed to load using context classloader, ignore
}
}
// try system class loader to load the resource
cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return ClassLoader.getSystemClassLoader();
}
});
if (cl != null) {
try {
return ResourceBundle.getBundle(resourceBundleName, Locale
.getDefault(), cl);
} catch (MissingResourceException e) {
// Failed to load using system classloader, ignore
}
}
// try all class loaders up the class stack
final Class<?>[] classes = AccessController
.doPrivileged(new PrivilegedAction<Class<?>[]>() {
public Class<?>[] run() {
return (new PrivateSecurityManager())
.privateGetClassContext();
}
});
// the first class, which is PrivateSecurityManager, is skipped
for (int i = 1; i < classes.length; i++) {
final int index = i;
try {
cl = AccessController
.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return classes[index].getClassLoader();
}
});
if (cl == null) {
continue;
}
return ResourceBundle.getBundle(resourceBundleName, Locale
.getDefault(), cl);
} catch (MissingResourceException e) {
// Failed to load using the current class's classloader, ignore
}
}
// logging.8=Failed to load the specified resource bundle "{0}".
throw new MissingResourceException(Messages.getString("logging.8", //$NON-NLS-1$
resourceBundleName), resourceBundleName, null);
}
/**
* Gets an anonymous logger to use internally in a thread. Anonymous loggers
* are not registered in the log manager's namespace. No security checks
* will be performed when updating an anonymous logger's control settings.
* <p>
* The anonymous loggers' parent is set to be the root logger. This way it
* inherits the default logging level and handlers from the root logger.
*
* @return a new instance of anonymous logger.
*/
public static Logger getAnonymousLogger() {
return getAnonymousLogger(null);
}
/**
* Gets an anonymous logger to use internally in a thread. Anonymous loggers
* are not registered in the log manager's namespace. No security checks
* will be performed when updating an anonymous logger's control settings.
* <p>
* The anonymous loggers' parent is set to be the root logger. This way it
* inherits default logging level and handlers from the root logger.
*
* @param resourceBundleName
* the name of the resource bundle used to localize log messages.
* @return a new instance of anonymous logger.
* @throws MissingResourceException
* if the specified resource bundle can not be loaded.
*/
public static Logger getAnonymousLogger(String resourceBundleName) {
Logger result = new Logger(null, resourceBundleName);
result.isNamed = false;
LogManager logManager = LogManager.getLogManager();
logManager.setParent(result, logManager.getLogger(""));
return result;
}
/**
* Initializes this logger's resource bundle.
*
* @throws IllegalArgumentException if this logger's resource bundle already
* exists and is different from the resource bundle specified.
*/
private synchronized void initResourceBundle(String resourceBundleName) {
String current = getResourceBundleName();
if (current != null) {
if (current.equals(resourceBundleName)) {
return;
} else {
// logging.9=The specified resource bundle name "{0}" is
// inconsistent with the existing one "{1}".
throw new IllegalArgumentException(Messages.getString(
"logging.9", //$NON-NLS-1$
resourceBundleName, current));
}
}
if (resourceBundleName != null) {
this.resBundle = loadResourceBundle(resourceBundleName);
this.resBundleName = resourceBundleName;
}
}
/**
* Gets a named logger. The returned logger may already exist or may be
* newly created. In the latter case, its level will be set to the
* configured level according to the {@code LogManager}'s properties.
*
* @param name
* the name of the logger to get, cannot be {@code null}.
* @return a named logger.
* @throws MissingResourceException
* If the specified resource bundle can not be loaded.
*/
public static Logger getLogger(String name) {
return LogManager.getLogManager().getOrCreate(name, null);
}
/**
* Gets a named logger associated with the supplied resource bundle. The
* resource bundle will be used to localize logging messages.
*
* @param name
* the name of the logger to get, cannot be {@code null}.
* @param resourceBundleName
* the name of the resource bundle, may be {@code null}.
* @throws IllegalArgumentException
* if the logger identified by {@code name} is associated with a
* resource bundle and its name is not equal to
* {@code resourceBundleName}.
* @throws MissingResourceException
* if the name of the resource bundle cannot be found.
* @return a named logger.
*/
public static Logger getLogger(String name, String resourceBundleName) {
Logger result = LogManager.getLogManager()
.getOrCreate(name, resourceBundleName);
result.initResourceBundle(resourceBundleName);
return result;
}
/**
* Adds a handler to this logger. The {@code name} will be fed with log
* records received by this logger.
*
* @param handler
* the handler object to add, cannot be {@code null}.
* @throws SecurityException
* if a security manager determines that the caller does not
* have the required permission.
*/
public void addHandler(Handler handler) {
if (handler == null) {
// logging.A=The 'handler' parameter is null.
throw new NullPointerException(Messages.getString("logging.A")); //$NON-NLS-1$
}
// Anonymous loggers can always add handlers
if (this.isNamed) {
LogManager.getLogManager().checkAccess();
}
initHandlers();
synchronized (this) {
this.handlers.add(handler);
}
}
/**
* Initializes this logger's handlers using the log manager's properties.
*/
@SuppressWarnings("nls")
private void initHandlers() {
if (handlerInited) {
return;
}
synchronized (this) {
if (handlerInited) {
return;
}
/*
* Force LogManager to be initialized, since its
* class init code performs necessary one-time setup.
*/
LogManager.getLogManager();
if (handlers == null) {
handlers = new ArrayList<Handler>();
}
if (manager == null) {
return;
}
String handlerStr = manager.getProperty(
"".equals(name) ? "handlers" : name + ".handlers");
if (handlerStr == null) {
return;
}
for (String handlerName : handlerStr.split(",|\\s")) {
if (handlerName.equals("")) {
continue;
}
// deal with non-existing handler
try {
Handler handler = (Handler) LogManager
.getInstanceByClass(handlerName);
handlers.add(handler);
String level = manager.getProperty(handlerName + ".level");
if (level != null) {
handler.setLevel(Level.parse(level));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
handlerInited = true;
}
}
/**
* Gets all the handlers associated with this logger.
*
* @return an array of all the handlers associated with this logger.
*/
public Handler[] getHandlers() {
initHandlers();
synchronized (this) {
return handlers.toArray(new Handler[handlers.size()]);
}
}
/**
* Removes a handler from this logger. If the specified handler does not
* exist then this method has no effect.
*
* @param handler
* the handler to be removed.
* @throws SecurityException
* if a security manager determines that the caller does not
* have the required permission.
*/
public void removeHandler(Handler handler) {
// Anonymous loggers can always remove handlers
if (this.isNamed) {
LogManager.getLogManager().checkAccess();
}
if (handler == null) {
return;
}
initHandlers();
synchronized (this) {
this.handlers.remove(handler);
}
}
/**
* Gets the filter used by this logger.
*
* @return the filter used by this logger, may be {@code null}.
*/
public Filter getFilter() {
return this.filter;
}
/**
* Sets the filter used by this logger.
*
* @param newFilter
* the filter to set, may be {@code null}.
* @throws SecurityException
* if a security manager determines that the caller does not
* have the required permission.
*/
public void setFilter(Filter newFilter) {
// Anonymous loggers can always set the filter
if (this.isNamed) {
LogManager.getLogManager().checkAccess();
}
filter = newFilter;
}
/**
* Gets the logging level of this logger. A {@code null} level indicates
* that this logger inherits its parent's level.
*
* @return the logging level of this logger.
*/
public Level getLevel() {
return levelObjVal;
}
/**
* Sets the logging level for this logger. A {@code null} level indicates
* that this logger will inherit its parent's level.
*
* <p>This method synchronizes on the global log manager, so it is an
* error to call this method while synchronized on any logger.
*
* @param newLevel
* the logging level to set.
* @throws SecurityException
* if a security manager determines that the caller does not
* have the required permission.
*/
public void setLevel(Level newLevel) {
// Anonymous loggers can always set the level
LogManager logManager = LogManager.getLogManager();
if (this.isNamed) {
logManager.checkAccess();
}
logManager.setLevelRecursively(this, newLevel);
}
/**
* Gets the flag which indicates whether to use the handlers of this
* logger's parent to publish incoming log records, potentially recursively
* up the namespace.
*
* @return {@code true} if set to use parent's handlers, {@code false}
* otherwise.
*/
public boolean getUseParentHandlers() {
return this.notifyParentHandlers;
}
/**
* Sets the flag which indicates whether to use the handlers of this
* logger's parent, potentially recursively up the namespace.
*
* @param notifyParentHandlers
* the new flag indicating whether to use the parent's handlers.
* @throws SecurityException
* if a security manager determines that the caller does not
* have the required permission.
*/
public void setUseParentHandlers(boolean notifyParentHandlers) {
// Anonymous loggers can always set the useParentHandlers flag
if (this.isNamed) {
LogManager.getLogManager().checkAccess();
}
this.notifyParentHandlers = notifyParentHandlers;
}
/**
* Gets the nearest parent of this logger in the namespace, a {@code null}
* value will be returned if called on the root logger.
*
* @return the parent of this logger in the namespace.
*/
public Logger getParent() {
return parent;
}
/**
* Sets the parent of this logger in the namespace. This method should be
* used by the {@code LogManager} object only.
*
* @param parent
* the parent logger to set.
* @throws SecurityException
* if a security manager determines that the caller does not
* have the required permission.
*/
public void setParent(Logger parent) {
if (parent == null) {
// logging.B=The 'parent' parameter is null.
throw new NullPointerException(Messages.getString("logging.B")); //$NON-NLS-1$
}
// even anonymous loggers are checked
LogManager logManager = LogManager.getLogManager();
logManager.checkAccess();
logManager.setParent(this, parent);
}
/**
* Gets the name of this logger, {@code null} for anonymous loggers.
*
* @return the name of this logger.
*/
public String getName() {
return this.name;
}
/**
* Gets the loaded resource bundle used by this logger to localize logging
* messages. If the value is {@code null}, the parent's resource bundle will be
* inherited.
*
* @return the loaded resource bundle used by this logger.
*/
public ResourceBundle getResourceBundle() {
return this.resBundle;
}
/**
* Gets the name of the loaded resource bundle used by this logger to
* localize logging messages. If the value is {@code null}, the parent's resource
* bundle name will be inherited.
*
* @return the name of the loaded resource bundle used by this logger.
*/
public String getResourceBundleName() {
return this.resBundleName;
}
/**
* This method is for compatibility. Tests written to the reference
* implementation API imply that the isLoggable() method is not called
* directly. This behavior is important because subclass may override
* isLoggable() method, so that affect the result of log methods.
*/
private boolean internalIsLoggable(Level l) {
int effectiveLevel = levelIntVal;
if (effectiveLevel == Level.OFF.intValue()) {
// always return false if the effective level is off
return false;
}
return l.intValue() >= effectiveLevel;
}
/**
* Determines whether this logger will actually log messages of the
* specified level. The effective level used to do the determination may be
* inherited from its parent. The default level is {@code Level.INFO}.
*
* @param l
* the level to check.
* @return {@code true} if this logger will actually log this level,
* otherwise {@code false}.
*/
public boolean isLoggable(Level l) {
return internalIsLoggable(l);
}
/*
* Sets the resource bundle and its name for a supplied LogRecord object.
* This method first tries to use this logger's resource bundle if any,
* otherwise try to inherit from this logger's parent, recursively up the
* namespace. Synchronize to ensure the consistency between resource bundle
* and its name.
*/
private void setResourceBundle(LogRecord record) {
if (this.resBundleName != null) {
record.setResourceBundle(this.resBundle);
record.setResourceBundleName(this.resBundleName);
} else {
Logger anyParent = this.parent;
// no need to synchronize here, because if resBundleName
// is not null, there is no chance to modify it
while (anyParent != null) {
if (anyParent.resBundleName != null) {
record.setResourceBundle(anyParent.resBundle);
record.setResourceBundleName(anyParent.resBundleName);
return;
}
anyParent = anyParent.parent;
}
}
}
/**
* Logs a message indicating that a method has been entered. A log record
* with log level {@code Level.FINER}, log message "ENTRY", the specified
* source class name and source method name is submitted for logging.
*
* @param sourceClass
* the calling class name.
* @param sourceMethod
* the method name.
*/
public void entering(String sourceClass, String sourceMethod) {
if (!internalIsLoggable(Level.FINER)) {
return;
}
LogRecord record = new LogRecord(Level.FINER, "ENTRY"); //$NON-NLS-1$
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
setResourceBundle(record);
log(record);
}
/**
* Logs a message indicating that a method has been entered. A log record
* with log level {@code Level.FINER}, log message "ENTRY", the specified
* source class name, source method name and one parameter is submitted for
* logging.
*
* @param sourceClass
* the source class name.
* @param sourceMethod
* the source method name.
* @param param
* the parameter for the method call.
*/
public void entering(String sourceClass, String sourceMethod, Object param) {
if (!internalIsLoggable(Level.FINER)) {
return;
}
LogRecord record = new LogRecord(Level.FINER, "ENTRY" + " {0}"); //$NON-NLS-1$ //$NON-NLS-2$
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
record.setParameters(new Object[] { param });
setResourceBundle(record);
log(record);
}
/**
* Logs a message indicating that a method has been entered. A log record
* with log level {@code Level.FINER}, log message "ENTRY", the specified
* source class name, source method name and array of parameters is
* submitted for logging.
*
* @param sourceClass
* the source class name.
* @param sourceMethod
* the source method name.
* @param params
* an array of parameters for the method call.
*/
@SuppressWarnings("nls")
public void entering(String sourceClass, String sourceMethod,
Object[] params) {
if (!internalIsLoggable(Level.FINER)) {
return;
}
String msg = "ENTRY";
if (params != null) {
StringBuilder msgBuffer = new StringBuilder("ENTRY");
for (int i = 0; i < params.length; i++) {
msgBuffer.append(" {").append(i).append("}");
}
msg = msgBuffer.toString();
}
LogRecord record = new LogRecord(Level.FINER, msg);
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
record.setParameters(params);
setResourceBundle(record);
log(record);
}
/**
* Logs a message indicating that a method is exited. A log record with log
* level {@code Level.FINER}, log message "RETURN", the specified source
* class name and source method name is submitted for logging.
*
* @param sourceClass
* the calling class name.
* @param sourceMethod
* the method name.
*/
public void exiting(String sourceClass, String sourceMethod) {
if (!internalIsLoggable(Level.FINER)) {
return;
}
LogRecord record = new LogRecord(Level.FINER, "RETURN"); //$NON-NLS-1$
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
setResourceBundle(record);
log(record);
}
/**
* Logs a message indicating that a method is exited. A log record with log
* level {@code Level.FINER}, log message "RETURN", the specified source
* class name, source method name and return value is submitted for logging.
*
* @param sourceClass
* the source class name.
* @param sourceMethod
* the source method name.
* @param result
* the return value of the method call.
*/
public void exiting(String sourceClass, String sourceMethod, Object result) {
if (!internalIsLoggable(Level.FINER)) {
return;
}
LogRecord record = new LogRecord(Level.FINER, "RETURN" + " {0}"); //$NON-NLS-1$ //$NON-NLS-2$
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
record.setParameters(new Object[] { result });
setResourceBundle(record);
log(record);
}
/**
* Logs a message indicating that an exception is thrown. A log record with
* log level {@code Level.FINER}, log message "THROW", the specified source
* class name, source method name and the {@code Throwable} object is
* submitted for logging.
*
* @param sourceClass
* the source class name.
* @param sourceMethod
* the source method name.
* @param thrown
* the {@code Throwable} object.
*/
public void throwing(String sourceClass, String sourceMethod,
Throwable thrown) {
if (!internalIsLoggable(Level.FINER)) {
return;
}
LogRecord record = new LogRecord(Level.FINER, "THROW"); //$NON-NLS-1$
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
record.setThrown(thrown);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of level {@code Level.SEVERE}; the message is transmitted
* to all subscribed handlers.
*
* @param msg
* the message to log.
*/
public void severe(String msg) {
if (!internalIsLoggable(Level.SEVERE)) {
return;
}
LogRecord record = new LogRecord(Level.SEVERE, msg);
record.setLoggerName(this.name);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of level {@code Level.WARNING}; the message is
* transmitted to all subscribed handlers.
*
* @param msg
* the message to log.
*/
public void warning(String msg) {
if (!internalIsLoggable(Level.WARNING)) {
return;
}
LogRecord record = new LogRecord(Level.WARNING, msg);
record.setLoggerName(this.name);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of level {@code Level.INFO}; the message is transmitted
* to all subscribed handlers.
*
* @param msg
* the message to log.
*/
public void info(String msg) {
if (!internalIsLoggable(Level.INFO)) {
return;
}
LogRecord record = new LogRecord(Level.INFO, msg);
record.setLoggerName(this.name);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of level {@code Level.CONFIG}; the message is transmitted
* to all subscribed handlers.
*
* @param msg
* the message to log.
*/
public void config(String msg) {
if (!internalIsLoggable(Level.CONFIG)) {
return;
}
LogRecord record = new LogRecord(Level.CONFIG, msg);
record.setLoggerName(this.name);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of level {@code Level.FINE}; the message is transmitted
* to all subscribed handlers.
*
* @param msg
* the message to log.
*/
public void fine(String msg) {
if (!internalIsLoggable(Level.FINE)) {
return;
}
LogRecord record = new LogRecord(Level.FINE, msg);
record.setLoggerName(this.name);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of level {@code Level.FINER}; the message is transmitted
* to all subscribed handlers.
*
* @param msg
* the message to log.
*/
public void finer(String msg) {
if (!internalIsLoggable(Level.FINER)) {
return;
}
LogRecord record = new LogRecord(Level.FINER, msg);
record.setLoggerName(this.name);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of level {@code Level.FINEST}; the message is transmitted
* to all subscribed handlers.
*
* @param msg
* the message to log.
*/
public void finest(String msg) {
if (!internalIsLoggable(Level.FINEST)) {
return;
}
LogRecord record = new LogRecord(Level.FINEST, msg);
record.setLoggerName(this.name);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of the specified level. The message is transmitted to all
* subscribed handlers.
*
* @param logLevel
* the level of the specified message.
* @param msg
* the message to log.
*/
public void log(Level logLevel, String msg) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
record.setLoggerName(this.name);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of the specified level with the supplied parameter. The
* message is then transmitted to all subscribed handlers.
*
* @param logLevel
* the level of the given message.
* @param msg
* the message to log.
* @param param
* the parameter associated with the event that is logged.
*/
public void log(Level logLevel, String msg, Object param) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
record.setLoggerName(this.name);
record.setParameters(new Object[] { param });
setResourceBundle(record);
log(record);
}
/**
* Logs a message of the specified level with the supplied parameter array.
* The message is then transmitted to all subscribed handlers.
*
* @param logLevel
* the level of the given message
* @param msg
* the message to log.
* @param params
* the parameter array associated with the event that is logged.
*/
public void log(Level logLevel, String msg, Object[] params) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
record.setLoggerName(this.name);
record.setParameters(params);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of the specified level with the supplied {@code Throwable}
* object. The message is then transmitted to all subscribed handlers.
*
* @param logLevel
* the level of the given message.
* @param msg
* the message to log.
* @param thrown
* the {@code Throwable} object associated with the event that is
* logged.
*/
public void log(Level logLevel, String msg, Throwable thrown) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
record.setLoggerName(this.name);
record.setThrown(thrown);
setResourceBundle(record);
log(record);
}
/**
* Logs a given log record. Only records with a logging level that is equal
* or greater than this logger's level will be submitted to this logger's
* handlers for logging. If {@code getUseParentHandlers()} returns {@code
* true}, the log record will also be submitted to the handlers of this
* logger's parent, potentially recursively up the namespace.
* <p>
* Since all other log methods call this method to actually perform the
* logging action, subclasses of this class can override this method to
* catch all logging activities.
* </p>
*
* @param record
* the log record to be logged.
*/
public void log(LogRecord record) {
if (!internalIsLoggable(record.getLevel())) {
return;
}
// apply the filter if any
Filter f = filter;
if (f != null && !f.isLoggable(record)) {
return;
}
initHandlers();
/*
* call the handlers of this logger, throw any exception that occurs
*/
Handler[] allHandlers = getHandlers();
for (Handler element : allHandlers) {
element.publish(record);
}
// call the parent's handlers if set useParentHandlers
Logger temp = this;
Logger theParent = temp.parent;
while (theParent != null && temp.getUseParentHandlers()) {
Handler[] ha = theParent.getHandlers();
for (Handler element : ha) {
element.publish(record);
}
temp = theParent;
theParent = temp.parent;
}
}
/**
* Logs a message of the given level with the specified source class name
* and source method name.
*
* @param logLevel
* the level of the given message.
* @param sourceClass
* the source class name.
* @param sourceMethod
* the source method name.
* @param msg
* the message to be logged.
*/
public void logp(Level logLevel, String sourceClass, String sourceMethod,
String msg) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of the given level with the specified source class name,
* source method name and parameter.
*
* @param logLevel
* the level of the given message
* @param sourceClass
* the source class name
* @param sourceMethod
* the source method name
* @param msg
* the message to be logged
* @param param
* the parameter associated with the event that is logged.
*/
public void logp(Level logLevel, String sourceClass, String sourceMethod,
String msg, Object param) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
record.setParameters(new Object[] { param });
setResourceBundle(record);
log(record);
}
/**
* Logs a message of the given level with the specified source class name,
* source method name and parameter array.
*
* @param logLevel
* the level of the given message.
* @param sourceClass
* the source class name.
* @param sourceMethod
* the source method name.
* @param msg
* the message to be logged.
* @param params
* the parameter array associated with the event that is logged.
*/
public void logp(Level logLevel, String sourceClass, String sourceMethod,
String msg, Object[] params) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
record.setParameters(params);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of the given level with the specified source class name,
* source method name and {@code Throwable} object.
*
* @param logLevel
* the level of the given message.
* @param sourceClass
* the source class name.
* @param sourceMethod
* the source method name.
* @param msg
* the message to be logged.
* @param thrown
* the {@code Throwable} object.
*/
public void logp(Level logLevel, String sourceClass, String sourceMethod,
String msg, Throwable thrown) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
record.setThrown(thrown);
setResourceBundle(record);
log(record);
}
/**
* Logs a message of the given level with the specified source class name
* and source method name, using the given resource bundle to localize the
* message. If {@code bundleName} is null, the empty string or not valid then
* the message is not localized.
*
* @param logLevel
* the level of the given message.
* @param sourceClass
* the source class name.
* @param sourceMethod
* the source method name.
* @param bundleName
* the name of the resource bundle used to localize the message.
* @param msg
* the message to be logged.
*/
public void logrb(Level logLevel, String sourceClass, String sourceMethod,
String bundleName, String msg) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
if (bundleName != null) {
try {
record.setResourceBundle(loadResourceBundle(bundleName));
} catch (MissingResourceException e) {
// ignore
}
record.setResourceBundleName(bundleName);
}
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
log(record);
}
/**
* Logs a message of the given level with the specified source class name,
* source method name and parameter, using the given resource bundle to
* localize the message. If {@code bundleName} is null, the empty string
* or not valid then the message is not localized.
*
* @param logLevel
* the level of the given message.
* @param sourceClass
* the source class name.
* @param sourceMethod
* the source method name.
* @param bundleName
* the name of the resource bundle used to localize the message.
* @param msg
* the message to be logged.
* @param param
* the parameter associated with the event that is logged.
*/
public void logrb(Level logLevel, String sourceClass, String sourceMethod,
String bundleName, String msg, Object param) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
if (bundleName != null) {
try {
record.setResourceBundle(loadResourceBundle(bundleName));
} catch (MissingResourceException e) {
// ignore
}
record.setResourceBundleName(bundleName);
}
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
record.setParameters(new Object[] { param });
log(record);
}
/**
* Logs a message of the given level with the specified source class name,
* source method name and parameter array, using the given resource bundle
* to localize the message. If {@code bundleName} is null, the empty string
* or not valid then the message is not localized.
*
* @param logLevel
* the level of the given message.
* @param sourceClass
* the source class name.
* @param sourceMethod
* the source method name.
* @param bundleName
* the name of the resource bundle used to localize the message.
* @param msg
* the message to be logged.
* @param params
* the parameter array associated with the event that is logged.
*/
public void logrb(Level logLevel, String sourceClass, String sourceMethod,
String bundleName, String msg, Object[] params) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
if (bundleName != null) {
try {
record.setResourceBundle(loadResourceBundle(bundleName));
} catch (MissingResourceException e) {
// ignore
}
record.setResourceBundleName(bundleName);
}
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
record.setParameters(params);
log(record);
}
/**
* Logs a message of the given level with the specified source class name,
* source method name and {@code Throwable} object, using the given resource
* bundle to localize the message. If {@code bundleName} is null, the empty
* string or not valid then the message is not localized.
*
* @param logLevel
* the level of the given message
* @param sourceClass
* the source class name
* @param sourceMethod
* the source method name
* @param bundleName
* the name of the resource bundle used to localize the message.
* @param msg
* the message to be logged.
* @param thrown
* the {@code Throwable} object.
*/
public void logrb(Level logLevel, String sourceClass, String sourceMethod,
String bundleName, String msg, Throwable thrown) {
if (!internalIsLoggable(logLevel)) {
return;
}
LogRecord record = new LogRecord(logLevel, msg);
if (bundleName != null) {
try {
record.setResourceBundle(loadResourceBundle(bundleName));
} catch (MissingResourceException e) {
// ignore
}
record.setResourceBundleName(bundleName);
}
record.setLoggerName(this.name);
record.setSourceClassName(sourceClass);
record.setSourceMethodName(sourceMethod);
record.setThrown(thrown);
log(record);
}
/*
* This security manager is used to access the class context.
*/
static class PrivateSecurityManager extends SecurityManager {
public Class<?>[] privateGetClassContext() {
return super.getClassContext();
}
}
void setManager(LogManager manager) {
if (this.manager != manager) {
this.manager = manager;
handlerInited = false;
}
// init level here, but let handlers be for lazy loading
final String configuredLevel = manager.getProperty(name + ".level"); //$NON-NLS-1$
if (configuredLevel != null) {
try {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
setLevel(Level.parse(configuredLevel));
return null;
}
});
} catch (IllegalArgumentException e) {
// ignore
}
}
}
synchronized void reset() {
levelObjVal = null;
levelIntVal = Level.INFO.intValue();
if (handlers != null) {
for (Handler element : handlers) {
// close all handlers, when unknown exceptions happen,
// ignore them and go on
try {
element.close();
} catch (Exception e) {
// Ignored.
}
}
handlers.clear();
}
handlerInited = false;
}
}