/* LogManager.java -- a class for maintaining Loggers and managing
   configuration properties
   Copyright (C) 2002, 2005, 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.classpath.SystemProperties;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

/**
 * The <code>LogManager</code> maintains a hierarchical namespace
 * of Logger objects and manages properties for configuring the logging
 * framework. There exists only one single <code>LogManager</code>
 * per virtual machine. This instance can be retrieved using the
 * static method {@link #getLogManager()}.
 *
 * <p><strong>Configuration Process:</strong> The global LogManager
 * object is created and configured when the class
 * <code>java.util.logging.LogManager</code> is initialized.
 * The configuration process includes the subsequent steps:
 *
 * <ul>
 * <li>If the system property <code>java.util.logging.manager</code>
 *     is set to the name of a subclass of
 *     <code>java.util.logging.LogManager</code>, an instance of
 *     that subclass is created and becomes the global LogManager.
 *     Otherwise, a new instance of LogManager is created.</li>
 * <li>The <code>LogManager</code> constructor tries to create
 *     a new instance of the class specified by the system
 *     property <code>java.util.logging.config.class</code>.
 *     Typically, the constructor of this class will call
 *     <code>LogManager.getLogManager().readConfiguration(java.io.InputStream)</code>
 *     for configuring the logging framework.
 *     The configuration process stops at this point if
 *     the system property <code>java.util.logging.config.class</code>
 *     is set (irrespective of whether the class constructor
 *     could be called or an exception was thrown).</li>
 *
 * <li>If the system property <code>java.util.logging.config.class</code>
 *     is <em>not</em> set, the configuration parameters are read in from
 *     a file and passed to
 *     {@link #readConfiguration(java.io.InputStream)}.
 *     The name and location of this file are specified by the system
 *     property <code>java.util.logging.config.file</code>.</li>
 * <li>If the system property <code>java.util.logging.config.file</code>
 *     is not set, however, the contents of the URL
 *     "{gnu.classpath.home.url}/logging.properties" are passed to
 *     {@link #readConfiguration(java.io.InputStream)}.
 *     Here, "{gnu.classpath.home.url}" stands for the value of
 *     the system property <code>gnu.classpath.home.url</code>.</li>
 * </ul>
 *
 * <p>The <code>LogManager</code> has a level of <code>INFO</code> by
 * default, and this will be inherited by <code>Logger</code>s unless they
 * override it either by properties or programmatically.
 *
 * @author Sascha Brawer (brawer@acm.org)
 */
public class LogManager
{
  /**
   * The object name for the logging management bean.
   * @since 1.5
   */
  public static final String LOGGING_MXBEAN_NAME
    = "java.util.logging:type=Logging";

  /**
   * The singleton LogManager instance.
   */
  private static LogManager logManager;

  /**
   * The singleton logging bean.
   */
  private static LoggingMXBean loggingBean;

  /**
   * The registered named loggers; maps the name of a Logger to
   * a WeakReference to it.
   */
  private Map<String, WeakReference<Logger>> loggers;

  /**
   * The properties for the logging framework which have been
   * read in last.
   */
  private Properties properties;

  /**
   * A delegate object that provides support for handling
   * PropertyChangeEvents.  The API specification does not
   * mention which bean should be the source in the distributed
   * PropertyChangeEvents, but Mauve test code has determined that
   * the Sun J2SE 1.4 reference implementation uses the LogManager
   * class object. This is somewhat strange, as the class object
   * is not the bean with which listeners have to register, but
   * there is no reason for the GNU Classpath implementation to
   * behave differently from the reference implementation in
   * this case.
   */
  private final PropertyChangeSupport pcs = new PropertyChangeSupport( /* source bean */
                                                                      LogManager.class);

  protected LogManager()
  {
    loggers = new HashMap();
  }

  /**
   * Returns the globally shared LogManager instance.
   */
  public static synchronized LogManager getLogManager()
  {
    if (logManager == null)
      {
        logManager = makeLogManager();
        initLogManager();
      }
    return logManager;
  }

  private static final String MANAGER_PROPERTY = "java.util.logging.manager";

  private static LogManager makeLogManager()
  {
    String managerClassName = SystemProperties.getProperty(MANAGER_PROPERTY);
    LogManager manager = (LogManager) createInstance
      (managerClassName, LogManager.class, MANAGER_PROPERTY);
    if (manager == null)
      manager = new LogManager();
    return manager;
  }

  private static final String CONFIG_PROPERTY = "java.util.logging.config.class";

  private static void initLogManager()
  {
    LogManager manager = getLogManager();
    Logger.root.setLevel(Level.INFO);
    manager.addLogger(Logger.root);

    /* The Javadoc description of the class explains
     * what is going on here.
     */
    Object configurator = createInstance(System.getProperty(CONFIG_PROPERTY),
                                         /* must be instance of */ Object.class,
                                         CONFIG_PROPERTY);

    try
      {
        if (configurator == null)
          manager.readConfiguration();
      }
    catch (IOException ex)
      {
        /* FIXME: Is it ok to ignore exceptions here? */
      }
  }

  /**
   * Registers a listener which will be notified when the
   * logging properties are re-read.
   *
   * @param listener the event listener to register.
   * @throws NullPointerException if the listener is {@code null}.
   * @throws SecurityException if a security manager exists and the
   *                           calling code does not have the permission
   *                           {@code LoggingPermission("control")}.
   */
  public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  {
    if (listener == null)
      throw new NullPointerException("Attempt to add null property change listener");

    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkPermission(new LoggingPermission("control", null));

    pcs.addPropertyChangeListener(listener);
  }

  /**
   * Unregisters a listener.
   *
   * If <code>listener</code> has not been registered previously,
   * nothing happens.  Also, no exception is thrown if
   * <code>listener</code> is <code>null</code>.
   *
   * @param listener the listener to remove.
   * @throws SecurityException if a security manager exists and the
   *                           calling code does not have the permission
   *                           {@code LoggingPermission("control")}.
   */
  public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  {
    if (listener != null)
      {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null)
          sm.checkPermission(new LoggingPermission("control", null));

        pcs.removePropertyChangeListener(listener);
      }
  }

  /**
   * Adds a named logger.  If a logger with the same name has
   * already been registered, the method returns <code>false</code>
   * without adding the logger.
   *
   * <p>The <code>LogManager</code> only keeps weak references
   * to registered loggers.  Therefore, names can become available
   * after automatic garbage collection.
   *
   * @param logger the logger to be added.
   *
   * @return <code>true</code>if <code>logger</code> was added,
   *         <code>false</code> otherwise.
   *
   * @throws NullPointerException if <code>name</code> is
   *         <code>null</code>.
   */
  public synchronized boolean addLogger(Logger logger)
  {
    /* To developers thinking about to remove the 'synchronized'
     * declaration from this method: Please read the comment
     * in java.util.logging.Logger.getLogger(String, String)
     * and make sure that whatever you change wrt. synchronization
     * does not endanger thread-safety of Logger.getLogger.
     * The current implementation of Logger.getLogger assumes
     * that LogManager does its synchronization on the globally
     * shared instance of LogManager.
     */
    String name;
    WeakReference ref;

    /* This will throw a NullPointerException if logger is null,
     * as required by the API specification.
     */
    name = logger.getName();

    ref = loggers.get(name);
    if (ref != null)
      {
        if (ref.get() != null)
          return false;

        /* There has been a logger under this name in the past,
         * but it has been garbage collected.
         */
        loggers.remove(ref);
      }

    /* Adding a named logger requires a security permission. */
    if ((name != null) && ! name.equals(""))
      checkAccess();

    Logger parent = findAncestor(logger);
    loggers.put(name, new WeakReference<Logger>(logger));
    if (parent != logger.getParent())
      logger.setParent(parent);

    // The level of the newly added logger must be specified.
    // The easiest case is if there is a level for exactly this logger
    // in the properties. If no such level exists the level needs to be
    // searched along the hirachy. So if there is a new logger 'foo.blah.blub'
    // and an existing parent logger 'foo' the properties 'foo.blah.blub.level'
    // and 'foo.blah.level' need to be checked. If both do not exist in the
    // properties the level of the new logger is set to 'null' (i.e. it uses the
    // level of its parent 'foo').
    Level logLevel = logger.getLevel();
    String searchName = name;
    String parentName = parent != null ? parent.getName() : "";
    while (logLevel == null && ! searchName.equals(parentName))
      {
        logLevel = getLevelProperty(searchName + ".level", logLevel);
        int index = searchName.lastIndexOf('.');
        if(index > -1)
          searchName = searchName.substring(0,index);
        else
          searchName = "";
      }
    logger.setLevel(logLevel);

    /* It can happen that existing loggers should be children of
     * the newly added logger. For example, assume that there
     * already exist loggers under the names "", "foo", and "foo.bar.baz".
     * When adding "foo.bar", the logger "foo.bar.baz" should change
     * its parent to "foo.bar".
     */
    for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
      {
        Logger possChild = (Logger) ((WeakReference) loggers.get(iter.next()))
          .get();
        if ((possChild == null) || (possChild == logger)
            || (possChild.getParent() != parent))
          continue;

        if (! possChild.getName().startsWith(name))
          continue;

        if (possChild.getName().charAt(name.length()) != '.')
          continue;

        possChild.setParent(logger);
      }

    return true;
  }

  /**
   * Finds the closest ancestor for a logger among the currently
   * registered ones.  For example, if the currently registered
   * loggers have the names "", "foo", and "foo.bar", the result for
   * "foo.bar.baz" will be the logger whose name is "foo.bar".
   *
   * @param child a logger for whose name no logger has been
   *        registered.
   *
   * @return the closest ancestor for <code>child</code>,
   *         or <code>null</code> if <code>child</code>
   *         is the root logger.
   *
   * @throws NullPointerException if <code>child</code>
   *         is <code>null</code>.
   */
  private synchronized Logger findAncestor(Logger child)
  {
    String childName = child.getName();
    int childNameLength = childName.length();
    Logger best = Logger.root;
    int bestNameLength = 0;

    Logger cand;
    int candNameLength;

    if (child == Logger.root)
      return null;

    for (String candName : loggers.keySet())
      {
        candNameLength = candName.length();

        if (candNameLength > bestNameLength
            && childNameLength > candNameLength
            && childName.startsWith(candName)
            && childName.charAt(candNameLength) == '.')
          {
            cand = loggers.get(candName).get();
            if ((cand == null) || (cand == child))
              continue;

            bestNameLength = candName.length();
            best = cand;
          }
      }

    return best;
  }

  /**
   * Returns a Logger given its name.
   *
   * @param name the name of the logger.
   *
   * @return a named Logger, or <code>null</code> if there is no
   *     logger with that name.
   *
   * @throw java.lang.NullPointerException if <code>name</code>
   *     is <code>null</code>.
   */
  public synchronized Logger getLogger(String name)
  {
    WeakReference<Logger> ref;

    /* Throw a NullPointerException if name is null. */
    name.getClass();

    ref = loggers.get(name);
    if (ref != null)
      return ref.get();
    else
      return null;
  }

  /**
   * Returns an Enumeration of currently registered Logger names.
   * Since other threads can register loggers at any time, the
   * result could be different any time this method is called.
   *
   * @return an Enumeration with the names of the currently
   *    registered Loggers.
   */
  public synchronized Enumeration<String> getLoggerNames()
  {
    return Collections.enumeration(loggers.keySet());
  }

  /**
   * Resets the logging configuration by removing all handlers for
   * registered named loggers and setting their level to <code>null</code>.
   * The level of the root logger will be set to <code>Level.INFO</code>.
   *
   * @throws SecurityException if a security manager exists and
   *         the caller is not granted the permission to control
   *         the logging infrastructure.
   */
  public synchronized void reset() throws SecurityException
  {
    /* Throw a SecurityException if the caller does not have the
     * permission to control the logging infrastructure.
     */
    checkAccess();

    properties = new Properties();

    Iterator<WeakReference<Logger>> iter = loggers.values().iterator();
    while (iter.hasNext())
      {
        WeakReference<Logger> ref;
        Logger logger;

        ref = iter.next();
        if (ref != null)
          {
            logger = ref.get();

            if (logger == null)
              iter.remove();
            else if (logger != Logger.root)
              {
                logger.resetLogger();
                logger.setLevel(null);
              }
          }
      }

    Logger.root.setLevel(Level.INFO);
    Logger.root.resetLogger();
  }

  /**
   * Configures the logging framework by reading a configuration file.
   * The name and location of this file are specified by the system
   * property <code>java.util.logging.config.file</code>.  If this
   * property is not set, the URL
   * "{gnu.classpath.home.url}/logging.properties" is taken, where
   * "{gnu.classpath.home.url}" stands for the value of the system
   * property <code>gnu.classpath.home.url</code>.
   *
   * <p>The task of configuring the framework is then delegated to
   * {@link #readConfiguration(java.io.InputStream)}, which will
   * notify registered listeners after having read the properties.
   *
   * @throws SecurityException if a security manager exists and
   *         the caller is not granted the permission to control
   *         the logging infrastructure, or if the caller is
   *         not granted the permission to read the configuration
   *         file.
   *
   * @throws IOException if there is a problem reading in the
   *         configuration file.
   */
  public synchronized void readConfiguration()
    throws IOException, SecurityException
  {
    String path;
    InputStream inputStream;

    path = System.getProperty("java.util.logging.config.file");
    if ((path == null) || (path.length() == 0))
      {
        String url = (System.getProperty("gnu.classpath.home.url")
                      + "/logging.properties");
        try
          {
            inputStream = new URL(url).openStream();
          }
        catch (Exception e)
          {
            inputStream=null;
          }

        // If no config file could be found use a default configuration.
        if(inputStream == null)
          {
            String defaultConfig = "handlers = java.util.logging.ConsoleHandler   \n"
              + ".level=INFO \n";
            inputStream = new ByteArrayInputStream(defaultConfig.getBytes());
          }
      }
    else
      inputStream = new java.io.FileInputStream(path);

    try
      {
        readConfiguration(inputStream);
      }
    finally
      {
        // Close the stream in order to save
        // resources such as file descriptors.
        inputStream.close();
      }
  }

  public synchronized void readConfiguration(InputStream inputStream)
    throws IOException, SecurityException
  {
    Properties newProperties;
    Enumeration keys;

    checkAccess();
    newProperties = new Properties();
    newProperties.load(inputStream);
    reset();
    this.properties = newProperties;
    keys = newProperties.propertyNames();

    while (keys.hasMoreElements())
      {
        String key = ((String) keys.nextElement()).trim();
        String value = newProperties.getProperty(key);

        if (value == null)
          continue;

        value = value.trim();

        if ("handlers".equals(key))
          {
            // In Java 5 and earlier this was specified to be
            // whitespace-separated, but in reality it also accepted
            // commas (tomcat relied on this), and in Java 6 the
            // documentation was updated to fit the implementation.
            StringTokenizer tokenizer = new StringTokenizer(value,
                                                            " \t\n\r\f,");
            while (tokenizer.hasMoreTokens())
              {
                String handlerName = tokenizer.nextToken();
                Handler handler = (Handler)
                  createInstance(handlerName, Handler.class, key);
                // Tomcat also relies on the implementation ignoring
                // items in 'handlers' which are not class names.
                if (handler != null)
                  Logger.root.addHandler(handler);
              }
          }

        if (key.endsWith(".level"))
          {
            String loggerName = key.substring(0, key.length() - 6);
            Logger logger = getLogger(loggerName);

            if (logger == null)
              {
                logger = Logger.getLogger(loggerName);
                addLogger(logger);
              }
            Level level = null;
            try
              {
                level = Level.parse(value);
              }
            catch (IllegalArgumentException e)
              {
                warn("bad level \'" + value + "\'", e);
              }
            if (level != null)
              {
                logger.setLevel(level);
              }
            continue;
          }
      }

    /* The API specification does not talk about the
     * property name that is distributed with the
     * PropertyChangeEvent.  With test code, it could
     * be determined that the Sun J2SE 1.4 reference
     * implementation uses null for the property name.
     */
    pcs.firePropertyChange(null, null, null);
  }

  /**
   * Returns the value of a configuration property as a String.
   */
  public synchronized String getProperty(String name)
  {
    if (properties != null)
      return properties.getProperty(name);
    else
      return null;
  }

  /**
   * Returns the value of a configuration property as an integer.
   * This function is a helper used by the Classpath implementation
   * of java.util.logging, it is <em>not</em> specified in the
   * logging API.
   *
   * @param name the name of the configuration property.
   *
   * @param defaultValue the value that will be returned if the
   *        property is not defined, or if its value is not an integer
   *        number.
   */
  static int getIntProperty(String name, int defaultValue)
  {
    try
      {
        return Integer.parseInt(getLogManager().getProperty(name));
      }
    catch (Exception ex)
      {
        return defaultValue;
      }
  }

  /**
   * Returns the value of a configuration property as an integer,
   * provided it is inside the acceptable range.
   * This function is a helper used by the Classpath implementation
   * of java.util.logging, it is <em>not</em> specified in the
   * logging API.
   *
   * @param name the name of the configuration property.
   *
   * @param minValue the lowest acceptable value.
   *
   * @param maxValue the highest acceptable value.
   *
   * @param defaultValue the value that will be returned if the
   *        property is not defined, or if its value is not an integer
   *        number, or if it is less than the minimum value,
   *        or if it is greater than the maximum value.
   */
  static int getIntPropertyClamped(String name, int defaultValue,
                                   int minValue, int maxValue)
  {
    int val = getIntProperty(name, defaultValue);
    if ((val < minValue) || (val > maxValue))
      val = defaultValue;
    return val;
  }

  /**
   * Returns the value of a configuration property as a boolean.
   * This function is a helper used by the Classpath implementation
   * of java.util.logging, it is <em>not</em> specified in the
   * logging API.
   *
   * @param name the name of the configuration property.
   *
   * @param defaultValue the value that will be returned if the
   *        property is not defined, or if its value is neither
   *        <code>"true"</code> nor <code>"false"</code>.
   */
  static boolean getBooleanProperty(String name, boolean defaultValue)
  {
    try
      {
        return (Boolean.valueOf(getLogManager().getProperty(name))).booleanValue();
      }
    catch (Exception ex)
      {
        return defaultValue;
      }
  }

  /**
   * Returns the value of a configuration property as a Level.
   * This function is a helper used by the Classpath implementation
   * of java.util.logging, it is <em>not</em> specified in the
   * logging API.
   *
   * @param propertyName the name of the configuration property.
   *
   * @param defaultValue the value that will be returned if the
   *        property is not defined, or if
   *        {@link Level#parse(java.lang.String)} does not like
   *        the property value.
   */
  static Level getLevelProperty(String propertyName, Level defaultValue)
  {
    try
      {
        String value = getLogManager().getProperty(propertyName);
        if (value != null)
          return Level.parse(getLogManager().getProperty(propertyName));
        else
           return defaultValue;
      }
    catch (Exception ex)
      {
        return defaultValue;
      }
  }

  /**
   * Returns the value of a configuration property as a Class.
   * This function is a helper used by the Classpath implementation
   * of java.util.logging, it is <em>not</em> specified in the
   * logging API.
   *
   * @param propertyName the name of the configuration property.
   *
   * @param defaultValue the value that will be returned if the
   *        property is not defined, or if it does not specify
   *        the name of a loadable class.
   */
  static final Class getClassProperty(String propertyName, Class defaultValue)
  {
    String propertyValue = logManager.getProperty(propertyName);

    if (propertyValue != null)
      try
        {
          return locateClass(propertyValue);
        }
      catch (ClassNotFoundException e)
        {
          warn(propertyName + " = " + propertyValue, e);
        }

    return defaultValue;
  }

  static final Object getInstanceProperty(String propertyName, Class ofClass,
                                          Class defaultClass)
  {
    Class klass = getClassProperty(propertyName, defaultClass);
    if (klass == null)
      return null;

    try
      {
        Object obj = klass.newInstance();
        if (ofClass.isInstance(obj))
          return obj;
      }
    catch (InstantiationException e)
      {
        warn(propertyName + " = " + klass.getName(), e);
      }
    catch (IllegalAccessException e)
      {
        warn(propertyName + " = " + klass.getName(), e);
      }

    if (defaultClass == null)
      return null;

    try
      {
        return defaultClass.newInstance();
      }
    catch (java.lang.InstantiationException ex)
      {
        throw new RuntimeException(ex.getMessage());
      }
    catch (java.lang.IllegalAccessException ex)
      {
        throw new RuntimeException(ex.getMessage());
      }
  }

  /**
   * An instance of <code>LoggingPermission("control")</code>
   * that is shared between calls to <code>checkAccess()</code>.
   */
  private static final LoggingPermission controlPermission = new LoggingPermission("control",
                                                                                   null);

  /**
   * Checks whether the current security context allows changing
   * the configuration of the logging framework.  For the security
   * context to be trusted, it has to be granted
   * a LoggingPermission("control").
   *
   * @throws SecurityException if a security manager exists and
   *         the caller is not granted the permission to control
   *         the logging infrastructure.
   */
  public void checkAccess() throws SecurityException
  {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkPermission(controlPermission);
  }

  /**
   * Creates a new instance of a class specified by name and verifies
   * that it is an instance (or subclass of) a given type.
   *
   * @param className the name of the class of which a new instance
   *        should be created.
   *
   * @param type the object created must be an instance of
   * <code>type</code> or any subclass of <code>type</code>
   *
   * @param property the system property to reference in error
   * messages
   *
   * @return the new instance, or <code>null</code> if
   *         <code>className</code> is <code>null</code>, if no class
   *         with that name could be found, if there was an error
   *         loading that class, or if the constructor of the class
   *         has thrown an exception.
   */
  private static final Object createInstance(String className, Class type,
                                             String property)
  {
    Class klass = null;

    if ((className == null) || (className.length() == 0))
      return null;

    try
      {
        klass = locateClass(className);
        if (type.isAssignableFrom(klass))
          return klass.newInstance();
        warn(property, className, "not an instance of " + type.getName());
      }
    catch (ClassNotFoundException e)
      {
        warn(property, className, "class not found", e);
      }
    catch (IllegalAccessException e)
      {
        warn(property, className, "illegal access", e);
      }
    catch (InstantiationException e)
      {
        warn(property, className, e);
      }
    catch (java.lang.LinkageError e)
      {
        warn(property, className, "linkage error", e);
      }

    return null;
  }

  private static final void warn(String property, String klass, Throwable t)
  {
    warn(property, klass, null, t);
  }

  private static final void warn(String property, String klass, String msg)
  {
    warn(property, klass, msg, null);
  }

  private static final void warn(String property, String klass, String msg,
                                 Throwable t)
  {
    warn("error instantiating '" + klass + "' referenced by " + property +
         (msg == null ? "" : ", " + msg), t);
  }

  /**
   * All debug warnings go through this method.
   */

  private static final void warn(String msg, Throwable t)
  {
    System.err.println("WARNING: " + msg);
    if (t != null)
      t.printStackTrace(System.err);
  }

  /**
   * Locates a class by first checking the system class loader and
   * then checking the context class loader.
   *
   * @param name the fully qualified name of the Class to locate
   * @return Class the located Class
   */

  private static Class locateClass(String name) throws ClassNotFoundException
  {
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    try
      {
        return Class.forName(name, true, loader);
      }
    catch (ClassNotFoundException e)
      {
        loader = ClassLoader.getSystemClassLoader();
        return Class.forName(name, true, loader);
      }
  }

  /**
   * Return the logging bean.  There is a single logging bean per
   * VM instance.
   * @since 1.5
   */
  public static synchronized LoggingMXBean getLoggingMXBean()
  {
    if (loggingBean == null)
      {
        loggingBean = new LoggingMXBean()
        {
          public String getLoggerLevel(String logger)
          {
            LogManager mgr = getLogManager();
            Logger l = mgr.getLogger(logger);
            if (l == null)
              return null;
            Level lev = l.getLevel();
            if (lev == null)
              return "";
            return lev.getName();
          }

          public List getLoggerNames()
          {
            LogManager mgr = getLogManager();
            // This is inefficient, but perhaps better for maintenance.
            return Collections.list(mgr.getLoggerNames());
          }

          public String getParentLoggerName(String logger)
          {
            LogManager mgr = getLogManager();
            Logger l = mgr.getLogger(logger);
            if (l == null)
              return null;
            l = l.getParent();
            if (l == null)
              return "";
            return l.getName();
          }

          public void setLoggerLevel(String logger, String level)
          {
            LogManager mgr = getLogManager();
            Logger l = mgr.getLogger(logger);
            if (l == null)
              throw new IllegalArgumentException("no logger named " + logger);
            Level newLevel;
            if (level == null)
              newLevel = null;
            else
              newLevel = Level.parse(level);
            l.setLevel(newLevel);
          }
        };
      }
    return loggingBean;
  }
}
