Package org.apache.avalon.fortress.impl

Source Code of org.apache.avalon.fortress.impl.DefaultECMContainer

/*
* 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.impl;

import java.util.Iterator;
import java.util.Map;

import org.apache.avalon.fortress.MetaInfoEntry;
import org.apache.avalon.fortress.util.Service;
import org.apache.avalon.fortress.impl.handler.ComponentHandler;
import org.apache.avalon.fortress.impl.handler.LEAwareComponentHandler;
import org.apache.avalon.fortress.impl.lookup.FortressServiceSelector;
import org.apache.avalon.fortress.impl.role.ECMMetaInfoManager;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.avalon.framework.thread.SingleThreaded;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.excalibur.instrument.Instrumentable;
import org.d_haven.mpool.ObjectFactory;

/**
* Customize the Fortress container to handle ECM compatibility
*
* @author <a href="mailto:dev@avalon.apache.org">The Avalon Team</a>
* @version CVS $ Revision: 1.1 $
*/
public class DefaultECMContainer extends DefaultContainer {

    /**
     * Retrieve the role for the component.
     *
     * @param config the component configuration
     * @return the class name
     */
    private String getRole( final Configuration config )
    throws ConfigurationException {
        final String className;

        if ( "component".equals( config.getName() ) )
        {
            className = config.getAttribute( "role" );
        }
        else
        {
            final MetaInfoEntry roleEntry = m_metaManager.getMetaInfoForShortName( config.getName() );
            if ( null == roleEntry )
            {

                final String message = "No class found matching configuration name " +
                        "[name: " + config.getName() + ", location: " + config.getLocation() + "]";
                throw new ConfigurationException( message );
            }

            Iterator roleIterator = roleEntry.getRoles();
            if ( roleIterator.hasNext() )
            {
                className = (String)roleIterator.next();
            }
            else
            {
                className = roleEntry.getComponentClass().getName();
            }
        }

        return className;
    }

    /**
     * Retrieve the classname (impl) for the component.
     *
     * @param config the component configuration
     * @return the class name
     */
    private String getClassname( final Configuration config )
    throws ConfigurationException {
        final String className;

        if ( "component".equals( config.getName() ) )
        {
            className = config.getAttribute( "class" );
        }
        else
        {
            if ( config.getAttribute("class", null) != null )
            {
                className = config.getAttribute("class");
            }
            else
            {
                final MetaInfoEntry roleEntry = m_metaManager.getMetaInfoForShortName( config.getName() );
                if ( null == roleEntry )
                {

                    final String message = "No class found matching configuration name " +
                        "[name: " + config.getName() + ", location: " + config.getLocation() + "]";
                    throw new ConfigurationException( message );
                }

                className = roleEntry.getComponentClass().getName();
            }
        }

        return className;
    }

    /**
     * Provide some validation for the core Cocoon components
     *
     * @param conf The configuration
     * @throws ConfigurationException if the coniguration is invalid
     */
    public void configure( Configuration conf )
    throws ConfigurationException {
        this.interpretProxy( conf.getAttribute("proxy-type", this.getDefaultProxyType()) );

        final Configuration[] elements = conf.getChildren();
        for ( int i = 0; i < elements.length; i++ )
        {
            final Configuration element = elements[i];

            // figure out Role
            String role = getRole( element );
            if ( role.endsWith("Selector") )
            {
                processSelector(role.substring(0, role.length()-8), element );
            }
            else
            {

                // get the implementation
                final String className = getClassname( element );

                final int pos = role.indexOf('/');
                final String hint;
                if ( pos != -1 )
                {
                    hint = role.substring(pos+1);
                    role = role.substring(0, pos);
                }
                else
                {
                    hint = null;
                }

                final String shortName;
                if ( "component".equals( element.getName() ))
                {
                    shortName = null;
                }
                else
                {
                    shortName = element.getName();
                }

                this.addComponent(role, hint, shortName, className, element );
            }

            if ( getLogger().isDebugEnabled() )
            {
                getLogger().debug( "Configuration processed for: " + role );
            }
        }
    }

    /**
     * Get a ComponentHandler with the default constructor for the component class passed in.
     *
     * @param classname     the name of the component's class
     * @param handlerClass  the class used to handle the component
     * @param metaData      the information needed to construct a ComponentHandler for the component
     * @return the component handler
     * @throws Exception if unable to provide a componenthandler
     */
    private ComponentHandler getComponentHandler( final String classname,
                                                  final Class  handlerClass,
                                                  final ComponentHandlerMetaData metaData)
            throws Exception
    {
        final Configuration configuration = metaData.getConfiguration();

        // get info from params
        final ComponentHandler handler;

        try
        {
            final ObjectFactory factory =
                    createObjectFactory( classname, configuration );

            // create the appropriate handler instance
            final ComponentHandler targetHandler =
                    (ComponentHandler) handlerClass.newInstance();

            // do the handler lifecycle
            ContainerUtil.enableLogging( targetHandler, getLogger() );
            ContainerUtil.contextualize( targetHandler, m_context );
            final DefaultServiceManager serviceManager =
                    new DefaultServiceManager( getServiceManager() );
            serviceManager.put( ObjectFactory.class.getName(), factory );
            serviceManager.makeReadOnly();

            ContainerUtil.service( targetHandler, serviceManager );
            ContainerUtil.configure( targetHandler, configuration );
            ContainerUtil.initialize( targetHandler );

            if ( targetHandler instanceof Instrumentable )
            {
                final Instrumentable instrumentable = (Instrumentable) targetHandler;
                final String name = instrumentable.getInstrumentableName();
                m_instrumentManager.registerInstrumentable( instrumentable, name );
            }

            // no other lifecycle stages supported for ComponentHandler;
            // ComponentHandler is not a "true" avalon component

            handler = new LEAwareComponentHandler( targetHandler, m_extManager, m_context );
        }
        catch ( final Exception e )
        {
            // if anything went wrong, the component cannot be worked with
            // and it cannot be added into the impl, so don't provide
            // a handler
            if ( getLogger().isDebugEnabled() )
            {
                final String message =
                        "Could not create the handler for the '" +
                        classname + "' component.";
                getLogger().debug( message, e );
            }
            throw e;
        }

        if ( getLogger().isDebugEnabled() )
        {
            final String message =
                    "Component " + classname +
                    " uses handler " + handlerClass.getName();
            getLogger().debug( message );
        }

        // we're still here, so everything went smooth. Register the handler
        // and return it
        final ComponentHandlerEntry entry =
                new ComponentHandlerEntry( handler, metaData );
        m_components.add( entry );

        return handler;
    }

    protected Class getComponentHandlerClass(final String defaultClassName, final String shortName )
        throws Exception
    {
        if ( shortName == null )
        {
            String handlerClassName = null;

            Class clazz;
            try
            {
                clazz = m_classLoader.loadClass( defaultClassName );

                if ( ThreadSafe.class.isAssignableFrom( clazz ) )
                {
                    handlerClassName = MetaInfoEntry.THREADSAFE_HANDLER;
                }
                else if ( Service.isClassPoolable(clazz) )
                {
                    handlerClassName = MetaInfoEntry.POOLABLE_HANDLER;
                }
                else if ( SingleThreaded.class.isAssignableFrom( clazz) )
                {
                    handlerClassName = MetaInfoEntry.FACTORY_HANDLER;
                }
            }
            catch ( final Exception e )
            {
                final String message =
                    "Unable to load class " + defaultClassName + ". Using dfault component handler.";
                getLogger().warn( message );
            }

            // Don't know, use default
            if ( handlerClassName == null )
            {
                handlerClassName = MetaInfoEntry.THREADSAFE_HANDLER;
            }
            return m_classLoader.loadClass( handlerClassName ) ;
        }
        else
        {
            final MetaInfoEntry roleEntry = m_metaManager.getMetaInfoForShortName( shortName );
            if ( null == roleEntry )
            {

                final String message = "No class found matching configuration name " +
                        "[name: " + shortName + "]";
                throw new ConfigurationException( message );
            }

            return roleEntry.getHandlerClass();
        }
    }

    protected void processSelector(String role, Configuration config)
        throws ConfigurationException
    {
        final String selectorRole = role + "Selector";
        FortressServiceSelector fss = new FortressServiceSelector(this, selectorRole);
        Map hintMap = createHintMap();
        hintMap.put( DEFAULT_ENTRY, fss );
        hintMap.put( SELECTOR_ENTRY,
                    new FortressServiceSelector( this, selectorRole ) );
        m_mapper.put( selectorRole, hintMap );

        final Configuration[] children = config.getChildren();
        if ( children != null )
        {
            for(int i=0; i<children.length; i++)
            {
                final Configuration element = children[i];
                final String hint = element.getAttribute("name");
                final String className = element.getAttribute("class");

                if ( m_metaManager instanceof ECMMetaInfoManager )
                {
                    try
                    {
                        ((ECMMetaInfoManager)m_metaManager).addSelectorComponent(role, hint, className, getComponentHandlerClass(className, null).getName());
                    }
                    catch (ConfigurationException ce )
                    {
                        throw ce;
                    }
                    catch (Exception e)
                    {
                        throw new ConfigurationException("Unable to add selector component.", e);
                    }
                }
                addComponent(role, hint, null, className, element );
            }
        }
    }

    protected void addComponent(final String role,
                                String hint,
                                String shortName,
                                final String className,
                                final Configuration element)
        throws ConfigurationException
    {
        final int activation = ComponentHandlerMetaData.ACTIVATION_BACKGROUND;

        // Fortress requires a hint, so we just give it one :) (if missing)
        final String metaDataHint = element.getAttribute( "id", element.getLocation() );

        if ( hint == null )
        {
            hint = metaDataHint;
        }

        final ComponentHandlerMetaData metaData =
            new ComponentHandlerMetaData( metaDataHint, className, element, activation );

        try
        {

            if ( DEFAULT_ENTRY.equals( metaData.getName() ) ||
                    SELECTOR_ENTRY.equals( metaData.getName() ) )
            {
                throw new IllegalArgumentException( "Using a reserved id name" + metaData.getName() );
            }

            // create a handler for the combo of Role+MetaData
            final ComponentHandler handler =
                    getComponentHandler( className,
                                         getComponentHandlerClass( className, shortName),
                                         metaData );

            // put the role into our role mapper. If the role doesn't exist
            // yet, just stuff it in as DEFAULT_ENTRY. If it does, we create a
            // ServiceSelector and put that in as SELECTOR_ENTRY.
            Map hintMap = (Map) m_mapper.get( role );

            // Initialize the hintMap if it doesn't exist yet.
            if ( null == hintMap )
            {
                hintMap = createHintMap();
                hintMap.put( DEFAULT_ENTRY, handler );
                hintMap.put( SELECTOR_ENTRY,
                        new FortressServiceSelector( this, role ) );
                m_mapper.put( role, hintMap );
            }

            hintMap.put( hint, handler );

            if ( element.getAttributeAsBoolean( "default", false ) )
            {
                hintMap.put( DEFAULT_ENTRY, handler );
            }
        }
        catch ( ConfigurationException ce )
        {
            throw ce;
        }
        catch ( Exception e )
        {
            throw new ConfigurationException( "Could not add component", e );
        }
    }

    /**
     * Return the default proxy type.
     * This method can be overwritten in subclasses to provide a different
     * default proxy type.
     */
    protected String getDefaultProxyType() {
        return "none";
    }
}
TOP

Related Classes of org.apache.avalon.fortress.impl.DefaultECMContainer

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.