/*
 * 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.
 */
package org.apache.avalon.excalibur.logger;

import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;

import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;

import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.logger.Log4JLogger2;

import org.apache.log4j.LogManager;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.xml.DOMConfigurator;

import java.util.Map;
import java.util.HashMap;

import java.io.File;


/**
 * Log4JLoggerManager implementation.  This is the interface used to get instances of
 * a Logger for your system.  This manager does not set up the categories--it
 * leaves that as an excercise for Log4J's construction.
 *
 * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
 * @version CVS $Revision: 1.1 $ $Date: 2002/01/17 20:44:59 $
 * @since 4.1
 */
public class Log4JLoggerManager2
    implements LoggerManager, Contextualizable, Configurable
{
    /** Map for name to logger mapping */
    final private Map         m_loggers = new HashMap();

    /** The root logger to configure */
    private String            m_prefix;

    /** The hierarchy private to Log4JLoggerManager */
    private LoggerRepository  m_hierarchy;

    /** The default logger used for this system */
    final private Logger      m_defaultLogger;

    /** The home directory of the application */
    private String            m_appHome;



    /**
     * Creates a new <code>DefaultLogKitManager</code>.
     * It will use a new <code>LoggerRepository</code>.
     */
    public Log4JLoggerManager2()
    {
        this( LogManager.getLoggerRepository() );
    }

    /**
     * Creates a new <code>DefaultLogKitManager</code> with an existing
     * <code>LoggerRepository</code>.
     */
    public Log4JLoggerManager2( final LoggerRepository hierarchy )
    {
        this( null, hierarchy );
    }

    /**
     * Creates a new <code>DefaultLogKitManager</code> using
     * specified logger name as root logger.
     */
    public Log4JLoggerManager2( final String prefix )
    {
        this( prefix, LogManager.getLoggerRepository() );
    }

    /**
     * Creates a new <code>Log4JLoggerManager</code> with an existing
     * <code>LoggerRepository</code> using
     * specified logger name as root logger.
     */
    public Log4JLoggerManager2( final String prefix, final LoggerRepository hierarchy )
    {
        this( prefix, hierarchy,
              new Log4JLogger2( hierarchy.getLogger( "" ) ) );
    }

    /**
     * Creates a new <code>DefaultLogKitManager</code> with an existing
     * <code>LoggerRepository</code> using
     * specified logger name as root logger.
     */
    public Log4JLoggerManager2( final String prefix,
                                final LoggerRepository hierarchy,
                                final Logger defaultLogger )
    {
        m_prefix = prefix;
        m_hierarchy = hierarchy;
        m_defaultLogger = defaultLogger;
    }

    /**
     * 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.
     *
     * @param categoryName  The category name of a configured Logger.
     * @return the Logger.
     */
    public final Logger getLoggerForCategory( final String categoryName )
    {
        Logger logger = (Logger) m_loggers.get( categoryName );

        if( null != logger )
        {
            if( m_defaultLogger.isDebugEnabled() )
            {
                m_defaultLogger.debug( "Logger for category " + categoryName + " returned" );
            }
            return logger;
        }

        if( m_defaultLogger.isDebugEnabled() )
        {
            m_defaultLogger.debug( "Logger for category " + categoryName
                              + " not defined in configuration. New Logger created and returned" );
        }

        logger = new Log4JLogger2( m_hierarchy.getLogger( categoryName ) );
        m_loggers.put( categoryName, logger );
        return logger;
    }

    public final Logger getDefaultLogger()
    {
        return m_defaultLogger;
    }


    /**
     * Reads a context object.
     *
     * @param context The context object.
     * @throws ContextException if the context is malformed
     */
    public final void contextualize( final Context context )
        throws ContextException
    {
        m_appHome = ((File) context.get("app.home")).getAbsolutePath();
    }

    /**
     * Reads a configuration object and creates the category mapping.
     *
     * @param configuration  The configuration object.
     * @throws ConfigurationException if the configuration is malformed
     */
    public final void configure( final Configuration configuration )
        throws ConfigurationException
    {
        final Configuration log4jConfig = configuration.getChild( "configuration" );
        final String log4jConfigFile = m_appHome + File.separator
                                       + configuration.getAttribute( "configFile" );
        DOMConfigurator.configure(log4jConfigFile);
    }

} // class Log4JLoggerManager
