| /* 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(); |
| } |
| } |