mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1194 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1194 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Java
		
	
	
	
/* Logger.java -- a class for logging messages
 | 
						|
   Copyright (C) 2002, 2004, 2006, 2007 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 gnu.java.lang.CPStringBuilder;
 | 
						|
 | 
						|
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;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Use to lock methods on this class instead of calling synchronize on methods
 | 
						|
   * to avoid deadlocks. Yeah, no kidding, we got them :)
 | 
						|
   */
 | 
						|
  private static final Object[] lock = new Object[0];
 | 
						|
 | 
						|
  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;
 | 
						|
 | 
						|
    if (name == null)
 | 
						|
      throw new NullPointerException();
 | 
						|
 | 
						|
    /*
 | 
						|
     * 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 (lock)
 | 
						|
      {
 | 
						|
        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 String getResourceBundleName()
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 ResourceBundle getResourceBundle()
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 Level getLevel()
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 boolean isLoggable(Level level)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void setLevel(Level level)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        /*
 | 
						|
         * 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 Filter getFilter()
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void setFilter(Filter filter) throws SecurityException
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        /*
 | 
						|
         * 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 void log(LogRecord record)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void log(Level level, String message, Object param)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (isLoggable(level))
 | 
						|
          {
 | 
						|
            StackTraceElement caller = getCallerStackFrame();
 | 
						|
            logp(level, caller != null ? caller.getClassName() : "<unknown>",
 | 
						|
                 caller != null ? caller.getMethodName() : "<unknown>",
 | 
						|
                 message, param);
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void log(Level level, String message, Object[] params)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (isLoggable(level))
 | 
						|
          {
 | 
						|
            StackTraceElement caller = getCallerStackFrame();
 | 
						|
            logp(level, caller != null ? caller.getClassName() : "<unknown>",
 | 
						|
                 caller != null ? caller.getMethodName() : "<unknown>",
 | 
						|
                 message, params);
 | 
						|
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void log(Level level, String message, Throwable thrown)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (isLoggable(level))
 | 
						|
          {
 | 
						|
            StackTraceElement caller = getCallerStackFrame();
 | 
						|
            logp(level, caller != null ? caller.getClassName() : "<unknown>",
 | 
						|
                 caller != null ? caller.getMethodName() : "<unknown>",
 | 
						|
                 message, thrown);
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void logp(Level level, String sourceClass, String sourceMethod,
 | 
						|
                   String message)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        logp(level, sourceClass, sourceMethod, message, (Object[]) null);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void logp(Level level, String sourceClass, String sourceMethod,
 | 
						|
                   String message, Object param)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        logp(level, sourceClass, sourceMethod, message, new Object[] { param });
 | 
						|
      }
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  private ResourceBundle findResourceBundle()
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (resourceBundle != null)
 | 
						|
          return resourceBundle;
 | 
						|
 | 
						|
        if (parent != null)
 | 
						|
          return parent.findResourceBundle();
 | 
						|
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  private void logImpl(Level level, String sourceClass, String sourceMethod,
 | 
						|
                       String message, Object[] params)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        LogRecord rec = new LogRecord(level, message);
 | 
						|
 | 
						|
        rec.setResourceBundle(findResourceBundle());
 | 
						|
        rec.setSourceClassName(sourceClass);
 | 
						|
        rec.setSourceMethodName(sourceMethod);
 | 
						|
        rec.setParameters(params);
 | 
						|
 | 
						|
        log(rec);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void logp(Level level, String sourceClass, String sourceMethod,
 | 
						|
                   String message, Object[] params)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        logImpl(level, sourceClass, sourceMethod, message, params);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void logp(Level level, String sourceClass, String sourceMethod,
 | 
						|
                   String message, Throwable thrown)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        LogRecord rec = new LogRecord(level, message);
 | 
						|
 | 
						|
        rec.setResourceBundle(resourceBundle);
 | 
						|
        rec.setSourceClassName(sourceClass);
 | 
						|
        rec.setSourceMethodName(sourceMethod);
 | 
						|
        rec.setThrown(thrown);
 | 
						|
 | 
						|
        log(rec);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void logrb(Level level, String sourceClass, String sourceMethod,
 | 
						|
                    String bundleName, String message)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        logrb(level, sourceClass, sourceMethod, bundleName, message,
 | 
						|
              (Object[]) null);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void logrb(Level level, String sourceClass, String sourceMethod,
 | 
						|
                    String bundleName, String message, Object param)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        logrb(level, sourceClass, sourceMethod, bundleName, message,
 | 
						|
              new Object[] { param });
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void logrb(Level level, String sourceClass, String sourceMethod,
 | 
						|
                    String bundleName, String message, Object[] params)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        LogRecord rec = new LogRecord(level, message);
 | 
						|
 | 
						|
        rec.setResourceBundleName(bundleName);
 | 
						|
        rec.setSourceClassName(sourceClass);
 | 
						|
        rec.setSourceMethodName(sourceMethod);
 | 
						|
        rec.setParameters(params);
 | 
						|
 | 
						|
        log(rec);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void logrb(Level level, String sourceClass, String sourceMethod,
 | 
						|
                    String bundleName, String message, Throwable thrown)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        LogRecord rec = new LogRecord(level, message);
 | 
						|
 | 
						|
        rec.setResourceBundleName(bundleName);
 | 
						|
        rec.setSourceClassName(sourceClass);
 | 
						|
        rec.setSourceMethodName(sourceMethod);
 | 
						|
        rec.setThrown(thrown);
 | 
						|
 | 
						|
        log(rec);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void entering(String sourceClass, String sourceMethod)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (isLoggable(Level.FINER))
 | 
						|
          logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void entering(String sourceClass, String sourceMethod, Object param)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (isLoggable(Level.FINER))
 | 
						|
          logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void entering(String sourceClass, String sourceMethod, Object[] params)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (isLoggable(Level.FINER))
 | 
						|
          {
 | 
						|
            CPStringBuilder buf = new CPStringBuilder(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 void exiting(String sourceClass, String sourceMethod)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (isLoggable(Level.FINER))
 | 
						|
          logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void exiting(String sourceClass, String sourceMethod, Object result)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (isLoggable(Level.FINER))
 | 
						|
          logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void throwing(String sourceClass, String sourceMethod, Throwable thrown)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void severe(String message)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void warning(String message)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void info(String message)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void config(String message)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void fine(String message)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void finer(String message)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void finest(String message)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void addHandler(Handler handler) throws SecurityException
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (handler == null)
 | 
						|
          throw new NullPointerException();
 | 
						|
 | 
						|
        /*
 | 
						|
         * 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 void removeHandler(Handler handler) throws SecurityException
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        /*
 | 
						|
         * An application is allowed to control an anonymous logger without
 | 
						|
         * having the permission to control the logging infrastructure.
 | 
						|
         */
 | 
						|
        if (! anonymous)
 | 
						|
          LogManager.getLogManager().checkAccess();
 | 
						|
 | 
						|
        if (handler == null)
 | 
						|
          throw new NullPointerException();
 | 
						|
 | 
						|
        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 Handler[] getHandlers()
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        /*
 | 
						|
         * 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 boolean getUseParentHandlers()
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void setUseParentHandlers(boolean useParentHandlers)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        /*
 | 
						|
         * 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 Logger getParent()
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        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 void setParent(Logger parent)
 | 
						|
  {
 | 
						|
    synchronized (lock)
 | 
						|
      {
 | 
						|
        if (parent == null)
 | 
						|
          throw new NullPointerException();
 | 
						|
 | 
						|
        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 StackTraceElement getCallerStackFrame()
 | 
						|
  {
 | 
						|
    Throwable t = new Throwable();
 | 
						|
    StackTraceElement[] stackTrace = t.getStackTrace();
 | 
						|
    int index = 0;
 | 
						|
 | 
						|
    // skip to stackentries until this class
 | 
						|
    while (index < stackTrace.length
 | 
						|
           && ! stackTrace[index].getClassName().equals(getClass().getName()))
 | 
						|
      index++;
 | 
						|
 | 
						|
    // skip the stackentries of this class
 | 
						|
    while (index < stackTrace.length
 | 
						|
           && stackTrace[index].getClassName().equals(getClass().getName()))
 | 
						|
      index++;
 | 
						|
 | 
						|
    return index < stackTrace.length ? stackTrace[index] : null;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Reset and close handlers attached to this logger. This function is package
 | 
						|
   * private because it must only be available to the LogManager.
 | 
						|
   */
 | 
						|
  void resetLogger()
 | 
						|
  {
 | 
						|
    for (int i = 0; i < handlers.length; i++)
 | 
						|
      {
 | 
						|
        handlers[i].close();
 | 
						|
        handlerList.remove(handlers[i]);
 | 
						|
      }
 | 
						|
    handlers = getHandlers();
 | 
						|
  }
 | 
						|
}
 |