Package org.apache.avalon.fortress.impl.handler

Source Code of org.apache.avalon.fortress.impl.handler.ComponentFactory

/*
* Copyright 2003-2004 The Apache Software Foundation
* Licensed  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.impl.handler;

import org.apache.avalon.excalibur.logger.LoggerManager;
import org.apache.avalon.fortress.util.LifecycleExtensionManager;
import org.apache.avalon.framework.CascadingException;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.WrapperComponentManager;
import org.apache.avalon.framework.configuration.Configuration;
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.LogKit2AvalonLoggerAdapter;
import org.apache.avalon.framework.logger.Loggable;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.excalibur.instrument.AbstractLogEnabledInstrumentable;
import org.apache.excalibur.instrument.CounterInstrument;
import org.apache.excalibur.mpool.ObjectFactory;

/**
* Factory for Avalon components.
*
* @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
* @version CVS $Revision: 1.28 $ $Date: 2004/02/28 15:16:25 $
* @since 4.0
*/
public final class ComponentFactory
    extends AbstractLogEnabledInstrumentable
    implements ObjectFactory
{
    private final CounterInstrument m_newInstance;
    private final CounterInstrument m_dispose;

    /** The class which this <code>ComponentFactory</code>
     * should create.
     */
    private final Class m_componentClass;

    /** The Context for the component
     */
    private final Context m_context;

    /** The component manager for this component.
     */
    private final ServiceManager m_serviceManager;

    /** The configuration for this component.
     */
    private final Configuration m_configuration;

    /** The LogKitManager for child ComponentSelectors
     */
    private final LoggerManager m_loggerManager;

    /** Lifecycle extensions manager
     */
    private final LifecycleExtensionManager m_extManager;

    /** The component's logger
     */
    private final Logger m_componentLogger;

    /**
     * Construct a new component factory for the specified component.
     *
     * @param componentClass the class to instantiate (must have a default constructor).
     * @param configuration the <code>Configuration</code> object to pass to new instances.
     * @param serviceManager the service manager to pass to <code>Serviceable</code>s.
     * @param context the <code>Context</code> to pass to <code>Contexutalizable</code>s.
     * @param loggerManager the loggerManager manager instance.
     */
    public ComponentFactory( final Class componentClass,
                             final Configuration configuration,
                             final ServiceManager serviceManager,
                             final Context context,
                             final LoggerManager loggerManager,
                             final LifecycleExtensionManager extManager )
    {
        m_componentClass = componentClass;
        m_configuration = configuration;
        m_serviceManager = serviceManager;
        m_context = new DefaultContext( context );
        final String name = configuration.getAttribute( "id", componentClass.getName() );
        ( (DefaultContext) m_context ).put( "component.name", name );
        ( (DefaultContext) m_context ).put( "component.logger", configuration.getAttribute( "logger", name ) );
        // Take each configuration attribute, and make a context entry of form "component.<attribName>"
        String[] attribNames = configuration.getAttributeNames();

        for ( int index = 0; index < attribNames.length; index++ )
        {
            String oneName = attribNames[index];
            ( (DefaultContext) m_context ).put( "component." + oneName, configuration.getAttribute( oneName, "" ) );
        }

        ( (DefaultContext) m_context ).put( "component.configuration", configuration );
        ( (DefaultContext) m_context ).makeReadOnly();
        m_loggerManager = loggerManager;
        m_extManager = extManager;
        enableLogging( m_loggerManager.getLoggerForCategory( "system.factory" ) );
        m_componentLogger = aquireLogger();

        m_newInstance = new CounterInstrument( "creates" );
        m_dispose = new CounterInstrument( "destroys" );

        setInstrumentableName( "factory" );

        addInstrument( m_newInstance );
        addInstrument( m_dispose );
    }

    /**
     * Returns a new instance of a component and optionally applies a logging channel,
     * instrumentation, context, a component or service manager, configuration, parameters,
     * lifecycle extensions, initialization, and execution phases based on the interfaces
     * implemented by the component class.
     *
     * @return the new instance
     */
    public Object newInstance()
        throws Exception
    {
        final Object component;

        try
        {
            component = m_componentClass.newInstance();

            if ( getLogger().isDebugEnabled() )
            {
                final String message =
                    "ComponentFactory creating new instance of " +
                    m_componentClass.getName() + ".";
                getLogger().debug( message );
            }

            ContainerUtil.enableLogging( component, m_componentLogger );

            if ( component instanceof Loggable )
            {
                final org.apache.log.Logger logkitLogger =
                    LogKit2AvalonLoggerAdapter.createLogger( m_componentLogger );
                ( (Loggable) component ).setLogger( logkitLogger );
            }

            ContainerUtil.contextualize( component, m_context );
            if ( component instanceof Composable )
            {
                ContainerUtil.compose( component, new WrapperComponentManager( m_serviceManager ) );
            }
            ContainerUtil.service( component, m_serviceManager );
            ContainerUtil.configure( component, m_configuration );

            if ( component instanceof Parameterizable )
            {
                ContainerUtil.parameterize( component, Parameters.fromConfiguration( m_configuration ) );
            }

            m_extManager.executeCreationExtensions( component, m_context );

            ContainerUtil.initialize( component );

            ContainerUtil.start( component );

            if ( m_newInstance.isActive() )
            {
                m_newInstance.increment();
            }
        }
        catch (LinkageError le)
        {
            throw new CascadingException("Could not load component", le);
        }

        return component;
    }

    private Logger aquireLogger()
    {
        Logger logger;

        try
        {
            final String name = (String) m_context.get( "component.logger" );
            if ( getLogger().isDebugEnabled() )
            {
                final String message = "logger name is " + name;
                getLogger().debug( message );
            }
            logger = m_loggerManager.getLoggerForCategory( name );
        }
        catch ( ContextException ce )
        {
            if ( getLogger().isDebugEnabled() )
            {
                final String message = "no logger name available, using standard name";
                getLogger().debug( message );
            }
            logger = m_loggerManager.getDefaultLogger();
        }
        return logger;
    }

    /**
     * Returns the component class.
     * @return the class
     */
    public final Class getCreatedClass()
    {
        return m_componentClass;
    }

    /**
     * Disposal of the supplied component instance.
     * @param component the component to dispose of
     * @exception Exception if a disposal error occurs
     */
    public final void dispose( final Object component )
        throws Exception
    {
        if ( getLogger().isDebugEnabled() )
        {
            final String message = "ComponentFactory decommissioning instance of " +
                getCreatedClass().getName() + ".";
            getLogger().debug( message );
        }

        if ( getCreatedClass().equals( component.getClass() ) )
        {
            ContainerUtil.shutdown( component );

            m_extManager.executeDestructionExtensions( component, m_context );

            if ( m_dispose.isActive() )
            {
                m_dispose.increment();
            }
        }
        else
        {
            final String message = "The object given to be disposed does " +
                "not come from this ObjectFactory";
            throw new IllegalArgumentException( message );
        }
    }
}
TOP

Related Classes of org.apache.avalon.fortress.impl.handler.ComponentFactory

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.