Package org.apache.avalon.fortress.util

Source Code of org.apache.avalon.fortress.util.ContextManager

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed  under the  License is distributed on an "AS IS" BASIS,
* WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
* implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.avalon.fortress.util;

import org.apache.avalon.excalibur.logger.LogKitLoggerManager;
import org.apache.avalon.excalibur.logger.LoggerManager;
import org.apache.avalon.fortress.MetaInfoManager;
import org.apache.avalon.fortress.RoleManager;
import org.apache.avalon.fortress.impl.role.ConfigurableRoleManager;
import org.apache.avalon.fortress.impl.role.ECMMetaInfoManager;
import org.apache.avalon.fortress.impl.role.ECMRoleManager;
import org.apache.avalon.fortress.impl.role.FortressRoleManager;
import org.apache.avalon.fortress.impl.role.Role2MetaInfoManager;
import org.apache.avalon.fortress.impl.role.ServiceMetaManager;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.logger.ConsoleLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.avalon.framework.service.DefaultServiceSelector;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceException;
import org.d_haven.event.Sink;
import org.d_haven.event.Pipe;
import org.d_haven.event.command.*;
import org.apache.excalibur.instrument.InstrumentManager;
import org.apache.excalibur.instrument.manager.impl.DefaultInstrumentManagerImpl;
import org.d_haven.mpool.DefaultPoolManager;
import org.d_haven.mpool.PoolManager;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.source.impl.ResourceSourceFactory;
import org.apache.excalibur.source.impl.SourceResolverImpl;
import org.apache.excalibur.source.impl.URLSourceFactory;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;

/**
* <p>You can get two different contexts from the ContextManager:
* the container context (m_childContext)
* and the container manager context (m_containerManagerContext)</p>
*
* <p>You can get two different contexts from the ContextManager: the child
* context and the impl manager context. The former contains all
* managers, such as the pool manager etc. necessary for a child impl to
* create additional child containers. The impl manager context contains
* all of the child context, but also initialization parameters for the
* impl, such as a Configuration object, a ComponentLocator, etc., that
* the impl wants, but does not want to pass on to its children.</p>
*
* <p>The container manager context is used to provide the container manager
* with all the data needed to initialize the container.</p>
* <p>The container context is passed directly to the container.</p>
*
* <p>The ContextManager will sometimes create new components, such as
* a service manager, a pool manager, etc. It will manage these components
* and dispose of them properly when it itself is disposed .</p>
*
* @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
* @version CVS $Revision: 1.55 $ $Date: 2004/04/05 12:05:38 $
* @since 4.1
*/
public class ContextManager
        implements ContextManagerConstants, Initializable, Disposable
{
    protected static final Configuration EMPTY_CONFIG;

    static
    {
        DefaultConfiguration config =
                new DefaultConfiguration( "", "", "", "" );
        config.makeReadOnly();
        EMPTY_CONFIG = config;
    }

    /**
     * The root context.
     */
    protected final Context m_rootContext;

    /**
     * The context of the new impl. This context has the rootContext
     * as its parent. Put everything here that you want the new impl
     * to have in its own context.
     */
    protected final DefaultContext m_childContext;

    /**
     * Container manager's context. This context has the child context
     * as parent. Put things here that you want the impl manager
     * to see, but do not wish to expose to the impl.
     */
    protected final DefaultContext m_containerManagerContext;

    protected Logger m_logger;
    protected final Logger m_primordialLogger;

    /**
     *  Source resolver used to read-in the configurations.
     *  and provided as a default source resolver if the
     *  user has not supplied a ServiceManager.
     */
    protected SourceResolver m_defaultSourceResolver;

    /**
     * The logger manager in use.
     * Either supplied via rootContext, or created locally.
     */
    protected LoggerManager m_loggerManager;

    /**
     * The Sink in use.
     * Either supplied via rootContext or created locally.
     */
    protected Sink m_sink;

    /**
     * The MetaInfoManager to be used by the container.
     * Either supplied via rootContext or created locally.
     */
    protected MetaInfoManager m_metaInfoManager;

    /**
     * The PoolManager to be used by the container.
     * Either supplied via rootContext or created locally.
     */
    protected PoolManager m_poolManager;

    /**
     * The ThreadManager to be used by the container.
     * Either supplied via rootContext or created locally.
     */
    protected ThreadManager m_threadManager;

    /**
     * The InstrumentManager to be used by the container.
     * Either supplied via rootContext or created locally.
     */
    protected InstrumentManager m_instrumentManager;

    /**
     * The components that are "owned" by this context and should
     * be disposed by it. Any manager that is created as a result
     * of it not being in the rootContext, or having been created
     * by the ContextManager should go in here.
     */
    private final ArrayList ownedComponents = new ArrayList();

    /**
     * The ConfigurationBuilder is instantiated lazilly in getConfiguration
     * to avoid LinkageErrors in some environments.
     */
    private DefaultConfigurationBuilder configBuilder;
    private CommandManager m_commandManager;

    /**
     * Create a new ContextManager.
     *
     * @param rootContext the default values.
     * @param logger      logger to use when creating new components.
     */
    public ContextManager( final Context rootContext, final Logger logger )
    {
        m_rootContext = rootContext;
        m_childContext = new OverridableContext( m_rootContext );
        m_containerManagerContext = new OverridableContext( m_childContext );
        m_logger = logger;

        // The primordial logger is used for all output up until the point where
        //  the logger manager has been initialized.  However it is set into
        //  two objects used to load the configuration resource files within
        //  the ContextManager.  Any problems loading these files will result in
        //  warning or error messages.  However in most cases, the debug
        //  information should not be displayed, so turn it off by default.
        //  Unfortunately, there is not a very good place to make this settable.
        if ( m_logger == null )
        {
            m_primordialLogger = new ConsoleLogger( ConsoleLogger.LEVEL_INFO );
        }
        else
        {
            m_primordialLogger = null;
        }
    }

    /**
     * Method to assume ownership of one of the managers the
     * <code>ContextManager</code> created.  Ownership means that the
     * <code>ContextManager</code> is responsible for destroying the
     * manager when the <code>ContextManager</code> is destroyed.
     *
     * @param object  The object being claimed
     *
     * @throws IllegalArgumentException if the object is null.
     */
    protected void assumeOwnership( final Object object )
    {
        if ( object == null )
        {
            throw new NullPointerException( "object: Can not assume ownership of a null!" );
        }
        ownedComponents.add( object );
    }

    /**
     * Initialize the <code>ContextManager</code>.  This will cause the
     * <code>ContextManager</code> to create any managers it needs.
     *
     * @throws Exception if there is a problem at any point in the
     *         initialization.
     */
    public void initialize() throws Exception
    {
        initializeDefaultSourceResolver();
        initializeLoggerManager();
        initializeMetaInfoManager();
        initializeThreadManager();
        initializeCommandSink();
        initializePoolManager();
        initializeContext();
        initializeInstrumentManager();
        initializeConfiguration();
        initializeServiceManager();

        m_childContext.makeReadOnly();
        m_containerManagerContext.makeReadOnly();

        m_defaultSourceResolver = null;
    }

    /**
     * Load the configuration file that the Container will need to operate.
     */
    protected void initializeConfiguration()
    {
        try
        {
            copyEntry( CONFIGURATION );
            return;
        }
        catch ( ContextException ce )
        {
            final Configuration containerConfig =
                    getConfiguration( CONFIGURATION, CONFIGURATION_URI );

            if ( containerConfig == null )
            {
                getLogger().debug( "Could not initialize the Configuration", ce );
                // Guess there is none.
                return;
            }
            else
            {
                m_containerManagerContext.put( CONFIGURATION, containerConfig );
            }
        }
    }

    /**
     * Initialize the context that will be passed into the impl.
     *
     * @throws Exception if any of the parameters cannot be copied properly.
     */
    protected void initializeContext() throws Exception
    {
        copyEntry( CONTAINER_CLASS );

        try
        {
            copyEntry( PARAMETERS );
        }
        catch ( ContextException ce )
        {
            getLogger().debug( "Could not copy Context parameters.  This may be Ok depending on "
                    + "other configured context values." );
        }

        // hide from the container implementation what it does not need
        m_childContext.put( CONFIGURATION, null );
        m_childContext.put( CONFIGURATION_URI, null );
        m_childContext.put( RoleManager.ROLE, null );
        m_childContext.put( ROLE_MANAGER_CONFIGURATION, null );
        m_childContext.put( ROLE_MANAGER_CONFIGURATION_URI, null );
        m_childContext.put( LoggerManager.ROLE, null );
        m_childContext.put( LOGGER_MANAGER_CONFIGURATION, null );
        m_childContext.put( LOGGER_MANAGER_CONFIGURATION_URI, null );
        m_childContext.put( InstrumentManager.ROLE, null );
        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION, null );
        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION_URI, null );
        m_childContext.put( Sink.class.getName(), null );
        m_childContext.put( MetaInfoManager.ROLE, null );
        m_childContext.put( PoolManager.class.getName(), null );
        m_childContext.put( LifecycleExtensionManager.ROLE, null );
    }

    /**
     * Copies the specified entry from the <code>rootContext</code> to the
     * <code>containerManagerContext</code>.
     *
     * @throws ContextException if the parameter does not exist
     */
    protected void copyEntry( final String key ) throws ContextException
    {
        m_containerManagerContext.put( key, m_rootContext.get( key ) );
        m_childContext.put( key, null );
    }

    /**
     * Checks if a specified entry in <code>context</code>
     * has been supplied by the invoker.
     *
     * @param context  The context to check
     * @param key      The key name to check
     */
    protected boolean entryPresent( Context context, final String key )
    {
        boolean isPresent = false;

        try
        {
            context.get( key );
            isPresent = true;
        }
        catch ( ContextException ce )
        {
            // It is not present, so the value remains false
        }

        return isPresent;
    }

    /**
     * Disposes all items that this ContextManager has created.
     */
    public void dispose()
    {
        // Dispose all items owned by ContextManager
        disposeOwned();

        // Now dispose the Logger (cannot log to logger after its shutdown)
        if ( getLogger().isDebugEnabled() )
        {
            getLogger().debug( "Shutting down: " + m_loggerManager );
        }

        try
        {
            ContainerUtil.shutdown( m_loggerManager );
        }
        catch (final Exception ex)
        {
            if m_primordialLogger.isDebugEnabled() )
            {
                m_primordialLogger.debug( "Failed to shutdown loggerManager", ex );
            }
        }
    }

    /**
     * Disposes all items ContextManager has assumed ownership over
     */
    public void disposeOwned()
    {
        Collections.sort( ownedComponents, new DestroyOrderComparator() );

        // Dispose owned components
        final Iterator ownedComponentsIter = ownedComponents.iterator();
        while ( ownedComponentsIter.hasNext() )
        {
            final Object o = ownedComponentsIter.next();

            try
            {
                if ( getLogger().isDebugEnabled() ) getLogger().debug( "Shutting down: " + o );
                ContainerUtil.shutdown( o );
                if ( getLogger().isDebugEnabled() ) getLogger().debug( "Done." );
            }
            catch ( Exception e )
            {
                getLogger().warn( "Unable to dispose of owned component "
                        + o.getClass().getName(), e );
            }

            ownedComponentsIter.remove();
        }
    }

    /**
     * Convenience method to obtain a value, or defer to a default if it does
     * not exist.
     *
     * @param context       The context object we intend to get a value from.
     * @param key           The key we want to use to get the value.
     * @param defaultValue  The default value we return if the key does not
     *                      exist.
     */
    protected Object get( final Context context, final String key, final Object defaultValue )
    {
        try
        {
            return context.get( key );
        }
        catch ( ContextException ce )
        {
            return defaultValue;
        }
    }

    /**
     * Set up the CommandSink to enable asynchronous management.
     *
     * @throws Exception if the <code>CommandSink</code> could not be
     *         created.
     */
    protected void initializeCommandSink() throws Exception
    {
        try
        {
            m_sink = (Sink) m_rootContext.get( Sink.class.getName() );
        }
        catch ( ContextException ce )
        {
            // No CommandSink specified, create a default one
            m_sink = createCommandSink();
        }
    }

    /**
     * Helper method for creating a default CommandSink
     *
     * @return a default <code>CommandSink</code>
     * @throws Exception if an error occurs
     */
    private Sink createCommandSink() throws Exception
    {
        m_commandManager = new DefaultCommandManager(m_threadManager);
        m_commandManager.start();

        assumeOwnership( m_commandManager );

        m_containerManagerContext.put( CommandManager.class.getName(), m_commandManager);

        // Set the CommandFailureHandler
        Class failureHandlerClass;
        try
        {
            failureHandlerClass = (Class)m_rootContext.get( COMMAND_FAILURE_HANDLER_CLASS );
        }
        catch ( ContextException ce )
        {
            // Not set.  Use the default.
            failureHandlerClass = FortressCommandFailureHandler.class;
        }
        CommandFailureHandler fh = (CommandFailureHandler)failureHandlerClass.newInstance();
        final Logger fhLogger = m_loggerManager.getLoggerForCategory( "system.command" );
        ContainerUtil.enableLogging( fh, fhLogger );
        ContainerUtil.initialize( fh );
        m_commandManager.setCommandFailureHandler( fh );

        return new CommandSink(m_commandManager);
    }

    /**
     * Helper method for creating ThreadManager configuration.
     *
     * @return ThreadManager configuration as a <code>Parameters</code>
     *         instance
     */
    private ThreadPolicy buildThreadPolicy()
    {
        String version = System.getProperty( "java.version" );

        if ( version.charAt( 2 ) < '4' ) {
            return new OneThreadPolicy();
        }

        Integer threadsPerProcessor;
        Long threadBlockTimeout;

        try
        {
            threadsPerProcessor = (Integer) m_rootContext.get( THREADS_CPU );
        }
        catch ( ContextException e )
        {
            threadsPerProcessor = new Integer( 2 );
        }

        try
        {
            threadBlockTimeout = (Long) m_rootContext.get( THREAD_TIMEOUT );
        }
        catch ( ContextException e )
        {
            threadBlockTimeout = new Long( 1000 );
        }

        return new ProcessorBoundThreadPolicy(threadsPerProcessor.intValue(), threadBlockTimeout.longValue());
    }

    /**
     * Set up the Pool Manager for the managed pool.
     *
     * @throws Exception if there is an error.
     */
    protected void initializePoolManager() throws Exception
    {
        try
        {
            m_poolManager = (PoolManager) m_rootContext.get( PoolManager.class.getName() );
        }
        catch ( ContextException ce )
        {
            final PoolManager pm = new DefaultPoolManager( m_commandManager );
            assumeOwnership( pm );
            m_poolManager = pm;
        }
    }

    /**
     * Set up a RoleManager for the Container if configuration for
     * it has been supplied.
     *
     * @throws Exception if there is an error.
     */
    protected RoleManager obtainRoleManager() throws Exception
    {
        /* we don't want an error message from getConfiguration, so
         * check if there is job to do first
         */
        if ( entryPresent( m_rootContext, RoleManager.ROLE ) )
        {
            return (RoleManager) m_rootContext.get( RoleManager.ROLE );
        }

        if ( !entryPresent( m_rootContext, ROLE_MANAGER_CONFIGURATION ) &&
                !entryPresent( m_rootContext, ROLE_MANAGER_CONFIGURATION_URI ) )
        {
            return null;
        }

        Configuration roleConfig =
                getConfiguration( ROLE_MANAGER_CONFIGURATION, ROLE_MANAGER_CONFIGURATION_URI );

        if ( roleConfig == null )
        {
            // Something went wrong, but the error has already been reported
            return null;
        }

        // Lookup the context class loader
        final ClassLoader classLoader =
                (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );

        // Create a logger for the role manager
        final Logger rmLogger = m_loggerManager.getLoggerForCategory(
                roleConfig.getAttribute( "logger", "system.roles" ) );

        // Create a parent role manager with all the default roles
        final FortressRoleManager frm = new FortressRoleManager( null, classLoader );
        frm.enableLogging( rmLogger.getChildLogger( "defaults" ) );
        frm.initialize();

        RoleManager rm;
        if ( entryPresent( m_rootContext, ROLE_MANAGER_CLASS ) )
        {
            Class clazz = (Class)m_rootContext.get( ROLE_MANAGER_CLASS );
            // Test if the class implements a constructor to pass into the parent
            try
            {
                Constructor parentAwareConstructor = clazz.getConstructor(new Class[] {RoleManager.class});
                rm = (RoleManager)parentAwareConstructor.newInstance(new Object[] {frm});
            }
            catch (NoSuchMethodException ignore )
            {
                rm = (RoleManager)clazz.newInstance();
            }
        }
        else
        {
            // Create a role manager with the configured roles
            rm = new ConfigurableRoleManager( frm, classLoader );
        }

        ContainerUtil.enableLogging(rm, rmLogger );
        ContainerUtil.configure( rm, roleConfig );
        ContainerUtil.initialize( rm );

        assumeOwnership( rm );
        return rm;
    }

    protected void initializeMetaInfoManager() throws Exception
    {
        boolean mmSupplied = false;

        try
        {
            m_metaInfoManager = (MetaInfoManager) m_rootContext.get( MetaInfoManager.ROLE );
            mmSupplied = true;
        }
        catch ( ContextException ce )
        {
            // okay, we will create one
        }

        RoleManager roleManager = obtainRoleManager();
        final boolean rmSupplied = roleManager != null;

        if ( mmSupplied )
        {
            if ( rmSupplied )
            {
                getLogger().warn( "MetaInfoManager found, ignoring RoleManager" );
            }

            // Otherwise everything is ok, and we continue on (i.e. return)
        }
        else
        {
            final ClassLoader classLoader =
                    (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );

            if ( !rmSupplied )
            {
                final FortressRoleManager newRoleManager =
                        new FortressRoleManager( null, classLoader );
                newRoleManager.enableLogging(
                        m_loggerManager.getLoggerForCategory( "system.roles.defaults" ) );
                newRoleManager.initialize();

                roleManager = newRoleManager;
            }

            final MetaInfoManager mim;
            // if we use the ecm role manager then we don't wrap it inside a service meta manager!
            if ( roleManager instanceof ECMRoleManager )
            {
                final ECMMetaInfoManager metaManager =
                    new ECMMetaInfoManager( new Role2MetaInfoManager( roleManager ), classLoader );
                metaManager.enableLogging( m_loggerManager.getLoggerForCategory( "system.meta" ) );
                mim = metaManager;
            }
            else
            {
                final ServiceMetaManager metaManager =
                      new ServiceMetaManager( new Role2MetaInfoManager( roleManager ), classLoader );
                metaManager.enableLogging( m_loggerManager.getLoggerForCategory( "system.meta" ) );
                metaManager.initialize();
                mim = metaManager;
            }

            assumeOwnership( mim );
            m_metaInfoManager = mim;
        }
    }

    /**
     * Initialize the default source resolver
     *
     * @throws Exception when there is an error.
     */
    protected void initializeDefaultSourceResolver() throws Exception
    {
        final DefaultServiceManager manager = new DefaultServiceManager();
        final DefaultServiceSelector selector = new DefaultServiceSelector();
        final URLSourceFactory file = new URLSourceFactory();
        file.enableLogging( getLogger() );
        selector.put( "*", file );
        final ResourceSourceFactory resource = new ResourceSourceFactory();
        resource.enableLogging( getLogger() );
        selector.put( "resource", resource );

        manager.put( ResourceSourceFactory.ROLE + "Selector", selector );

        final SourceResolverImpl resolver = new SourceResolverImpl();
        ContainerUtil.enableLogging( resolver, getLogger() );
        ContainerUtil.contextualize( resolver, m_childContext );
        ContainerUtil.service( resolver, manager );
        ContainerUtil.parameterize( resolver, new Parameters() );

        m_defaultSourceResolver = resolver;
    }

    /**
     * Get a reference to the initial ComponentLocator used by the
     * ContainerManager to hold the Components used for parsing the config
     * files and setting up the environment.
     *
     * @throws Exception when there is an error.
     */
    protected void initializeServiceManager() throws Exception
    {
        final ServiceManager parent = (ServiceManager) get( m_rootContext, SERVICE_MANAGER, null );
        final DefaultServiceManager manager = new EAServiceManager( parent, getLogger().getChildLogger("compat") );

        /**
         * If there is a parent ServiceManager, we need to see if it has a SourceResolver,
         * and if not, make sure that one is available to fortress
         */

        if ( parent == null || !parent.hasService( SourceResolver.ROLE ) )
        {
            manager.put( SourceResolver.ROLE, m_defaultSourceResolver );
        }

        Object lem = get( m_rootContext, LifecycleExtensionManager.ROLE, null);

        /**
         * Role manager won't be passed here as it is now only
         * an utility for reading ECM role files.
         */

        manager.put( LoggerManager.ROLE, m_loggerManager );
        manager.put( Sink.class.getName(), m_sink );
        manager.put( MetaInfoManager.ROLE, m_metaInfoManager );
        manager.put( PoolManager.class.getName(), m_poolManager );
        manager.put( InstrumentManager.ROLE, m_instrumentManager );
        manager.put( ThreadManager.class.getName(), m_threadManager );

        if ( lem != null )
        {
            manager.put( LifecycleExtensionManager.ROLE, lem );
        }

        manager.makeReadOnly();

        m_containerManagerContext.put( SERVICE_MANAGER, manager );
        m_childContext.put( SERVICE_MANAGER, manager );
    }

    /**
     * Get a configuration based on a config and URI key.
     *
     * @param configKey  Get the <code>Configuration</code> object directly
     *                   from the context.
     * @param uriKey     Get the uri from the context.
     */
    protected Configuration getConfiguration( final String configKey, final String uriKey )
    {
        try
        {
            return (Configuration) m_rootContext.get( configKey );
        }
        catch ( ContextException ce )
        {
            getLogger().debug( "A preloaded Configuration was not found for key: " + configKey
                    + "  This may be Ok depending on other configured context values." );
        }

        final String configUri;
        try
        {
            configUri = (String) m_rootContext.get( uriKey );
        }
        catch ( ContextException ce )
        {
            getLogger().debug( "A configuration URI was not specified: " + uriKey );
            return null;
        }

        Source src = null;
        try
        {
            src = m_defaultSourceResolver.resolveURI( configUri );
            if ( configBuilder == null )
            {
                configBuilder = new DefaultConfigurationBuilder();
            }

            return configBuilder.build( src.getInputStream(), src.getURI() );
        }
        catch ( Exception e )
        {
            getLogger().warn( "Could not read configuration file: " + configUri, e );

            return null;
        }
        finally
        {
            m_defaultSourceResolver.release( src );
        }
    }

    /**
     * Finalizes and returns the context.
     *
     * @return a <code>Context</code>
     */
    public Context getContainerManagerContext()
    {
        return m_containerManagerContext;
    }

    /**
     * Finalizes and returns the context.
     *
     * @return a <code>Context</code>
     */
    public Context getChildContext()
    {
        return m_childContext;
    }

    /**
     * Get a reference the Logger.
     *
     * @return a <code>Logger</code>
     */
    protected Logger getLogger()
    {
        if ( m_logger == null )
        {
            return m_primordialLogger;
        }
        else
        {
            return m_logger;
        }
    }

    /**
     * Will set up a LogKitLoggerManager if none is supplied.  This can be
     * overridden if you don't want a LogKitLoggerManager.
     *
     * <p>The postcondition is that
     * <code>childContext.get( LoggerManager.ROLE )</code> should
     * return a valid logger manager.</p>
     *
     * @throws Exception if it cannot instantiate the LoggerManager
     */
    protected void initializeLoggerManager() throws Exception
    {
        try
        {
            // Try copying an already existing logger manager from the override context.
            m_loggerManager = (LoggerManager) m_rootContext.get( LoggerManager.ROLE );
        }
        catch ( ContextException ce )
        {
            // Should we set one up?
            // Try to get a configuration for it...
            Configuration loggerManagerConfig =
                    getConfiguration( LOGGER_MANAGER_CONFIGURATION,
                            LOGGER_MANAGER_CONFIGURATION_URI );

            if ( loggerManagerConfig == null )
            {
                // Create an empty configuration so that
                // a default logger can be created.
                loggerManagerConfig = EMPTY_CONFIG;
            }

            final String lmDefaultLoggerName =
                (String) get( m_rootContext, ContextManagerConstants.LOG_CATEGORY, "fortress" );
            final String lmLoggerName = loggerManagerConfig.getAttribute( "logger", "system.logkit" );

            // Setup the Logger Manager
            m_loggerManager = new LogKitLoggerManager( lmDefaultLoggerName, lmLoggerName );

            ContainerUtil.enableLogging( m_loggerManager, getLogger() );
            ContainerUtil.contextualize( m_loggerManager, m_rootContext );
            ContainerUtil.configure( m_loggerManager, loggerManagerConfig );
            ContainerUtil.start( m_loggerManager );
        }

        // Since we now have a LoggerManager, we can update the this.logger field
        // if it is null and start logging to the "right" logger.

        if ( m_logger == null )
        {
            getLogger().debug( "Switching to default Logger provided by LoggerManager." );

            m_logger = m_loggerManager.getDefaultLogger();
        }

        // pass our own logger to the ContainerManager
        m_containerManagerContext.put( LOGGER, m_logger );
    }

    protected void initializeThreadManager() throws Exception
    {
        try
        {
            m_threadManager = (ThreadManager)m_rootContext.get( ThreadManager.class.getName() );
        }
        catch( ContextException e )
        {
            final ThreadGroup group = new ThreadGroup("fortress.threads");
            final GroupedThreadFactory factory = new GroupedThreadFactory(group);

            final ThreadPolicy policy = buildThreadPolicy();
            policy.setThreadFactory( factory );

            final DefaultThreadManager tm = new DefaultThreadManager(policy);

            assumeOwnership( tm );

            m_threadManager = tm;
        }
    }

    /**
     * Will set up an InstrumentManager if none is supplied.  This can be
     * overridden if you don't want an InstrumentManager
     *
     * <p>The postcondition is that
     * <code>childContext.get( InstrumentManager.ROLE )</code> should
     * return a valid instrument manager.</p>
     *
     * @throws Exception if it cannot instantiate the InstrumentManager
     */
    protected void initializeInstrumentManager() throws Exception
    {
        try
        {
            // Try copying an already existing instrument manager from the override context.
            m_instrumentManager = (InstrumentManager) m_rootContext.get( InstrumentManager.ROLE );
        }
        catch ( ContextException ce )
        {
            // Should we set one up?
            // Try to get a configuration for it...
            Configuration instrumentConfig = getConfiguration( INSTRUMENT_MANAGER_CONFIGURATION,
                    INSTRUMENT_MANAGER_CONFIGURATION_URI );
            if ( instrumentConfig == null )
            {
                // No config.
                instrumentConfig = EMPTY_CONFIG;
            }

            // Get the logger for the instrument manager
            final Logger imLogger = m_loggerManager.getLoggerForCategory(
                    instrumentConfig.getAttribute( "logger", "system.instrument" ) );

            // Set up the Instrument Manager
            final DefaultInstrumentManagerImpl instrumentManager =
                new DefaultInstrumentManagerImpl();
            instrumentManager.enableLogging( imLogger );
            instrumentManager.configure( instrumentConfig );
            instrumentManager.initialize();

            assumeOwnership( instrumentManager );

            m_instrumentManager = instrumentManager;
        }
    }

    private final class DestroyOrderComparator implements Comparator
    {
        public boolean equals( final Object other )
        {
            return other instanceof DestroyOrderComparator;
        }

        public int hashCode()
        {
            return DestroyOrderComparator.class.hashCode();
        }

        public int compare( final Object a, final Object b )
        {
            final int typeA = typeOf( a );
            final int typeB = typeOf( b );

            if ( typeA < typeB ) return -1;
            if ( typeA > typeB ) return 1;
            return 0;
        }

        private int typeOf( final Object obj )
        {
            int retVal = 1; // Doesn't matter the type

            if ( obj instanceof CommandManager ) retVal = 0;
            if ( obj instanceof ThreadManager ) retVal = 2;
            if ( obj instanceof LoggerManager ) retVal = 3;

            return retVal;
        }
    }

    /**
     * This is a compatibility thing for early adopters of Fortress so that they will use the
     * correct ROLE for the CommandSink.
     */
    private static final class EAServiceManager extends DefaultServiceManager
    {
        private final Logger m_ealogger;

        public EAServiceManager( ServiceManager parent, Logger logger )
        {
            super( parent );
            m_ealogger = logger;
        }

        public Object lookup(String role) throws ServiceException
        {
            if ( Pipe.class.getName().equals( role ) )
            {
                m_ealogger.info("Using deprecated role (Queue.ROLE) for the Command Sink.  Use \"Sink.ROLE\" instead.");
                return lookup(Sink.class.getName());
            }

            return super.lookup( role );
        }

        public boolean hasService(String role)
        {
            if (Pipe.class.getName().equals( role ) ) return hasService(Sink.class.getName());

            return super.hasService( role );
        }
    }
}
TOP

Related Classes of org.apache.avalon.fortress.util.ContextManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.