| /* Logger.java -- a class for logging messages | |
| Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. | |
| This file is part of GNU Classpath. | |
| GNU Classpath is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2, or (at your option) | |
| any later version. | |
| GNU Classpath 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 for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with GNU Classpath; see the file COPYING. If not, write to the | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 02110-1301 USA. | |
| Linking this library statically or dynamically with other modules is | |
| making a combined work based on this library. Thus, the terms and | |
| conditions of the GNU General Public License cover the whole | |
| combination. | |
| As a special exception, the copyright holders of this library give you | |
| permission to link this library with independent modules to produce an | |
| executable, regardless of the license terms of these independent | |
| modules, and to copy and distribute the resulting executable under | |
| terms of your choice, provided that you also meet, for each linked | |
| independent module, the terms and conditions of the license of that | |
| module. An independent module is a module which is not derived from | |
| or based on this library. If you modify this library, you may extend | |
| this exception to your version of the library, but you are not | |
| obligated to do so. If you do not wish to do so, delete this | |
| exception statement from your version. */ | |
| package java.util.logging; | |
| import java.util.List; | |
| import java.util.MissingResourceException; | |
| import java.util.ResourceBundle; | |
| import java.security.AccessController; | |
| import java.security.PrivilegedAction; | |
| /** | |
| * A Logger is used for logging information about events. Usually, there | |
| * is a seprate logger for each subsystem or component, although there | |
| * is a shared instance for components that make only occasional use of | |
| * the logging framework. | |
| * | |
| * <p>It is common to name a logger after the name of a corresponding | |
| * Java package. Loggers are organized into a hierarchical namespace; | |
| * for example, the logger <code>"org.gnu.foo"</code> is the | |
| * <em>parent</em> of logger <code>"org.gnu.foo.bar"</code>. | |
| * | |
| * <p>A logger for a named subsystem can be obtained through {@link | |
| * java.util.logging.Logger#getLogger(java.lang.String)}. However, | |
| * only code which has been granted the permission to control the | |
| * logging infrastructure will be allowed to customize that logger. | |
| * Untrusted code can obtain a private, anonymous logger through | |
| * {@link #getAnonymousLogger()} if it wants to perform any | |
| * modifications to the logger. | |
| * | |
| * <p>FIXME: Write more documentation. | |
| * | |
| * @author Sascha Brawer (brawer@acm.org) | |
| */ | |
| public class Logger | |
| { | |
| static final Logger root = new Logger("", null); | |
| /** | |
| * A logger provided to applications that make only occasional use | |
| * of the logging framework, typically early prototypes. Serious | |
| * products are supposed to create and use their own Loggers, so | |
| * they can be controlled individually. | |
| */ | |
| public static final Logger global; | |
| static | |
| { | |
| // Our class might be initialized from an unprivileged context | |
| global = (Logger) AccessController.doPrivileged | |
| (new PrivilegedAction() | |
| { | |
| public Object run() | |
| { | |
| return getLogger("global"); | |
| } | |
| }); | |
| } | |
| /** | |
| * The name of the Logger, or <code>null</code> if the logger is | |
| * anonymous. | |
| * | |
| * <p>A previous version of the GNU Classpath implementation granted | |
| * untrusted code the permission to control any logger whose name | |
| * was null. However, test code revealed that the Sun J2SE 1.4 | |
| * reference implementation enforces the security control for any | |
| * logger that was not created through getAnonymousLogger, even if | |
| * it has a null name. Therefore, a separate flag {@link | |
| * Logger#anonymous} was introduced. | |
| */ | |
| private final String name; | |
| /** | |
| * The name of the resource bundle used for localization. | |
| * | |
| * <p>This variable cannot be declared as <code>final</code> | |
| * because its value can change as a result of calling | |
| * getLogger(String,String). | |
| */ | |
| private String resourceBundleName; | |
| /** | |
| * The resource bundle used for localization. | |
| * | |
| * <p>This variable cannot be declared as <code>final</code> | |
| * because its value can change as a result of calling | |
| * getLogger(String,String). | |
| */ | |
| private ResourceBundle resourceBundle; | |
| private Filter filter; | |
| private final List handlerList = new java.util.ArrayList(4); | |
| private Handler[] handlers = new Handler[0]; | |
| /** | |
| * Indicates whether or not this logger is anonymous. While | |
| * a LoggingPermission is required for any modifications to | |
| * a normal logger, untrusted code can obtain an anonymous logger | |
| * and modify it according to its needs. | |
| * | |
| * <p>A previous version of the GNU Classpath implementation | |
| * granted access to every logger whose name was null. | |
| * However, test code revealed that the Sun J2SE 1.4 reference | |
| * implementation enforces the security control for any logger | |
| * that was not created through getAnonymousLogger, even | |
| * if it has a null name. | |
| */ | |
| private boolean anonymous; | |
| private boolean useParentHandlers; | |
| private Level level; | |
| private Logger parent; | |
| /** | |
| * Constructs a Logger for a subsystem. Most applications do not | |
| * need to create new Loggers explicitly; instead, they should call | |
| * the static factory methods | |
| * {@link #getLogger(java.lang.String,java.lang.String) getLogger} | |
| * (with ResourceBundle for localization) or | |
| * {@link #getLogger(java.lang.String) getLogger} (without | |
| * ResourceBundle), respectively. | |
| * | |
| * @param name the name for the logger, for example "java.awt" | |
| * or "com.foo.bar". The name should be based on | |
| * the name of the package issuing log records | |
| * and consist of dot-separated Java identifiers. | |
| * | |
| * @param resourceBundleName the name of a resource bundle | |
| * for localizing messages, or <code>null</code> | |
| * to indicate that messages do not need to be localized. | |
| * | |
| * @throws java.util.MissingResourceException if | |
| * <code>resourceBundleName</code> is not <code>null</code> | |
| * and no such bundle could be located. | |
| */ | |
| protected Logger(String name, String resourceBundleName) | |
| throws MissingResourceException | |
| { | |
| this.name = name; | |
| this.resourceBundleName = resourceBundleName; | |
| if (resourceBundleName == null) | |
| resourceBundle = null; | |
| else | |
| resourceBundle = ResourceBundle.getBundle(resourceBundleName); | |
| level = null; | |
| /* This is null when the root logger is being constructed, | |
| * and the root logger afterwards. | |
| */ | |
| parent = root; | |
| useParentHandlers = (parent != null); | |
| } | |
| /** | |
| * Finds a registered logger for a subsystem, or creates one in | |
| * case no logger has been registered yet. | |
| * | |
| * @param name the name for the logger, for example "java.awt" | |
| * or "com.foo.bar". The name should be based on | |
| * the name of the package issuing log records | |
| * and consist of dot-separated Java identifiers. | |
| * | |
| * @throws IllegalArgumentException if a logger for the subsystem | |
| * identified by <code>name</code> has already been created, | |
| * but uses a a resource bundle for localizing messages. | |
| * | |
| * @throws NullPointerException if <code>name</code> is | |
| * <code>null</code>. | |
| * | |
| * @return a logger for the subsystem specified by <code>name</code> | |
| * that does not localize messages. | |
| */ | |
| public static Logger getLogger(String name) | |
| { | |
| return getLogger(name, null); | |
| } | |
| /** | |
| * Finds a registered logger for a subsystem, or creates one in case | |
| * no logger has been registered yet. | |
| * | |
| * <p>If a logger with the specified name has already been | |
| * registered, the behavior depends on the resource bundle that is | |
| * currently associated with the existing logger. | |
| * | |
| * <ul><li>If the existing logger uses the same resource bundle as | |
| * specified by <code>resourceBundleName</code>, the existing logger | |
| * is returned.</li> | |
| * | |
| * <li>If the existing logger currently does not localize messages, | |
| * the existing logger is modified to use the bundle specified by | |
| * <code>resourceBundleName</code>. The existing logger is then | |
| * returned. Therefore, all subsystems currently using this logger | |
| * will produce localized messages from now on.</li> | |
| * | |
| * <li>If the existing logger already has an associated resource | |
| * bundle, but a different one than specified by | |
| * <code>resourceBundleName</code>, an | |
| * <code>IllegalArgumentException</code> is thrown.</li></ul> | |
| * | |
| * @param name the name for the logger, for example "java.awt" | |
| * or "org.gnu.foo". The name should be based on | |
| * the name of the package issuing log records | |
| * and consist of dot-separated Java identifiers. | |
| * | |
| * @param resourceBundleName the name of a resource bundle | |
| * for localizing messages, or <code>null</code> | |
| * to indicate that messages do not need to be localized. | |
| * | |
| * @return a logger for the subsystem specified by <code>name</code>. | |
| * | |
| * @throws java.util.MissingResourceException if | |
| * <code>resourceBundleName</code> is not <code>null</code> | |
| * and no such bundle could be located. | |
| * | |
| * @throws IllegalArgumentException if a logger for the subsystem | |
| * identified by <code>name</code> has already been created, | |
| * but uses a different resource bundle for localizing | |
| * messages. | |
| * | |
| * @throws NullPointerException if <code>name</code> is | |
| * <code>null</code>. | |
| */ | |
| public static Logger getLogger(String name, String resourceBundleName) | |
| { | |
| LogManager lm = LogManager.getLogManager(); | |
| Logger result; | |
| /* Throw NullPointerException if name is null. */ | |
| name.getClass(); | |
| /* Without synchronized(lm), it could happen that another thread | |
| * would create a logger between our calls to getLogger and | |
| * addLogger. While addLogger would indicate this by returning | |
| * false, we could not be sure that this other logger was still | |
| * existing when we called getLogger a second time in order | |
| * to retrieve it -- note that LogManager is only allowed to | |
| * keep weak references to registered loggers, so Loggers | |
| * can be garbage collected at any time in general, and between | |
| * our call to addLogger and our second call go getLogger | |
| * in particular. | |
| * | |
| * Of course, we assume here that LogManager.addLogger etc. | |
| * are synchronizing on the global LogManager object. There | |
| * is a comment in the implementation of LogManager.addLogger | |
| * referring to this comment here, so that any change in | |
| * the synchronization of LogManager will be reflected here. | |
| */ | |
| synchronized (lm) | |
| { | |
| result = lm.getLogger(name); | |
| if (result == null) | |
| { | |
| boolean couldBeAdded; | |
| result = new Logger(name, resourceBundleName); | |
| couldBeAdded = lm.addLogger(result); | |
| if (!couldBeAdded) | |
| throw new IllegalStateException("cannot register new logger"); | |
| } | |
| else | |
| { | |
| /* The logger already exists. Make sure it uses | |
| * the same resource bundle for localizing messages. | |
| */ | |
| String existingBundleName = result.getResourceBundleName(); | |
| /* The Sun J2SE 1.4 reference implementation will return the | |
| * registered logger object, even if it does not have a resource | |
| * bundle associated with it. However, it seems to change the | |
| * resourceBundle of the registered logger to the bundle | |
| * whose name was passed to getLogger. | |
| */ | |
| if ((existingBundleName == null) && (resourceBundleName != null)) | |
| { | |
| /* If ResourceBundle.getBundle throws an exception, the | |
| * existing logger will be unchanged. This would be | |
| * different if the assignment to resourceBundleName | |
| * came first. | |
| */ | |
| result.resourceBundle = ResourceBundle.getBundle(resourceBundleName); | |
| result.resourceBundleName = resourceBundleName; | |
| return result; | |
| } | |
| if ((existingBundleName != resourceBundleName) | |
| && ((existingBundleName == null) | |
| || !existingBundleName.equals(resourceBundleName))) | |
| { | |
| throw new IllegalArgumentException(); | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| /** | |
| * Creates a new, unnamed logger. Unnamed loggers are not | |
| * registered in the namespace of the LogManager, and no special | |
| * security permission is required for changing their state. | |
| * Therefore, untrusted applets are able to modify their private | |
| * logger instance obtained through this method. | |
| * | |
| * <p>The parent of the newly created logger will the the root | |
| * logger, from which the level threshold and the handlers are | |
| * inherited. | |
| */ | |
| public static Logger getAnonymousLogger() | |
| { | |
| return getAnonymousLogger(null); | |
| } | |
| /** | |
| * Creates a new, unnamed logger. Unnamed loggers are not | |
| * registered in the namespace of the LogManager, and no special | |
| * security permission is required for changing their state. | |
| * Therefore, untrusted applets are able to modify their private | |
| * logger instance obtained through this method. | |
| * | |
| * <p>The parent of the newly created logger will the the root | |
| * logger, from which the level threshold and the handlers are | |
| * inherited. | |
| * | |
| * @param resourceBundleName the name of a resource bundle | |
| * for localizing messages, or <code>null</code> | |
| * to indicate that messages do not need to be localized. | |
| * | |
| * @throws java.util.MissingResourceException if | |
| * <code>resourceBundleName</code> is not <code>null</code> | |
| * and no such bundle could be located. | |
| */ | |
| public static Logger getAnonymousLogger(String resourceBundleName) | |
| throws MissingResourceException | |
| { | |
| Logger result; | |
| result = new Logger(null, resourceBundleName); | |
| result.anonymous = true; | |
| return result; | |
| } | |
| /** | |
| * Returns the name of the resource bundle that is being used for | |
| * localizing messages. | |
| * | |
| * @return the name of the resource bundle used for localizing messages, | |
| * or <code>null</code> if the parent's resource bundle | |
| * is used for this purpose. | |
| */ | |
| public synchronized String getResourceBundleName() | |
| { | |
| return resourceBundleName; | |
| } | |
| /** | |
| * Returns the resource bundle that is being used for localizing | |
| * messages. | |
| * | |
| * @return the resource bundle used for localizing messages, | |
| * or <code>null</code> if the parent's resource bundle | |
| * is used for this purpose. | |
| */ | |
| public synchronized ResourceBundle getResourceBundle() | |
| { | |
| return resourceBundle; | |
| } | |
| /** | |
| * Returns the severity level threshold for this <code>Handler</code>. | |
| * All log records with a lower severity level will be discarded; | |
| * a log record of the same or a higher level will be published | |
| * unless an installed <code>Filter</code> decides to discard it. | |
| * | |
| * @return the severity level below which all log messages will be | |
| * discarded, or <code>null</code> if the logger inherits | |
| * the threshold from its parent. | |
| */ | |
| public synchronized Level getLevel() | |
| { | |
| return level; | |
| } | |
| /** | |
| * Returns whether or not a message of the specified level | |
| * would be logged by this logger. | |
| * | |
| * @throws NullPointerException if <code>level</code> | |
| * is <code>null</code>. | |
| */ | |
| public synchronized boolean isLoggable(Level level) | |
| { | |
| if (this.level != null) | |
| return this.level.intValue() <= level.intValue(); | |
| if (parent != null) | |
| return parent.isLoggable(level); | |
| else | |
| return false; | |
| } | |
| /** | |
| * Sets the severity level threshold for this <code>Handler</code>. | |
| * All log records with a lower severity level will be discarded | |
| * immediately. A log record of the same or a higher level will be | |
| * published unless an installed <code>Filter</code> decides to | |
| * discard it. | |
| * | |
| * @param level the severity level below which all log messages | |
| * will be discarded, or <code>null</code> to | |
| * indicate that the logger should inherit the | |
| * threshold from its parent. | |
| * | |
| * @throws SecurityException if this logger is not anonymous, a | |
| * security manager exists, and the caller is not granted | |
| * the permission to control the logging infrastructure by | |
| * having LoggingPermission("control"). Untrusted code can | |
| * obtain an anonymous logger through the static factory method | |
| * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. | |
| */ | |
| public synchronized void setLevel(Level level) | |
| { | |
| /* An application is allowed to control an anonymous logger | |
| * without having the permission to control the logging | |
| * infrastructure. | |
| */ | |
| if (!anonymous) | |
| LogManager.getLogManager().checkAccess(); | |
| this.level = level; | |
| } | |
| public synchronized Filter getFilter() | |
| { | |
| return filter; | |
| } | |
| /** | |
| * @throws SecurityException if this logger is not anonymous, a | |
| * security manager exists, and the caller is not granted | |
| * the permission to control the logging infrastructure by | |
| * having LoggingPermission("control"). Untrusted code can | |
| * obtain an anonymous logger through the static factory method | |
| * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. | |
| */ | |
| public synchronized void setFilter(Filter filter) | |
| throws SecurityException | |
| { | |
| /* An application is allowed to control an anonymous logger | |
| * without having the permission to control the logging | |
| * infrastructure. | |
| */ | |
| if (!anonymous) | |
| LogManager.getLogManager().checkAccess(); | |
| this.filter = filter; | |
| } | |
| /** | |
| * Returns the name of this logger. | |
| * | |
| * @return the name of this logger, or <code>null</code> if | |
| * the logger is anonymous. | |
| */ | |
| public String getName() | |
| { | |
| /* Note that the name of a logger cannot be changed during | |
| * its lifetime, so no synchronization is needed. | |
| */ | |
| return name; | |
| } | |
| /** | |
| * Passes a record to registered handlers, provided the record | |
| * is considered as loggable both by {@link #isLoggable(Level)} | |
| * and a possibly installed custom {@link #setFilter(Filter) filter}. | |
| * | |
| * <p>If the logger has been configured to use parent handlers, | |
| * the record will be forwarded to the parent of this logger | |
| * in addition to being processed by the handlers registered with | |
| * this logger. | |
| * | |
| * <p>The other logging methods in this class are convenience methods | |
| * that merely create a new LogRecord and pass it to this method. | |
| * Therefore, subclasses usually just need to override this single | |
| * method for customizing the logging behavior. | |
| * | |
| * @param record the log record to be inspected and possibly forwarded. | |
| */ | |
| public synchronized void log(LogRecord record) | |
| { | |
| if (!isLoggable(record.getLevel())) | |
| return; | |
| if ((filter != null) && !filter.isLoggable(record)) | |
| return; | |
| /* If no logger name has been set for the log record, | |
| * use the name of this logger. | |
| */ | |
| if (record.getLoggerName() == null) | |
| record.setLoggerName(name); | |
| /* Avoid that some other thread is changing the logger hierarchy | |
| * while we are traversing it. | |
| */ | |
| synchronized (LogManager.getLogManager()) | |
| { | |
| Logger curLogger = this; | |
| do | |
| { | |
| /* The Sun J2SE 1.4 reference implementation seems to call the | |
| * filter only for the logger whose log method is called, | |
| * never for any of its parents. Also, parent loggers publish | |
| * log record whatever their level might be. This is pretty | |
| * weird, but GNU Classpath tries to be as compatible as | |
| * possible to the reference implementation. | |
| */ | |
| for (int i = 0; i < curLogger.handlers.length; i++) | |
| curLogger.handlers[i].publish(record); | |
| if (curLogger.getUseParentHandlers() == false) | |
| break; | |
| curLogger = curLogger.getParent(); | |
| } | |
| while (parent != null); | |
| } | |
| } | |
| public void log(Level level, String message) | |
| { | |
| if (isLoggable(level)) | |
| log(level, message, (Object[]) null); | |
| } | |
| public synchronized void log(Level level, | |
| String message, | |
| Object param) | |
| { | |
| if (isLoggable(level)) | |
| { | |
| StackTraceElement caller = getCallerStackFrame(); | |
| logp(level, | |
| caller != null ? caller.getClassName() : "<unknown>", | |
| caller != null ? caller.getMethodName() : "<unknown>", | |
| message, | |
| param); | |
| } | |
| } | |
| public synchronized void log(Level level, | |
| String message, | |
| Object[] params) | |
| { | |
| if (isLoggable(level)) | |
| { | |
| StackTraceElement caller = getCallerStackFrame(); | |
| logp(level, | |
| caller != null ? caller.getClassName() : "<unknown>", | |
| caller != null ? caller.getMethodName() : "<unknown>", | |
| message, | |
| params); | |
| } | |
| } | |
| public synchronized void log(Level level, | |
| String message, | |
| Throwable thrown) | |
| { | |
| if (isLoggable(level)) | |
| { | |
| StackTraceElement caller = getCallerStackFrame(); | |
| logp(level, | |
| caller != null ? caller.getClassName() : "<unknown>", | |
| caller != null ? caller.getMethodName() : "<unknown>", | |
| message, | |
| thrown); | |
| } | |
| } | |
| public synchronized void logp(Level level, | |
| String sourceClass, | |
| String sourceMethod, | |
| String message) | |
| { | |
| logp(level, sourceClass, sourceMethod, message, | |
| (Object[]) null); | |
| } | |
| public synchronized void logp(Level level, | |
| String sourceClass, | |
| String sourceMethod, | |
| String message, | |
| Object param) | |
| { | |
| logp(level, sourceClass, sourceMethod, message, | |
| new Object[] { param }); | |
| } | |
| private synchronized ResourceBundle findResourceBundle() | |
| { | |
| if (resourceBundle != null) | |
| return resourceBundle; | |
| if (parent != null) | |
| return parent.findResourceBundle(); | |
| return null; | |
| } | |
| private synchronized void logImpl(Level level, | |
| String sourceClass, | |
| String sourceMethod, | |
| String message, | |
| Object[] params) | |
| { | |
| LogRecord rec = new LogRecord(level, message); | |
| rec.setResourceBundle(findResourceBundle()); | |
| rec.setSourceClassName(sourceClass); | |
| rec.setSourceMethodName(sourceMethod); | |
| rec.setParameters(params); | |
| log(rec); | |
| } | |
| public synchronized void logp(Level level, | |
| String sourceClass, | |
| String sourceMethod, | |
| String message, | |
| Object[] params) | |
| { | |
| logImpl(level, sourceClass, sourceMethod, message, params); | |
| } | |
| public synchronized void logp(Level level, | |
| String sourceClass, | |
| String sourceMethod, | |
| String message, | |
| Throwable thrown) | |
| { | |
| LogRecord rec = new LogRecord(level, message); | |
| rec.setResourceBundle(resourceBundle); | |
| rec.setSourceClassName(sourceClass); | |
| rec.setSourceMethodName(sourceMethod); | |
| rec.setThrown(thrown); | |
| log(rec); | |
| } | |
| public synchronized void logrb(Level level, | |
| String sourceClass, | |
| String sourceMethod, | |
| String bundleName, | |
| String message) | |
| { | |
| logrb(level, sourceClass, sourceMethod, bundleName, | |
| message, (Object[]) null); | |
| } | |
| public synchronized void logrb(Level level, | |
| String sourceClass, | |
| String sourceMethod, | |
| String bundleName, | |
| String message, | |
| Object param) | |
| { | |
| logrb(level, sourceClass, sourceMethod, bundleName, | |
| message, new Object[] { param }); | |
| } | |
| public synchronized void logrb(Level level, | |
| String sourceClass, | |
| String sourceMethod, | |
| String bundleName, | |
| String message, | |
| Object[] params) | |
| { | |
| LogRecord rec = new LogRecord(level, message); | |
| rec.setResourceBundleName(bundleName); | |
| rec.setSourceClassName(sourceClass); | |
| rec.setSourceMethodName(sourceMethod); | |
| rec.setParameters(params); | |
| log(rec); | |
| } | |
| public synchronized void logrb(Level level, | |
| String sourceClass, | |
| String sourceMethod, | |
| String bundleName, | |
| String message, | |
| Throwable thrown) | |
| { | |
| LogRecord rec = new LogRecord(level, message); | |
| rec.setResourceBundleName(bundleName); | |
| rec.setSourceClassName(sourceClass); | |
| rec.setSourceMethodName(sourceMethod); | |
| rec.setThrown(thrown); | |
| log(rec); | |
| } | |
| public synchronized void entering(String sourceClass, | |
| String sourceMethod) | |
| { | |
| if (isLoggable(Level.FINER)) | |
| logp(Level.FINER, sourceClass, sourceMethod, "ENTRY"); | |
| } | |
| public synchronized void entering(String sourceClass, | |
| String sourceMethod, | |
| Object param) | |
| { | |
| if (isLoggable(Level.FINER)) | |
| logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param); | |
| } | |
| public synchronized void entering(String sourceClass, | |
| String sourceMethod, | |
| Object[] params) | |
| { | |
| if (isLoggable(Level.FINER)) | |
| { | |
| StringBuffer buf = new StringBuffer(80); | |
| buf.append("ENTRY"); | |
| for (int i = 0; i < params.length; i++) | |
| { | |
| buf.append(" {"); | |
| buf.append(i); | |
| buf.append('}'); | |
| } | |
| logp(Level.FINER, sourceClass, sourceMethod, buf.toString(), params); | |
| } | |
| } | |
| public synchronized void exiting(String sourceClass, | |
| String sourceMethod) | |
| { | |
| if (isLoggable(Level.FINER)) | |
| logp(Level.FINER, sourceClass, sourceMethod, "RETURN"); | |
| } | |
| public synchronized void exiting(String sourceClass, | |
| String sourceMethod, | |
| Object result) | |
| { | |
| if (isLoggable(Level.FINER)) | |
| logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result); | |
| } | |
| public synchronized void throwing(String sourceClass, | |
| String sourceMethod, | |
| Throwable thrown) | |
| { | |
| if (isLoggable(Level.FINER)) | |
| logp(Level.FINER, sourceClass, sourceMethod, "THROW", thrown); | |
| } | |
| /** | |
| * Logs a message with severity level SEVERE, indicating a serious | |
| * failure that prevents normal program execution. Messages at this | |
| * level should be understandable to an inexperienced, non-technical | |
| * end user. Ideally, they explain in simple words what actions the | |
| * user can take in order to resolve the problem. | |
| * | |
| * @see Level#SEVERE | |
| * | |
| * @param message the message text, also used as look-up key if the | |
| * logger is localizing messages with a resource | |
| * bundle. While it is possible to pass | |
| * <code>null</code>, this is not recommended, since | |
| * a logging message without text is unlikely to be | |
| * helpful. | |
| */ | |
| public synchronized void severe(String message) | |
| { | |
| if (isLoggable(Level.SEVERE)) | |
| log(Level.SEVERE, message); | |
| } | |
| /** | |
| * Logs a message with severity level WARNING, indicating a | |
| * potential problem that does not prevent normal program execution. | |
| * Messages at this level should be understandable to an | |
| * inexperienced, non-technical end user. Ideally, they explain in | |
| * simple words what actions the user can take in order to resolve | |
| * the problem. | |
| * | |
| * @see Level#WARNING | |
| * | |
| * @param message the message text, also used as look-up key if the | |
| * logger is localizing messages with a resource | |
| * bundle. While it is possible to pass | |
| * <code>null</code>, this is not recommended, since | |
| * a logging message without text is unlikely to be | |
| * helpful. | |
| */ | |
| public synchronized void warning(String message) | |
| { | |
| if (isLoggable(Level.WARNING)) | |
| log(Level.WARNING, message); | |
| } | |
| /** | |
| * Logs a message with severity level INFO. {@link Level#INFO} is | |
| * intended for purely informational messages that do not indicate | |
| * error or warning situations. In the default logging | |
| * configuration, INFO messages will be written to the system | |
| * console. For this reason, the INFO level should be used only for | |
| * messages that are important to end users and system | |
| * administrators. Messages at this level should be understandable | |
| * to an inexperienced, non-technical user. | |
| * | |
| * @param message the message text, also used as look-up key if the | |
| * logger is localizing messages with a resource | |
| * bundle. While it is possible to pass | |
| * <code>null</code>, this is not recommended, since | |
| * a logging message without text is unlikely to be | |
| * helpful. | |
| */ | |
| public synchronized void info(String message) | |
| { | |
| if (isLoggable(Level.INFO)) | |
| log(Level.INFO, message); | |
| } | |
| /** | |
| * Logs a message with severity level CONFIG. {@link Level#CONFIG} is | |
| * intended for static configuration messages, for example about the | |
| * windowing environment, the operating system version, etc. | |
| * | |
| * @param message the message text, also used as look-up key if the | |
| * logger is localizing messages with a resource bundle. While | |
| * it is possible to pass <code>null</code>, this is not | |
| * recommended, since a logging message without text is unlikely | |
| * to be helpful. | |
| */ | |
| public synchronized void config(String message) | |
| { | |
| if (isLoggable(Level.CONFIG)) | |
| log(Level.CONFIG, message); | |
| } | |
| /** | |
| * Logs a message with severity level FINE. {@link Level#FINE} is | |
| * intended for messages that are relevant for developers using | |
| * the component generating log messages. Examples include minor, | |
| * recoverable failures, or possible inefficiencies. | |
| * | |
| * @param message the message text, also used as look-up key if the | |
| * logger is localizing messages with a resource | |
| * bundle. While it is possible to pass | |
| * <code>null</code>, this is not recommended, since | |
| * a logging message without text is unlikely to be | |
| * helpful. | |
| */ | |
| public synchronized void fine(String message) | |
| { | |
| if (isLoggable(Level.FINE)) | |
| log(Level.FINE, message); | |
| } | |
| /** | |
| * Logs a message with severity level FINER. {@link Level#FINER} is | |
| * intended for rather detailed tracing, for example entering a | |
| * method, returning from a method, or throwing an exception. | |
| * | |
| * @param message the message text, also used as look-up key if the | |
| * logger is localizing messages with a resource | |
| * bundle. While it is possible to pass | |
| * <code>null</code>, this is not recommended, since | |
| * a logging message without text is unlikely to be | |
| * helpful. | |
| */ | |
| public synchronized void finer(String message) | |
| { | |
| if (isLoggable(Level.FINER)) | |
| log(Level.FINER, message); | |
| } | |
| /** | |
| * Logs a message with severity level FINEST. {@link Level#FINEST} | |
| * is intended for highly detailed tracing, for example reaching a | |
| * certain point inside the body of a method. | |
| * | |
| * @param message the message text, also used as look-up key if the | |
| * logger is localizing messages with a resource | |
| * bundle. While it is possible to pass | |
| * <code>null</code>, this is not recommended, since | |
| * a logging message without text is unlikely to be | |
| * helpful. | |
| */ | |
| public synchronized void finest(String message) | |
| { | |
| if (isLoggable(Level.FINEST)) | |
| log(Level.FINEST, message); | |
| } | |
| /** | |
| * Adds a handler to the set of handlers that get notified | |
| * when a log record is to be published. | |
| * | |
| * @param handler the handler to be added. | |
| * | |
| * @throws NullPointerException if <code>handler</code> | |
| * is <code>null</code>. | |
| * | |
| * @throws SecurityException if this logger is not anonymous, a | |
| * security manager exists, and the caller is not granted | |
| * the permission to control the logging infrastructure by | |
| * having LoggingPermission("control"). Untrusted code can | |
| * obtain an anonymous logger through the static factory method | |
| * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. | |
| */ | |
| public synchronized void addHandler(Handler handler) | |
| throws SecurityException | |
| { | |
| /* Throw a new NullPointerException if handler is null. */ | |
| handler.getClass(); | |
| /* An application is allowed to control an anonymous logger | |
| * without having the permission to control the logging | |
| * infrastructure. | |
| */ | |
| if (!anonymous) | |
| LogManager.getLogManager().checkAccess(); | |
| if (!handlerList.contains(handler)) | |
| { | |
| handlerList.add(handler); | |
| handlers = getHandlers(); | |
| } | |
| } | |
| /** | |
| * Removes a handler from the set of handlers that get notified | |
| * when a log record is to be published. | |
| * | |
| * @param handler the handler to be removed. | |
| * | |
| * @throws SecurityException if this logger is not anonymous, a | |
| * security manager exists, and the caller is not granted the | |
| * permission to control the logging infrastructure by having | |
| * LoggingPermission("control"). Untrusted code can obtain an | |
| * anonymous logger through the static factory method {@link | |
| * #getAnonymousLogger(java.lang.String) getAnonymousLogger}. | |
| * | |
| * @throws NullPointerException if <code>handler</code> | |
| * is <code>null</code>. | |
| */ | |
| public synchronized void removeHandler(Handler handler) | |
| throws SecurityException | |
| { | |
| /* An application is allowed to control an anonymous logger | |
| * without having the permission to control the logging | |
| * infrastructure. | |
| */ | |
| if (!anonymous) | |
| LogManager.getLogManager().checkAccess(); | |
| /* Throw a new NullPointerException if handler is null. */ | |
| handler.getClass(); | |
| handlerList.remove(handler); | |
| handlers = getHandlers(); | |
| } | |
| /** | |
| * Returns the handlers currently registered for this Logger. | |
| * When a log record has been deemed as being loggable, | |
| * it will be passed to all registered handlers for | |
| * publication. In addition, if the logger uses parent handlers | |
| * (see {@link #getUseParentHandlers() getUseParentHandlers} | |
| * and {@link #setUseParentHandlers(boolean) setUseParentHandlers}, | |
| * the log record will be passed to the parent's handlers. | |
| */ | |
| public synchronized Handler[] getHandlers() | |
| { | |
| /* We cannot return our internal handlers array | |
| * because we do not have any guarantee that the | |
| * caller would not change the array entries. | |
| */ | |
| return (Handler[]) handlerList.toArray(new Handler[handlerList.size()]); | |
| } | |
| /** | |
| * Returns whether or not this Logger forwards log records to | |
| * handlers registered for its parent loggers. | |
| * | |
| * @return <code>false</code> if this Logger sends log records | |
| * merely to Handlers registered with itself; | |
| * <code>true</code> if this Logger sends log records | |
| * not only to Handlers registered with itself, but also | |
| * to those Handlers registered with parent loggers. | |
| */ | |
| public synchronized boolean getUseParentHandlers() | |
| { | |
| return useParentHandlers; | |
| } | |
| /** | |
| * Sets whether or not this Logger forwards log records to | |
| * handlers registered for its parent loggers. | |
| * | |
| * @param useParentHandlers <code>false</code> to let this | |
| * Logger send log records merely to Handlers registered | |
| * with itself; <code>true</code> to let this Logger | |
| * send log records not only to Handlers registered | |
| * with itself, but also to those Handlers registered with | |
| * parent loggers. | |
| * | |
| * @throws SecurityException if this logger is not anonymous, a | |
| * security manager exists, and the caller is not granted | |
| * the permission to control the logging infrastructure by | |
| * having LoggingPermission("control"). Untrusted code can | |
| * obtain an anonymous logger through the static factory method | |
| * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. | |
| * | |
| */ | |
| public synchronized void setUseParentHandlers(boolean useParentHandlers) | |
| { | |
| /* An application is allowed to control an anonymous logger | |
| * without having the permission to control the logging | |
| * infrastructure. | |
| */ | |
| if (!anonymous) | |
| LogManager.getLogManager().checkAccess(); | |
| this.useParentHandlers = useParentHandlers; | |
| } | |
| /** | |
| * Returns the parent of this logger. By default, the parent is | |
| * assigned by the LogManager by inspecting the logger's name. | |
| * | |
| * @return the parent of this logger (as detemined by the LogManager | |
| * by inspecting logger names), the root logger if no other | |
| * logger has a name which is a prefix of this logger's name, or | |
| * <code>null</code> for the root logger. | |
| */ | |
| public synchronized Logger getParent() | |
| { | |
| return parent; | |
| } | |
| /** | |
| * Sets the parent of this logger. Usually, applications do not | |
| * call this method directly. Instead, the LogManager will ensure | |
| * that the tree of loggers reflects the hierarchical logger | |
| * namespace. Basically, this method should not be public at all, | |
| * but the GNU implementation follows the API specification. | |
| * | |
| * @throws NullPointerException if <code>parent</code> is | |
| * <code>null</code>. | |
| * | |
| * @throws SecurityException if this logger is not anonymous, a | |
| * security manager exists, and the caller is not granted | |
| * the permission to control the logging infrastructure by | |
| * having LoggingPermission("control"). Untrusted code can | |
| * obtain an anonymous logger through the static factory method | |
| * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. | |
| */ | |
| public synchronized void setParent(Logger parent) | |
| { | |
| /* Throw a new NullPointerException if parent is null. */ | |
| parent.getClass(); | |
| if (this == root) | |
| throw new IllegalArgumentException( | |
| "the root logger can only have a null parent"); | |
| /* An application is allowed to control an anonymous logger | |
| * without having the permission to control the logging | |
| * infrastructure. | |
| */ | |
| if (!anonymous) | |
| LogManager.getLogManager().checkAccess(); | |
| this.parent = parent; | |
| } | |
| /** | |
| * Gets the StackTraceElement of the first class that is not this class. | |
| * That should be the initial caller of a logging method. | |
| * @return caller of the initial logging method or null if unknown. | |
| */ | |
| private native StackTraceElement getCallerStackFrame(); | |
| /** | |
| * Reset and close handlers attached to this logger. This function is package | |
| * private because it must only be avaiable to the LogManager. | |
| */ | |
| void resetLogger() | |
| { | |
| for (int i = 0; i < handlers.length; i++) | |
| { | |
| handlers[i].close(); | |
| handlerList.remove(handlers[i]); | |
| } | |
| handlers = getHandlers(); | |
| } | |
| } |