avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From atagu...@apache.org
Subject cvs commit: avalon-excalibur/logger/src/java/org/apache/avalon/excalibur/logger AbstractLoggerManager.java LogKitLoggerManager.java Log4JLoggerManager.java Log4JConfLoggerManager.java
Date Tue, 10 Jun 2003 08:29:38 GMT
atagunov    2003/06/10 01:29:38

  Modified:    logger/src/java/org/apache/avalon/excalibur/logger
                        LogKitLoggerManager.java Log4JLoggerManager.java
                        Log4JConfLoggerManager.java
  Added:       logger/src/java/org/apache/avalon/excalibur/logger
                        AbstractLoggerManager.java
  Log:
  *LoggerManager rework: now the logger manager never
  log to an uninitialized logging backend
  (which resulted for instance in logging some messages
  to the console)
  new constructors have been added.
  All existing code should work, but an upgrade to the
  newer constructors is recommended.
  
  Revision  Changes    Path
  1.17      +365 -113  avalon-excalibur/logger/src/java/org/apache/avalon/excalibur/logger/LogKitLoggerManager.java
  
  Index: LogKitLoggerManager.java
  ===================================================================
  RCS file: /home/cvs/avalon-excalibur/logger/src/java/org/apache/avalon/excalibur/logger/LogKitLoggerManager.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- LogKitLoggerManager.java	27 May 2003 07:40:10 -0000	1.16
  +++ LogKitLoggerManager.java	10 Jun 2003 08:29:37 -0000	1.17
  @@ -49,10 +49,8 @@
   */
   package org.apache.avalon.excalibur.logger;
   
  -import java.util.HashMap;
   import java.util.HashSet;
   import java.util.Iterator;
  -import java.util.Map;
   import java.util.Set;
   import org.apache.avalon.framework.activity.Disposable;
   import org.apache.avalon.framework.configuration.Configurable;
  @@ -69,6 +67,8 @@
   import org.apache.log.LogTarget;
   import org.apache.log.Priority;
   import org.apache.log.util.Closeable;
  +import org.apache.log.ErrorHandler;
  +import org.apache.log.LogEvent;
   
   /**
    * LogKitLoggerManager implementation.  It populates the LoggerManager
  @@ -77,15 +77,13 @@
    * @author <a href="mailto:giacomo@apache.org">Giacomo Pati</a>
    * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
    * @author <a href="mailto:proyal@apache.org">Peter Royal</a>
  + * @author <a href="mailto:tagunov at apache.org">Anton Tagunov</a>
    * @version CVS $Revision$ $Date$
    * @since 4.0
    */
  -public class LogKitLoggerManager
  -    implements LoggerManager, LogEnabled, Contextualizable, Configurable, Disposable
  +public class LogKitLoggerManager extends AbstractLoggerManager
  +    implements LoggerManager, Contextualizable, Configurable, Disposable
   {
  -    /** Map for name to logger mapping */
  -    final private Map m_loggers = new HashMap();
  -
       /** Set of log targets */
       final private Set m_targets = new HashSet();
   
  @@ -93,121 +91,316 @@
       private Context m_context;
   
       /** The hierarchy private to LogKitManager */
  -    private Hierarchy m_hierarchy;
  -
  -    /** The root logger to configure */
  -    private String m_prefix;
  +    private final Hierarchy m_hierarchy;
   
  -    /** The default logger used for this system */
  -    final private Logger m_defaultLogger;
  -
  -    /** The logger used to log output from the logger manager. */
  -    private Logger m_logger;
  +    /** The error handler we will supply to m_hierarchy if we create it locally.*/
  +    private OurErrorHandler m_errorHandler;
   
       /**
  -     * Creates a new <code>DefaultLogKitManager</code>. It will use a new <code>Hierarchy</code>.
  +     * Creates a new <code>LogKitLoggerManager</code>;
  +     * one of the preferred constructors.
  +     * Please also invoke <code>enableLogging()</code>
  +     * to supply a fallback logger.
        */
       public LogKitLoggerManager()
       {
  -        this( new Hierarchy() );
  +        this( (String)null, (Hierarchy)null, (String)null, (Logger)null, (Logger)null );
       }
   
       /**
  -     * Creates a new <code>DefaultLogKitManager</code> with an existing <code>Hierarchy</code>.
  +     * Creates a new <code>LogKitLoggerManager</code>;
  +     * one of the preferred constructors.
  +     * Please also invoke <code>enableLogging()</code>
  +     * to supply a fallback logger.
  +     *
  +     * @param prefix to prepended to category name on each 
  +     *         invocation of <code>getLoggerForCategory()</code>.
        */
  -    public LogKitLoggerManager( final Hierarchy hierarchy )
  +    public LogKitLoggerManager( final String prefix )
       {
  -        this( null, hierarchy );
  +        this( prefix, (Hierarchy)null, (String)null, (Logger)null, (Logger)null );
       }
   
       /**
  -     * Creates a new <code>DefaultLogKitManager</code> using
  -     * specified logger name as root logger.
  +     * Creates a new <code>LogKitLoggerManager</code>;
  +     * one of the preferred constructors,
  +     * intended for the widest usage.
  +     *
  +     * Please also invoke <code>enableLogging()</code>
  +     * to supply a fallback logger.
  +     * <p>
  +     * Example:
  +     * <pre>
  +     * LogKitLoggerManager l = new LogKitLoggerManager( "fortress", "system.logkit" );
  +     * l.enableLogging( bootstrapLogger );
  +     * l.configure( loggerManagerConfiguration );
  +     * </pre>
  +     *
  +     * @param prefix to prepended to category name on each 
  +     *         invocation of <code>getLoggerForCategory()</code>.
  +     * @param switchToCategory if this parameter is not null
  +     *         after <code>start()</code>
  +     *         <code>LogKitLoggerManager</code> will start
  +     *         to log its own debug and error messages to
  +     *         a logger obtained via
  +     *         <code>this.getLoggerForCategory( switchToCategory )</code>.
  +     *         Note that prefix will be prepended to
  +     *         the value of <code>switchToCategory</code> also.
  +     */
  +    public LogKitLoggerManager( final String prefix, final String switchToCategory )
  +    {
  +        this( prefix, (Hierarchy)null, switchToCategory, (Logger)null, (Logger)null );
  +    }
  +
  +    /**
  +     * Creates a new <code>LogKitLoggerManager</code> 
  +     * with an existing <code>Hierarchy</code>;
  +     * use with caution.
  +     *
  +     * Please also invoke <code>enableLogging()</code>
  +     * to supply a fallback logger.
  +     * See <a href="#h-warning">comments on the root constructor</a> 
  +     * for details on why constructors supplying an existing hierarchy 
  +     * should be used with caution.
  +     *
  +     * @param prefix to prepended to category name on each 
  +     *         invocation of <code>getLoggerForCategory()</code>.
  +     * @param switchToCategory if this parameter is not null
  +     *         after <code>start()</code>
  +     *         <code>LogKitLoggerManager</code> will start
  +     *         to log its own debug and error messages to
  +     *         a logger obtained via
  +     *         <code>this.getLoggerForCategory( switchToCategory )</code>.
  +     *         Note that prefix will be prepended to
  +     *         the value of <code>switchToCategory</code> also.
        */
  -    public LogKitLoggerManager( final String prefix )
  +    public LogKitLoggerManager( final String prefix, final Hierarchy hierarchy,
  +            final String switchToCategory )
       {
  -        this( prefix, new Hierarchy() );
  +        this( prefix, hierarchy, switchToCategory, (Logger)null, (Logger)null );
       }
   
       /**
  -     * Creates a new <code>DefaultLogKitManager</code> with an existing <code>Hierarchy</code> using
  -     * specified logger name as root logger.
  +     * Creates a new <code>LogKitLoggerManager</code> 
  +     * with an existing <code>Hierarchy</code>;
  +     * use with caution.
  +     *
  +     * Please also invoke <code>enableLogging()</code>
  +     * to supply a fallback logger.
  +     * See <a href="#h-warning">comments on the root constructor</a> 
  +     * for details on why constructors supplying an existing hierarchy 
  +     * should be used with caution.
        */
  -    public LogKitLoggerManager( final String prefix, final Hierarchy hierarchy )
  +    public LogKitLoggerManager( final Hierarchy hierarchy )
       {
  -        this( prefix, hierarchy,
  -              new LogKitLogger( hierarchy.getRootLogger() ) );
  +        this( (String)null, hierarchy, (String)null, (Logger)null, (Logger)null );
       }
   
       /**
  -     * Creates a new <code>DefaultLogKitManager</code> with an existing <code>Hierarchy</code> using
  -     * specified logger name as root logger.
  +     * Creates a new <code>LogKitLoggerManager</code> 
  +     * with an existing <code>Hierarchy</code>;
  +     * use with caution.
  +     *
  +     * Please also invoke <code>enableLogging()</code>
  +     * to supply a fallback logger.
  +     * See <a href="#h-warning">comments on the root constructor</a> 
  +     * for details on why constructors supplying an existing hierarchy 
  +     * should be used with caution.
  +     *
  +     * @param prefix to prepended to category name on each 
  +     *         invocation of <code>getLoggerForCategory()</code>.
        */
  -    public LogKitLoggerManager( final String prefix, final Hierarchy hierarchy,
  -                                final Logger defaultLogger )
  +    public LogKitLoggerManager( final String prefix, final Hierarchy hierarchy )
       {
  -        this( prefix, hierarchy, defaultLogger, defaultLogger );
  +        this( prefix, hierarchy, (String)null, (Logger)null, (Logger)null );
       }
   
       /**
  -     * Creates a new <code>DefaultLogKitManager</code> with an existing <code>Hierarchy</code> using
  -     * specified logger name as root logger.
  +     * Creates a new <code>LogKitLoggerManager</code>
  +     * with an existing <code>Hierarchy</code> using
  +     * specified logger name as a fallback logger and to
  +     * <strong>forcibly override</strong> the root logger;
  +     * compatibility constructor.
  +     *
  +     * The configuration for the <code>""</code>
  +     * category in the configuration will supply the defaults for
  +     * all other categories, but <code>getDefaultLogger()</code>
  +     * and <code>getLoggerForCategory()</code> will still
  +     * use logger supplied by this constructor.
  +     *
  +     * <p>
  +     * See <a href="#h-warning">comments on the root constructor</a> 
  +     * for details on why constructors supplying an existing hierarchy 
  +     * should be used with caution.
  +     *
  +     * <p>
  +     * As this constructor provides a logger to be used as a fallback
  +     * a subsequent <code>enableLogging()</code> stage is unnecessary.
  +     * Moreover, it will fail.
  +     *
  +     * @param prefix to prepended to category name on each 
  +     *         invocation of <code>getLoggerForCategory()</code>.
  +     * @param defaultOverrideAndFallback the logger used to 
  +     *         a) <strong>forcibly</strong>
  +     *         override the root logger that will further be obtained from
  +     *         the configuration and b) as the fallback logger. Note that
  +     *         specifying a logger as this parameter crucially differs from
  +     *         supplying it via <code>enableLogging()</code>. The logger
  +     *         supplied via <code>enableLogging</code> will only be used
  +     *         as the fallback logger and to log messages during initialization
  +     *         while this constructor argument also has the described
  +     *         <strong>override</strong> semantics.
        */
       public LogKitLoggerManager( final String prefix, final Hierarchy hierarchy,
  -                                final Logger defaultLogger, final Logger logger )
  +                                final Logger defaultOverrideAndFallback )
       {
  -        m_prefix = prefix;
  -        m_hierarchy = hierarchy;
  -        m_defaultLogger = defaultLogger;
  -        m_logger = logger;
  +        this( prefix, hierarchy, (String)null, 
  +                defaultOverrideAndFallback, defaultOverrideAndFallback );
       }
   
       /**
  -     * Provide a logger.
  +     * Creates a new <code>LogKitLoggerManager</code>
  +     * with an existing <code>Hierarchy</code> using
  +     * specified loggers to <strong>forcibly override</strong>
  +     * the default logger and to provide a fallback logger;
  +     * compatibility constructor.
  +     *
  +     * See <a href="#h-warning">comments on the root constructor</a> 
  +     * for details on why constructors supplying an existing hierarchy 
  +     * should be used with caution.
  +     * <p>
  +     * As this constructor provides a logger to be used as a fallback
  +     * a subsequent <code>enableLogging()</code> stage is unnecessary.
  +     * Moreover, it will fail.
        *
  -     * @param logger the logger
  -     **/
  -    public void enableLogging( final Logger logger )
  +     * @param prefix to prepended to category name on each 
  +     *         invocation of <code>getLoggerForCategory()</code>.
  +     * @param defaultLoggerOverride the logger to be used to <strong>forcibly</strong>
  +     *         override the root logger that will further be obtained from
  +     *         the configuration
  +     * @param fallbackLogger the logger to as a fallback logger
  +     *         (passing non-null as this argument eliminates the need
  +     *         to invoke <code>enableLogging()</code>)
  +     */
  +    public LogKitLoggerManager( final String prefix, final Hierarchy hierarchy,
  +                                final Logger defaultLoggerOverride, 
  +                                final Logger fallbackLogger )
       {
  -        m_logger = logger;
  +        this( prefix, hierarchy, (String)null, defaultLoggerOverride, fallbackLogger );
       }
   
       /**
  -     * Retrieves a Logger from a category name. Usually
  -     * the category name refers to a configuration attribute name.  If
  -     * this LogKitManager does not have the match the default Logger will
  -     * be returned and a warning is issued.
  +     * <a name="h-warning" id="h-warning"/>
  +     *
  +     * Creates a new <code>LogKitLoggerManager</code>;
  +     * "root" constructor invoked by all other constructors.
  +     * <p>
  +     *
  +     * If the <code>hierarchy</code> parameter is not <code>null</code>
  +     * this instructs this constructor to use an existing hierarchy
  +     * instead of creating a new one. This also disables removing
  +     * the default log target configured by the <code>Hierarchy()</code>
  +     * constructor (this target logs to <code>System.out</code>) and
  +     * installing our own <code>ErrorHandler</code> for our
  +     * <code>Hierarchy</code> (the default <code>ErrorHandler</code>
  +     * writes to <code>System.err</code>).
  +     * <p>
  +     * The configuration of the resulting <code>Hierarchy</code>
  +     * is a combination of the original configuraiton that
  +     * existed when this <code>Hierarchy</code> was handled to us
  +     * and the configuration supplied to use via <code>configure()</code>.
  +     * <code>LogTarget</code>s for those categories for which a
  +     * configuration node has been supplied in the configuration
  +     * supplied via <code>configure()</code> are replaced during
  +     * the <code>configure()</code> process. <code>LogTargets</code>
  +     * for those categories for which configuration nodes have
  +     * not been supplied are left as they were. A special case
  +     * is when a node in configuration for a category exists but
  +     * it does not enlist log targets. In this case the original
  +     * targets if any are left as they were.
  +     *
  +     * <p>
  +     * Generally it is preferrable to
  +     * <ul>
  +     * <li>have the <code>Hierarchy</code> be configured
  +     * from top to bottom via the configuration</li>
  +     * <li>have our custom <code>ErrorHandler</code> reporting
  +     * errors via the fallback logger (supplied either as
  +     * the <code>fallbackLogger</code> to this constructor or
  +     * via the <code>enableLogging()</code> method) installed</li>
  +     * </ul>
  +     * That's why it is preferrable to pass <code>null</code>
  +     * for the <code>hierarchy</code> parameter of this constructor
  +     * or, which is easier to read but has the same effect, to
  +     * invoke a constructor which does not accept a <code>Hierarchy</code>
  +     * argument.
  +     * </p>
        *
  -     * @param categoryName  The category name of a configured Logger.
  -     * @return the Logger.
  +     * <p>The <code>defaultLoggerOverride</code> and <code>fallbackLogger</code>
  +     * are a special case too. <code>defaultLoggerOverride</code> 
  +     * <strong>forcibly overrides</strong>
  +     * the root logger configured via <code>configure()</code>.
  +     * As there is little reason to take away users's freedom to configure
  +     * whatever he likes as the default logger, it is preferrable to pass
  +     * <code>null</code> for this parameter or better still to invoke
  +     * a constructor without <code>Logger</code> parameters at all.</p>
  +     *
  +     * <p>There is nothing wrong with passing <code>fallbackLogger</code>
  +     * via this constructor, but as this constructor is not convinient to
  +     * be invoked (too many arguments, some of them likely to be null) and the 
  +     * {@link #LogKitLogger(java.lang.String,org.apache.log.Hierarchy,org.apache.framework.logger.Logger}
  +     * constructor is broken
  +     * in using its <code>Logger</code> argument both as 
  +     * <code>fallbackLogger</code> (which is okay) and as 
  +     * a <code>defaultLoggerOverride</code> (which is probably not 
  +     * desired for the reasons given above) it is preferrable not to 
  +     * specify a logger
  +     * as a constructor argument but rather supply it via
  +     * <code>enableLogging()</code> call, like this happens with all
  +     * other normal Avalon components after all.
  +     *
  +     * @param prefix to prepended to category name on each 
  +     *         invocation of <code>getLoggerForCategory()</code>.
  +     * @param switchToCategory if this parameter is not null
  +     *         after <code>start()</code>
  +     *         <code>LogKitLoggerManager</code> will start
  +     *         to log its own debug and error messages to
  +     *         a logger obtained via
  +     *         <code>this.getLoggerForCategory( switchToCategory )</code>.
  +     *         Note that prefix will be prepended to
  +     *         the value of <code>switchToCategory</code> also.
  +     * @param defaultLoggerOverride the logger to be used to 
  +     *         <strong>forcibly override</strong>
  +     *         the root logger that would further be obtained from
  +     *         the configuration
  +     * @param fallbackLogger the logger to as a fallback logger
  +     *         (passing non-null as this argument eliminates the need
  +     *         to invoke <code>enableLogging()</code>)
        */
  -    public final Logger getLoggerForCategory( final String categoryName )
  +    public LogKitLoggerManager( final String prefix, final Hierarchy hierarchy,
  +                                final String switchToCategory,
  +                                final Logger defaultLoggerOverride, 
  +                                final Logger fallbackLogger )
       {
  -        final String fullCategoryName = getFullCategoryName( m_prefix, categoryName );
  -
  -        final Logger logger = (Logger)m_loggers.get( fullCategoryName );
  +        super( prefix, switchToCategory, defaultLoggerOverride );
  +        m_prefix = prefix;
   
  -        if( null != logger )
  +        if ( hierarchy == null )
           {
  -            if( m_logger.isDebugEnabled() )
  -            {
  -                m_logger.debug( "Logger for category " + fullCategoryName + " returned" );
  -            }
  -            return logger;
  +            m_hierarchy = new Hierarchy();
  +            m_hierarchy.getRootLogger().unsetLogTargets( true );
  +            m_errorHandler = new OurErrorHandler( getLogger() );
  +            m_hierarchy.setErrorHandler( m_errorHandler );
           }
  -
  -        if( m_logger.isDebugEnabled() )
  +        else
           {
  -            m_logger.debug( "Logger for category " + fullCategoryName + " not defined in "
  -                            + "configuration. New Logger created and returned" );
  +            m_hierarchy = hierarchy;
           }
   
  -        return new LogKitLogger( m_hierarchy.getLoggerFor( fullCategoryName ) );
  -    }
  -
  -    public final Logger getDefaultLogger()
  -    {
  -        return m_defaultLogger;
  +        if ( fallbackLogger != null )
  +        {
  +            this.enableLogging( fallbackLogger );
  +        }
       }
   
       /**
  @@ -223,6 +416,16 @@
       }
   
       /**
  +     * Actually create a logger for the given category.
  +     * The result will be cached by 
  +     * <code>AbstractLoggerManager.getLoggerForCategory()</code>.
  +     */
  +    protected Logger doGetLoggerForCategory( final String fullCategoryName )
  +    {
  +        return new LogKitLogger( m_hierarchy.getLoggerFor( fullCategoryName ) );
  +    }
  +
  +    /**
        * Reads a configuration object and creates the category mapping.
        *
        * @param configuration  The configuration object.
  @@ -242,7 +445,13 @@
           setupLoggers( targetManager,
                         m_prefix,
                         category,
  +                      true,
                         categories.getAttributeAsBoolean( "additive", false ) );
  +
  +        /**
  +         * This is the last configuration stage, if we to initialize() or start()
  +         * we would call it from that method.
  +         */
       }
   
       /**
  @@ -256,7 +465,7 @@
       {
           final DefaultLogTargetFactoryManager targetFactoryManager = new DefaultLogTargetFactoryManager();
   
  -        ContainerUtil.enableLogging( targetFactoryManager, m_logger );
  +        ContainerUtil.enableLogging( targetFactoryManager, getLogger() );
   
           try
           {
  @@ -284,7 +493,7 @@
       {
           final DefaultLogTargetManager targetManager = new DefaultLogTargetManager();
   
  -        ContainerUtil.enableLogging( targetManager, m_logger );
  +        ContainerUtil.enableLogging( targetManager, getLogger() );
   
           if( targetManager instanceof LogTargetFactoryManageable )
           {
  @@ -297,50 +506,21 @@
       }
   
       /**
  -     * Generates a full category name given a prefix and category.  Either may be
  -     *  null.
  -     *
  -     * @param prefix Prefix or parent category.
  -     * @param category Child category name.
  -     */
  -    private final String getFullCategoryName( String prefix, String category )
  -    {
  -        if( ( null == prefix ) || ( prefix.length() == 0 ) )
  -        {
  -            if( category == null )
  -            {
  -                return "";
  -            }
  -            else
  -            {
  -                return category;
  -            }
  -        }
  -        else
  -        {
  -            if( ( null == category ) || ( category.length() == 0 ) )
  -            {
  -                return prefix;
  -            }
  -            else
  -            {
  -                return prefix + org.apache.log.Logger.CATEGORY_SEPARATOR + category;
  -            }
  -        }
  -    }
  -
  -    /**
        * Setup Loggers
        *
        * @param categories []  The array object of configurations for categories.
  +     * @param root shows if we're processing the root of the configuration
        * @throws ConfigurationException if the configuration is malformed
        */
       private final void setupLoggers( final LogTargetManager targetManager,
                                        final String parentCategory,
                                        final Configuration[] categories,
  +                                     boolean root,
                                        final boolean defaultAdditive )
           throws ConfigurationException
       {
  +        boolean rootLoggerAlive = false;
  +
           for( int i = 0; i < categories.length; i++ )
           {
               final String category = categories[ i ].getAttribute( "name" );
  @@ -360,19 +540,20 @@
                   }
               }
   
  -            if( "".equals( category ) && logTargets.length > 0 )
  +            if( root && "".equals( category ) && logTargets.length > 0 )
               {
                   m_hierarchy.setDefaultPriority( Priority.getPriorityForName( loglevel ) );
                   m_hierarchy.setDefaultLogTargets( logTargets );
  +                rootLoggerAlive = true;
               }
   
               final String fullCategory = getFullCategoryName( parentCategory, category );
   
               final org.apache.log.Logger logger = m_hierarchy.getLoggerFor( fullCategory );
               m_loggers.put( fullCategory, new LogKitLogger( logger ) );
  -            if( m_logger.isDebugEnabled() )
  +            if( getLogger().isDebugEnabled() )
               {
  -                m_logger.debug( "added logger for category " + fullCategory );
  +                getLogger().debug( "added logger for category " + fullCategory );
               }
               logger.setPriority( Priority.getPriorityForName( loglevel ) );
               logger.setLogTargets( logTargets );
  @@ -381,9 +562,16 @@
               final Configuration[] subCategories = categories[ i ].getChildren( "category" );
               if( null != subCategories )
               {
  -                setupLoggers( targetManager, fullCategory, subCategories, defaultAdditive );
  +                setupLoggers( targetManager, fullCategory, subCategories, false, defaultAdditive );
               }
           }
  +
  +        if ( root && !rootLoggerAlive )
  +        {
  +            final String message = "No log targets configured for the root logger.";
  +
  +            throw new ConfigurationException( message );
  +        }
       }
   
       public void dispose()
  @@ -397,6 +585,70 @@
                   ( (Closeable)target ).close();
               }
   
  +        }
  +    }
  +
  +    private static class OurErrorHandler implements ErrorHandler
  +    {
  +        /** 
  +         * This will be initialized to an instance of LoggerSwitch.SwitchingLogger;
  +         * that is really reliable.
  +         */
  +        private Logger m_reliableLogger;
  +        private boolean m_wasError = false;
  +        /**
  +         * Access to this variable is not synchronized. Justification: it is only
  +         * intended to be accessed from postConfigure when only one thread
  +         * is assumed to be using the whole LogKitLoggerManager.
  +         */
  +        public boolean getWasError() { return m_wasError; }
  +
  +        OurErrorHandler( final Logger reliableLogger )
  +        {
  +           if ( reliableLogger == null )
  +           {
  +               throw new NullPointerException( "reliableLogger" );
  +           }
  +           m_reliableLogger = reliableLogger;
  +        }
  +
  +        public void error( final String message, final Throwable throwable, final LogEvent event )
  +        {
  +            // let them know if they are interested
  +            m_wasError = true;
  +            // let them know we're not OK
  +            m_reliableLogger.fatalError( message, throwable );
  +
  +            // transmit the original error
  +            final Priority p = event.getPriority();
  +            final String nestedMessage = "nested log event: " + event.getMessage();
  +
  +            if ( p == Priority.DEBUG )
  +            {
  +                m_reliableLogger.debug( nestedMessage, event.getThrowable() );
  +            }
  +            else if ( p == Priority.INFO )
  +            {
  +                m_reliableLogger.info( nestedMessage, event.getThrowable() );
  +            }
  +            else if ( p == Priority.WARN )
  +            {
  +                m_reliableLogger.warn( nestedMessage, event.getThrowable() );
  +            }
  +            else if ( p == Priority.ERROR )
  +            {
  +                m_reliableLogger.error( nestedMessage, event.getThrowable() );
  +            }
  +            else if ( p == Priority.FATAL_ERROR)
  +            {
  +                m_reliableLogger.fatalError( nestedMessage, event.getThrowable() );
  +            }
  +            else
  +            {
  +                /** This just plainly can't happen :-)*/
  +                m_reliableLogger.error( "unrecognized priority " + nestedMessage, 
  +                    event.getThrowable() );
  +            }
           }
       }
   }
  
  
  
  1.16      +69 -60    avalon-excalibur/logger/src/java/org/apache/avalon/excalibur/logger/Log4JLoggerManager.java
  
  Index: Log4JLoggerManager.java
  ===================================================================
  RCS file: /home/cvs/avalon-excalibur/logger/src/java/org/apache/avalon/excalibur/logger/Log4JLoggerManager.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- Log4JLoggerManager.java	27 May 2003 07:30:27 -0000	1.15
  +++ Log4JLoggerManager.java	10 Jun 2003 08:29:37 -0000	1.16
  @@ -63,26 +63,15 @@
    * leaves that as an excercise for Log4J's construction.
    *
    * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
  + * @author <a href="mailto:tagunov at apache.org">Anton Tagunov</a>
    * @version CVS $Revision$ $Date$
    * @since 4.1
    */
  -public class Log4JLoggerManager
  +public class Log4JLoggerManager extends AbstractLoggerManager
       implements LoggerManager, LogEnabled
   {
  -    /** Map for name to logger mapping */
  -    private final Map m_loggers = new HashMap();
  -
  -    /** The root logger to configure */
  -    //private String m_prefix;
  -
       /** The hierarchy private to Log4JManager */
  -    private LoggerRepository m_hierarchy;
  -
  -    /** The default logger used for this system */
  -    private final Logger m_defaultLogger;
  -
  -    /** The logger used to log output from the logger manager. */
  -    private Logger m_logger;
  +    private final LoggerRepository m_hierarchy;
   
       /**
        * Creates a new <code>DefaultLog4JManager</code>. It will use a new <code>Hierarchy</code>.
  @@ -97,7 +86,7 @@
        */
       public Log4JLoggerManager( final LoggerRepository hierarchy )
       {
  -        this( null, hierarchy );
  +        this( (String) null, hierarchy, (String) null, (Logger) null, (Logger) null );
       }
   
       /**
  @@ -106,7 +95,7 @@
        */
       public Log4JLoggerManager( final String prefix )
       {
  -        this( prefix, LogManager.getLoggerRepository() );
  +        this( prefix, (LoggerRepository) null, (String) null, (Logger) null, (Logger) null );
       }
   
       /**
  @@ -116,8 +105,16 @@
       public Log4JLoggerManager( final String prefix,
                                  final LoggerRepository hierarchy )
       {
  -        this( prefix, hierarchy,
  -              new Log4JLogger( hierarchy.getRootLogger() ) );
  +        this( prefix, hierarchy, (String) null, (Logger) null, (Logger) null );
  +    }
  +
  +    /**
  +     * Creates a new <code>DefaultLog4JManager</code> using
  +     * specified logger name as root logger.
  +     */
  +    public Log4JLoggerManager( final String prefix, final String switchToCategory )
  +    {
  +        this( prefix, (LoggerRepository) null, switchToCategory, (Logger) null, (Logger) null );
       }
   
       /**
  @@ -126,9 +123,9 @@
        */
       public Log4JLoggerManager( final String prefix,
                                  final LoggerRepository hierarchy,
  -                               final Logger defaultLogger )
  +                               final String switchToCategory )
       {
  -        this( prefix, hierarchy, defaultLogger, defaultLogger );
  +        this( prefix, hierarchy, switchToCategory, (Logger) null, (Logger) null );
       }
   
       /**
  @@ -137,63 +134,75 @@
        */
       public Log4JLoggerManager( final String prefix,
                                  final LoggerRepository hierarchy,
  -                               final Logger defaultLogger,
  -                               final Logger logger )
  +                               final Logger defaultLogger )
       {
  -        //m_prefix = prefix;
  -        m_hierarchy = hierarchy;
  -        m_defaultLogger = defaultLogger;
  -        m_logger = logger;
  +        this( prefix, hierarchy, (String) null, defaultLogger, defaultLogger );
       }
   
       /**
  -     * Provide a logger.
  -     *
  -     * @param logger the logger
  -     **/
  -    public void enableLogging( final Logger logger )
  +     * Creates a new <code>DefaultLog4JManager</code> with an existing <code>Hierarchy</code> using
  +     * specified logger name as root logger.
  +     */
  +    public Log4JLoggerManager( final String prefix,
  +                               final LoggerRepository hierarchy,
  +                               final Logger defaultLogger,
  +                               final Logger logger )
       {
  -        m_logger = logger;
  +        this( prefix, hierarchy, (String) null, defaultLogger, logger );
       }
   
       /**
  -     * Retrieves a Logger from a category name. Usually
  -     * the category name refers to a configuration attribute name.  If
  -     * this Log4JManager does not have the match the default Logger will
  -     * be returned and a warning is issued.
  -     *
  -     * @param categoryName  The category name of a configured Logger.
  -     * @return the Logger.
  +     * Creates a new <code>DefaultLog4JManager</code>.
  +     * @param prefix to prepend to every category name on 
  +     *         <code>getLoggerForCategory()</code>
  +     * @param hierarchy a Log4J LoggerRepository to run with
  +     * @param switchToCategory if this parameter is not null
  +     *         after <code>start()</code>
  +     *         <code>LogKitLoggerManager</code> will start
  +     *         to log its own debug and error messages to
  +     *         a logger obtained via
  +     *         <code>this.getLoggerForCategory( switchToCategory )</code>.
  +     *         Note that prefix will be prepended to
  +     *         the value of <code>switchToCategory</code> also.
  +     * @param defaultLogger the logger to override the default
  +     *         logger configured by Log4J; probably should be
  +     *         null to allow users set up whatever logger they
  +     *         like as the root logger via Log4J configuration
  +     * @param logger the logger to log our own initialization
  +     *         messages (currently we have none) and to log
  +     *         errors (currently this functionality is not used
  +     *         either)
        */
  -    public final Logger getLoggerForCategory( final String categoryName )
  +    public Log4JLoggerManager( final String prefix,
  +                               final LoggerRepository hierarchy,
  +                               final String switchToCategory,
  +                               final Logger defaultLogger,
  +                               final Logger logger )
       {
  -        Logger logger = (Logger)m_loggers.get( categoryName );
  +        super( prefix, switchToCategory, defaultLogger );
   
  -        if( null != logger )
  +        if ( hierarchy == null )
           {
  -            if( m_logger.isDebugEnabled() )
  -            {
  -                final String message =
  -                    "Logger for category " + categoryName + " returned";
  -                m_logger.debug( message );
  -            }
  -            return logger;
  +            // is this an analog of new Hierarchy() or an
  +            // analog of Hierarchy.getDefaultHierarchy()?
  +            // we should have an analog of new Hierarchy() here
  +            // I guess - Anton Tagunov
  +            m_hierarchy = LogManager.getLoggerRepository();
           }
  -
  -        if( m_logger.isDebugEnabled() )
  +        else
           {
  -            final String message = "Logger for category " + categoryName +
  -                " not defined in configuration. New Logger created and returned";
  -            m_logger.debug( message );
  +            m_hierarchy = hierarchy;
           }
   
  -        logger = new Log4JLogger( m_hierarchy.getLogger( categoryName ) );
  -        m_loggers.put( categoryName, logger );
  -        return logger;
  +        if ( logger != null )
  +        {
  +            this.enableLogging( logger );
  +        }
       }
   
  -    public final Logger getDefaultLogger()
  +    /* Actaully create the Logger */
  +    protected Logger doGetLoggerForCategory( final String fullCategoryName )
       {
  -        return m_defaultLogger;
  +        return new Log4JLogger( m_hierarchy.getLogger( fullCategoryName ) );
       }
   }
  
  
  
  1.5       +23 -1     avalon-excalibur/logger/src/java/org/apache/avalon/excalibur/logger/Log4JConfLoggerManager.java
  
  Index: Log4JConfLoggerManager.java
  ===================================================================
  RCS file: /home/cvs/avalon-excalibur/logger/src/java/org/apache/avalon/excalibur/logger/Log4JConfLoggerManager.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Log4JConfLoggerManager.java	27 May 2003 07:30:27 -0000	1.4
  +++ Log4JConfLoggerManager.java	10 Jun 2003 08:29:37 -0000	1.5
  @@ -70,6 +70,28 @@
       extends Log4JLoggerManager
       implements Configurable
   {
  +    /**
  +     * Work around a weird compilation problem. Can not call
  +     * the constructor from fortress/ContextManager, get a
  +     * file org\apache\log4j\spi\LoggerRepository.class not found
  +     *         new Log4JConfLoggerManager( lmDefaultLoggerName, lmLoggerName );
  +     */
  +
  +    public static Log4JConfLoggerManager newInstance( final String prefix,
  +            final String switchToCategory )
  +    {
  +        return new Log4JConfLoggerManager( prefix, switchToCategory );
  +    }
  +
  +    public Log4JConfLoggerManager( final String prefix, final String switchToCategory )
  +    {
  +        super( prefix, switchToCategory );
  +    }
  +
  +    public Log4JConfLoggerManager()
  +    {
  +    }
  +
       public void configure( final Configuration configuration )
           throws ConfigurationException
       {
  
  
  
  1.1                  avalon-excalibur/logger/src/java/org/apache/avalon/excalibur/logger/AbstractLoggerManager.java
  
  Index: AbstractLoggerManager.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
      must not be used to endorse or promote products derived from this  software
      without  prior written permission. For written permission, please contact
      apache@apache.org.
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.avalon.excalibur.logger;
  
  import java.util.Map;
  import java.util.HashMap;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.logger.LogEnabled;
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.excalibur.logger.util.LoggerSwitch;
  
  /**
   *
   * This abstract class implements LogEnabled.
   * A derived class is expected to obtain a logger via
   * <code>getLogger()</code> and live with it.
   * The <code>Logger</code> supplied via <code>enableLogging</code>
   * will be used both as the "initial" and as the "fallback" logger.
   * <ul><li>
   * "initial" means that until a call to 
   * <code>start()</code> the messages logger via
   * <code>getLogger().xxx()</code> will go to this logger</li><li>
   * "fallback" means that if after a successfull <code>start</code>
   * a recursive invocation of <code>getLogger().xxx()</code> will be detected
   * the message will be logged via the initial logger as a fallback.</li></ul>
   * See {@link org.apache.avalon.excalibur.logger.util.LoggerSwitch} for
   * more details.
   *
   * @author <a href="mailto:giacomo@apache.org">Giacomo Pati</a>
   * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
   * @author <a href="mailto:proyal@apache.org">Peter Royal</a>
   * @author <a href="mailto:tagunov at apache.org">Anton Tagunov</a>
   * @version CVS $Revision: 1.1 $ $Date: 2003/06/10 08:29:37 $
   * @since 4.0
   */
  public abstract class AbstractLoggerManager
      implements LogEnabled, LoggerManager
  {
      /** 
       * Map for name to logger mapping.
       * This instance variable is protected (not privated)
       * so that it may be pre-filled at configuration stage.
       */
      final protected Map m_loggers = new HashMap();
  
      /** The root logger to configure */
      protected String m_prefix;
  
      /** 
       * The object that wraps a swithing logger.
       * The switching logger itself for security reasons
       * has no methods of controlling it, but its wrapping
       * object has.
       */
      private LoggerSwitch m_switch;
  
      /** Always equals to m_switch.get() */
      private Logger m_logger;
  
      /** 
       * category we should switch our own loggin to 
       * on <code>start()</code>.
       */
      private String m_switchTo;
  
      /** safeguards against double <code>enableLogging()</code> invocation. */
      private boolean m_enableLoggingInvoked = false;
  
      /** safeguards against double <code>start()</code> invocation. */
      private boolean m_startInvoked = false;
  
      /** 
       * The logger used to be returned from <code>getDefaultLogger()</code>
       * and <code>getLoggerForCategory("")</code>,
       * if one has been forcibly set via a constructor. 
       */
      final private Logger m_defaultLoggerOverride;
  
      /**
       * Derived LoggerManager implementations should obtain
       * a logger to log their own messages via this call.
       * It is also safe to log messages about logging failures
       * via this logger as it safeguards internally gainst
       * recursion.
       */
      protected Logger getLogger()
      {
          return m_logger;
      }
  
      /**
       * Initializes AbstractLoggerManager.
       * @param prefix the prefix to prepended to the category name
       *         on each invocation of getLoggerForCategory before
       *         passing the category name on to the underlying logging
       *         system (currently LogKit or Log4J).
       * @param switchTo fuel for the <code>start()</code> method; 
       *         if null <code>start()</code> will do nothing; 
       *         if empty <code>start()</code> will switch to
       *         <code>getLoggerForCategory("")</code>.
       */
      public AbstractLoggerManager( final String prefix, final String switchTo, 
              Logger defaultLoggerOverride )
      {
          m_prefix = prefix;
          m_switchTo = switchTo;
  
          m_switch = new LoggerSwitch( null, null );
          m_logger = m_switch.get();
  
          m_defaultLoggerOverride = defaultLoggerOverride;
      }
  
      /**
       * Accept the logger we shall use as the initial and the fallback logger.
       */
      public void enableLogging( final Logger fallbackLogger )
      {
          if ( m_enableLoggingInvoked )
          {
              throw new IllegalStateException( "enableLogging() already called" );
          }
          m_switch.setFallback( fallbackLogger );
          m_enableLoggingInvoked = true;
      }
  
      /**
       * Get a logger from ourselves and pass it to <code>m_switch</code>.
       */
      public void start()
      {
          if ( m_startInvoked )
          {
              throw new IllegalStateException( "start() already invoked" );
          }
  
          if ( m_switchTo != null )
          {
              if ( m_logger.isDebugEnabled() )
              {
                  final String message = "LogKitLoggerManager: switching logging to " + 
                          "this.getLoggerForCategory('" +
                          getFullCategoryName( m_prefix, m_switchTo) + "').";
                  m_logger.debug( message );
              }
  
              final Logger ourOwn = this.getLoggerForCategory( m_switchTo );
          
              if ( ourOwn == null )
              {
                  throw new NullPointerException( "ourOwn" );
              }
              
              m_switch.setPreferred( ourOwn );
  
              if ( m_logger.isDebugEnabled() )
              {
                  final String message = "LogKitLoggerManager: have switched logging to " + 
                          "this.getLoggerForCategory('" +
                          getFullCategoryName( m_prefix, m_switchTo) + "').";
                  m_logger.debug( message );
              }
          }
          else
          {
              if ( m_logger.isDebugEnabled() )
              {
                  final String message = "LogKitLoggerManager: m_switchTo is null, " +
                          "no switch of our own logging.";
                  m_logger.debug( message );
              }
          }
          m_startInvoked = true;
      }
  
      /** Startable.stop() empty implementation. */
      public void stop(){}
  
      /**
       * Generates a full category name given a prefix and category.  Either may be
       *  null.
       *
       * @param prefix Prefix or parent category.
       * @param category Child category name.
       */
      protected final String getFullCategoryName( String prefix, String category )
      {
          if( ( null == prefix ) || ( prefix.length() == 0 ) )
          {
              if( category == null )
              {
                  return "";
              }
              else
              {
                  return category;
              }
          }
          else
          {
              if( ( null == category ) || ( category.length() == 0 ) )
              {
                  return prefix;
              }
              else
              {
                  return prefix + org.apache.log.Logger.CATEGORY_SEPARATOR + category;
              }
          }
      }
  
      /**
       * Retruns the logger for the <code>""</code> category.
       */
      public final Logger getDefaultLogger()
      {
          return getLoggerForCategory( null );
      }
  
      /**
       * Actually create a logger wrapping underlying logger
       * backed implementation for a give category. Bypasses the caching.
       * Derived LoggerManager implementations should provide an implementation
       * of this method.
       */
      protected abstract Logger doGetLoggerForCategory( final String fullCategoryName );
  
      /**
       * Retrieves a Logger from a category name. Usually
       * the category name refers to a configuration attribute name.  If
       * this LogKitManager does not have the match the default Logger will
       * be returned and a warning is issued.
       */
      public final Logger getLoggerForCategory( final String categoryName )
      {
          if ( m_defaultLoggerOverride != null &&
                  ( categoryName == null || categoryName.length() == 0 ) )
          {
              return m_defaultLoggerOverride;
          }
  
          final String fullCategoryName = getFullCategoryName( m_prefix, categoryName );
  
          final Logger logger;
          final Logger newLogger;
  
          synchronized( m_loggers )
          {
              logger = (Logger)m_loggers.get( fullCategoryName );
              
              if ( logger == null )
              {
                  newLogger = doGetLoggerForCategory( fullCategoryName );
                  m_loggers.put( fullCategoryName, newLogger );
              }
              else
              {
                  /* Let's have no "variable might not have been initialized". */
                  newLogger = null;
              }
          }
  
          if( null != logger )
          {
              if( m_logger.isDebugEnabled() )
              {
                  m_logger.debug( "Logger for category " + fullCategoryName + " returned" );
              }
              return logger;
          }
  
          if( m_logger.isDebugEnabled() )
          {
              m_logger.debug( "Logger for category " + fullCategoryName + " not defined in "
                              + "configuration. New Logger created and returned" );
          }
  
          return newLogger;
      }
  }
  
  
  

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


Mime
View raw message