mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1207 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1207 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* Logger.java -- a class for logging messages
 | |
|    Copyright (C) 2002, 2004, 2006, 2007 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| 
 | |
| package java.util.logging;
 | |
| 
 | |
| import java.util.List;
 | |
| import java.util.MissingResourceException;
 | |
| import java.util.ResourceBundle;
 | |
| import java.security.AccessController;
 | |
| import java.security.PrivilegedAction;
 | |
| 
 | |
| /**
 | |
|  * A Logger is used for logging information about events. Usually, there
 | |
|  * is a seprate logger for each subsystem or component, although there
 | |
|  * is a shared instance for components that make only occasional use of
 | |
|  * the logging framework.
 | |
|  *
 | |
|  * <p>It is common to name a logger after the name of a corresponding
 | |
|  * Java package.  Loggers are organized into a hierarchical namespace;
 | |
|  * for example, the logger <code>"org.gnu.foo"</code> is the
 | |
|  * <em>parent</em> of logger <code>"org.gnu.foo.bar"</code>.
 | |
|  *
 | |
|  * <p>A logger for a named subsystem can be obtained through {@link
 | |
|  * java.util.logging.Logger#getLogger(java.lang.String)}.  However,
 | |
|  * only code which has been granted the permission to control the
 | |
|  * logging infrastructure will be allowed to customize that logger.
 | |
|  * Untrusted code can obtain a private, anonymous logger through
 | |
|  * {@link #getAnonymousLogger()} if it wants to perform any
 | |
|  * modifications to the logger.
 | |
|  *
 | |
|  * <p>FIXME: Write more documentation.
 | |
|  *
 | |
|  * @author Sascha Brawer (brawer@acm.org)
 | |
|  */
 | |
| public class Logger
 | |
| {
 | |
| 
 | |
|   static final Logger root = new Logger("", null);
 | |
| 
 | |
|   /**
 | |
|    * A logger provided to applications that make only occasional use
 | |
|    * of the logging framework, typically early prototypes.  Serious
 | |
|    * products are supposed to create and use their own Loggers, so
 | |
|    * they can be controlled individually.
 | |
|    */
 | |
|   public static final Logger global;
 | |
| 
 | |
|   static
 | |
|     {
 | |
|       // Our class might be initialized from an unprivileged context
 | |
|       global = (Logger) AccessController.doPrivileged
 | |
| 	(new PrivilegedAction()
 | |
| 	  {
 | |
| 	    public Object run()
 | |
| 	    {
 | |
| 	      return getLogger("global");
 | |
| 	    }
 | |
| 	  });
 | |
|     }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * The name of the Logger, or <code>null</code> if the logger is
 | |
|    * anonymous.
 | |
|    *
 | |
|    * <p>A previous version of the GNU Classpath implementation granted
 | |
|    * untrusted code the permission to control any logger whose name
 | |
|    * was null.  However, test code revealed that the Sun J2SE 1.4
 | |
|    * reference implementation enforces the security control for any
 | |
|    * logger that was not created through getAnonymousLogger, even if
 | |
|    * it has a null name.  Therefore, a separate flag {@link
 | |
|    * Logger#anonymous} was introduced.
 | |
|    */
 | |
|   private final String name;
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * The name of the resource bundle used for localization.
 | |
|    *
 | |
|    * <p>This variable cannot be declared as <code>final</code>
 | |
|    * because its value can change as a result of calling
 | |
|    * getLogger(String,String).
 | |
|    */
 | |
|   private String resourceBundleName;
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * The resource bundle used for localization.
 | |
|    *
 | |
|    * <p>This variable cannot be declared as <code>final</code>
 | |
|    * because its value can change as a result of calling
 | |
|    * getLogger(String,String).
 | |
|    */
 | |
|   private ResourceBundle resourceBundle;
 | |
| 
 | |
|   private Filter filter;
 | |
| 
 | |
|   private final List handlerList = new java.util.ArrayList(4);
 | |
|   private Handler[] handlers = new Handler[0];
 | |
| 
 | |
|   /**
 | |
|    * Indicates whether or not this logger is anonymous.  While
 | |
|    * a LoggingPermission is required for any modifications to
 | |
|    * a normal logger, untrusted code can obtain an anonymous logger
 | |
|    * and modify it according to its needs.
 | |
|    *
 | |
|    * <p>A previous version of the GNU Classpath implementation
 | |
|    * granted access to every logger whose name was null.
 | |
|    * However, test code revealed that the Sun J2SE 1.4 reference
 | |
|    * implementation enforces the security control for any logger
 | |
|    * that was not created through getAnonymousLogger, even
 | |
|    * if it has a null name.
 | |
|    */
 | |
|   private boolean anonymous;
 | |
| 
 | |
| 
 | |
|   private boolean useParentHandlers;
 | |
| 
 | |
|   private Level level;
 | |
| 
 | |
|   private Logger parent;
 | |
| 
 | |
|   /**
 | |
|    * Constructs a Logger for a subsystem.  Most applications do not
 | |
|    * need to create new Loggers explicitly; instead, they should call
 | |
|    * the static factory methods
 | |
|    * {@link #getLogger(java.lang.String,java.lang.String) getLogger}
 | |
|    * (with ResourceBundle for localization) or
 | |
|    * {@link #getLogger(java.lang.String) getLogger} (without
 | |
|    * ResourceBundle), respectively.
 | |
|    *
 | |
|    * @param name the name for the logger, for example "java.awt"
 | |
|    *             or "com.foo.bar". The name should be based on
 | |
|    *             the name of the package issuing log records
 | |
|    *             and consist of dot-separated Java identifiers.
 | |
|    *
 | |
|    * @param resourceBundleName the name of a resource bundle
 | |
|    *        for localizing messages, or <code>null</code>
 | |
|    *	    to indicate that messages do not need to be localized.
 | |
|    *
 | |
|    * @throws java.util.MissingResourceException if
 | |
|    *         <code>resourceBundleName</code> is not <code>null</code>
 | |
|    *         and no such bundle could be located.
 | |
|    */
 | |
|   protected Logger(String name, String resourceBundleName)
 | |
|     throws MissingResourceException
 | |
|   {
 | |
|     this.name = name;
 | |
|     this.resourceBundleName = resourceBundleName;
 | |
| 
 | |
|     if (resourceBundleName == null)
 | |
|       resourceBundle = null;
 | |
|     else
 | |
|       resourceBundle = ResourceBundle.getBundle(resourceBundleName);
 | |
| 
 | |
|     level = null;
 | |
| 
 | |
|     /* This is null when the root logger is being constructed,
 | |
|      * and the root logger afterwards.
 | |
|      */
 | |
|     parent = root;
 | |
| 
 | |
|     useParentHandlers = (parent != null);
 | |
|   }
 | |
| 
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Finds a registered logger for a subsystem, or creates one in
 | |
|    * case no logger has been registered yet.
 | |
|    *
 | |
|    * @param name the name for the logger, for example "java.awt"
 | |
|    *             or "com.foo.bar". The name should be based on
 | |
|    *             the name of the package issuing log records
 | |
|    *             and consist of dot-separated Java identifiers.
 | |
|    *
 | |
|    * @throws IllegalArgumentException if a logger for the subsystem
 | |
|    *         identified by <code>name</code> has already been created,
 | |
|    *         but uses a a resource bundle for localizing messages.
 | |
|    *
 | |
|    * @throws NullPointerException if <code>name</code> is
 | |
|    *         <code>null</code>.
 | |
|    *
 | |
|    * @return a logger for the subsystem specified by <code>name</code>
 | |
|    *         that does not localize messages.
 | |
|    */
 | |
|   public static Logger getLogger(String name)
 | |
|   {
 | |
|     return getLogger(name, null);
 | |
|   }
 | |
| 
 | |
|     
 | |
|   /**
 | |
|    * Finds a registered logger for a subsystem, or creates one in case
 | |
|    * no logger has been registered yet.
 | |
|    *
 | |
|    * <p>If a logger with the specified name has already been
 | |
|    * registered, the behavior depends on the resource bundle that is
 | |
|    * currently associated with the existing logger.
 | |
|    *
 | |
|    * <ul><li>If the existing logger uses the same resource bundle as
 | |
|    * specified by <code>resourceBundleName</code>, the existing logger
 | |
|    * is returned.</li>
 | |
|    *
 | |
|    * <li>If the existing logger currently does not localize messages,
 | |
|    * the existing logger is modified to use the bundle specified by
 | |
|    * <code>resourceBundleName</code>.  The existing logger is then
 | |
|    * returned.  Therefore, all subsystems currently using this logger
 | |
|    * will produce localized messages from now on.</li>
 | |
|    *
 | |
|    * <li>If the existing logger already has an associated resource
 | |
|    * bundle, but a different one than specified by
 | |
|    * <code>resourceBundleName</code>, an
 | |
|    * <code>IllegalArgumentException</code> is thrown.</li></ul>
 | |
|    *
 | |
|    * @param name the name for the logger, for example "java.awt"
 | |
|    *             or "org.gnu.foo". The name should be based on
 | |
|    *             the name of the package issuing log records
 | |
|    *             and consist of dot-separated Java identifiers.
 | |
|    *
 | |
|    * @param resourceBundleName the name of a resource bundle
 | |
|    *        for localizing messages, or <code>null</code>
 | |
|    *	    to indicate that messages do not need to be localized.
 | |
|    *
 | |
|    * @return a logger for the subsystem specified by <code>name</code>.
 | |
|    *
 | |
|    * @throws java.util.MissingResourceException if
 | |
|    *         <code>resourceBundleName</code> is not <code>null</code>
 | |
|    *         and no such bundle could be located.   
 | |
|    *
 | |
|    * @throws IllegalArgumentException if a logger for the subsystem
 | |
|    *         identified by <code>name</code> has already been created,
 | |
|    *         but uses a different resource bundle for localizing
 | |
|    *         messages.
 | |
|    *
 | |
|    * @throws NullPointerException if <code>name</code> is
 | |
|    *         <code>null</code>.
 | |
|    */
 | |
|   public static Logger getLogger(String name, String resourceBundleName)
 | |
|   {
 | |
|     LogManager lm = LogManager.getLogManager();
 | |
|     Logger     result;
 | |
| 
 | |
|     if (name == null)
 | |
|       throw new NullPointerException();
 | |
| 
 | |
|     /* Without synchronized(lm), it could happen that another thread
 | |
|      * would create a logger between our calls to getLogger and
 | |
|      * addLogger.  While addLogger would indicate this by returning
 | |
|      * false, we could not be sure that this other logger was still
 | |
|      * existing when we called getLogger a second time in order
 | |
|      * to retrieve it -- note that LogManager is only allowed to
 | |
|      * keep weak references to registered loggers, so Loggers
 | |
|      * can be garbage collected at any time in general, and between
 | |
|      * our call to addLogger and our second call go getLogger
 | |
|      * in particular.
 | |
|      *
 | |
|      * Of course, we assume here that LogManager.addLogger etc.
 | |
|      * are synchronizing on the global LogManager object. There
 | |
|      * is a comment in the implementation of LogManager.addLogger
 | |
|      * referring to this comment here, so that any change in
 | |
|      * the synchronization of LogManager will be reflected here.
 | |
|      */
 | |
|     synchronized (lm)
 | |
|     {
 | |
|       result = lm.getLogger(name);
 | |
|       if (result == null)
 | |
|       {
 | |
| 	boolean couldBeAdded;
 | |
| 
 | |
| 	result = new Logger(name, resourceBundleName);
 | |
| 	couldBeAdded = lm.addLogger(result);
 | |
| 	if (!couldBeAdded)
 | |
| 	  throw new IllegalStateException("cannot register new logger");
 | |
|       }
 | |
|       else
 | |
|       {
 | |
| 	/* The logger already exists. Make sure it uses
 | |
| 	 * the same resource bundle for localizing messages.
 | |
| 	 */
 | |
| 	String existingBundleName = result.getResourceBundleName();
 | |
| 
 | |
| 	/* The Sun J2SE 1.4 reference implementation will return the
 | |
| 	 * registered logger object, even if it does not have a resource
 | |
| 	 * bundle associated with it. However, it seems to change the
 | |
| 	 * resourceBundle of the registered logger to the bundle
 | |
| 	 * whose name was passed to getLogger.
 | |
| 	 */
 | |
| 	if ((existingBundleName == null) && (resourceBundleName != null))
 | |
| 	{
 | |
| 	  /* If ResourceBundle.getBundle throws an exception, the
 | |
| 	   * existing logger will be unchanged.  This would be
 | |
| 	   * different if the assignment to resourceBundleName
 | |
| 	   * came first.
 | |
| 	   */
 | |
| 	  result.resourceBundle = ResourceBundle.getBundle(resourceBundleName);
 | |
| 	  result.resourceBundleName = resourceBundleName;
 | |
| 	  return result;
 | |
| 	}
 | |
| 
 | |
| 	if ((existingBundleName != resourceBundleName)
 | |
| 	    && ((existingBundleName == null)
 | |
| 		|| !existingBundleName.equals(resourceBundleName)))
 | |
| 	{
 | |
| 	  throw new IllegalArgumentException();
 | |
| 	}
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   
 | |
|   /**
 | |
|    * Creates a new, unnamed logger.  Unnamed loggers are not
 | |
|    * registered in the namespace of the LogManager, and no special
 | |
|    * security permission is required for changing their state.
 | |
|    * Therefore, untrusted applets are able to modify their private
 | |
|    * logger instance obtained through this method.
 | |
|    *
 | |
|    * <p>The parent of the newly created logger will the the root
 | |
|    * logger, from which the level threshold and the handlers are
 | |
|    * inherited.
 | |
|    */
 | |
|   public static Logger getAnonymousLogger()
 | |
|   {
 | |
|     return getAnonymousLogger(null);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Creates a new, unnamed logger.  Unnamed loggers are not
 | |
|    * registered in the namespace of the LogManager, and no special
 | |
|    * security permission is required for changing their state.
 | |
|    * Therefore, untrusted applets are able to modify their private
 | |
|    * logger instance obtained through this method.
 | |
|    *
 | |
|    * <p>The parent of the newly created logger will the the root
 | |
|    * logger, from which the level threshold and the handlers are
 | |
|    * inherited.
 | |
|    *
 | |
|    * @param resourceBundleName the name of a resource bundle
 | |
|    *        for localizing messages, or <code>null</code>
 | |
|    *	    to indicate that messages do not need to be localized.
 | |
|    *
 | |
|    * @throws java.util.MissingResourceException if
 | |
|    *         <code>resourceBundleName</code> is not <code>null</code>
 | |
|    *         and no such bundle could be located.
 | |
|    */
 | |
|   public static Logger getAnonymousLogger(String resourceBundleName)
 | |
|     throws MissingResourceException
 | |
|   {
 | |
|     Logger  result;
 | |
| 
 | |
|     result = new Logger(null, resourceBundleName);
 | |
|     result.anonymous = true;
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Returns the name of the resource bundle that is being used for
 | |
|    * localizing messages.
 | |
|    *
 | |
|    * @return the name of the resource bundle used for localizing messages,
 | |
|    *         or <code>null</code> if the parent's resource bundle
 | |
|    *         is used for this purpose.
 | |
|    */
 | |
|   public synchronized String getResourceBundleName()
 | |
|   {
 | |
|     return resourceBundleName;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Returns the resource bundle that is being used for localizing
 | |
|    * messages.
 | |
|    *
 | |
|    * @return the resource bundle used for localizing messages,
 | |
|    *         or <code>null</code> if the parent's resource bundle
 | |
|    *         is used for this purpose.
 | |
|    */
 | |
|   public synchronized ResourceBundle getResourceBundle()
 | |
|   {
 | |
|     return resourceBundle;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Returns the severity level threshold for this <code>Handler</code>.
 | |
|    * All log records with a lower severity level will be discarded;
 | |
|    * a log record of the same or a higher level will be published
 | |
|    * unless an installed <code>Filter</code> decides to discard it.
 | |
|    *
 | |
|    * @return the severity level below which all log messages will be
 | |
|    *         discarded, or <code>null</code> if the logger inherits
 | |
|    *         the threshold from its parent.
 | |
|    */
 | |
|   public synchronized Level getLevel()
 | |
|   {
 | |
|     return level;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Returns whether or not a message of the specified level
 | |
|    * would be logged by this logger.
 | |
|    *
 | |
|    * @throws NullPointerException if <code>level</code>
 | |
|    *         is <code>null</code>.
 | |
|    */
 | |
|   public synchronized boolean isLoggable(Level level)
 | |
|   {
 | |
|     if (this.level != null)
 | |
|       return this.level.intValue() <= level.intValue();
 | |
| 
 | |
|     if (parent != null)
 | |
|       return parent.isLoggable(level);
 | |
|     else
 | |
|       return false;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Sets the severity level threshold for this <code>Handler</code>.
 | |
|    * All log records with a lower severity level will be discarded
 | |
|    * immediately.  A log record of the same or a higher level will be
 | |
|    * published unless an installed <code>Filter</code> decides to
 | |
|    * discard it.
 | |
|    *
 | |
|    * @param level the severity level below which all log messages
 | |
|    *              will be discarded, or <code>null</code> to
 | |
|    *              indicate that the logger should inherit the
 | |
|    *              threshold from its parent.
 | |
|    *
 | |
|    * @throws SecurityException if this logger is not anonymous, a
 | |
|    *     security manager exists, and the caller is not granted
 | |
|    *     the permission to control the logging infrastructure by
 | |
|    *     having LoggingPermission("control").  Untrusted code can
 | |
|    *     obtain an anonymous logger through the static factory method
 | |
|    *     {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
 | |
|    */
 | |
|   public synchronized void setLevel(Level level)
 | |
|   {
 | |
|     /* An application is allowed to control an anonymous logger
 | |
|      * without having the permission to control the logging
 | |
|      * infrastructure.
 | |
|      */
 | |
|     if (!anonymous)
 | |
|       LogManager.getLogManager().checkAccess();
 | |
| 
 | |
|     this.level = level;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized Filter getFilter()
 | |
|   {
 | |
|     return filter;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * @throws SecurityException if this logger is not anonymous, a
 | |
|    *     security manager exists, and the caller is not granted
 | |
|    *     the permission to control the logging infrastructure by
 | |
|    *     having LoggingPermission("control").  Untrusted code can
 | |
|    *     obtain an anonymous logger through the static factory method
 | |
|    *     {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
 | |
|    */
 | |
|   public synchronized void setFilter(Filter filter)
 | |
|     throws SecurityException
 | |
|   {
 | |
|     /* An application is allowed to control an anonymous logger
 | |
|      * without having the permission to control the logging
 | |
|      * infrastructure.
 | |
|      */
 | |
|     if (!anonymous)
 | |
|       LogManager.getLogManager().checkAccess();
 | |
| 
 | |
|     this.filter = filter;
 | |
|   }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Returns the name of this logger.
 | |
|    *
 | |
|    * @return the name of this logger, or <code>null</code> if
 | |
|    *         the logger is anonymous.
 | |
|    */
 | |
|   public String getName()
 | |
|   {
 | |
|     /* Note that the name of a logger cannot be changed during
 | |
|      * its lifetime, so no synchronization is needed.
 | |
|      */
 | |
|     return name;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Passes a record to registered handlers, provided the record
 | |
|    * is considered as loggable both by {@link #isLoggable(Level)}
 | |
|    * and a possibly installed custom {@link #setFilter(Filter) filter}.
 | |
|    *
 | |
|    * <p>If the logger has been configured to use parent handlers,
 | |
|    * the record will be forwarded to the parent of this logger
 | |
|    * in addition to being processed by the handlers registered with
 | |
|    * this logger.
 | |
|    *
 | |
|    * <p>The other logging methods in this class are convenience methods
 | |
|    * that merely create a new LogRecord and pass it to this method.
 | |
|    * Therefore, subclasses usually just need to override this single
 | |
|    * method for customizing the logging behavior.
 | |
|    *
 | |
|    * @param record the log record to be inspected and possibly forwarded.
 | |
|    */
 | |
|   public synchronized void log(LogRecord record)
 | |
|   {
 | |
|     if (!isLoggable(record.getLevel()))
 | |
|       return;
 | |
| 
 | |
|     if ((filter != null) && !filter.isLoggable(record))
 | |
|       return;
 | |
| 
 | |
|     /* If no logger name has been set for the log record,
 | |
|      * use the name of this logger.
 | |
|      */
 | |
|     if (record.getLoggerName() == null)
 | |
|       record.setLoggerName(name);
 | |
| 
 | |
|     /* Avoid that some other thread is changing the logger hierarchy
 | |
|      * while we are traversing it.
 | |
|      */
 | |
|     synchronized (LogManager.getLogManager())
 | |
|     {
 | |
|       Logger curLogger = this;
 | |
| 
 | |
|       do
 | |
|       {
 | |
|         /* The Sun J2SE 1.4 reference implementation seems to call the
 | |
| 	 * filter only for the logger whose log method is called,
 | |
| 	 * never for any of its parents.  Also, parent loggers publish
 | |
| 	 * log record whatever their level might be.  This is pretty
 | |
| 	 * weird, but GNU Classpath tries to be as compatible as
 | |
| 	 * possible to the reference implementation.
 | |
| 	 */
 | |
|         for (int i = 0; i < curLogger.handlers.length; i++)
 | |
|           curLogger.handlers[i].publish(record);
 | |
| 
 | |
| 	if (curLogger.getUseParentHandlers() == false)
 | |
| 	  break;
 | |
| 	
 | |
| 	curLogger = curLogger.getParent();
 | |
|       }
 | |
|       while (parent != null);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public void log(Level level, String message)
 | |
|   {
 | |
|     if (isLoggable(level))
 | |
|       log(level, message, (Object[]) null);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void log(Level level,
 | |
| 			       String message,
 | |
| 			       Object param)
 | |
|   {
 | |
|     if (isLoggable(level))
 | |
|       {
 | |
|         StackTraceElement caller = getCallerStackFrame();
 | |
|         logp(level,
 | |
|              caller != null ? caller.getClassName() : "<unknown>",
 | |
|              caller != null ? caller.getMethodName() : "<unknown>",
 | |
|              message,
 | |
|              param);
 | |
|       }
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void log(Level level,
 | |
| 			       String message,
 | |
| 			       Object[] params)
 | |
|   {
 | |
|     if (isLoggable(level))
 | |
|       {
 | |
|         StackTraceElement caller = getCallerStackFrame();
 | |
|         logp(level,
 | |
|              caller != null ? caller.getClassName() : "<unknown>",
 | |
|              caller != null ? caller.getMethodName() : "<unknown>",
 | |
|              message,
 | |
|              params);
 | |
|       }
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void log(Level level,
 | |
| 			       String message,
 | |
| 			       Throwable thrown)
 | |
|   {
 | |
|     if (isLoggable(level))
 | |
|       {
 | |
|         StackTraceElement caller = getCallerStackFrame();    
 | |
|         logp(level,
 | |
|              caller != null ? caller.getClassName() : "<unknown>",
 | |
|              caller != null ? caller.getMethodName() : "<unknown>",
 | |
|              message,
 | |
|              thrown);
 | |
|       }
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void logp(Level level,
 | |
| 				String sourceClass,
 | |
| 				String sourceMethod,
 | |
| 				String message)
 | |
|   {
 | |
|     logp(level, sourceClass, sourceMethod, message,
 | |
| 	 (Object[]) null);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void logp(Level level,
 | |
| 				String sourceClass,
 | |
| 				String sourceMethod,
 | |
| 				String message,
 | |
| 				Object param)
 | |
|   {
 | |
|     logp(level, sourceClass, sourceMethod, message,
 | |
| 	 new Object[] { param });
 | |
|   }
 | |
| 
 | |
| 
 | |
|   private synchronized ResourceBundle findResourceBundle()
 | |
|   {
 | |
|     if (resourceBundle != null)
 | |
|       return resourceBundle;
 | |
| 
 | |
|     if (parent != null)
 | |
|       return parent.findResourceBundle();
 | |
| 
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   private synchronized void logImpl(Level level,
 | |
| 				    String sourceClass,
 | |
| 				    String sourceMethod,
 | |
| 				    String message,
 | |
| 				    Object[] params)
 | |
|   {
 | |
|     LogRecord rec = new LogRecord(level, message);
 | |
| 
 | |
|     rec.setResourceBundle(findResourceBundle());
 | |
|     rec.setSourceClassName(sourceClass);
 | |
|     rec.setSourceMethodName(sourceMethod);
 | |
|     rec.setParameters(params);
 | |
| 
 | |
|     log(rec);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void logp(Level level,
 | |
| 				String sourceClass,
 | |
| 				String sourceMethod,
 | |
| 				String message,
 | |
| 				Object[] params)
 | |
|   {
 | |
|     logImpl(level, sourceClass, sourceMethod, message, params);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void logp(Level level,
 | |
| 				String sourceClass,
 | |
| 				String sourceMethod,
 | |
| 				String message,
 | |
| 				Throwable thrown)
 | |
|   {
 | |
|     LogRecord rec = new LogRecord(level, message);
 | |
| 
 | |
|     rec.setResourceBundle(resourceBundle);
 | |
|     rec.setSourceClassName(sourceClass);
 | |
|     rec.setSourceMethodName(sourceMethod);
 | |
|     rec.setThrown(thrown);
 | |
| 
 | |
|     log(rec);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void logrb(Level level,
 | |
| 				 String sourceClass,
 | |
| 				 String sourceMethod,
 | |
| 				 String bundleName,
 | |
| 				 String message)
 | |
|   {
 | |
|     logrb(level, sourceClass, sourceMethod, bundleName,
 | |
| 	  message, (Object[]) null);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void logrb(Level level,
 | |
| 				 String sourceClass,
 | |
| 				 String sourceMethod,
 | |
| 				 String bundleName,
 | |
| 				 String message,
 | |
| 				 Object param)
 | |
|   {
 | |
|     logrb(level, sourceClass, sourceMethod, bundleName,
 | |
| 	  message, new Object[] { param });
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void logrb(Level level,
 | |
| 				 String sourceClass,
 | |
| 				 String sourceMethod,
 | |
| 				 String bundleName,
 | |
| 				 String message,
 | |
| 				 Object[] params)
 | |
|   {
 | |
|     LogRecord rec = new LogRecord(level, message);
 | |
| 
 | |
|     rec.setResourceBundleName(bundleName);
 | |
|     rec.setSourceClassName(sourceClass);
 | |
|     rec.setSourceMethodName(sourceMethod);
 | |
|     rec.setParameters(params);
 | |
| 
 | |
|     log(rec);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void logrb(Level level,
 | |
| 				 String sourceClass,
 | |
| 				 String sourceMethod,
 | |
| 				 String bundleName,
 | |
| 				 String message,
 | |
| 				 Throwable thrown)
 | |
|   {
 | |
|     LogRecord rec = new LogRecord(level, message);
 | |
| 
 | |
|     rec.setResourceBundleName(bundleName);
 | |
|     rec.setSourceClassName(sourceClass);
 | |
|     rec.setSourceMethodName(sourceMethod);
 | |
|     rec.setThrown(thrown);
 | |
| 
 | |
|     log(rec);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void entering(String sourceClass,
 | |
| 				    String sourceMethod)
 | |
|   {
 | |
|     if (isLoggable(Level.FINER))
 | |
|       logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void entering(String sourceClass,
 | |
| 				    String sourceMethod,
 | |
| 				    Object param)
 | |
|   {
 | |
|     if (isLoggable(Level.FINER))
 | |
|       logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void entering(String sourceClass,
 | |
| 				    String sourceMethod,
 | |
| 				    Object[] params)
 | |
|   {
 | |
|     if (isLoggable(Level.FINER))
 | |
|     {
 | |
|       StringBuffer buf = new StringBuffer(80);
 | |
|       buf.append("ENTRY");
 | |
|       for (int i = 0; i < params.length; i++)
 | |
|       {
 | |
| 	buf.append(" {");
 | |
| 	buf.append(i);
 | |
| 	buf.append('}');
 | |
|       }
 | |
|       
 | |
|       logp(Level.FINER, sourceClass, sourceMethod, buf.toString(), params);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| 
 | |
|   public synchronized void exiting(String sourceClass,
 | |
| 				   String sourceMethod)
 | |
|   {
 | |
|     if (isLoggable(Level.FINER))
 | |
|       logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
 | |
|   }
 | |
| 
 | |
|    
 | |
|   public synchronized void exiting(String sourceClass,
 | |
| 				   String sourceMethod,
 | |
| 				   Object result)
 | |
|   {
 | |
|     if (isLoggable(Level.FINER))
 | |
|       logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
 | |
|   }
 | |
| 
 | |
|  
 | |
|   public synchronized void throwing(String sourceClass,
 | |
| 				    String sourceMethod,
 | |
| 				    Throwable thrown)
 | |
|   {
 | |
|     if (isLoggable(Level.FINER))
 | |
|       logp(Level.FINER, sourceClass, sourceMethod, "THROW", thrown);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Logs a message with severity level SEVERE, indicating a serious
 | |
|    * failure that prevents normal program execution.  Messages at this
 | |
|    * level should be understandable to an inexperienced, non-technical
 | |
|    * end user.  Ideally, they explain in simple words what actions the
 | |
|    * user can take in order to resolve the problem.
 | |
|    *
 | |
|    * @see Level#SEVERE
 | |
|    *
 | |
|    * @param message the message text, also used as look-up key if the
 | |
|    *                logger is localizing messages with a resource
 | |
|    *                bundle.  While it is possible to pass
 | |
|    *                <code>null</code>, this is not recommended, since
 | |
|    *                a logging message without text is unlikely to be
 | |
|    *                helpful.
 | |
|    */
 | |
|   public synchronized void severe(String message)
 | |
|   {
 | |
|     if (isLoggable(Level.SEVERE))
 | |
|       log(Level.SEVERE, message);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Logs a message with severity level WARNING, indicating a
 | |
|    * potential problem that does not prevent normal program execution.
 | |
|    * Messages at this level should be understandable to an
 | |
|    * inexperienced, non-technical end user.  Ideally, they explain in
 | |
|    * simple words what actions the user can take in order to resolve
 | |
|    * the problem.
 | |
|    *
 | |
|    * @see Level#WARNING
 | |
|    *
 | |
|    * @param message the message text, also used as look-up key if the
 | |
|    *                logger is localizing messages with a resource
 | |
|    *                bundle.  While it is possible to pass
 | |
|    *                <code>null</code>, this is not recommended, since
 | |
|    *                a logging message without text is unlikely to be
 | |
|    *                helpful.
 | |
|    */
 | |
|   public synchronized void warning(String message)
 | |
|   {
 | |
|     if (isLoggable(Level.WARNING))
 | |
|       log(Level.WARNING, message);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Logs a message with severity level INFO.  {@link Level#INFO} is
 | |
|    * intended for purely informational messages that do not indicate
 | |
|    * error or warning situations. In the default logging
 | |
|    * configuration, INFO messages will be written to the system
 | |
|    * console.  For this reason, the INFO level should be used only for
 | |
|    * messages that are important to end users and system
 | |
|    * administrators.  Messages at this level should be understandable
 | |
|    * to an inexperienced, non-technical user.
 | |
|    *
 | |
|    * @param message the message text, also used as look-up key if the
 | |
|    *                logger is localizing messages with a resource
 | |
|    *                bundle.  While it is possible to pass
 | |
|    *                <code>null</code>, this is not recommended, since
 | |
|    *                a logging message without text is unlikely to be
 | |
|    *                helpful.
 | |
|    */
 | |
|   public synchronized void info(String message)
 | |
|   {
 | |
|     if (isLoggable(Level.INFO))
 | |
|       log(Level.INFO, message);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Logs a message with severity level CONFIG.  {@link Level#CONFIG} is
 | |
|    * intended for static configuration messages, for example about the
 | |
|    * windowing environment, the operating system version, etc.
 | |
|    *
 | |
|    * @param message the message text, also used as look-up key if the
 | |
|    *     logger is localizing messages with a resource bundle.  While
 | |
|    *     it is possible to pass <code>null</code>, this is not
 | |
|    *     recommended, since a logging message without text is unlikely
 | |
|    *     to be helpful.
 | |
|    */
 | |
|   public synchronized void config(String message)
 | |
|   {
 | |
|     if (isLoggable(Level.CONFIG))
 | |
|       log(Level.CONFIG, message);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Logs a message with severity level FINE.  {@link Level#FINE} is
 | |
|    * intended for messages that are relevant for developers using
 | |
|    * the component generating log messages. Examples include minor,
 | |
|    * recoverable failures, or possible inefficiencies.
 | |
|    *
 | |
|    * @param message the message text, also used as look-up key if the
 | |
|    *                logger is localizing messages with a resource
 | |
|    *                bundle.  While it is possible to pass
 | |
|    *                <code>null</code>, this is not recommended, since
 | |
|    *                a logging message without text is unlikely to be
 | |
|    *                helpful.
 | |
|    */
 | |
|   public synchronized void fine(String message)
 | |
|   {
 | |
|     if (isLoggable(Level.FINE))
 | |
|       log(Level.FINE, message);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Logs a message with severity level FINER.  {@link Level#FINER} is
 | |
|    * intended for rather detailed tracing, for example entering a
 | |
|    * method, returning from a method, or throwing an exception.
 | |
|    *
 | |
|    * @param message the message text, also used as look-up key if the
 | |
|    *                logger is localizing messages with a resource
 | |
|    *                bundle.  While it is possible to pass
 | |
|    *                <code>null</code>, this is not recommended, since
 | |
|    *                a logging message without text is unlikely to be
 | |
|    *                helpful.
 | |
|    */
 | |
|   public synchronized void finer(String message)
 | |
|   {
 | |
|     if (isLoggable(Level.FINER))
 | |
|       log(Level.FINER, message);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Logs a message with severity level FINEST.  {@link Level#FINEST}
 | |
|    * is intended for highly detailed tracing, for example reaching a
 | |
|    * certain point inside the body of a method.
 | |
|    *
 | |
|    * @param message the message text, also used as look-up key if the
 | |
|    *                logger is localizing messages with a resource
 | |
|    *                bundle.  While it is possible to pass
 | |
|    *                <code>null</code>, this is not recommended, since
 | |
|    *                a logging message without text is unlikely to be
 | |
|    *                helpful.
 | |
|    */
 | |
|   public synchronized void finest(String message)
 | |
|   {
 | |
|     if (isLoggable(Level.FINEST))
 | |
|       log(Level.FINEST, message);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Adds a handler to the set of handlers that get notified
 | |
|    * when a log record is to be published.
 | |
|    *
 | |
|    * @param handler the handler to be added.
 | |
|    *
 | |
|    * @throws NullPointerException if <code>handler</code>
 | |
|    *     is <code>null</code>.
 | |
|    *
 | |
|    * @throws SecurityException if this logger is not anonymous, a
 | |
|    *     security manager exists, and the caller is not granted
 | |
|    *     the permission to control the logging infrastructure by
 | |
|    *     having LoggingPermission("control").  Untrusted code can
 | |
|    *     obtain an anonymous logger through the static factory method
 | |
|    *     {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
 | |
|    */
 | |
|   public synchronized void addHandler(Handler handler)
 | |
|     throws SecurityException
 | |
|   {
 | |
|     if (handler == null)
 | |
|       throw new NullPointerException();
 | |
| 
 | |
|     /* An application is allowed to control an anonymous logger
 | |
|      * without having the permission to control the logging
 | |
|      * infrastructure.
 | |
|      */
 | |
|     if (!anonymous)
 | |
|       LogManager.getLogManager().checkAccess();
 | |
| 
 | |
|     if (!handlerList.contains(handler))
 | |
|     {
 | |
|       handlerList.add(handler);
 | |
|       handlers = getHandlers();
 | |
|     }
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Removes a handler from the set of handlers that get notified
 | |
|    * when a log record is to be published.
 | |
|    *
 | |
|    * @param handler the handler to be removed.
 | |
|    *
 | |
|    * @throws SecurityException if this logger is not anonymous, a
 | |
|    *     security manager exists, and the caller is not granted the
 | |
|    *     permission to control the logging infrastructure by having
 | |
|    *     LoggingPermission("control").  Untrusted code can obtain an
 | |
|    *     anonymous logger through the static factory method {@link
 | |
|    *     #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
 | |
|    *
 | |
|    * @throws NullPointerException if <code>handler</code>
 | |
|    *     is <code>null</code>.
 | |
|    */
 | |
|   public 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();
 | |
| 
 | |
|     if (handler == null)
 | |
|       throw new NullPointerException();
 | |
| 
 | |
|     handlerList.remove(handler);
 | |
|     handlers = getHandlers();
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Returns the handlers currently registered for this Logger.
 | |
|    * When a log record has been deemed as being loggable,
 | |
|    * it will be passed to all registered handlers for
 | |
|    * publication.  In addition, if the logger uses parent handlers
 | |
|    * (see {@link #getUseParentHandlers() getUseParentHandlers}
 | |
|    * and {@link #setUseParentHandlers(boolean) setUseParentHandlers},
 | |
|    * the log record will be passed to the parent's handlers.
 | |
|    */
 | |
|   public 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)
 | |
|   {
 | |
|     if (parent == null)
 | |
|       throw new NullPointerException();
 | |
| 
 | |
|     if (this == root)
 | |
|         throw new IllegalArgumentException(
 | |
|           "the root logger can only have a null parent");
 | |
| 
 | |
|     /* An application is allowed to control an anonymous logger
 | |
|      * without having the permission to control the logging
 | |
|      * infrastructure.
 | |
|      */
 | |
|     if (!anonymous)
 | |
|       LogManager.getLogManager().checkAccess();
 | |
| 
 | |
|     this.parent = parent;
 | |
|   }
 | |
|   
 | |
|   /**
 | |
|    * Gets the StackTraceElement of the first class that is not this class.
 | |
|    * That should be the initial caller of a logging method.
 | |
|    * @return caller of the initial logging method or null if unknown.
 | |
|    */
 | |
|   private native StackTraceElement getCallerStackFrame();
 | |
|   
 | |
|   /**
 | |
|    * Reset and close handlers attached to this logger. This function is package
 | |
|    * private because it must only be avaiable to the LogManager.
 | |
|    */
 | |
|   void resetLogger()
 | |
|   {
 | |
|     for (int i = 0; i < handlers.length; i++)
 | |
|       {
 | |
|         handlers[i].close();
 | |
|         handlerList.remove(handlers[i]);
 | |
|       }
 | |
|     handlers = getHandlers();
 | |
|   }
 | |
| }
 |