/* Logger.java
   -- a class for logging messages

Copyright (C) 2002 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version.

*/


package java.util.logging;

import java.util.ResourceBundle;
import java.util.MissingResourceException;
import java.util.List;

/**
 * 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
{
  /**
   * 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 = 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 = LogManager.getLogManager().rootLogger;

    useParentHandlers = (parent != null);
  }



  /**
   * Finds a registered logger for a subsystem, or creates one in
   * case no logger has been registered yet.
   *
   * @param name the name for the logger, for example "java.awt"
   *             or "com.foo.bar". The name should be based on
   *             the name of the package issuing log records
   *             and consist of dot-separated Java identifiers.
   *
   * @throws IllegalArgumentException if a logger for the subsystem
   *         identified by <code>name</code> has already been created,
   *         but uses a a resource bundle for localizing messages.
   *
   * @throws NullPointerException if <code>name</code> is
   *         <code>null</code>.
   *
   * @return a logger for the subsystem specified by <code>name</code>
   *         that does not localize messages.
   */
  public static Logger getLogger(String name)
  {
    return getLogger(name, null);
  }

    
  /**
   * Finds a registered logger for a subsystem, or creates one in case
   * no logger has been registered yet.
   *
   * <p>If a logger with the specified name has already been
   * registered, the behavior depends on the resource bundle that is
   * currently associated with the existing logger.
   *
   * <ul><li>If the existing logger uses the same resource bundle as
   * specified by <code>resourceBundleName</code>, the existing logger
   * is returned.</li>
   *
   * <li>If the existing logger currently does not localize messages,
   * the existing logger is modified to use the bundle specified by
   * <code>resourceBundleName</code>.  The existing logger is then
   * returned.  Therefore, all subsystems currently using this logger
   * will produce localized messages from now on.</li>
   *
   * <li>If the existing logger already has an associated resource
   * bundle, but a different one than specified by
   * <code>resourceBundleName</code>, an
   * <code>IllegalArgumentException</code> is thrown.</li></ul>
   *
   * @param name the name for the logger, for example "java.awt"
   *             or "org.gnu.foo". The name should be based on
   *             the name of the package issuing log records
   *             and consist of dot-separated Java identifiers.
   *
   * @param resourceBundleName the name of a resource bundle
   *        for localizing messages, or <code>null</code>
   *	    to indicate that messages do not need to be localized.
   *
   * @return a logger for the subsystem specified by <code>name</code>.
   *
   * @throws java.util.MissingResourceException if
   *         <code>resourceBundleName</code> is not <code>null</code>
   *         and no such bundle could be located.   
   *
   * @throws IllegalArgumentException if a logger for the subsystem
   *         identified by <code>name</code> has already been created,
   *         but uses a different resource bundle for localizing
   *         messages.
   *
   * @throws NullPointerException if <code>name</code> is
   *         <code>null</code>.
   */
  public static Logger getLogger(String name, String resourceBundleName)
  {
    LogManager lm = LogManager.getLogManager();
    Logger     result;

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

    /* Without synchronized(lm), it could happen that another thread
     * would create a logger between our calls to getLogger and
     * addLogger.  While addLogger would indicate this by returning
     * false, we could not be sure that this other logger was still
     * existing when we called getLogger a second time in order
     * to retrieve it -- note that LogManager is only allowed to
     * keep weak references to registered loggers, so Loggers
     * can be garbage collected at any time in general, and between
     * our call to addLogger and our second call go getLogger
     * in particular.
     *
     * Of course, we assume here that LogManager.addLogger etc.
     * are synchronizing on the global LogManager object. There
     * is a comment in the implementation of LogManager.addLogger
     * referring to this comment here, so that any change in
     * the synchronization of LogManager will be reflected here.
     */
    synchronized (lm)
    {
      result = lm.getLogger(name);
      if (result == null)
      {
	boolean couldBeAdded;

	result = new Logger(name, resourceBundleName);
	couldBeAdded = lm.addLogger(result);
	if (!couldBeAdded)
	  throw new IllegalStateException("cannot register new logger");
      }
      else
      {
	/* The logger already exists. Make sure it uses
	 * the same resource bundle for localizing messages.
	 */
	String existingBundleName = result.getResourceBundleName();

	/* The Sun J2SE 1.4 reference implementation will return the
	 * registered logger object, even if it does not have a resource
	 * bundle associated with it. However, it seems to change the
	 * resourceBundle of the registered logger to the bundle
	 * whose name was passed to getLogger.
	 */
	if ((existingBundleName == null) && (resourceBundleName != null))
	{
	  /* If ResourceBundle.getBundle throws an exception, the
	   * existing logger will be unchanged.  This would be
	   * different if the assignment to resourceBundleName
	   * came first.
	   */
	  result.resourceBundle = ResourceBundle.getBundle(resourceBundleName);
	  result.resourceBundleName = resourceBundleName;
	  return result;
	}

	if ((existingBundleName != resourceBundleName)
	    && ((existingBundleName == null)
		|| !existingBundleName.equals(resourceBundleName)))
	{
	  throw new IllegalArgumentException();
	}
      }
    }

    return result;
  }

  
  /**
   * Creates a new, unnamed logger.  Unnamed loggers are not
   * registered in the namespace of the LogManager, and no special
   * security permission is required for changing their state.
   * Therefore, untrusted applets are able to modify their private
   * logger instance obtained through this method.
   *
   * <p>The parent of the newly created logger will the the root
   * logger, from which the level threshold and the handlers are
   * inherited.
   */
  public static Logger getAnonymousLogger()
  {
    return getAnonymousLogger(null);
  }


  /**
   * Creates a new, unnamed logger.  Unnamed loggers are not
   * registered in the namespace of the LogManager, and no special
   * security permission is required for changing their state.
   * Therefore, untrusted applets are able to modify their private
   * logger instance obtained through this method.
   *
   * <p>The parent of the newly created logger will the the root
   * logger, from which the level threshold and the handlers are
   * inherited.
   *
   * @param resourceBundleName the name of a resource bundle
   *        for localizing messages, or <code>null</code>
   *	    to indicate that messages do not need to be localized.
   *
   * @throws java.util.MissingResourceException if
   *         <code>resourceBundleName</code> is not <code>null</code>
   *         and no such bundle could be located.
   */
  public static Logger getAnonymousLogger(String resourceBundleName)
    throws MissingResourceException
  {
    Logger  result;

    result = new Logger(null, resourceBundleName);
    result.anonymous = true;
    return result;
  }


  /**
   * Returns the name of the resource bundle that is being used for
   * localizing messages.
   *
   * @return the name of the resource bundle used for localizing messages,
   *         or <code>null</code> if the parent's resource bundle
   *         is used for this purpose.
   */
  public synchronized String getResourceBundleName()
  {
    return resourceBundleName;
  }


  /**
   * Returns the resource bundle that is being used for localizing
   * messages.
   *
   * @return the resource bundle used for localizing messages,
   *         or <code>null</code> if the parent's resource bundle
   *         is used for this purpose.
   */
  public synchronized ResourceBundle getResourceBundle()
  {
    return resourceBundle;
  }


  /**
   * Returns the severity level threshold for this <code>Handler</code>.
   * All log records with a lower severity level will be discarded;
   * a log record of the same or a higher level will be published
   * unless an installed <code>Filter</code> decides to discard it.
   *
   * @return the severity level below which all log messages will be
   *         discarded, or <code>null</code> if the logger inherits
   *         the threshold from its parent.
   */
  public synchronized Level getLevel()
  {
    return level;
  }


  /**
   * Returns whether or not a message of the specified level
   * would be logged by this logger.
   *
   * @throws NullPointerException if <code>level</code>
   *         is <code>null</code>.
   */
  public synchronized boolean isLoggable(Level level)
  {
    if (this.level != null)
      return this.level.intValue() <= level.intValue();

    if (parent != null)
      return parent.isLoggable(level);
    else
      return false;
  }


  /**
   * Sets the severity level threshold for this <code>Handler</code>.
   * All log records with a lower severity level will be discarded
   * immediately.  A log record of the same or a higher level will be
   * published unless an installed <code>Filter</code> decides to
   * discard it.
   *
   * @param level the severity level below which all log messages
   *              will be discarded, or <code>null</code> to
   *              indicate that the logger should inherit the
   *              threshold from its parent.
   *
   * @throws SecurityException if this logger is not anonymous, a
   *     security manager exists, and the caller is not granted
   *     the permission to control the logging infrastructure by
   *     having LoggingPermission("control").  Untrusted code can
   *     obtain an anonymous logger through the static factory method
   *     {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
   */
  public synchronized void setLevel(Level level)
  {
    /* An application is allowed to control an anonymous logger
     * without having the permission to control the logging
     * infrastructure.
     */
    if (!anonymous)
      LogManager.getLogManager().checkAccess();

    this.level = level;
  }


  public synchronized Filter getFilter()
  {
    return filter;
  }


  /**
   * @throws SecurityException if this logger is not anonymous, a
   *     security manager exists, and the caller is not granted
   *     the permission to control the logging infrastructure by
   *     having LoggingPermission("control").  Untrusted code can
   *     obtain an anonymous logger through the static factory method
   *     {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
   */
  public synchronized void setFilter(Filter filter)
    throws SecurityException
  {
    /* An application is allowed to control an anonymous logger
     * without having the permission to control the logging
     * infrastructure.
     */
    if (!anonymous)
      LogManager.getLogManager().checkAccess();

    this.filter = filter;
  }




  /**
   * Returns the name of this logger.
   *
   * @return the name of this logger, or <code>null</code> if
   *         the logger is anonymous.
   */
  public String getName()
  {
    /* Note that the name of a logger cannot be changed during
     * its lifetime, so no synchronization is needed.
     */
    return name;
  }


  /**
   * Passes a record to registered handlers, provided the record
   * is considered as loggable both by {@link #isLoggable(Level)}
   * and a possibly installed custom {@link #setFilter(Filter) filter}.
   *
   * <p>If the logger has been configured to use parent handlers,
   * the record will be forwarded to the parent of this logger
   * in addition to being processed by the handlers registered with
   * this logger.
   *
   * <p>The other logging methods in this class are convenience methods
   * that merely create a new LogRecord and pass it to this method.
   * Therefore, subclasses usually just need to override this single
   * method for customizing the logging behavior.
   *
   * @param record the log record to be inspected and possibly forwarded.
   */
  public synchronized void log(LogRecord record)
  {
    if (!isLoggable(record.getLevel()))
      return;

    if ((filter != null) && !filter.isLoggable(record))
      return;

    /* If no logger name has been set for the log record,
     * use the name of this logger.
     */
    if (record.getLoggerName() == null)
      record.setLoggerName(name);

    /* Avoid that some other thread is changing the logger hierarchy
     * while we are traversing it.
     */
    synchronized (LogManager.getLogManager())
    {
      Logger curLogger = this;

      do
      {
        /* The Sun J2SE 1.4 reference implementation seems to call the
	 * filter only for the logger whose log method is called,
	 * never for any of its parents.  Also, parent loggers publish
	 * log record whatever their level might be.  This is pretty
	 * weird, but GNU Classpath tries to be as compatible as
	 * possible to the reference implementation.
	 */
        for (int i = 0; i < curLogger.handlers.length; i++)
          curLogger.handlers[i].publish(record);

	if (curLogger.getUseParentHandlers() == false)
	  break;
	
	curLogger = curLogger.getParent();
      }
      while (parent != null);
    }
  }


  public void log(Level level, String message)
  {
    log(level, message, (Object[]) null);
  }


  public synchronized void log(Level level,
			       String message,
			       Object param)
  {
  	StackTraceElement caller = getCallerStackFrame();
    logp(level,
	 caller.getClassName(),
	 caller.getMethodName(),
	 message,
	 param);
  }


  public synchronized void log(Level level,
			       String message,
			       Object[] params)
  {
    StackTraceElement caller = getCallerStackFrame();
    logp(level,
	 caller.getClassName(),
	 caller.getMethodName(),
	 message,
	 params);
  }


  public synchronized void log(Level level,
			       String message,
			       Throwable thrown)
  {
	StackTraceElement caller = getCallerStackFrame();    
    logp(level,
	 caller.getClassName(),
	 caller.getMethodName(),
	 message,
	 thrown);
  }


  public synchronized void logp(Level level,
				String sourceClass,
				String sourceMethod,
				String message)
  {
    logp(level, sourceClass, sourceMethod, message,
	 (Object[]) null);
  }


  public synchronized void logp(Level level,
				String sourceClass,
				String sourceMethod,
				String message,
				Object param)
  {
    logp(level, sourceClass, sourceMethod, message,
	 new Object[] { param });
  }


  private synchronized ResourceBundle findResourceBundle()
  {
    if (resourceBundle != null)
      return resourceBundle;

    if (parent != null)
      return parent.findResourceBundle();

    return null;
  }


  private synchronized void logImpl(Level level,
				    String sourceClass,
				    String sourceMethod,
				    String message,
				    Object[] params)
  {
    LogRecord rec = new LogRecord(level, message);

    rec.setResourceBundle(findResourceBundle());
    rec.setSourceClassName(sourceClass);
    rec.setSourceMethodName(sourceMethod);
    rec.setParameters(params);

    log(rec);
  }


  public synchronized void logp(Level level,
				String sourceClass,
				String sourceMethod,
				String message,
				Object[] params)
  {
    logImpl(level, sourceClass, sourceMethod, message, params);
  }


  public synchronized void logp(Level level,
				String sourceClass,
				String sourceMethod,
				String message,
				Throwable thrown)
  {
    LogRecord rec = new LogRecord(level, message);

    rec.setResourceBundle(resourceBundle);
    rec.setSourceClassName(sourceClass);
    rec.setSourceMethodName(sourceMethod);
    rec.setThrown(thrown);

    log(rec);
  }


  public synchronized void logrb(Level level,
				 String sourceClass,
				 String sourceMethod,
				 String bundleName,
				 String message)
  {
    logrb(level, sourceClass, sourceMethod, bundleName,
	  message, (Object[]) null);
  }


  public synchronized void logrb(Level level,
				 String sourceClass,
				 String sourceMethod,
				 String bundleName,
				 String message,
				 Object param)
  {
    logrb(level, sourceClass, sourceMethod, bundleName,
	  message, new Object[] { param });
  }


  public synchronized void logrb(Level level,
				 String sourceClass,
				 String sourceMethod,
				 String bundleName,
				 String message,
				 Object[] params)
  {
    LogRecord rec = new LogRecord(level, message);

    rec.setResourceBundleName(bundleName);
    rec.setSourceClassName(sourceClass);
    rec.setSourceMethodName(sourceMethod);
    rec.setParameters(params);

    log(rec);
  }


  public synchronized void logrb(Level level,
				 String sourceClass,
				 String sourceMethod,
				 String bundleName,
				 String message,
				 Throwable thrown)
  {
    LogRecord rec = new LogRecord(level, message);

    rec.setResourceBundleName(bundleName);
    rec.setSourceClassName(sourceClass);
    rec.setSourceMethodName(sourceMethod);
    rec.setThrown(thrown);

    log(rec);
  }


  public synchronized void entering(String sourceClass,
				    String sourceMethod)
  {
    if (isLoggable(Level.FINER))
      logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
  }


  public synchronized void entering(String sourceClass,
				    String sourceMethod,
				    Object param)
  {
    if (isLoggable(Level.FINER))
      logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param);
  }


  public synchronized void entering(String sourceClass,
				    String sourceMethod,
				    Object[] params)
  {
    if (isLoggable(Level.FINER))
    {
      StringBuffer buf = new StringBuffer(80);
      buf.append("ENTRY");
      for (int i = 0; i < params.length; i++)
      {
	buf.append(" {");
	buf.append(i);
	buf.append('}');
      }
      
      logp(Level.FINER, sourceClass, sourceMethod, buf.toString(), params);
    }
  }


  public synchronized void exiting(String sourceClass,
				   String sourceMethod)
  {
    if (isLoggable(Level.FINER))
      logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
  }

   
  public synchronized void exiting(String sourceClass,
				   String sourceMethod,
				   Object result)
  {
    if (isLoggable(Level.FINER))
      logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
  }

 
  public synchronized void throwing(String sourceClass,
				    String sourceMethod,
				    Throwable thrown)
  {
    if (isLoggable(Level.FINER))
      logp(Level.FINER, sourceClass, sourceMethod, "THROW", thrown);
  }


  /**
   * Logs a message with severity level SEVERE, indicating a serious
   * failure that prevents normal program execution.  Messages at this
   * level should be understandable to an inexperienced, non-technical
   * end user.  Ideally, they explain in simple words what actions the
   * user can take in order to resolve the problem.
   *
   * @see Level#SEVERE
   *
   * @param message the message text, also used as look-up key if the
   *                logger is localizing messages with a resource
   *                bundle.  While it is possible to pass
   *                <code>null</code>, this is not recommended, since
   *                a logging message without text is unlikely to be
   *                helpful.
   */
  public synchronized void severe(String message)
  {
    if (isLoggable(Level.SEVERE))
      log(Level.SEVERE, message);
  }


  /**
   * Logs a message with severity level WARNING, indicating a
   * potential problem that does not prevent normal program execution.
   * Messages at this level should be understandable to an
   * inexperienced, non-technical end user.  Ideally, they explain in
   * simple words what actions the user can take in order to resolve
   * the problem.
   *
   * @see Level#WARNING
   *
   * @param message the message text, also used as look-up key if the
   *                logger is localizing messages with a resource
   *                bundle.  While it is possible to pass
   *                <code>null</code>, this is not recommended, since
   *                a logging message without text is unlikely to be
   *                helpful.
   */
  public synchronized void warning(String message)
  {
    if (isLoggable(Level.WARNING))
      log(Level.WARNING, message);
  }


  /**
   * Logs a message with severity level INFO.  {@link Level#INFO} is
   * intended for purely informational messages that do not indicate
   * error or warning situations. In the default logging
   * configuration, INFO messages will be written to the system
   * console.  For this reason, the INFO level should be used only for
   * messages that are important to end users and system
   * administrators.  Messages at this level should be understandable
   * to an inexperienced, non-technical user.
   *
   * @param message the message text, also used as look-up key if the
   *                logger is localizing messages with a resource
   *                bundle.  While it is possible to pass
   *                <code>null</code>, this is not recommended, since
   *                a logging message without text is unlikely to be
   *                helpful.
   */
  public synchronized void info(String message)
  {
    if (isLoggable(Level.INFO))
      log(Level.INFO, message);
  }


  /**
   * Logs a message with severity level CONFIG.  {@link Level#CONFIG} is
   * intended for static configuration messages, for example about the
   * windowing environment, the operating system version, etc.
   *
   * @param message the message text, also used as look-up key if the
   *     logger is localizing messages with a resource bundle.  While
   *     it is possible to pass <code>null</code>, this is not
   *     recommended, since a logging message without text is unlikely
   *     to be helpful.
   */
  public synchronized void config(String message)
  {
    if (isLoggable(Level.CONFIG))
      log(Level.CONFIG, message);
  }


  /**
   * Logs a message with severity level FINE.  {@link Level#FINE} is
   * intended for messages that are relevant for developers using
   * the component generating log messages. Examples include minor,
   * recoverable failures, or possible inefficiencies.
   *
   * @param message the message text, also used as look-up key if the
   *                logger is localizing messages with a resource
   *                bundle.  While it is possible to pass
   *                <code>null</code>, this is not recommended, since
   *                a logging message without text is unlikely to be
   *                helpful.
   */
  public synchronized void fine(String message)
  {
    if (isLoggable(Level.FINE))
      log(Level.FINE, message);
  }


  /**
   * Logs a message with severity level FINER.  {@link Level#FINER} is
   * intended for rather detailed tracing, for example entering a
   * method, returning from a method, or throwing an exception.
   *
   * @param message the message text, also used as look-up key if the
   *                logger is localizing messages with a resource
   *                bundle.  While it is possible to pass
   *                <code>null</code>, this is not recommended, since
   *                a logging message without text is unlikely to be
   *                helpful.
   */
  public synchronized void finer(String message)
  {
    if (isLoggable(Level.FINER))
      log(Level.FINER, message);
  }


  /**
   * Logs a message with severity level FINEST.  {@link Level#FINEST}
   * is intended for highly detailed tracing, for example reaching a
   * certain point inside the body of a method.
   *
   * @param message the message text, also used as look-up key if the
   *                logger is localizing messages with a resource
   *                bundle.  While it is possible to pass
   *                <code>null</code>, this is not recommended, since
   *                a logging message without text is unlikely to be
   *                helpful.
   */
  public synchronized void finest(String message)
  {
    if (isLoggable(Level.FINEST))
      log(Level.FINEST, message);
  }


  /**
   * Adds a handler to the set of handlers that get notified
   * when a log record is to be published.
   *
   * @param handler the handler to be added.
   *
   * @throws NullPointerException if <code>handler</code>
   *     is <code>null</code>.
   *
   * @throws SecurityException if this logger is not anonymous, a
   *     security manager exists, and the caller is not granted
   *     the permission to control the logging infrastructure by
   *     having LoggingPermission("control").  Untrusted code can
   *     obtain an anonymous logger through the static factory method
   *     {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
   */
  public synchronized void addHandler(Handler handler)
    throws SecurityException
  {
    /* Throw a new NullPointerException if handler is null. */
    handler.getClass();

    /* An application is allowed to control an anonymous logger
     * without having the permission to control the logging
     * infrastructure.
     */
    if (!anonymous)
      LogManager.getLogManager().checkAccess();

    if (!handlerList.contains(handler))
    {
      handlerList.add(handler);
      handlers = getHandlers();
    }
  }


  /**
   * Removes a handler from the set of handlers that get notified
   * when a log record is to be published.
   *
   * @param handler the handler to be removed.
   *
   * @throws SecurityException if this logger is not anonymous, a
   *     security manager exists, and the caller is not granted the
   *     permission to control the logging infrastructure by having
   *     LoggingPermission("control").  Untrusted code can obtain an
   *     anonymous logger through the static factory method {@link
   *     #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
   *
   * @throws NullPointerException if <code>handler</code>
   *     is <code>null</code>.
   */
  public synchronized void removeHandler(Handler handler)
    throws SecurityException
  {
    /* An application is allowed to control an anonymous logger
     * without having the permission to control the logging
     * infrastructure.
     */
    if (!anonymous)
      LogManager.getLogManager().checkAccess();

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

    handlerList.remove(handler);
    handlers = getHandlers();
  }


  /**
   * Returns the handlers currently registered for this Logger.
   * When a log record has been deemed as being loggable,
   * it will be passed to all registered handlers for
   * publication.  In addition, if the logger uses parent handlers
   * (see {@link #getUseParentHandlers() getUseParentHandlers}
   * and {@link #setUseParentHandlers(boolean) setUseParentHandlers},
   * the log record will be passed to the parent's handlers.
   */
  public synchronized Handler[] getHandlers()
  {
    /* We cannot return our internal handlers array
     * because we do not have any guarantee that the
     * caller would not change the array entries.
     */
    return (Handler[]) handlerList.toArray(new Handler[handlerList.size()]);
  }


  /**
   * Returns whether or not this Logger forwards log records to
   * handlers registered for its parent loggers.
   *
   * @return <code>false</code> if this Logger sends log records
   *         merely to Handlers registered with itself;
   *         <code>true</code> if this Logger sends log records
   *         not only to Handlers registered with itself, but also
   *         to those Handlers registered with parent loggers.
   */
  public synchronized boolean getUseParentHandlers()
  {
    return useParentHandlers;
  }


  /**
   * Sets whether or not this Logger forwards log records to
   * handlers registered for its parent loggers.
   *
   * @param useParentHandlers <code>false</code> to let this
   *         Logger send log records merely to Handlers registered
   *         with itself; <code>true</code> to let this Logger
   *         send log records not only to Handlers registered
   *         with itself, but also to those Handlers registered with
   *         parent loggers.
   *
   * @throws SecurityException if this logger is not anonymous, a
   *     security manager exists, and the caller is not granted
   *     the permission to control the logging infrastructure by
   *     having LoggingPermission("control").  Untrusted code can
   *     obtain an anonymous logger through the static factory method
   *     {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
   *
   */
  public synchronized void setUseParentHandlers(boolean useParentHandlers)
  {
    /* An application is allowed to control an anonymous logger
     * without having the permission to control the logging
     * infrastructure.
     */
    if (!anonymous)
      LogManager.getLogManager().checkAccess();

    this.useParentHandlers = useParentHandlers;
  }


  /**
   * Returns the parent of this logger.  By default, the parent is
   * assigned by the LogManager by inspecting the logger's name.
   *
   * @return the parent of this logger (as detemined by the LogManager
   *     by inspecting logger names), the root logger if no other
   *     logger has a name which is a prefix of this logger's name, or
   *     <code>null</code> for the root logger.
   */
  public synchronized Logger getParent()
  {
    return parent;
  }


  /**
   * Sets the parent of this logger.  Usually, applications do not
   * call this method directly.  Instead, the LogManager will ensure
   * that the tree of loggers reflects the hierarchical logger
   * namespace.  Basically, this method should not be public at all,
   * but the GNU implementation follows the API specification.
   *
   * @throws NullPointerException if <code>parent</code> is
   *     <code>null</code>.
   *
   * @throws SecurityException if this logger is not anonymous, a
   *     security manager exists, and the caller is not granted
   *     the permission to control the logging infrastructure by
   *     having LoggingPermission("control").  Untrusted code can
   *     obtain an anonymous logger through the static factory method
   *     {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
   */
  public synchronized void setParent(Logger parent)
  {
    LogManager lm;

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

    lm = LogManager.getLogManager();

    if (this == lm.rootLogger)
    {
      if (parent != null)
        throw new IllegalArgumentException(
          "only the root logger can have a null parent");
      this.parent = null;
      return;
    }

    /* 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 looging method
   */
  private StackTraceElement getCallerStackFrame()
  {
    Throwable t = new Throwable();
    StackTraceElement[] stackTrace = t.getStackTrace();
    int index = 0;
    // skip to stackentries until this class
    while(!stackTrace[index].getClassName().equals(getClass().getName())){index++;}
    // skip the stackentries of this class
    while(stackTrace[index].getClassName().equals(getClass().getName())){index++;}

    return stackTrace[index];
  }
  
}
