You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-cvs@jakarta.apache.org by ce...@apache.org on 2001/09/02 23:41:46 UTC

cvs commit: jakarta-log4j/src/java/org/apache/log4j Logger.java

ceki        01/09/02 14:41:46

  Added:       src/java/org/apache/log4j Logger.java
  Log:
  New central class in the package.
  
  Revision  Changes    Path
  1.1                  jakarta-log4j/src/java/org/apache/log4j/Logger.java
  
  Index: Logger.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software
   * License version 1.1, a copy of which has been included with this
   * distribution in the LICENSE.txt file.  */
  
  // Contibutors: Alex Blewitt <Al...@ioshq.com>
  //              Markus Oestreicher <oe...@zurich.ibm.com>
  //              Frank Hoering <fh...@zurich.ibm.com>
  //              Nelson Minar <ne...@media.mit.edu>
  //              Jim Cakalic <ji...@na.biomerieux.com>
  //              Avy Sharell <as...@club-internet.fr>
  //              Ciaran Treanor <ci...@xelector.com>
  //              Jeff Turner <je...@socialchange.net.au>
  //              Michael Horwitz <MH...@siemens.co.za>
  //              Calvin Chan <ca...@hic.gov.au>
  //              Aaron Greenhouse <aa...@cs.cmu.edu>
  //              Beat Meier <bm...@infovia.com.ar>
  //              Colin Sampaleanu <co...@exis.com> 
  
  package org.apache.log4j;
  
  import org.apache.log4j.spi.RootCategory;
  import org.apache.log4j.spi.AppenderAttachable;
  import org.apache.log4j.spi.CategoryFactory;
  import org.apache.log4j.spi.LoggingEvent;
  import org.apache.log4j.helpers.LogLog;
  import org.apache.log4j.helpers.NullEnumeration;
  import org.apache.log4j.helpers.OptionConverter;
  import org.apache.log4j.helpers.AppenderAttachableImpl;
  import org.apache.log4j.helpers.Loader;
  import org.apache.log4j.or.RendererMap;
  import org.apache.log4j.or.ObjectRenderer;
  
  import java.util.Enumeration;
  import java.util.Vector;
  import java.util.MissingResourceException;
  import java.text.MessageFormat;
  import java.util.ResourceBundle;
  import java.net.URL;
  import java.net.MalformedURLException;
  
  
  /**
    This is the central class in the log4j package. One of the
    distintive features of log4j are hierarchical categories and their
    evaluation.
  
    <p>See the <a href="../../../../manual.html">user manual</a> for an
    introduction on this class. 
  
    @author Ceki G&uuml;lc&uuml;
    @author Anders Kristensen */
  public class Logger implements AppenderAttachable {
  
    /**
       The hierarchy where categories are attached to by default.
    */
    static 
    public 
    final Hierarchy defaultHierarchy = new Hierarchy(new 
  						   RootCategory(Level.DEBUG));
  
  
    /**
       This string constant is set to <b>log4j.properties</b> the name
       of the file that will be searched by default in classpath. If the
       file can be found, then it is fed to the {@link
       PropertyConfigurator}.
  
       See also {@link #DEFAULT_CONFIGURATION_KEY} for a more general
       alternative.
  
       <p>See also the full description of <a
       href="../../../../manual.html#defaultInit">default
       intialization</a> procedure.
  
       @since 0.8.5 */
       static public final String DEFAULT_CONFIGURATION_FILE = "log4j.properties";
       
    /**
       This string constant is set to <b>log4j.configuration</b>. 
  
       <p>It corresponds to name of a system property that, if set,
       specifies the name of the resource containing the properties file
       or {@link URL} with which log4j should configure itself. See
       {@link OptionConverter#selectAndConfigure} for more detailed
       information on the processing of this option.
  
       <p>Setting the <b>log4j.configuration</b> system property
       overrides the default search for the file <b>log4j.properties</b>.
  
       <p>Note that all property keys are case sensitive.  
  
       <p>See also the full description of <a
       href="../../../../manual.html#defaultInit">default
       intialization</a> procedure.
  
       @since 1.0 */
       static final public String DEFAULT_CONFIGURATION_KEY="log4j.configuration";
  
   /**
       This string constant is set to <b>log4j.configuratorClass</b>. 
  
       <p>It corresponds to name of a system property that, if set,
       specifies the class name to use to automatically configure
       log4j. See {@link OptionConverter#selectAndConfigure} for more
       detailed information on the processing of this option.
  
       <p>Setting the <b>log4j.configuration</b> system property
       overrides the default search for the file <b>log4j.properties</b>.
  
       <p>Note that all property keys are case sensitive.  
  
       <p>See also the full description of <a
       href="../../../../manual.html#defaultInit">default
       intialization</a> procedure.
     
       @since 1.2 */
       static final public String CONFIGURATOR_CLASS_KEY="log4j.configuratorClass";
  
    /**
        Setting the system property <b>log4j.defaultInitOverride</b> to
        "true" or any other value than "false" will skip default
        configuration process.
  
       <p>The current value of the DEFAULT_INIT_OVERRIDE_KEY string
       constant is <b>log4j.defaultInitOverride</b>.
  
       <p>See also the full description of <a
       href="../../../../manual.html#defaultInit">default
       intialization</a> procedure.
  
       <p>Note that all property keys are case sensitive.  
  
       @since 0.8.5 */
    public static final String DEFAULT_INIT_OVERRIDE_KEY = 
                                                   "log4j.defaultInitOverride";
  
    /** Search for the properties file log4j.properties in the CLASSPATH.  */
    static {
  
      String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,
  						       null);
  
      // if there is no default init override, them get the resource
      // specified by the user or the default config file.
      if(override == null || "false".equalsIgnoreCase(override)) {
        String resource = OptionConverter.getSystemProperty(
                                                     DEFAULT_CONFIGURATION_KEY, 
  						   DEFAULT_CONFIGURATION_FILE);
  
        String configuratorClassName = OptionConverter.getSystemProperty(
                                                     CONFIGURATOR_CLASS_KEY, 
  						   null);
  
        URL url = null;
        try {
  	// so, resource is not a URL:
  	// attempt to get the resource from the class path
  	url = new URL(resource);
        } catch (MalformedURLException ex) {
  	url = Loader.getResource(resource); 
        }	
        
        // If we have a non-null url, then delegate the rest of the
        // configuration to the OptionConverter.selectAndConfigure
        // method.
        if(url != null) {
  	LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
  	OptionConverter.selectAndConfigure(url, configuratorClassName, 
  					   defaultHierarchy);
        } else {
  	LogLog.debug("Could not find resource: ["+resource+"].");
        }
      }  
    } 
  
    /**
       The name of this logger.
    */
    protected String   name;  
  
    /**
       The assigned level of this logger.  The
       <code>level</code> variable need not be assined a value in
       which case it is inherited form the hierarchy.  */
    volatile protected Level level;
  
    /**
       The parent of this logger. All categories have at least one
       ancestor which is the root logger. */
    volatile protected Logger parent;
  
    /**
       The fully qualified name of the Logger class. See also the 
       getFQCN method. */
    private static final String FQCN = Logger.class.getName();
    
    protected ResourceBundle resourceBundle;
    
    // Categories need to know what Hierarchy they are in
    protected Hierarchy hierarchy;
  
  
    AppenderAttachableImpl aai;
  
    /** Additivity is set to true by default, that is children inherit
        the appenders of their ancestors by default. If this variable is
        set to <code>false</code> then the appenders found in the
        ancestors of this logger are not used. However, the children
        of this logger will inherit its appenders, unless the children
        have their additivity flag set to <code>false</code> too. See
        the user manual for more details. */
    protected boolean additive = true;
    
    /**
       This constructor created a new <code>Logger</code> instance and
       sets its name.
  
       <p>It is intended to be used by sub-classes only. You should not
       create categories directly.
  
       @param name The name of the logger.  
    */
    protected 
    Logger(String name) {
      this.name = name;
    }
  
    /**
       Add <code>newAppender</code> to the list of appenders of this
       Logger instance.
  
       <p>If <code>newAppender</code> is already in the list of
       appenders, then it won't be added again.
    */
    synchronized  
    public 
    void addAppender(Appender newAppender) {
      if(aai == null) {
        aai = new AppenderAttachableImpl();
      }
      aai.addAppender(newAppender);
      hierarchy.fireAddAppenderEvent(this, newAppender);
    }
  
    /**
       If <code>assertion</code> parameter is <code>false</code>, then
       logs <code>msg</code> as an {@link #error(Object) error} statement.
  
       <p>The <code>assert</code> method has been renamed to
       <code>assertLog</code> because <code>assert</code> is a language
       reserved word in JDK 1.4.
  
       @param assertion 
       @param msg The message to print if <code>assertion</code> is
       false.
  
       @since 1.2 */
    public
    void assertLog(boolean assertion, String msg) {
      if(!assertion)
        this.error(msg);
    }
    
  
    /**
       Call the appenders in the hierrachy starting at
       <code>this</code>.  If no appenders could be found, emit a
       warning.
  
       <p>This method calls all the appenders inherited from the
       hierarchy circumventing any evaluation of whether to log or not
       to log the particular log request.
       
       @param LoggingEvent the event to log.  */
    public
    void callAppenders(LoggingEvent event) {
      int writes = 0;
  
      for(Logger l = this; l != null; l=l.parent) {
        // Protected against simultaneous call to addAppender, removeAppender,...
        synchronized(l) {
  	if(l.aai != null) {
  	  writes += l.aai.appendLoopOnAppenders(event);
  	}
  	if(!l.additive) {
  	  break;
  	}
        }
      }
      // No appenders in hierarchy, warn user only once.
      if(!hierarchy.emittedNoAppenderWarning && writes == 0) {
        LogLog.error("No appenders could be found for logger (" +
  		    this.getName() + ").");
        LogLog.error("Please initialize the log4j system properly.");
        hierarchy.emittedNoAppenderWarning = true;
      }
    }
  
    /**
       Close all attached appenders implementing the AppenderAttachable
       interface.  
       @since 1.0
    */
    synchronized
    void closeNestedAppenders() {
      Enumeration enum = this.getAllAppenders();
      if(enum != null) {
        while(enum.hasMoreElements()) {
  	Appender a = (Appender) enum.nextElement();
  	if(a instanceof AppenderAttachable) {
  	  a.close();
  	}
        }
      }
    }
  
    /** 
      Log a message object with the {@link Level#DEBUG DEBUG} level.
  
      <p>This method first checks if this logger is <code>DEBUG</code>
      enabled by comparing the level of this logger with the {@link
      Level#DEBUG DEBUG} level. If this logger is
      <code>DEBUG</code> enabled, then it converts the message object
      (passed as parameter) to a string by invoking the appropriate
      {@link ObjectRenderer}. It then proceeds to call all the
      registered appenders in this logger and also higher in the
      hierarchy depending on the value of the additivity flag.
  
      <p><b>WARNING</b> Note that passing a {@link Throwable} to this
      method will print the name of the <code>Throwable</code> but no
      stack trace. To print a stack trace use the {@link #debug(Object,
      Throwable)} form instead.
      
      @param message the message object to log. */
    public
    void debug(Object message) {
      if(hierarchy.enableInt >  Level.DEBUG_INT) 
        return;    
      if(Level.DEBUG.isGreaterOrEqual(this.getChainedLevel())) {
        forcedLog(FQCN, Level.DEBUG, message, null);
      }
    }
    
  
    /**  
     Log a message object with the <code>DEBUG</code> level including
     the stack trace of the {@link Throwable} <code>t</code> passed as
     parameter.
     
     <p>See {@link #debug(Object)} form for more detailed information.
     
     @param message the message object to log.
     @param t the exception to log, including its stack trace.  */  
    public
    void debug(Object message, Throwable t) {
      if(hierarchy.enableInt >  Level.DEBUG_INT) 
        return;
      if(Level.DEBUG.isGreaterOrEqual(this.getChainedLevel()))
        forcedLog(FQCN, Level.DEBUG, message, t);    
    }
  
    //public
    //void dump() {
    //  System.out.println("Logger " + name + " dump -----");
    //  for(Logger c = this; c != null; c=c.parent)
    //	System.out.println("("+c.name+", "+c.level+") ->");
    //  System.out.println("---------------------------");
    //
    //}
    
    /** 
      Log a message object with the {@link Level#ERROR ERROR} Level.
  
      <p>This method first checks if this logger is <code>ERROR</code>
      enabled by comparing the level of this logger with {@link
      Level#ERROR ERROR} Level. If this logger is
      <code>ERROR</code> enabled, then it converts the message object
      passed as parameter to a string by invoking the appropriate {@link
      ObjectRenderer}. It proceeds to call all the registered appenders
      in this logger and also higher in the hierarchy depending on
      the value of the additivity flag.
  
      <p><b>WARNING</b> Note that passing a {@link Throwable} to this
      method will print the name of the <code>Throwable</code> but no
      stack trace. To print a stack trace use the {@link #error(Object,
      Throwable)} form instead.
      
      @param message the message object to log */
    public
    void error(Object message) {
      if(hierarchy.enableInt >  Level.ERROR_INT) 
        return;
      if(Level.ERROR.isGreaterOrEqual(this.getChainedLevel()))
        forcedLog(FQCN, Level.ERROR, message, null);
    }
  
    /** 
     Log a message object with the <code>ERROR</code> level including
     the stack trace of the {@link Throwable} <code>t</code> passed as
     parameter.
     
     <p>See {@link #error(Object)} form for more detailed information.
     
     @param message the message object to log.
     @param t the exception to log, including its stack trace.  */  
    public
    void error(Object message, Throwable t) {
      if(hierarchy.enableInt >  Level.ERROR_INT) 
        return;
      if(Level.ERROR.isGreaterOrEqual(this.getChainedLevel()))
        forcedLog(FQCN, Level.ERROR, message, t);
      
    }
  
  
    /**
       If the named logger exists (in the default hierarchy) then it
       returns a reference to the logger, otherwise it returns
       <code>null</code>.
       
       <p>Contributed by Ciaran Treanor -  ciaran@xelector.com
       @version 0.8.5 */
    public
    static
    Logger exists(String name) {    
      return defaultHierarchy.exists(name);
    }
  
    /** 
      Log a message object with the {@link Level#FATAL FATAL} Level.
  
      <p>This method first checks if this logger is <code>FATAL</code>
      enabled by comparing the level of this logger with {@link
      Level#FATAL FATAL} Level. If the logger is <code>FATAL</code>
      enabled, then it converts the message object passed as parameter
      to a string by invoking the appropriate {@link ObjectRenderer}. It
      proceeds to call all the registered appenders in this logger and
      also higher in the hierarchy depending on the value of the
      additivity flag.
  
      <p><b>WARNING</b> Note that passing a {@link Throwable} to this
      method will print the name of the Throwable but no stack trace. To
      print a stack trace use the {@link #fatal(Object, Throwable)} form
      instead. 
      
      @param message the message object to log */
    public
    void fatal(Object message) {
      if(hierarchy.enableInt >  Level.FATAL_INT) 
        return;    
      if(Level.FATAL.isGreaterOrEqual(this.getChainedLevel()))
        forcedLog(FQCN, Level.FATAL, message, null);
    }
    
    /** 
     Log a message object with the <code>FATAL</code> level including
     the stack trace of the {@link Throwable} <code>t</code> passed as
     parameter.
     
     <p>See {@link #fatal(Object)} for more detailed information.
     
     @param message the message object to log.
     @param t the exception to log, including its stack trace.  */
    public
    void fatal(Object message, Throwable t) {
      if(hierarchy.enableInt >  Level.FATAL_INT) 
        return;   
      if(Level.FATAL.isGreaterOrEqual(this.getChainedLevel()))
        forcedLog(FQCN, Level.FATAL, message, t);
    }
  
  
    /**
       This method creates a new logging event and logs the event
       without further checks.  */
    protected
    void forcedLog(String fqcn, Level level, Object message, Throwable t) {
      callAppenders(new LoggingEvent(fqcn, this, level, message, t));
    }
  
  
    /**
       Get the additivity flag for this Logger instance.  
    */
    public
    boolean getAdditivity() {
      return additive;
    }
  
    /**
       Get the appenders contained in this logger as an {@link
       Enumeration}. If no appenders can be found, then a {@link NullEnumeration}
       is returned.
       
       @return Enumeration An enumeration of the appenders in this logger.  */
    synchronized
    public
    Enumeration getAllAppenders() {
      if(aai == null)
        return NullEnumeration.getInstance();
      else 
        return aai.getAllAppenders();
    }
  
    /**
       Look for the appender named as <code>name</code>.
  
       <p>Return the appender with that name if in the list. Return
       <code>null</code> otherwise.  */
    synchronized
    public
    Appender getAppender(String name) {
       if(aai == null || name == null)
        return null;
  
       return aai.getAppender(name);
    }
    
    /**
       Starting from this logger, search the logger hierarchy for a
       non-null level and return it. Otherwise, return the level of the
       root logger.
       
       <p>The Logger class is designed so that this method executes as
       quickly as possible.
     */
    public 
    Level getChainedLevel() {
      for(Logger c = this; c != null; c=c.parent) {
        if(c.level != null) 
  	return c.level;
      }
      return null; // If reached will cause an NullPointerException.
    }
  
    /**
       Returns all the currently defined categories in the default
       hierarchy as an {@link java.util.Enumeration Enumeration}.
  
       <p>The root logger is <em>not</em> included in the returned
       {@link Enumeration}.     
    */
    public
    static
    Enumeration getCurrentCategories() {
      return defaultHierarchy.getCurrentCategories();
    }
  
  
    /**
       Return the default Hierarchy instance.
  
       @since 1.0
     */
    public 
    static 
    Hierarchy getDefaultHierarchy() {
      return defaultHierarchy;
    }
  
    
    /**
       Return the the {@link Hierarchy} where this <code>Logger</code> instance is
       attached.
  
       @since 1.1 */
    public  
    Hierarchy getHierarchy() {
      return hierarchy;
    }
  
    
   /**
       Retrieve a logger with named as the <code>name</code>
       parameter. If the named logger already exists, then the
       existing instance will be reutrned. Otherwise, a new instance is
       created. 
  
       By default, categories do not have a set level but inherit
       it from the hierarchy. This is one of the central features of
       log4j.
  
       @param name The name of the logger to retrieve.  */
    public
    static
    Logger getLogger(String name) {
      return defaultHierarchy.getLogger(name);
    }	
  
   /**
      Shorthand for <code>getLogger(clazz.getName())</code>.
  
      @param clazz The name of <code>clazz</code> will be used as the
      name of the logger to retrieve.  See {@link
      #getInstance(String)} for more detailed information.
   */
    public
    static
    Logger getLogger(Class clazz) {
      return getLogger(clazz.getName());
    }	
  
  
    /**
       Like {@link #getInstance(String)} except that the type of logger
       instantiated depends on the type returned by the {@link
       CategoryFactory#makeNewCategoryInstance} method of the
       <code>factory</code> parameter.
       
       <p>This method is intended to be used by sub-classes.
       
       @param name The name of the category to retrieve.
  
       @param factory A {@link CategoryFactory} implementation that will
       actually create a new Instance.
  
       @since 0.8.5 */
    public
    static
    Logger getLogger(String name, CategoryFactory factory) {
      return defaultHierarchy.getLogger(name, factory);
    }	
  
    
    /**
       Return the logger name.  */
    public
    final
    String getName() {
      return name;
    }
  
      
    /**
       Returns the parent of this logger. Note that the parent of a
       given logger may change during the lifetime of the logger.
       
       <p>The root logger will return <code>null</code>.
  
       @since 1.2
    */
    final
    public
    Logger getParent() {
      return this.parent;
    }
  
      
    /**
       Returns the assigned {@link Level}, if any, for this Logger.  
       
       @return Level - the assigned Level, can be <code>null</code>.
    */
    final
    public
    Level getLevel() {
      return this.level;
    }
  
    /**
       @deprecated Please use {@link #getLevel} instead.
    */
    final
    public
    Level getPriority() {
      return this.level;
    }
  
  
    /**
       Return the root of the default logger hierrachy.
  
       <p>The root logger is always instantiated and available. It's
       name is "root".
  
       <p>Nevertheless, calling {@link #getInstance
       Category.getInstance("root")} does not retrieve the root category 
       but a category just under root named "root".
       
     */
    final
    public
    static
    Logger getRootLogger() {
      return defaultHierarchy.getRootLogger();
    }
  
    /**
       Return the <em>inherited</em> {@link ResourceBundle} for this
       logger.
  
       <p>This method walks the hierarchy to find the appropriate
       resource bundle. It will return the resource bundle attached to
       the closest ancestor of this logger, much like the way
       priorities are searched. In case there is no bundle in the
       hierarchy then <code>null</code> is returned.
  
       @since 0.9.0 */
    public
    ResourceBundle getResourceBundle() {
      for(Logger c = this; c != null; c=c.parent) {
        if(c.resourceBundle != null) 
  	return c.resourceBundle;
      }
      // It might be the case that there is no resource bundle 
      return null;
    }
  
    /**
       Returns the string resource coresponding to <code>key</code> in
       this logger's inherited resource bundle. See also {@link
       #getResourceBundle}.
  
       <p>If the resource cannot be found, then an {@link #error error}
       message will be logged complaining about the missing resource.
    */
    protected
    String getResourceBundleString(String key) {
      ResourceBundle rb = getResourceBundle();
      // This is one of the rare cases where we can use logging in order
      // to report errors from within log4j.
      if(rb == null) {
        if(!hierarchy.emittedNoResourceBundleWarning) {
  	error("No resource bundle has been set for logger "+name);
  	hierarchy.emittedNoResourceBundleWarning = true;
        }
        return null;
      }
      else {
        try {
  	return rb.getString(key);
        }
        catch(MissingResourceException mre) {
  	error("No resource is associated with key \""+key+"\".");
  	return null;
        }
      }
    }
    
    /** 
      Log a message object with the {@link Level#INFO INFO} Level.
  
      <p>This method first checks if this logger is <code>INFO</code>
      enabled by comparing the level of this logger with {@link
      Level#INFO INFO} Level. If the logger is <code>INFO</code>
      enabled, then it converts the message object passed as parameter
      to a string by invoking the appropriate {@link ObjectRenderer}. It
      proceeds to call all the registered appenders in this logger and
      also higher in the hierarchy depending on the value of the
      additivity flag.
  
      <p><b>WARNING</b> Note that passing a {@link Throwable} to this
      method will print the name of the Throwable but no stack trace. To
      print a stack trace use the {@link #info(Object, Throwable)} form
      instead. 
      
      @param message the message object to log */
    public
    void info(Object message) {
      if(hierarchy.enableInt >  Level.INFO_INT) 
        return;    
      if(Level.INFO.isGreaterOrEqual(this.getChainedLevel()))
        forcedLog(FQCN, Level.INFO, message, null);
    }
    
    /** 
     Log a message object with the <code>INFO</code> level including
     the stack trace of the {@link Throwable} <code>t</code> passed as
     parameter.
     
     <p>See {@link #info(Object)} for more detailed information.
     
     @param message the message object to log.
     @param t the exception to log, including its stack trace.  */
    public
    void info(Object message, Throwable t) {
      if(hierarchy.enableInt >  Level.INFO_INT) 
        return;   
      if(Level.INFO.isGreaterOrEqual(this.getChainedLevel()))
        forcedLog(FQCN, Level.INFO, message, t);
    }
  
    /**
      *  Check whether this logger is enabled for the <code>DEBUG</code>
      *  Level.
      *  
      *  <p> This function is intended to lessen the computational cost of
      *  disabled log debug statements.
      * 
      *  <p> For some <code>cat</code> Logger object, when you write,
      *  <pre>
      *      cat.debug("This is entry number: " + i );
      *  </pre>
      *  
      *  <p>You incur the cost constructing the message, concatenatiion in
      *  this case, regardless of whether the message is logged or not.
      * 
      *  <p>If you are worried about speed, then you should write
      *  <pre>
      * 	 if(cat.isDebugEnabled()) { 
      * 	   cat.debug("This is entry number: " + i );
      * 	 }
      *  </pre>
      * 
      *  <p>This way you will not incur the cost of parameter
      *  construction if debugging is disabled for <code>cat</code>. On
      *  the other hand, if the <code>cat</code> is debug enabled, you
      *  will incur the cost of evaluating whether the logger is debug
      *  enabled twice. Once in <code>isDebugEnabled</code> and once in
      *  the <code>debug</code>.  This is an insignificant overhead
      *  since evaluating a logger takes about 1%% of the time it
      *  takes to actually log.
      * 
      *  @return boolean - <code>true</code> if this logger is debug
      *  enabled, <code>false</code> otherwise.
      *   */
    public
    boolean isDebugEnabled() {
      if(hierarchy.enableInt >  Level.DEBUG_INT)
        return false;   
      return Level.DEBUG.isGreaterOrEqual(this.getChainedLevel());
    }
    
    /**
       Check whether this logger is enabled for a given {@link
       Level} passed as parameter.
  
       See also {@link #isDebugEnabled}.
         
       @return boolean True if this logger is enabled for <code>level</code>.
    */
    public
    boolean isEnabledFor(Level level) {
      if(hierarchy.enableInt >  level.level) 
        return false;
      return level.isGreaterOrEqual(this.getChainedLevel());
    }
  
    /**
      Check whether this logger is enabled for the info Level.
      See also {@link #isDebugEnabled}.
  
      @return boolean - <code>true</code> if this logger is enabled
      for level info, <code>false</code> otherwise.
    */
    public
    boolean isInfoEnabled() {
      if(hierarchy.enableInt > Level.INFO_INT)
        return false;   
      return Level.INFO.isGreaterOrEqual(this.getChainedLevel());
    }
  
  
    /**
       Log a localized message. The user supplied parameter
       <code>key</code> is replaced by its localized version from the
       resource bundle.
       
       @see #setResourceBundle
  
       @since 0.8.4 */
    public
    void l7dlog(Level level, String key, Throwable t) {
      if(hierarchy.enableInt > level.level) {
        return;
      }
      if(level.isGreaterOrEqual(this.getChainedLevel())) {
        String msg = getResourceBundleString(key);
        // if message corresponding to 'key' could not be found in the
        // resource bundle, then default to 'key'.
        if(msg == null) {
  	msg = key;
        }
        forcedLog(FQCN, level, msg, t);
      }
    }
    /**
       Log a localized and parameterized message. First, the user
       supplied <code>key</code> is searched in the resource
       bundle. Next, the resulting pattern is formatted using 
       {@link MessageFormat#format(String,Object[])} method with the user
       supplied object array <code>params</code>.
       
       @since 0.8.4
    */
    public
    void l7dlog(Level level, String key,  Object[] params, Throwable t) {
      if(hierarchy.enableInt > level.level) {
        return;
      }    
      if(level.isGreaterOrEqual(this.getChainedLevel())) {
        String pattern = getResourceBundleString(key);
        String msg;
        if(pattern == null) 
  	msg = key;
        else 
  	msg = java.text.MessageFormat.format(pattern, params);
        forcedLog(FQCN, level, msg, t);
      }
    }
    
    /**
       This generic form is intended to be used by wrappers.
     */
    public
    void log(Level level, Object message, Throwable t) {
      if(hierarchy.enableInt > level.level) {
        return;
      }
      if(level.isGreaterOrEqual(this.getChainedLevel())) 
        forcedLog(FQCN, level, message, t);
    }
    
   /**
      This generic form is intended to be used by wrappers. 
   */
    public
    void log(Level level, Object message) {
      if(hierarchy.enableInt > level.level) {
        return;
      }
      if(level.isGreaterOrEqual(this.getChainedLevel()))
        forcedLog(FQCN, level, message, null);
    }
  
    /**
       
       This is the most generic printing method. It is intended to be
       invoked by <b>wrapper</b> classes.
            
       @param callerFQCN The wrapper class' fully qualified class name.
       @param level The level of the logging request.
       @param message The message of the logging request.
       @param t The throwable of the logging request, may be null.  */
    public
    void log(String callerFQCN, Level level, Object message, Throwable t) {
      if(hierarchy.enableInt > level.level) {
        return;
      }
      if(level.isGreaterOrEqual(this.getChainedLevel())) {
        forcedLog(callerFQCN, level, message, t);
      }
    }
  
  
    /**
       Remove all previously added appenders from this Logger
       instance.
  
       <p>This is useful when re-reading configuration information.
    */
    synchronized
    public
    void removeAllAppenders() {
      if(aai != null) {
        aai.removeAllAppenders();
        aai = null;
      }
    }
  
    /**
       Remove the appender passed as parameter form the list of appenders.
  
       @since 0.8.2
    */
    synchronized
    public
    void removeAppender(Appender appender) {
      if(appender == null || aai == null) 
        return;
      aai.removeAppender(appender);
    }
  
    /**
       Remove the appender with the name passed as parameter form the
       list of appenders.
  
       @since 0.8.2 */
    synchronized
    public
    void removeAppender(String name) {
      if(name == null || aai == null) return;
      aai.removeAppender(name);
    }
    
    /**
       Set the additivity flag for this Logger instance.
       @since 0.8.1
     */
    public
    void setAdditivity(boolean additive) {
      this.additive = additive;
    }
  
    /**
       Only the Hiearchy class can set the hiearchy of a
       logger. Default package access is MANDATORY here.  */
    final
    void setHierarchy(Hierarchy hierarchy) {
      this.hierarchy = hierarchy;
    }
  
    /**
       Set the level of this Logger.
  
       <p>Null values are admitted.
    */
    public
    void setLevel(Level level) {
      this.level = level;
    }
  
    
    /**
       Set the level of this Logger.
  
       <p>Null values are admitted.
  
       @deprecated Please use {@link #setLevel} instead.
    */
    public
    void setPriority(Priority priority) {
      setLevel(priority);
    }
  
  
    /**
       Set the resource bundle to be used with localized logging
       methods {@link #l7dlog(Level,String,Throwable)} and {@link
       #l7dlog(Level,String,Object[],Throwable)}.
  
       @since 0.8.4
     */
    public
    void setResourceBundle(ResourceBundle bundle) {
      resourceBundle = bundle;
    }
  
    /**
       Calling this method will <em>safely</em> close and remove all
       appenders in all the categories including root contained in the
       default hierachy.
       
       <p>Some appenders such as {@link org.apache.log4j.net.SocketAppender}
       and {@link AsyncAppender} need to be closed before the
       application exists. Otherwise, pending logging events might be
       lost.
  
       <p>The <code>shutdown</code> method is careful to close nested
       appenders before closing regular appenders. This is allows
       configurations where a regular appender is attached to a logger
       and again to a nested appender.  
  
       @since 1.0
    */
    public
    static
    void shutdown() {
      defaultHierarchy.shutdown();
    }
  
    
    /** 
      Log a message object with the {@link Level#WARN WARN} Level.
  
      <p>This method first checks if this logger is <code>WARN</code>
      enabled by comparing the level of this logger with {@link
      Level#WARN WARN} Level. If the logger is <code>WARN</code>
      enabled, then it converts the message object passed as parameter
      to a string by invoking the appropriate {@link ObjectRenderer}. It
      proceeds to call all the registered appenders in this logger and
      also higher in the hieararchy depending on the value of the
      additivity flag.
  
      <p><b>WARNING</b> Note that passing a {@link Throwable} to this
      method will print the name of the Throwable but no stack trace. To
      print a stack trace use the {@link #warn(Object, Throwable)} form
      instead.  <p>
      
      @param message the message object to log.  */
    public
    void warn(Object message) {
      if(hierarchy.enableInt >  Level.WARN_INT) 
        return;   
  
      if(Level.WARN.isGreaterOrEqual(this.getChainedLevel()))
        forcedLog(FQCN, Level.WARN, message, null);    
    }
    
    /** 
     Log a message with the <code>WARN</code> level including the
     stack trace of the {@link Throwable} <code>t</code> passed as
     parameter.
     
     <p>See {@link #warn(Object)} for more detailed information.
     
     @param message the message object to log.
     @param t the exception to log, including its stack trace.  */
    public
    void warn(Object message, Throwable t) {
      if(hierarchy.enableInt >  Level.WARN_INT) 
        return;   
      if(Level.WARN.isGreaterOrEqual(this.getChainedLevel()))
        forcedLog(FQCN, Level.WARN, message, t);
    }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-cvs-unsubscribe@jakarta.apache.org
For additional commands, e-mail: log4j-cvs-help@jakarta.apache.org