/* LogManager.java -- a class for maintaining Loggers and managing
   configuration properties
   Copyright (C) 2002, 2005, 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 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 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.
   */
  public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  {
    /* do not register null. */
    listener.getClass();

    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>.
   */
  public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  {
    if (listener != 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 = (WeakReference) 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));
    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;
    String candName;
    int candNameLength;

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

    for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
      {
	candName = (String) iter.next();
	candNameLength = candName.length();

	if (candNameLength > bestNameLength
	    && childNameLength > candNameLength
	    && childName.startsWith(candName)
	    && childName.charAt(candNameLength) == '.')
	  {
	    cand = (Logger) ((WeakReference) 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 ref;

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

    ref = (WeakReference) loggers.get(name);
    if (ref != null)
      return (Logger) 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 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 iter = loggers.values().iterator();
    while (iter.hasNext())
      {
	WeakReference ref;
	Logger logger;

	ref = (WeakReference) iter.next();
	if (ref != null)
	  {
	    logger = (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))
	  {
	    StringTokenizer tokenizer = new StringTokenizer(value);
	    while (tokenizer.hasMoreTokens())
	      {
		String handlerName = tokenizer.nextToken();
                Handler handler = (Handler)
                  createInstance(handlerName, Handler.class, key);
                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
      {
	return Level.parse(getLogManager().getProperty(propertyName));
      }
    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
  {
    // GCJ LOCAL
    // Unfortunately this can be called during bootstrap when
    // Thread.currentThread() will return null.
    // See bug #27658
    Thread t = Thread.currentThread();
    ClassLoader loader = (t == null) ? null : t.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;
  }
}
