Return-Path: Delivered-To: apmail-avalon-cvs-archive@avalon.apache.org Received: (qmail 36299 invoked by uid 500); 10 Jun 2003 08:29:40 -0000 Mailing-List: contact cvs-help@avalon.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Avalon CVS List" Reply-To: "Avalon Developers List" Delivered-To: mailing list cvs@avalon.apache.org Received: (qmail 36277 invoked by uid 500); 10 Jun 2003 08:29:39 -0000 Received: (qmail 36272 invoked from network); 10 Jun 2003 08:29:39 -0000 Received: from icarus.apache.org (208.185.179.13) by daedalus.apache.org with SMTP; 10 Jun 2003 08:29:39 -0000 Received: (qmail 159 invoked by uid 1677); 10 Jun 2003 08:29:38 -0000 Date: 10 Jun 2003 08:29:38 -0000 Message-ID: <20030610082938.158.qmail@icarus.apache.org> From: atagunov@apache.org To: avalon-excalibur-cvs@apache.org Subject: cvs commit: avalon-excalibur/logger/src/java/org/apache/avalon/excalibur/logger AbstractLoggerManager.java LogKitLoggerManager.java Log4JLoggerManager.java Log4JConfLoggerManager.java X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N 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 Giacomo Pati * @author Berin Loritsch * @author Peter Royal + * @author Anton Tagunov * @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 DefaultLogKitManager. It will use a new Hierarchy. + * Creates a new LogKitLoggerManager; + * one of the preferred constructors. + * Please also invoke enableLogging() + * to supply a fallback logger. */ public LogKitLoggerManager() { - this( new Hierarchy() ); + this( (String)null, (Hierarchy)null, (String)null, (Logger)null, (Logger)null ); } /** - * Creates a new DefaultLogKitManager with an existing Hierarchy. + * Creates a new LogKitLoggerManager; + * one of the preferred constructors. + * Please also invoke enableLogging() + * to supply a fallback logger. + * + * @param prefix to prepended to category name on each + * invocation of getLoggerForCategory(). */ - 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 DefaultLogKitManager using - * specified logger name as root logger. + * Creates a new LogKitLoggerManager; + * one of the preferred constructors, + * intended for the widest usage. + * + * Please also invoke enableLogging() + * to supply a fallback logger. + *

+ * Example: + *

  +     * LogKitLoggerManager l = new LogKitLoggerManager( "fortress", "system.logkit" );
  +     * l.enableLogging( bootstrapLogger );
  +     * l.configure( loggerManagerConfiguration );
  +     * 
+ * + * @param prefix to prepended to category name on each + * invocation of getLoggerForCategory(). + * @param switchToCategory if this parameter is not null + * after start() + * LogKitLoggerManager will start + * to log its own debug and error messages to + * a logger obtained via + * this.getLoggerForCategory( switchToCategory ). + * Note that prefix will be prepended to + * the value of switchToCategory also. + */ + public LogKitLoggerManager( final String prefix, final String switchToCategory ) + { + this( prefix, (Hierarchy)null, switchToCategory, (Logger)null, (Logger)null ); + } + + /** + * Creates a new LogKitLoggerManager + * with an existing Hierarchy; + * use with caution. + * + * Please also invoke enableLogging() + * to supply a fallback logger. + * See comments on the root constructor + * 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 getLoggerForCategory(). + * @param switchToCategory if this parameter is not null + * after start() + * LogKitLoggerManager will start + * to log its own debug and error messages to + * a logger obtained via + * this.getLoggerForCategory( switchToCategory ). + * Note that prefix will be prepended to + * the value of switchToCategory 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 DefaultLogKitManager with an existing Hierarchy using - * specified logger name as root logger. + * Creates a new LogKitLoggerManager + * with an existing Hierarchy; + * use with caution. + * + * Please also invoke enableLogging() + * to supply a fallback logger. + * See comments on the root constructor + * 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 DefaultLogKitManager with an existing Hierarchy using - * specified logger name as root logger. + * Creates a new LogKitLoggerManager + * with an existing Hierarchy; + * use with caution. + * + * Please also invoke enableLogging() + * to supply a fallback logger. + * See comments on the root constructor + * 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 getLoggerForCategory(). */ - 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 DefaultLogKitManager with an existing Hierarchy using - * specified logger name as root logger. + * Creates a new LogKitLoggerManager + * with an existing Hierarchy using + * specified logger name as a fallback logger and to + * forcibly override the root logger; + * compatibility constructor. + * + * The configuration for the "" + * category in the configuration will supply the defaults for + * all other categories, but getDefaultLogger() + * and getLoggerForCategory() will still + * use logger supplied by this constructor. + * + *

+ * See comments on the root constructor + * for details on why constructors supplying an existing hierarchy + * should be used with caution. + * + *

+ * As this constructor provides a logger to be used as a fallback + * a subsequent enableLogging() stage is unnecessary. + * Moreover, it will fail. + * + * @param prefix to prepended to category name on each + * invocation of getLoggerForCategory(). + * @param defaultOverrideAndFallback the logger used to + * a) forcibly + * 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 enableLogging(). The logger + * supplied via enableLogging will only be used + * as the fallback logger and to log messages during initialization + * while this constructor argument also has the described + * override 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 LogKitLoggerManager + * with an existing Hierarchy using + * specified loggers to forcibly override + * the default logger and to provide a fallback logger; + * compatibility constructor. + * + * See comments on the root constructor + * for details on why constructors supplying an existing hierarchy + * should be used with caution. + *

+ * As this constructor provides a logger to be used as a fallback + * a subsequent enableLogging() 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 getLoggerForCategory(). + * @param defaultLoggerOverride the logger to be used to forcibly + * 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 enableLogging()) + */ + 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. + * + * + * Creates a new LogKitLoggerManager; + * "root" constructor invoked by all other constructors. + *

+ * + * If the hierarchy parameter is not null + * 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 Hierarchy() + * constructor (this target logs to System.out) and + * installing our own ErrorHandler for our + * Hierarchy (the default ErrorHandler + * writes to System.err). + *

+ * The configuration of the resulting Hierarchy + * is a combination of the original configuraiton that + * existed when this Hierarchy was handled to us + * and the configuration supplied to use via configure(). + * LogTargets for those categories for which a + * configuration node has been supplied in the configuration + * supplied via configure() are replaced during + * the configure() process. LogTargets + * 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. + * + *

+ * Generally it is preferrable to + *

+ * That's why it is preferrable to pass null + * for the hierarchy parameter of this constructor + * or, which is easier to read but has the same effect, to + * invoke a constructor which does not accept a Hierarchy + * argument. + *

* - * @param categoryName The category name of a configured Logger. - * @return the Logger. + *

The defaultLoggerOverride and fallbackLogger + * are a special case too. defaultLoggerOverride + * forcibly overrides + * the root logger configured via configure(). + * 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 + * null for this parameter or better still to invoke + * a constructor without Logger parameters at all.

+ * + *

There is nothing wrong with passing fallbackLogger + * 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 Logger argument both as + * fallbackLogger (which is okay) and as + * a defaultLoggerOverride (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 + * enableLogging() call, like this happens with all + * other normal Avalon components after all. + * + * @param prefix to prepended to category name on each + * invocation of getLoggerForCategory(). + * @param switchToCategory if this parameter is not null + * after start() + * LogKitLoggerManager will start + * to log its own debug and error messages to + * a logger obtained via + * this.getLoggerForCategory( switchToCategory ). + * Note that prefix will be prepended to + * the value of switchToCategory also. + * @param defaultLoggerOverride the logger to be used to + * forcibly override + * 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 enableLogging()) */ - 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 + * AbstractLoggerManager.getLoggerForCategory(). + */ + 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 Berin Loritsch + * @author Anton Tagunov * @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 DefaultLog4JManager. It will use a new Hierarchy. @@ -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 DefaultLog4JManager 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 DefaultLog4JManager with an existing Hierarchy 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 DefaultLog4JManager. + * @param prefix to prepend to every category name on + * getLoggerForCategory() + * @param hierarchy a Log4J LoggerRepository to run with + * @param switchToCategory if this parameter is not null + * after start() + * LogKitLoggerManager will start + * to log its own debug and error messages to + * a logger obtained via + * this.getLoggerForCategory( switchToCategory ). + * Note that prefix will be prepended to + * the value of switchToCategory 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 . */ 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 * getLogger() and live with it. * The Logger supplied via enableLogging * will be used both as the "initial" and as the "fallback" logger. *

  • * "initial" means that until a call to * start() the messages logger via * getLogger().xxx() will go to this logger
  • * "fallback" means that if after a successfull start * a recursive invocation of getLogger().xxx() will be detected * the message will be logged via the initial logger as a fallback.
* See {@link org.apache.avalon.excalibur.logger.util.LoggerSwitch} for * more details. * * @author Giacomo Pati * @author Berin Loritsch * @author Peter Royal * @author Anton Tagunov * @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 start(). */ private String m_switchTo; /** safeguards against double enableLogging() invocation. */ private boolean m_enableLoggingInvoked = false; /** safeguards against double start() invocation. */ private boolean m_startInvoked = false; /** * The logger used to be returned from getDefaultLogger() * and getLoggerForCategory(""), * 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 start() method; * if null start() will do nothing; * if empty start() will switch to * getLoggerForCategory(""). */ 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 m_switch. */ 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 "" 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