cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: rev 55250 - in cocoon/trunk/src: blocks/portal/java/org/apache/cocoon/portlet core core/java core/java/org core/java/org/apache core/java/org/apache/cocoon core/java/org/apache/cocoon/components core/java/org/apache/cocoon/core core/java/org/apache/cocoon/core/container core/test core/test/org core/test/org/apache core/test/org/apache/cocoon core/test/org/apache/cocoon/core core/test/org/apache/cocoon/core/container java/org/apache/cocoon java/org/apache/cocoon/bean java/org/apache/cocoon/components java/org/apache/cocoon/components/container java/org/apache/cocoon/components/treeprocessor java/org/apache/cocoon/components/treeprocessor/sitemap java/org/apache/cocoon/servlet test/org/apache/cocoon/transformation
Date Thu, 21 Oct 2004 19:25:58 GMT
Author: cziegeler
Date: Thu Oct 21 12:25:56 2004
New Revision: 55250

Added:
   cocoon/trunk/src/core/
   cocoon/trunk/src/core/java/
   cocoon/trunk/src/core/java/org/
   cocoon/trunk/src/core/java/org/apache/
   cocoon/trunk/src/core/java/org/apache/cocoon/
   cocoon/trunk/src/core/java/org/apache/cocoon/components/
   cocoon/trunk/src/core/java/org/apache/cocoon/core/
   cocoon/trunk/src/core/java/org/apache/cocoon/core/container/
   cocoon/trunk/src/core/java/org/apache/cocoon/core/container/AbstractComponentHandler.java
   cocoon/trunk/src/core/java/org/apache/cocoon/core/container/AbstractServiceManager.java
   cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CocoonServiceManager.java
   cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CocoonServiceSelector.java
   cocoon/trunk/src/core/java/org/apache/cocoon/core/container/ComponentFactory.java
   cocoon/trunk/src/core/java/org/apache/cocoon/core/container/PoolableComponentHandler.java
   cocoon/trunk/src/core/java/org/apache/cocoon/core/container/RoleManager.java
   cocoon/trunk/src/core/java/org/apache/cocoon/core/container/SingleThreadedComponentHandler.java
   cocoon/trunk/src/core/java/org/apache/cocoon/core/container/ThreadSafeComponentHandler.java
   cocoon/trunk/src/core/test/
   cocoon/trunk/src/core/test/org/
   cocoon/trunk/src/core/test/org/apache/
   cocoon/trunk/src/core/test/org/apache/cocoon/
   cocoon/trunk/src/core/test/org/apache/cocoon/core/
   cocoon/trunk/src/core/test/org/apache/cocoon/core/container/
   cocoon/trunk/src/core/test/org/apache/cocoon/core/container/RoleManagerTestCase.java
Removed:
   cocoon/trunk/src/java/org/apache/cocoon/components/ExtendedComponentSelector.java
   cocoon/trunk/src/java/org/apache/cocoon/components/container/CocoonComponentManager.java
   cocoon/trunk/src/java/org/apache/cocoon/components/container/ComponentLocatorImpl.java
   cocoon/trunk/src/java/org/apache/cocoon/components/container/ComponentManagerWrapper.java
Modified:
   cocoon/trunk/src/blocks/portal/java/org/apache/cocoon/portlet/CocoonPortlet.java
   cocoon/trunk/src/java/org/apache/cocoon/Cocoon.java
   cocoon/trunk/src/java/org/apache/cocoon/bean/BeanListener.java
   cocoon/trunk/src/java/org/apache/cocoon/bean/CocoonBean.java
   cocoon/trunk/src/java/org/apache/cocoon/bean/CocoonWrapper.java
   cocoon/trunk/src/java/org/apache/cocoon/components/container/DefaultSitemapConfigurationHolder.java
   cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
   cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
   cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ComponentsSelector.java
   cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
   cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java
   cocoon/trunk/src/test/org/apache/cocoon/transformation/AugmentTransformerTestCase.java
   cocoon/trunk/src/test/org/apache/cocoon/transformation/CIncludeTransformerTestCase.java
   cocoon/trunk/src/test/org/apache/cocoon/transformation/EncodeURLTransformerTestCase.java
   cocoon/trunk/src/test/org/apache/cocoon/transformation/I18NTransformerTestCase.java
   cocoon/trunk/src/test/org/apache/cocoon/transformation/XIncludeTransformerTestCase.java
Log:
Adding ECM++ - not working yet

Modified: cocoon/trunk/src/blocks/portal/java/org/apache/cocoon/portlet/CocoonPortlet.java
==============================================================================
--- cocoon/trunk/src/blocks/portal/java/org/apache/cocoon/portlet/CocoonPortlet.java	(original)
+++ cocoon/trunk/src/blocks/portal/java/org/apache/cocoon/portlet/CocoonPortlet.java	Thu Oct 21 12:25:56 2004
@@ -1600,9 +1600,6 @@
             if (parent != null) {
                 ContainerUtil.compose(c, parent);
             }
-            if (this.enableInstrumentation) {
-                c.setInstrumentManager(getInstrumentManager());
-            }
             ContainerUtil.initialize(c);
             this.creationTime = System.currentTimeMillis();
 

Added: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/AbstractComponentHandler.java
==============================================================================
--- (empty file)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/AbstractComponentHandler.java	Thu Oct 21 12:25:56 2004
@@ -0,0 +1,242 @@
+/* 
+ * Copyright 2002-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.cocoon.core.container;
+
+import org.apache.avalon.excalibur.logger.LoggerManager;
+import org.apache.avalon.excalibur.pool.Poolable;
+import org.apache.avalon.framework.component.Composable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.thread.SingleThreaded;
+import org.apache.avalon.framework.thread.ThreadSafe;
+
+/**
+ * This class acts like a Factory to instantiate the correct version
+ * of the component handler that you need.
+ *
+ * @version CVS $Id: AbstractComponentHandler.java 55144 2004-10-20 12:26:09Z ugo $
+ */
+public abstract class AbstractComponentHandler {
+    
+    private final Object referenceSemaphore = new Object();
+    private int references = 0;
+
+    protected final Logger logger;
+    
+    /** This factory is used to created new objects */
+    protected final ComponentFactory factory;
+    
+    /** State management boolean stating whether the Handler is disposed or not */
+    protected boolean disposed = false;
+
+    /** State management boolean stating whether the Handler is initialized or not */
+    protected boolean initialized = false;
+
+    /**
+     * Looks up and returns a component handler for a given component class.
+     *
+     * @param role           The role name of the component. This must be
+     *                       a fully-qualified classname
+     * @param componentClass Class of the component for which the handle is
+     *                       being requested.
+     * @param configuration The configuration for this component.
+     * @param serviceManager The service manager which will be managing the service.
+     * @param context The current context object.
+     * @param logger  The current logger
+     * @param loggerManager The current LoggerManager.
+     *
+     * @throws Exception If there were any problems obtaining a ComponentHandler
+     */
+    public static AbstractComponentHandler getComponentHandler( final String role,
+                                                        final Class componentClass,
+                                                        final Configuration configuration,
+                                                        final ServiceManager serviceManager,
+                                                        final Context context,
+                                                        final Logger logger,
+                                                        final LoggerManager loggerManager,
+                                                        final RoleManager roleManager)
+    throws Exception {
+        int numInterfaces = 0;
+
+        if( SingleThreaded.class.isAssignableFrom( componentClass ) ) {
+            numInterfaces++;
+        }
+
+        if( ThreadSafe.class.isAssignableFrom( componentClass ) ) {
+            numInterfaces++;
+        }
+
+        if( Poolable.class.isAssignableFrom( componentClass ) ) {
+            numInterfaces++;
+        }
+
+        if( numInterfaces > 1 ) {
+            throw new Exception( "[CONFLICT] More than one lifecycle interface in "
+                                 + componentClass.getName() + "  May implement no more than one of "
+                                 + "SingleThreaded, ThreadSafe, or Poolable" );
+        }
+
+        // Early check for Composable
+        if ( Composable.class.isAssignableFrom( componentClass ) ) {
+            throw new Exception("Interface Composable is not supported anymore. Please change class "
+                                + componentClass.getName() + " to use Serviceable instead.");
+        }
+        
+        // Create the factory to use to create the instances of the Component.
+        ComponentFactory factory = new ComponentFactory( role,
+                                         componentClass,
+                                         configuration,
+                                         serviceManager,
+                                         context,
+                                         logger,
+                                         loggerManager,
+                                         roleManager);
+
+        AbstractComponentHandler handler;
+        
+        if( Poolable.class.isAssignableFrom( componentClass ) )  {
+            handler = new PoolableComponentHandler( logger, factory, configuration );
+        } else if( ThreadSafe.class.isAssignableFrom( componentClass ) ) {
+            handler = new ThreadSafeComponentHandler( logger, factory );
+        } else {
+            // This is a SingleThreaded component
+            handler = new SingleThreadedComponentHandler( logger, factory );
+        }
+
+        return handler;
+    }
+
+    /**
+     * Creates a new ComponentHandler.
+     */
+    public AbstractComponentHandler(Logger logger, ComponentFactory factory) {
+        this.logger = logger;
+        this.factory = factory;
+    }
+
+    /**
+     * Get an instance of the type of component handled by this handler.
+     * <p>
+     * Subclasses should not extend this method but rather the doGet method below otherwise
+     *  reference counts will not be supported.
+     * <p>
+     *
+     * @return an instance
+     * @exception Exception if an error occurs
+     */
+    public final Object get() throws Exception {
+        if( !this.initialized ) {
+            throw new IllegalStateException(
+                "You cannot get a component from an uninitialized handler." );
+        }
+        if( this.disposed ) {
+            throw new IllegalStateException( "You cannot get a component from a disposed handler." );
+        }
+
+        final Object component = this.doGet();
+
+        synchronized( this.referenceSemaphore ) {
+            this.references++;
+        }
+
+        return component;
+    }
+
+    /**
+     * Put back an instance of the type of component handled by this handler.
+     * <p>
+     * Subclasses should not extend this method but rather the doPut method below otherwise
+     *  reference counts will not be supported.
+     * <p>
+     *
+     * @param component a service
+     * @exception Exception if an error occurs
+     */
+    public final void put( Object component ) 
+    throws Exception {
+        if( !this.initialized ) {
+            throw new IllegalStateException(
+                "You cannot put a component to an uninitialized handler." );
+        }
+        //  The reference count must be decremented before any calls to doPut.
+        //  If there is another thread blocking, then this thread could stay deep inside
+        //  doPut for an undetermined amount of time until the thread scheduler gives it
+        //  some cycles again.  (It happened).  All ComponentHandler state must therefor
+        //  reflect the thread having left this method before the call to doPut to avoid
+        //  warning messages from the dispose() cycle if that takes place before this
+        //  thread has a chance to continue.
+        synchronized( this.referenceSemaphore ) {
+            this.references--;
+        }
+
+        try {
+            this.doPut( component );
+        } catch( Throwable t ) {
+            this.logger.error("Exception during putting back a component.", t);
+        }
+    }
+
+    /**
+     * Concrete implementation of getting a component.
+     *
+     * @return a service
+     * @exception Exception if an error occurs
+     */
+    protected abstract Object doGet() throws Exception;
+
+    /**
+     * Concrete implementation of putting back a component.
+     *
+     * @param component a <code>Component</code> value
+     * @exception Exception if an error occurs
+     */
+    protected abstract void doPut( Object component ) throws Exception;
+
+    /**
+     * Returns <code>true</code> if this component handler can safely be
+     * disposed (i.e. none of the components it is handling are still
+     * being used).
+     *
+     * @return <code>true</code> if this component handler can safely be
+     *         disposed; <code>false</code> otherwise
+     */
+    public final boolean canBeDisposed() {
+        return ( this.references == 0 );
+    }
+    
+    /**
+     * Dispose of the component handler and any associated Pools and Factories.
+     */
+    public void dispose() {
+        this.disposed = true;
+    }
+    
+    /**
+     * Initialize this handler
+     */
+    public void initialize() throws Exception {
+        if( this.initialized ) {
+            return;
+        }
+        this.initialized = true;
+        if( this.logger.isDebugEnabled() ) {
+            this.logger.debug( "ThreadSafeComponentHandler initialized for: " + this.factory.getCreatedClass().getName() );
+        }
+    }
+}

Added: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/AbstractServiceManager.java
==============================================================================
--- (empty file)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/AbstractServiceManager.java	Thu Oct 21 12:25:56 2004
@@ -0,0 +1,185 @@
+/* 
+ * Copyright 2002-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.cocoon.core.container;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.avalon.excalibur.logger.LoggerManager;
+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.ConfigurationException;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.thread.ThreadSafe;
+
+/**
+ * Base class for all service managers: ServiceManager and ServiceSelector
+ *
+ * @version CVS $Id: AbstractServiceManager.java 55144 2004-10-20 12:26:09Z ugo $
+ */
+public abstract class AbstractServiceManager
+extends AbstractLogEnabled
+implements Contextualizable, ThreadSafe, Disposable, Initializable {
+    
+    /** The classloader used for this system. */
+    protected final ClassLoader loader;
+
+    /** The application context for components */
+    protected Context context;
+
+    /** Static component mapping handlers. */
+    protected final Map componentMapping = Collections.synchronizedMap(new HashMap());
+
+    /** Used to map roles to ComponentHandlers. */
+    protected final Map componentHandlers = Collections.synchronizedMap(new HashMap());
+
+    /** Is the Manager disposed or not? */
+    protected boolean disposed;
+
+    /** Is the Manager initialized? */
+    protected boolean initialized;
+
+    /** RoleInfos. */
+    protected RoleManager roleManager;
+
+    /** LoggerManager. */
+    protected LoggerManager loggerManager;
+
+    
+    /** 
+     * Create the ServiceManager with a Classloader
+     */
+    public AbstractServiceManager( final ClassLoader loader ) {
+        if( null == loader ) {
+            this.loader = Thread.currentThread().getContextClassLoader();
+        } else {
+            this.loader = loader;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
+     */
+    public void contextualize( final Context context ) {
+        this.context = context;
+    }
+
+    public void setRoleManager( final RoleManager roles ) {
+        this.roleManager = roles;
+    }
+
+    /**
+     * Configure the LoggerManager.
+     */
+    public void setLoggerManager( final LoggerManager manager ) {
+        this.loggerManager = manager;
+    }
+    
+    /**
+     * Obtain a new ComponentHandler for the specified component. 
+     * 
+     * @param role The role
+     * @param componentClass Class of the component for which the handle is
+     *                       being requested.
+     * @param configuration The configuration for this component.
+     * @param serviceManager The service manager which will be managing the Component.
+     *
+     * @throws Exception If there were any problems obtaining a ComponentHandler
+     */
+    protected AbstractComponentHandler getComponentHandler( final String role,
+                                                    final Class componentClass,
+                                                    final Configuration configuration,
+                                                    final ServiceManager serviceManager)
+    throws Exception {
+        return AbstractComponentHandler.getComponentHandler( role,
+                                                     componentClass,
+                                                     configuration,
+                                                     serviceManager,
+                                                     this.context,
+                                                     this.getLogger(),
+                                                     this.loggerManager,
+                                                     this.roleManager);
+    }
+
+    protected void addComponent(String className,
+                                Object role,
+                                Configuration configuration) 
+    throws ConfigurationException {
+        // check for old class names
+        // TODO We can remove this as soon as we changed cocoon.roles and cocoon.xconf
+        if ( "org.apache.cocoon.components.ExtendedComponentSelector".equals(className)) {
+            className = CocoonServiceSelector.class.getName();
+        }
+        
+        try {
+            if( this.getLogger().isDebugEnabled() ) {
+                this.getLogger().debug( "Adding component (" + role + " = " + className + ")" );
+            }
+
+            final Class clazz = this.loader.loadClass( className );
+            this.addComponent( role, clazz, configuration );
+        } catch( final ClassNotFoundException cnfe ) {
+            final String message = "Could not get class (" + className + ") for role "
+                                 + role + " on configuration element " + configuration.getName();
+
+            if( this.getLogger().isErrorEnabled() ) {
+                this.getLogger().error( message, cnfe );
+            }
+
+            throw new ConfigurationException( message, cnfe );
+        } catch( final ServiceException ce ) {
+            final String message = "Bad component "+ className + " for role " + role
+                                 + " on configuration element " + configuration.getName();
+
+            if( this.getLogger().isErrorEnabled() ) {
+                this.getLogger().error( message, ce );
+            }
+
+            throw new ConfigurationException( message, ce );
+        } catch( final Exception e ) {
+            final String message = "Unexpected exception for role: " + role;
+            if( this.getLogger().isErrorEnabled() ) {
+                this.getLogger().error( "Unexpected exception for role: " + role, e );
+            }
+            throw new ConfigurationException( message, e );
+        }        
+    }
+    
+    protected abstract void addComponent(Object role, Class clazz, Configuration config)
+    throws ServiceException;
+    
+    
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Disposable#dispose()
+     */
+    public void dispose() {
+        this.disposed = true;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Initializable#initialize()
+     */
+    public void initialize() throws Exception {
+        this.initialized = true;
+    }
+}

Added: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CocoonServiceManager.java
==============================================================================
--- (empty file)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CocoonServiceManager.java	Thu Oct 21 12:25:56 2004
@@ -0,0 +1,485 @@
+/* 
+ * Copyright 2002-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.cocoon.core.container;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+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.configuration.DefaultConfiguration;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.components.SitemapConfigurable;
+import org.apache.cocoon.components.SitemapConfigurationHolder;
+import org.apache.cocoon.components.container.DefaultSitemapConfigurationHolder;
+
+/**
+ * Default service manager for Cocoon's components.
+ *
+ * @version CVS $Revision: 1.6 $Id: CocoonServiceManager.java 55165 2004-10-20 16:51:50Z cziegeler $
+ */
+public class CocoonServiceManager
+extends AbstractServiceManager
+implements ServiceManager, Configurable {
+    
+    /** The parent ServiceManager */
+    private final ServiceManager parentManager;
+
+    /** added component handlers before initialization to maintain
+     *  the order of initialization
+     */
+    private final List newComponentHandlers = new ArrayList();
+
+    /** The {@link SitemapConfigurationHolder}s */
+    private Map sitemapConfigurationHolders = new HashMap(15);
+
+    /** Temporary list of parent-aware components.  Will be null for most of
+     * our lifecycle. */
+    private ArrayList parentAwareComponents = new ArrayList();
+
+    /** Create the ServiceManager with a Classloader and parent ServiceManager */
+    public CocoonServiceManager( final ServiceManager parent, 
+                                 final ClassLoader loader ) {
+        super(loader);
+        this.parentManager = parent;
+        // get role manager and logger manager
+        if ( parent instanceof CocoonServiceManager ) {
+            this.roleManager = ((CocoonServiceManager)parent).roleManager;
+            this.loggerManager = ((CocoonServiceManager)parent).loggerManager;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.service.ServiceManager#lookup(java.lang.String)
+     */
+    public Object lookup( final String role )
+    throws ServiceException {
+        if( !this.initialized ) {
+            if( this.getLogger().isWarnEnabled() ) {
+                this.getLogger().warn(
+                    "Looking up component on an uninitialized CocoonServiceManager [" + role + "]" );
+            }
+        }
+
+        if( this.disposed ) {
+            throw new IllegalStateException(
+                "You cannot lookup components on a disposed CocoonServiceManager" );
+        }
+
+        if( role == null ) {
+            final String message =
+                "CocoonServiceManager attempted to retrieve service with null role.";
+
+            if( this.getLogger().isErrorEnabled() ) {
+                this.getLogger().error( message );
+            }
+            throw new ServiceException( role, message );
+        }
+
+        AbstractComponentHandler handler = (AbstractComponentHandler)this.componentHandlers.get( role );
+
+        // Retrieve the instance of the requested component
+        if ( handler == null ) {
+            if( this.parentManager != null ) {
+                try {
+                    return this.parentManager.lookup( role );
+                } catch( Exception e ) {
+                    if( this.getLogger().isWarnEnabled() ) {
+                        final String message =
+                            "ComponentLocator exception from parent SM during lookup.";
+                        this.getLogger().warn( message, e );
+                    }
+                    // ignore.  If the exception is thrown, we try to
+                    // create the component next
+                }
+            }
+
+            if( this.roleManager != null ) {
+                final String className = this.roleManager.getDefaultClassNameForRole( role );
+
+                if( className != null ) {
+                    if( this.getLogger().isDebugEnabled() ) {
+                        this.getLogger().debug( "Could not find ComponentHandler, attempting to create "
+                            + "one for role [" + role + "]" );
+                    }
+
+                    try {
+                        final Class componentClass = this.loader.loadClass( className );
+
+                        final Configuration configuration = new DefaultConfiguration( "", "-" );
+
+                        handler = this.getComponentHandler( role,
+                                                       componentClass,
+                                                       configuration,
+                                                       this);
+
+                        handler.initialize();
+                    } catch (ServiceException se) {
+                        throw se;
+                    } catch( final Exception e ) {
+                        final String message = "Could not find component";
+                        if( this.getLogger().isDebugEnabled() ) {
+                            this.getLogger().debug( message + " for role: " + role, e );
+                        }
+                        throw new ServiceException( role, message, e );
+                    }
+
+                    this.componentHandlers.put( role, handler );
+                }
+            } else {
+                this.getLogger().debug( "Component requested without a RoleManager set.\n"
+                    + "That means setRoleManager() was not called during initialization." );
+            }
+        }
+
+        if( handler == null ) {
+            final String message = "Could not find component";
+            if( this.getLogger().isDebugEnabled() )
+            {
+                this.getLogger().debug( message + " for role: " + role );
+            }
+            throw new ServiceException( role, message );
+        }
+
+        Object component = null;
+
+        try {
+            component = handler.get();
+        } catch( final IllegalStateException ise ) {
+            try {
+                handler.initialize();
+                component = handler.get();
+            } catch( final ServiceException ce ) {
+                // Rethrow instead of wrapping a ComponentException with another one
+                throw ce;
+            } catch( final Exception e ) {
+                final String message = "Could not access the Component";
+                if( this.getLogger().isDebugEnabled() ) {
+                    this.getLogger().debug( message + " for role [" + role + "]", e );
+                }
+
+                throw new ServiceException( role, message, e );
+            }
+        } catch ( ServiceException se) {
+            throw se;
+        } catch( final Exception e ) {
+            final String message = "Could not access the Component";
+            if( this.getLogger().isDebugEnabled() ) {
+                this.getLogger().debug( message + " for role [" + role + "]", e );
+            }
+
+            throw new ServiceException( role, message, e );
+        }
+
+        // Add a mapping between the component and its handler.
+        //  In the case of a ThreadSafeComponentHandler, the same component will be mapped
+        //  multiple times but because each put will overwrite the last, this is not a
+        //  problem.  Checking to see if the put has already been done would be slower.
+        this.componentMapping.put( component, handler );
+
+        if ( null != component && component instanceof SitemapConfigurable) {
+
+            // FIXME: how can we prevent that this is called over and over again?
+            SitemapConfigurationHolder holder;
+
+            holder = (SitemapConfigurationHolder)this.sitemapConfigurationHolders.get( role );
+            if ( null == holder ) {
+                // create new holder
+                holder = new DefaultSitemapConfigurationHolder( role, this.roleManager );
+                this.sitemapConfigurationHolders.put( role, holder );
+            }
+
+            try {
+                ((SitemapConfigurable)component).configure(holder);
+            } catch (ConfigurationException ce) {
+                throw new ServiceException(role, "Exception during setup of SitemapConfigurable.", ce);
+            }
+        }
+        return component;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.service.ServiceManager#hasService(java.lang.String)
+     */
+    public boolean hasService( final String role ) {
+        if( !this.initialized ) return false;
+        if( this.disposed ) return false;
+
+        boolean exists = this.componentHandlers.containsKey( role );
+
+        if( !exists && null != this.parentManager ) {
+            exists = this.parentManager.hasService( role );
+        }
+
+        return exists;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.service.ServiceManager#release(java.lang.Object)
+     */
+    public void release( final Object component ) {
+        if( null == component ) {
+            return;
+        }
+
+        // The componentMapping StaticBucketMap itself is threadsafe, and because the same component
+        //  will never be released by more than one thread, this method does not need any
+        //  synchronization around the access to the map.
+
+        final AbstractComponentHandler handler =
+            (AbstractComponentHandler)this.componentMapping.get( component );
+
+        if ( handler != null ) {
+            // ThreadSafe components will always be using a ThreadSafeComponentHandler,
+            //  they will only have a single entry in the m_componentMapping map which
+            //  should not be removed until the ComponentLocator is disposed.  All
+            //  other components have an entry for each instance which should be
+            //  removed.
+            if( !( handler instanceof ThreadSafeComponentHandler ) ) {
+                // Remove the component before calling put.  This is critical to avoid the
+                //  problem where another thread calls put on the same component before
+                //  remove can be called.
+                this.componentMapping.remove( component );
+            }
+
+            try {
+                handler.put( component );
+            } catch( Exception e ) {
+                if( this.getLogger().isDebugEnabled() ) {
+                    this.getLogger().debug( "Error trying to release component.", e );
+                }
+            }
+        }
+        else if( this.parentManager != null ) {
+            this.parentManager.release( component );
+        } else {
+            this.getLogger().warn( "Attempted to release a " + component.getClass().getName() +
+                              " but its handler could not be located." );
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
+     */
+    public void configure( final Configuration configuration )
+    throws ConfigurationException {
+        if( null == roleManager ) {
+            final RoleManager roleInfo = new RoleManager();
+            roleInfo.enableLogging( getLogger() );
+            roleInfo.configure( configuration );
+            this.roleManager = roleInfo;
+            this.getLogger().debug( "No RoleManager given, deriving one from configuration" );
+        }
+
+        // Set components
+
+        final Configuration[] configurations = configuration.getChildren();
+
+        for( int i = 0; i < configurations.length; i++ ) {
+            String type = configurations[ i ].getName();
+
+            if( !type.equals( "role" ) ) {
+                String role = configurations[ i ].getAttribute( "role", "" );
+                String className = configurations[ i ].getAttribute( "class", "" );
+
+                if( role.equals( "" ) ) {
+                    role = roleManager.getRoleForName( type );
+                }
+
+                if( null != role && !role.equals( "" ) ) {
+                    if( className.equals( "" ) ) {
+                        className = roleManager.getDefaultClassNameForRole( role );
+                    }
+
+                    this.addComponent(className, role, configurations[i]);
+                }
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
+     */
+    public void contextualize( final Context context ) {
+        this.context = context;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Initializable#initialize()
+     */
+    public void initialize()
+    throws Exception {
+        super.initialize();
+
+        for( int i = 0; i < this.newComponentHandlers.size(); i++ )
+        {
+            final AbstractComponentHandler handler =
+                (AbstractComponentHandler)this.newComponentHandlers.get( i );
+            try {
+                handler.initialize();
+            } catch( Exception e ) {
+                if( this.getLogger().isErrorEnabled() )
+                {
+                    this.getLogger().error( "Caught an exception trying to initialize "
+                                       + "the component handler.", e );
+                }
+
+                // Rethrow the exception
+                throw e;
+            }
+        }
+
+        List keys = new ArrayList( this.componentHandlers.keySet() );
+
+        for( int i = 0; i < keys.size(); i++ ) {
+            final Object key = keys.get( i );
+            final AbstractComponentHandler handler =
+                (AbstractComponentHandler)this.componentHandlers.get( key );
+
+            if( !this.newComponentHandlers.contains( handler ) ) {
+                try {
+                    handler.initialize();
+
+                } catch( Exception e ) {
+                    if( this.getLogger().isErrorEnabled() ) {
+                        this.getLogger().error( "Caught an exception trying to initialize "
+                                           + "the component handler.", e );
+
+                    }
+                    // Rethrow the exception
+                    throw e;
+                }
+            }
+        }
+        this.newComponentHandlers.clear();
+
+        if (parentAwareComponents == null) {
+            throw new ServiceException(null, "CocoonServiceManager already initialized");
+        }
+        // Set parents for parentAware components
+        Iterator iter = parentAwareComponents.iterator();
+        while (iter.hasNext()) {
+            String role = (String)iter.next();
+            if ( parentManager != null && parentManager.hasService( role ) ) {
+                // lookup new component
+                Object component = null;
+                try {
+                    component = this.lookup( role );
+                    ((CocoonServiceSelector)component).setParentLocator( this.parentManager, role );
+                } catch (ServiceException ignore) {
+                    // we don't set the parent then
+                } finally {
+                    this.release( component );
+                }
+            }
+        }
+        parentAwareComponents = null;  // null to save memory, and catch logic bugs.
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Disposable#dispose()
+     */
+    public void dispose() {
+        boolean forceDisposal = false;
+
+        final List disposed = new ArrayList();
+
+        while( componentHandlers.size() > 0 ) {
+            for( Iterator iterator = componentHandlers.keySet().iterator();
+                 iterator.hasNext(); ) {
+                final Object role = iterator.next();
+
+                final AbstractComponentHandler handler =
+                    (AbstractComponentHandler)componentHandlers.get( role );
+
+                if( forceDisposal || handler.canBeDisposed() ) {
+                    if( forceDisposal && getLogger().isWarnEnabled() ) {
+                        this.getLogger().warn
+                            ( "disposing of handler for unreleased component."
+                              + " role [" + role + "]" );
+                    }
+
+                    handler.dispose();
+                    disposed.add( role );
+                }
+            }
+
+            if( disposed.size() > 0 ) {
+                final Iterator i = disposed.iterator();
+                while ( i.hasNext() ) {
+                    this.componentHandlers.remove( i.next() );
+                }
+                disposed.clear();
+            } else {   
+                // no more disposable handlers!
+                forceDisposal = true;
+            }
+        }
+        super.dispose();
+    }
+
+    /**
+     * Add a new component to the manager.
+     *
+     * @param role the role name for the new component.
+     * @param component the class of this component.
+     * @param configuration the configuration for this component.
+     */
+    public void addComponent( final Object role,
+                              final Class component,
+                              final Configuration configuration )
+    throws ServiceException {
+        if( this.initialized ) {
+            throw new ServiceException( role.toString(),
+                "Cannot add components to an initialized CocoonServiceManager." );
+        }
+
+        try {
+            if( this.getLogger().isDebugEnabled() ) {
+                this.getLogger().debug( "Attempting to get handler for role [" + role.toString() + "]" );
+            }
+
+            final AbstractComponentHandler handler = this.getComponentHandler( role.toString(),
+                                                                  component,
+                                                                  configuration,
+                                                                  this);
+
+            if( this.getLogger().isDebugEnabled() ) {
+                this.getLogger().debug( "Handler type = " + handler.getClass().getName() );
+            }
+
+            this.componentHandlers.put( role.toString(), handler );
+            this.newComponentHandlers.add( handler );
+        } catch ( final ServiceException se ) {
+            throw se;
+        } catch( final Exception e ) {
+            throw new ServiceException( role.toString(), "Could not set up component handler.", e );
+        }
+        // Note that at this point, we're not initialized and cannot do
+        // lookups, so defer parental introductions to initialize().
+        if ( CocoonServiceSelector.class.isAssignableFrom( component ) ) {
+            this.parentAwareComponents.add(role);
+        }
+    }
+
+}

Added: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CocoonServiceSelector.java
==============================================================================
--- (empty file)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CocoonServiceSelector.java	Thu Oct 21 12:25:56 2004
@@ -0,0 +1,487 @@
+/* 
+ * Copyright 2002-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.cocoon.core.container;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.component.ComponentException;
+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.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceSelector;
+import org.apache.avalon.framework.service.Serviceable;
+
+/**
+ * Default component selector for Cocoon's components.
+ *
+ * @version CVS $Id: CocoonServiceSelector.java 55144 2004-10-20 12:26:09Z ugo $
+ */
+public class CocoonServiceSelector
+extends AbstractServiceManager
+implements ServiceSelector, Serviceable, Configurable {
+    
+    /** The application context for components
+     */
+    private ServiceManager serviceManager;
+
+    /** The parent selector, if any */
+    protected CocoonServiceSelector parentSelector;
+
+    /** The parent locator, if any */
+    protected ServiceManager parentLocator;
+
+    /** The role of this selector. Set in <code>configure()</code>. */
+    protected String roleName;
+
+    /** The default hint */
+    protected String defaultHint;
+
+    /** Create the ComponentSelector */
+    public CocoonServiceSelector() {
+        super(null);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.service.ServiceSelector#select(java.lang.Object)
+     */
+    public Object select( Object hint )
+    throws ServiceException {
+        if( !this.initialized ) {
+            if( this.getLogger().isWarnEnabled() ) {
+                this.getLogger().warn( "Looking up component on an uninitialized ComponentLocator "
+                    + "with hint [" + hint + "]" );
+            }
+        }
+
+        if( this.disposed ) {
+            throw new IllegalStateException(
+                "You cannot select a Component from a disposed ComponentSelector" );
+        }
+
+        if (hint == null) {
+            hint = this.defaultHint;
+        }
+
+        AbstractComponentHandler handler = (AbstractComponentHandler)this.componentHandlers.get( hint );
+
+        // Retrieve the instance of the requested component
+        if( null == handler ) {
+            // Doesn't exist here : try in parent selector
+            if ( this.parentSelector != null ) {
+                return this.parentSelector.select(hint);                
+            }
+            final String message = this.roleName
+                + ": ComponentSelector could not find the component for hint [" + hint + "]";
+            if( this.getLogger().isDebugEnabled() ) {
+                this.getLogger().debug( message );
+            }
+            throw new ServiceException( hint.toString(), message );
+        }
+
+        Object component = null;
+
+        try {
+            component = handler.get();
+        } catch( final ServiceException ce ) {
+            //rethrow
+            throw ce;
+        } catch( final Exception e ) {
+            final String message = this.roleName
+                + ": ComponentSelector could not access the Component for hint [" + hint + "]";
+
+            if( this.getLogger().isDebugEnabled() ) {
+                this.getLogger().debug( message, e );
+            }
+            throw new ServiceException( hint.toString(), message, e );
+        }
+
+        if( null == component ) {
+            // Doesn't exist here : try in parent selector
+            if ( this.parentSelector != null ) {
+                component = this.parentSelector.select(hint);
+            } else {
+                final String message = this.roleName
+                    + ": ComponentSelector could not find the component for hint [" + hint + "]";
+                if( this.getLogger().isDebugEnabled() ) {
+                    this.getLogger().debug( message );
+                }
+                throw new ServiceException( hint.toString(), message );
+            }
+        }
+
+        this.componentMapping.put( component, handler );
+        return component;
+
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.service.ServiceSelector#isSelectable(java.lang.Object)
+     */
+    public boolean isSelectable( Object hint ) {
+        if( !this.initialized ) return false;
+        if( this.disposed ) return false;
+
+        if (hint == null) {
+            hint = this.defaultHint;
+        }
+
+        boolean exists = false;
+
+        try {
+            AbstractComponentHandler handler = (AbstractComponentHandler)this.componentHandlers.get( hint );
+            exists = (handler != null);
+        } catch( Throwable t ) {
+            // We can safely ignore all exceptions
+        }
+
+        if ( !exists && this.parentSelector != null ) {
+            exists = this.parentSelector.isSelectable( hint );
+        }
+        return exists;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.service.ServiceSelector#release(java.lang.Object)
+     */
+    public void release( final Object component ) {
+        if( null == component ) {
+            return;
+        }
+
+        // Was it selected on the parent ?
+        if ( this.parentSelector != null &&
+             this.parentSelector.canRelease(component) ) {
+            this.parentSelector.release(component);
+
+        } else {
+            final AbstractComponentHandler handler =
+                (AbstractComponentHandler)this.componentMapping.get( component );
+    
+            if( null == handler ) {
+                this.getLogger().warn( "Attempted to release a " + component.getClass().getName()
+                    + " but its handler could not be located." );
+                return;
+            }
+    
+            // ThreadSafe components will always be using a ThreadSafeComponentHandler,
+            //  they will only have a single entry in the m_componentMapping map which
+            //  should not be removed until the ComponentLocator is disposed.  All
+            //  other components have an entry for each instance which should be
+            //  removed.
+            if( !( handler instanceof ThreadSafeComponentHandler ) ) {
+                // Remove the component before calling put.  This is critical to avoid the
+                //  problem where another thread calls put on the same component before
+                //  remove can be called.
+                this.componentMapping.remove( component );
+            }
+    
+            try {
+                handler.put( component );
+            } catch( Exception e ) {
+                if( this.getLogger().isDebugEnabled() ) {
+                    this.getLogger().debug( "Error trying to release component", e );
+                }
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+     */
+    public void service( final ServiceManager componentManager )
+    throws ServiceException {
+        this.serviceManager = componentManager;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
+     */
+    public void configure( final Configuration config )
+    throws ConfigurationException {
+        this.roleName = getRoleName(config);
+
+        // Get default hint
+        this.defaultHint = config.getAttribute(this.getDefaultHintAttributeName(), null);
+
+        // Add components
+        String compInstanceName = getComponentInstanceName();
+
+        Configuration[] instances = config.getChildren();
+
+        for (int i = 0; i < instances.length; i++) {
+
+            Configuration instance = instances[i];
+
+            Object hint = instance.getAttribute("name").trim();
+
+            String classAttr = instance.getAttribute(getClassAttributeName(), null);
+            String className;
+
+            if (compInstanceName == null) {
+                // component-instance implicitly defined by the presence of the 'class' attribute
+                if (classAttr == null) {
+                    className = this.roleManager.getDefaultClassNameForHint(roleName, instance.getName());
+                } else {
+                    className = classAttr.trim();
+                }
+
+            } else {
+                // component-instances names explicitly defined
+                if (compInstanceName.equals(instance.getName())) {
+                    className = (classAttr == null) ? null : classAttr.trim();
+                } else {
+                    className = this.roleManager.getDefaultClassNameForHint(roleName, instance.getName());
+                }
+            }
+
+            if (className == null) {
+                String message = "Unable to determine class name for component named '" + hint +
+                    "' at " + instance.getLocation();
+
+                getLogger().error(message);
+                throw new ConfigurationException(message);
+            }
+            
+            this.addComponent( className, hint, instance );
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Initializable#initialize()
+     */
+    public void initialize() 
+    throws Exception {
+        super.initialize();
+
+        List keys = new ArrayList( this.componentHandlers.keySet() );
+
+        for( int i = 0; i < keys.size(); i++ ) {
+            final Object key = keys.get( i );
+            final AbstractComponentHandler handler =
+                (AbstractComponentHandler)this.componentHandlers.get( key );
+
+            try {
+                handler.initialize();
+            } catch( Exception e ) {
+                if( this.getLogger().isDebugEnabled() ) {
+                    this.getLogger().debug( "Caught an exception trying to initialize "
+                        + "of the component handler.", e );
+                }
+            }
+
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Disposable#dispose()
+     */
+    public void dispose() {
+        Iterator keys = this.componentHandlers.keySet().iterator();
+        List keyList = new ArrayList();
+
+        while( keys.hasNext() ) {
+            Object key = keys.next();
+            AbstractComponentHandler handler =
+                (AbstractComponentHandler)this.componentHandlers.get( key );
+
+            handler.dispose();
+
+            keyList.add( key );
+        }
+
+        keys = keyList.iterator();
+
+        while( keys.hasNext() ) {
+            this.componentHandlers.remove( keys.next() );
+        }
+
+        keyList.clear();
+
+        if ( this.parentLocator != null ) {
+            this.parentLocator.release( this.parentSelector );
+            this.parentLocator = null;
+            this.parentSelector = null;
+        }
+        
+        super.dispose();
+    }
+
+    /**
+     * Makes the ComponentHandlers available to subclasses.
+     *
+     * @return A reference to the componentHandler Map.
+     */
+    protected Map getComponentHandlers() {
+        return this.componentHandlers;
+    }
+
+    /** Add a new component to the manager.
+     * @param hint the hint name for the new component.
+     * @param component the class of this component.
+     * @param configuration the configuration for this component.
+     */
+    public void addComponent( final Object hint,
+                              final Class component,
+                              final Configuration configuration )
+    throws ServiceException {
+        if( this.initialized ) {
+            throw new ServiceException( hint.toString(),
+                "Cannot add components to an initialized ComponentSelector", null );
+        }
+
+        try {
+            final AbstractComponentHandler handler = getComponentHandler( this.roleName,
+                                                                  component,
+                                                                  configuration,
+                                                                  this.serviceManager);
+
+            handler.initialize();
+            this.componentHandlers.put( hint, handler );
+
+            if( this.getLogger().isDebugEnabled() ) {
+                this.getLogger().debug(
+                    "Adding " + component.getName() + " for hint [" + hint.toString() + "]" );
+            }
+        } catch (ServiceException se) {
+            throw se;
+        } catch( final Exception e ) {
+            final String message =
+                "Could not set up Component for hint [ " + hint + "]";
+            if( this.getLogger().isErrorEnabled() ) {
+                this.getLogger().error( message, e );
+            }
+
+            throw new ServiceException( hint.toString(), message, e );
+        }
+    }
+
+    /**
+     * Get the name for component-instance elements (i.e. components not defined
+     * by their role shortcut. If <code>null</code>, any element having a 'class'
+     * attribute will be considered as a component instance.
+     * <p>
+     * The default here is to return <code>null</code>, and subclasses can redefine
+     * this method to return particular values.
+     *
+     * @return <code>null</code>, but can be changed by subclasses
+     */
+    protected String getComponentInstanceName() {
+        return null;
+    }
+
+    /**
+     * Get the name of the attribute giving the class name of a component.
+     * The default here is "class", but this can be overriden in subclasses.
+     *
+     * @return "<code>class</code>", but can be changed by subclasses
+     */
+    protected String getClassAttributeName() {
+        return "class";
+    }
+
+    /**
+     * Get the name of the attribute giving the default hint to use if
+     * none is given. The default here is "default", but this can be
+     * overriden in subclasses. If this method returns <code>null</code>,
+     * no default hint can be specified.
+     *
+     * @return "<code>default</code>", but can be changed by subclasses
+     */
+    protected String getDefaultHintAttributeName() {
+        return "default";
+    }
+    
+    /**
+     * Get the role name for this selector. This is called by <code>configure()</code>
+     * to set the value of <code>this.roleName</code>.
+     *
+     * @return the role name, or <code>null<code> if it couldn't be determined.
+     */
+    protected String getRoleName(Configuration config) {
+        // Get the role for this selector
+        String name = config.getAttribute("role", null);
+        if (name == null && this.roleManager != null) {
+            name = this.roleManager.getRoleForName(config.getName());
+        }
+
+        return name;
+    }
+
+    /**
+     * Get the default hint, if any for this selector.
+     */
+    public String getDefaultHint() {
+        return this.defaultHint;
+    }
+
+    /**
+     * Does this selector declare a given hint? Check is performed on the components declared for this
+     * selector only, and <strong>not</strong> those potentially inherited from the parent selector.
+     * 
+     * @param hint the hint to check for
+     * @return <code>true</code> if this selector has the specified hint
+     */
+    protected boolean hasDeclaredComponent(Object hint) {
+        if (hint == null) {
+            hint = this.defaultHint;
+        }
+
+        return this.isSelectable(hint);
+    }
+
+    /**
+     * Set the ComponentLocatorImpl that allows access to a possible
+     * parent of this selector
+     * @param locator
+     * @throws ComponentException
+     */
+    public void setParentLocator(ServiceManager locator, String role)
+    throws ServiceException {
+        if (this.parentSelector != null) {
+            throw new ServiceException(null, "Parent selector is already set");
+        }
+        this.parentLocator = locator;
+        
+        // Get the parent, unwrapping it as far as needed
+        Object parent = locator.lookup(role);
+        
+        if (parent instanceof CocoonServiceSelector) {
+            this.parentSelector = (CocoonServiceSelector)parent;
+        } else {
+            throw new IllegalArgumentException("Parent selector is not an extended component selector (" + parent + ")");
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.excalibur.component.ExcaliburComponentSelector#canRelease(org.apache.avalon.framework.component.Component)
+     */
+    protected boolean canRelease(Object component) {
+        if ( this.parentSelector != null &&
+             this.parentSelector.canRelease(component) ) {
+            return true;
+        }
+        return this.componentMapping.containsKey( component );
+    }
+
+    
+
+}

Added: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/ComponentFactory.java
==============================================================================
--- (empty file)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/ComponentFactory.java	Thu Oct 21 12:25:56 2004
@@ -0,0 +1,169 @@
+/* 
+ * Copyright 2002-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.cocoon.core.container;
+
+import org.apache.avalon.excalibur.logger.LoggerManager;
+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.Contextualizable;
+import org.apache.avalon.framework.logger.LogEnabled;
+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.avalon.framework.service.Serviceable;
+
+/**
+ * Factory for Avalon based components.
+ *
+ * @version CVS $Id: ComponentFactory.java 55172 2004-10-20 17:52:18Z cziegeler $
+ */
+public class ComponentFactory {
+    
+    /** The class which this <code>ComponentFactory</code>
+     * should create.
+     */
+    private final Class componentClass;
+
+    /** The Context for the component
+     */
+    private final Context context;
+
+    /** The service manager for this component
+     */
+    private final ServiceManager serviceManager;
+    
+    /** The configuration for this component.
+     */
+    private final Configuration configuration;
+
+    /** The parameters for this component
+     */
+    private Parameters parameters;
+    
+    private final Logger logger;
+    
+    private final String role;
+    
+    private final LoggerManager loggerManager;
+
+    private final RoleManager roleManager;
+    
+    /**
+     * 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 seerviceManager the service manager to pass to <code>Serviceable</code>s.
+     * @param context the <code>Context</code> to pass to <code>Contexutalizable</code>s.
+     *
+     */
+    public ComponentFactory( final String role,
+                             final Class componentClass,
+                             final Configuration configuration,
+                             final ServiceManager serviceManager,
+                             final Context context,
+                             final Logger logger,
+                             final LoggerManager loggerManager,
+                             final RoleManager roleManager) {
+        this.role = role;
+        this.componentClass = componentClass;
+        this.configuration = configuration;
+        this.serviceManager = serviceManager;
+        this.context = context;
+        this.logger = logger;
+        this.loggerManager = loggerManager;
+        this.roleManager = roleManager;
+    }
+
+    /**
+     * Create a new instance
+     */
+    public Object newInstance()
+    throws Exception {
+        final Object component = this.componentClass.newInstance();
+
+        if( this.logger.isDebugEnabled() ) {
+            this.logger.debug( "ComponentFactory creating new instance of " +
+                    this.componentClass.getName() + "." );
+        }
+
+        if ( component instanceof LogEnabled ) {
+            if( null == this.configuration ) {
+                ContainerUtil.enableLogging( component, this.logger );
+            } else {
+                final String logger = this.configuration.getAttribute( "logger", null );
+                if( null == logger ) {
+                    this.logger.debug( "no logger attribute available, using standard logger" );
+                    ContainerUtil.enableLogging( component, this.logger );
+                } else {
+                    this.logger.debug( "logger attribute is " + this.logger );
+                    ContainerUtil.enableLogging( component, this.loggerManager.getLoggerForCategory( logger ) );
+                }
+            }
+        }
+
+
+        if( component instanceof Contextualizable ) {
+            ContainerUtil.contextualize( component, this.context );
+        }
+
+        if( component instanceof Serviceable ) {
+            ContainerUtil.service( component, this.serviceManager );
+        }
+
+        if ( component instanceof CocoonServiceSelector ) {
+            ((CocoonServiceSelector)component).setLoggerManager(this.loggerManager);
+            ((CocoonServiceSelector)component).setRoleManager(this.roleManager);
+        }
+        
+        ContainerUtil.configure( component, this.configuration );
+
+        if( component instanceof Parameterizable ) {
+            if ( this.parameters == null ) {
+                this.parameters = Parameters.fromConfiguration( this.configuration );
+            }
+            ContainerUtil.parameterize( component, this.parameters );
+        }
+
+        ContainerUtil.initialize( component );
+
+        ContainerUtil.start( component );
+
+        return component;
+    }
+
+    public Class getCreatedClass() {
+        return this.componentClass;
+    }
+
+    /**
+     * Destroy an instance
+     */
+    public void decommission( final Object component )
+    throws Exception {
+        if( this.logger.isDebugEnabled() ) {
+            this.logger.debug( "ComponentFactory decommissioning instance of " +
+                    this.componentClass.getName() + "." );
+        }
+
+        ContainerUtil.stop( component );
+        ContainerUtil.dispose( component );
+    }
+
+}

Added: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/PoolableComponentHandler.java
==============================================================================
--- (empty file)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/PoolableComponentHandler.java	Thu Oct 21 12:25:56 2004
@@ -0,0 +1,245 @@
+/* 
+ * Copyright 2002-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.cocoon.core.container;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import org.apache.avalon.excalibur.pool.Poolable;
+import org.apache.avalon.excalibur.pool.Recyclable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.logger.Logger;
+
+/**
+ * The PoolableComponentHandler to make sure that poolable components are initialized
+ * destroyed and pooled correctly.
+ * <p>
+ * Components which implement Poolable may be configured to be pooled using the following
+ *  example configuration.  This example assumes that the user component class MyComp
+ *  implements Poolable.
+ * <p>
+ * Configuration Example:
+ * <pre>
+ *   &lt;my-comp pool-max="8"/&gt;
+ * </pre>
+ * <p>
+ * Roles Example:
+ * <pre>
+ *   &lt;role name="com.mypkg.MyComponent"
+ *         shorthand="my-comp"
+ *         default-class="com.mypkg.DefaultMyComponent"/&gt;
+ * </pre>
+ * <p>
+ * Configuration Attributes:
+ * <ul>
+ * <li>The <code>pool-max</code> attribute is used to set the maximum number of components which
+ *  will be pooled. (Defaults to "8") If additional instances are required, they're created,
+ *  but not pooled.</li>
+ * </ul>
+ *
+ * @version CVS $Id: PoolableComponentHandler.java 55144 2004-10-20 12:26:09Z ugo $
+ */
+public class PoolableComponentHandler
+extends AbstractComponentHandler {
+    
+    /** The default max size of the pool */
+    public static final int DEFAULT_MAX_POOL_SIZE = 8;
+
+    /**
+     * Object used to synchronize access to the get and put methods
+     */
+    protected final Object semaphore = new Object();
+
+    /**
+     * The maximum size of the pool.
+     */
+    private final int max;
+
+    /**
+     * List of the Poolable instances which are available for use.
+     */
+    private LinkedList ready;
+
+    /**
+     * Store the size of the ready list to optimize operations which require this value.
+     */
+    private int readySize;
+
+    /**
+     * Total number of Poolable instances in the pool
+     */
+    private int size;
+    
+    /**
+     * Create a PoolableComponentHandler which manages a pool of Components
+     *  created by the specified factory object.
+     *
+     * @param factory The factory object which is responsible for creating the components
+     *                managed by the ComponentHandler.
+     * @param config The configuration to use to configure the pool.
+     */
+    public PoolableComponentHandler( final Logger logger,
+                                     final ComponentFactory factory,
+                                     final Configuration config )
+    throws Exception {
+        super(logger, factory);
+
+        final int poolMax = config.getAttributeAsInteger( "pool-max", DEFAULT_MAX_POOL_SIZE );
+        this.max = ( poolMax <= 0 ? Integer.MAX_VALUE : poolMax );
+
+        // Create the pool lists.
+        this.ready = new LinkedList();
+    }
+
+    /**
+     * Dispose of the ComponentHandler and any associated Pools and Factories.
+     */
+    public void dispose() {
+        super.dispose();
+
+        // Any Poolables in the m_ready list need to be disposed of
+        synchronized( this.semaphore ) {
+            // Remove objects in the ready list.
+            for( Iterator iter = this.ready.iterator(); iter.hasNext(); ) {
+                Poolable poolable = (Poolable)iter.next();
+                iter.remove();
+                this.readySize--;
+                permanentlyRemovePoolable( poolable );
+            }
+
+            if( ( this.size > 0 ) && this.logger.isDebugEnabled() ) {
+                this.logger.debug( "There were " + this.size
+                                   + " outstanding objects when the pool was disposed." );
+            }
+        }
+    }
+    
+    /**
+     * Permanently removes a poolable from the pool's active list and
+     *  destroys it so that it will not ever be reused.
+     * <p>
+     * This method is only called by threads that have m_semaphore locked.
+     */
+    protected void permanentlyRemovePoolable( Object poolable ) {
+        this.size--;
+        this.removePoolable( poolable );
+    }
+
+    /**
+     * Called when an object is being removed permanently from the pool.
+     * This is the method to override when you need to enforce destructional
+     * policies.
+     * <p>
+     * This method is only called by threads that have m_semaphore locked.
+     *
+     * @param poolable Poolable to be completely removed from the pool.
+     */
+    protected void removePoolable( Object poolable ) {
+        try {
+            this.factory.decommission( poolable );
+        } catch( Exception e ) {
+            if( this.logger.isDebugEnabled() ) {
+                this.logger.debug( "Error decommissioning object", e );
+            }
+        }
+    }
+
+    /**
+     * Gets a Poolable from the pool.  If there is room in the pool, a new Poolable will be
+     *  created.  Depending on the parameters to the constructor, the method may block or throw
+     *  an exception if a Poolable is not available on the pool.
+     *
+     * @return Always returns a Poolable.  Contract requires that put must always be called with
+     *  the Poolable returned.
+     * @throws Exception An exception may be thrown as described above or if there is an exception
+     *  thrown by the ObjectFactory's newInstance() method.
+     */
+    protected Object doGet() throws Exception {
+        Object poolable;
+        synchronized( this.semaphore ) {
+            // Look for a Poolable at the end of the m_ready list
+            if( this.readySize > 0 ){
+                // A poolable is ready and waiting in the pool
+                poolable = (Poolable)this.ready.removeLast();
+                this.readySize--;
+            } else {
+                // Create a new poolable.  May throw an exception if the poolable can not be
+                //  instantiated.
+                poolable = this.factory.newInstance();
+                this.size++;
+
+                if( this.logger.isDebugEnabled() ) {
+                    this.logger.debug( "Created a new " + poolable.getClass().getName()
+                                       + " from the object factory." );
+                }
+            }
+        }
+
+        if( this.logger.isDebugEnabled() ) {
+            this.logger.debug( "Got a " + poolable.getClass().getName() + " from the pool." );
+        }
+
+        return poolable;
+    }
+
+    /**
+     * Returns a poolable to the pool 
+     *
+     * @param poolable Poolable to return to the pool.
+     */
+    protected void doPut( final Object poolable ) {
+        // Handle Recyclable objects
+        if( poolable instanceof Recyclable ) {
+            ( (Recyclable)poolable ).recycle();
+        }
+
+        synchronized( this.semaphore ) {
+            if( this.size <= this.max )
+            {
+                if( this.disposed ) {
+                    // The pool has already been disposed.
+                    if( this.logger.isDebugEnabled() ) {
+                        this.logger.debug( "Put called for a " + poolable.getClass().getName()
+                                           + " after the pool was disposed." );
+                    }
+
+                    this.permanentlyRemovePoolable( poolable );
+                } else {
+                    // There is room in the pool to keep this poolable.
+                    if( this.logger.isDebugEnabled() ) {
+                        this.logger.debug( "Put a " + poolable.getClass().getName()
+                                           + " back into the pool." );
+                    }
+
+                    this.ready.addLast( poolable );
+                    this.readySize++;
+
+                }
+            } else {
+                // More Poolables were created than can be held in the pool, so remove.
+                if( this.logger.isDebugEnabled() ) {
+                    this.logger.debug( "No room to put a " + poolable.getClass().getName()
+                                       + " back into the pool, so remove it." );
+                }
+
+                this.permanentlyRemovePoolable( poolable );
+            }
+        }
+    }
+
+    
+}

Added: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/RoleManager.java
==============================================================================
--- (empty file)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/RoleManager.java	Thu Oct 21 12:25:56 2004
@@ -0,0 +1,205 @@
+/* 
+ * Copyright 2002-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.cocoon.core.container;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+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.AbstractLogEnabled;
+
+/**
+ * Default RoleManager implementation.  It populates the RoleManager
+ * from a configuration file.
+ *
+ * @version CVS $Id: RoleManager.java 55144 2004-10-20 12:26:09Z ugo $
+ */
+public class RoleManager
+extends AbstractLogEnabled
+implements Configurable {
+    
+    /** Map for shorthand to role mapping */
+    private Map shorthands;
+
+    /** Map for role to default classname mapping */
+    private Map classNames;
+
+    /** Map for role->hint to classname mapping */
+    private Map hintClassNames;
+
+    /** Parent <code>RoleManager</code> for nested resolution */
+    private final RoleManager parent;
+
+    /**
+     * Default constructor--this RoleManager has no parent.
+     */
+    public RoleManager() {
+        this.parent = null;
+    }
+
+    /**
+     * Alternate constructor--this RoleManager has the specified
+     * parent.
+     *
+     * @param parent  The parent <code>RoleManager</code>.
+     */
+    public RoleManager( RoleManager parent ) {
+        this.parent = parent;
+    }
+
+    /**
+     * Retrieves the real role name from a shorthand name.  Usually
+     * the shorthand name refers to a configuration element name.  If
+     * this RoleManager does not have the match, and there is a parent
+     * RoleManager, the parent will be asked to resolve the role.
+     *
+     * @param shorthandName  The shortname that is an alias for the role.
+     * @return the official role name.
+     */
+    public final String getRoleForName( final String shorthandName ) {
+        final String role = (String)this.shorthands.get( shorthandName );
+
+        if( null == role && null != this.parent ) {
+            return this.parent.getRoleForName( shorthandName );
+        }
+
+        if( this.getLogger().isDebugEnabled() ) {
+            this.getLogger().debug( "looking up shorthand " + shorthandName +
+                               ", returning " + role );
+        }
+
+        return role;
+    }
+
+    /**
+     * Retrieves the default class name for the specified role.  This
+     * is only called when the configuration does not specify the
+     * class explicitly.  If this RoleManager does not have the match,
+     * and there is a parent RoleManager, the parent will be asked
+     * to resolve the class name.
+     *
+     * @param role  The role that has a default implementation.
+     * @return the Fully Qualified Class Name (FQCN) for the role.
+     */
+    public final String getDefaultClassNameForRole( final String role ) {
+        final String className = (String)this.classNames.get( role );
+
+        if( null == className && null != this.parent ) {
+            return this.parent.getDefaultClassNameForRole( role );
+        }
+
+        return className;
+    }
+
+    /**
+     * Retrieves a default class name for a role/hint combination.
+     * This is only called when a role is mapped to a
+     * DefaultComponentSelector, and the configuration elements use
+     * shorthand names for the type of component.  If this RoleManager
+     * does not have the match, and there is a parent RoleManager, the
+     * parent will be asked to resolve the class name.
+     *
+     * @param role  The role that this shorthand refers to.
+     * @param shorthand  The shorthand name for the type of Component
+     * @return the FQCN for the role/hint combination.
+     */
+    public final String getDefaultClassNameForHint( final String role,
+                                                    final String shorthand ) {
+        if( this.getLogger().isDebugEnabled() ) {
+            this.getLogger().debug( "looking up hintmap for role " + role );
+        }
+
+        final Map hintMap = (Map)this.hintClassNames.get( role );
+
+        if( null == hintMap ) {
+            if( null != this.parent ) {
+                return this.parent.getDefaultClassNameForHint( role, shorthand );
+            } 
+            return "";
+        }
+
+        if( this.getLogger().isDebugEnabled() ) {
+            this.getLogger().debug( "looking up classname for hint " + shorthand );
+        }
+
+        final String s = ( String ) hintMap.get( shorthand );
+
+        if( s == null && null != this.parent ) {
+            return this.parent.getDefaultClassNameForHint( role, shorthand );
+        } 
+        return s;
+    }
+
+    /**
+     * Reads a configuration object and creates the role, shorthand,
+     * and class name mapping.
+     *
+     * @param configuration  The configuration object.
+     * @throws ConfigurationException if the configuration is malformed
+     */
+    public final void configure( final Configuration configuration )
+    throws ConfigurationException {
+        final Map shorts = new HashMap();
+        final Map classes = new HashMap();
+        final Map hintclasses = new HashMap();
+
+        final Configuration[] roles = configuration.getChildren( "role" );
+
+        for( int i = 0; i < roles.length; i++ ) {
+            final String name = roles[ i ].getAttribute( "name" );
+            final String shorthand = roles[ i ].getAttribute( "shorthand" );
+            final String defaultClassName = roles[ i ].getAttribute( "default-class", null );
+
+            shorts.put( shorthand, name );
+
+            if( null != defaultClassName ) {
+                classes.put( name, defaultClassName );
+            }
+
+            final Configuration[] hints = roles[ i ].getChildren( "hint" );
+            if( hints.length > 0 ) {
+                HashMap hintMap = new HashMap();
+
+                for( int j = 0; j < hints.length; j++ ) {
+                    final String shortHand = hints[ j ].getAttribute( "shorthand" ).trim();
+                    String className = hints[ j ].getAttribute( "class" ).trim();
+
+                    hintMap.put( shortHand, className );
+                    if( this.getLogger().isDebugEnabled() ) {
+                        this.getLogger().debug( "Adding hint type " + shortHand +
+                                                " associated with role " + name +
+                                                " and class " + className );
+                    }
+                }
+
+                hintclasses.put( name, Collections.unmodifiableMap( hintMap ) );
+            }
+
+            if( this.getLogger().isDebugEnabled() ) {
+                this.getLogger().debug( "added Role " + name + " with shorthand " +
+                                   shorthand + " for " + defaultClassName );
+            }
+        }
+
+        this.shorthands = Collections.unmodifiableMap( shorts );
+        this.classNames = Collections.unmodifiableMap( classes );
+        this.hintClassNames = Collections.unmodifiableMap( hintclasses );
+    }
+}

Added: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/SingleThreadedComponentHandler.java
==============================================================================
--- (empty file)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/SingleThreadedComponentHandler.java	Thu Oct 21 12:25:56 2004
@@ -0,0 +1,73 @@
+/* 
+ * Copyright 2002-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.cocoon.core.container;
+
+import org.apache.avalon.framework.logger.Logger;
+
+/**
+ * The DefaultComponentHandler to make sure components are initialized
+ * and destroyed correctly.
+ *
+ * @version CVS $Id: SingleThreadedComponentHandler.java 55144 2004-10-20 12:26:09Z ugo $
+ */
+public class SingleThreadedComponentHandler
+extends AbstractComponentHandler {
+
+    /**
+     * Create a SingleThreadedComponentHandler which manages a pool of Components
+     *  created by the specified factory object.
+     *
+     * @param logger The logger to use
+     * @param factory The factory object which is responsible for creating the components
+     *                managed by the handler.
+     */
+    public SingleThreadedComponentHandler( final Logger logger,
+                                    final ComponentFactory factory ) {
+        super(logger, factory);
+    }
+
+    /**
+     * Get a reference of the desired Component
+     *
+     * @return A component instance.
+     *
+     * @throws Exception If there are any problems encountered acquiring a
+     *                   component instance.
+     */
+    protected Object doGet()
+    throws Exception {
+        return this.factory.newInstance();
+    }
+
+    /**
+     * Return a reference of the desired Component
+     *
+     * @param component Component to be be put/released back to the handler.
+     */
+    protected void doPut( final Object component ) {
+        try {
+            this.factory.decommission( component );
+        } catch( final Exception e ) {
+            if( this.logger.isWarnEnabled() )
+            {
+                this.logger.warn( "Error decommissioning component: "
+                    + this.factory.getCreatedClass().getName(), e );
+            }
+        }
+    }
+
+}

Added: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/ThreadSafeComponentHandler.java
==============================================================================
--- (empty file)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/ThreadSafeComponentHandler.java	Thu Oct 21 12:25:56 2004
@@ -0,0 +1,85 @@
+/* 
+ * Copyright 2002-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.cocoon.core.container;
+
+import org.apache.avalon.framework.logger.Logger;
+
+/**
+ * The ThreadSafeComponentHandler to make sure components are initialized
+ * and destroyed correctly.
+ *
+ * @version CVS $Id: ThreadSafeComponentHandler.java 55144 2004-10-20 12:26:09Z ugo $
+ */
+public class ThreadSafeComponentHandler
+extends AbstractComponentHandler {
+    
+    private Object instance;
+
+    /**
+     * Create a ThreadSafeComponentHandler which manages a single instance
+     * of an object return by the component factory.
+     * @param logger The logger to use
+     * @param factory The factory object which is responsible for creating the components
+     *                managed by the handler.
+     */
+    public ThreadSafeComponentHandler( final Logger logger,
+                                       final ComponentFactory factory ) {
+        super(logger, factory);
+    }
+    
+    public void initialize() 
+    throws Exception {
+        if( this.initialized ) {
+            return;
+        }
+        if( this.instance == null ) {
+            this.instance = this.factory.newInstance();
+        }
+        super.initialize();
+    }
+
+    /**
+     * Get a reference of the desired Component
+     */
+    protected Object doGet()
+    throws Exception {
+        return this.instance;
+    }
+
+    /**
+     * Return a reference of the desired Component
+     */
+    protected void doPut( final Object component ) {
+        // nothing to do
+    }
+
+    /**
+     * Dispose of the ComponentHandler and any associated Pools and Factories.
+     */
+    public void dispose() {
+        try {
+            this.factory.decommission( this.instance );
+            this.instance = null;
+        } catch( final Exception e ) {
+            if( this.logger.isWarnEnabled() ) {
+                this.logger.warn( "Error decommissioning component: " +
+                                  this.factory.getCreatedClass().getName(), e );
+            }
+        }
+        super.dispose();
+    }
+}

Added: cocoon/trunk/src/core/test/org/apache/cocoon/core/container/RoleManagerTestCase.java
==============================================================================
--- (empty file)
+++ cocoon/trunk/src/core/test/org/apache/cocoon/core/container/RoleManagerTestCase.java	Thu Oct 21 12:25:56 2004
@@ -0,0 +1,75 @@
+/*
+ * Copyright 1999-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.cocoon.components.container;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.cocoon.core.container.RoleManager;
+import org.jmock.Mock;
+import org.jmock.MockObjectTestCase;
+
+
+/**
+ * Test cases for {@link RoleManager}.
+ * 
+ * @version CVS $Id: RoleManagerTestCase.java 55163 2004-10-20 16:41:11Z ugo $
+ */
+public class RoleManagerTestCase extends MockObjectTestCase {
+    
+    /**
+     * Constructor for RoleManagerTestCase.
+     * @param name The test name
+     */
+    public RoleManagerTestCase(String name) {
+        super(name);
+    }
+
+    /*
+     * @see TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+    }
+    
+    public void testConfigureWithoutHints() throws ConfigurationException {
+        Mock conf = new Mock(Configuration.class);
+        Mock child0 = new Mock(Configuration.class);
+        Configuration roles[] = new Configuration[1];
+        roles[0] = (Configuration) child0.proxy();
+        Configuration hints[] = new Configuration[0];
+        conf.expects(once()).method("getChildren").with(eq("role"))
+                .will(returnValue(roles));
+        child0.expects(once()).method("getAttribute").with(eq("name"))
+                .will(returnValue("testName"));
+        child0.expects(once()).method("getAttribute").with(eq("shorthand"))
+                .will(returnValue("testShorthand"));
+        child0.expects(once()).method("getAttribute").with(eq("default-class"), eq(null))
+                .will(returnValue("testClass"));
+        child0.expects(once()).method("getChildren").with(eq("hint"))
+                .will(returnValue(hints));
+        Mock logger = new Mock(Logger.class);
+        logger.expects(this.atLeastOnce()).method("isDebugEnabled").will(returnValue(false));
+        RoleManager rm = new RoleManager(null);
+        rm.enableLogging((Logger) logger.proxy());
+        rm.configure((Configuration) conf.proxy());
+        conf.verify();
+        child0.verify();
+        assertEquals("Role name for shorthand incorrect", "testName", rm.getRoleForName("testShorthand"));
+        assertEquals("Default class for role incorrect", "testClass", rm.getDefaultClassNameForRole("testName"));
+        assertEquals("Default class for hint must be empty", "", rm.getDefaultClassNameForHint("testName", "testShorthand"));
+    }
+
+}

Modified: cocoon/trunk/src/java/org/apache/cocoon/Cocoon.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/Cocoon.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/Cocoon.java	Thu Oct 21 12:25:56 2004
@@ -23,17 +23,10 @@
 import java.util.Enumeration;
 import java.util.Map;
 
-import org.apache.avalon.excalibur.component.ComponentProxyGenerator;
-import org.apache.avalon.excalibur.component.DefaultRoleManager;
-import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
 import org.apache.avalon.excalibur.logger.LoggerManager;
 
 import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.activity.Initializable;
-import org.apache.avalon.framework.component.Component;
-import org.apache.avalon.framework.component.ComponentException;
-import org.apache.avalon.framework.component.ComponentManager;
-import org.apache.avalon.framework.component.Composable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.configuration.DefaultConfiguration;
@@ -45,15 +38,17 @@
 import org.apache.avalon.framework.context.DefaultContext;
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
 import org.apache.avalon.framework.thread.ThreadSafe;
 
 import org.apache.cocoon.components.ContextHelper;
-import org.apache.cocoon.components.container.CocoonComponentManager;
 import org.apache.cocoon.components.container.ComponentContext;
-import org.apache.cocoon.components.container.ComponentManagerWrapper;
 import org.apache.cocoon.components.source.SourceUtil;
 import org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper;
+import org.apache.cocoon.core.container.CocoonServiceManager;
+import org.apache.cocoon.core.container.RoleManager;
 import org.apache.cocoon.environment.Environment;
 import org.apache.cocoon.environment.ObjectModelHelper;
 import org.apache.cocoon.environment.Request;
@@ -66,8 +61,6 @@
 import org.apache.excalibur.event.command.CommandManager;
 import org.apache.excalibur.event.command.TPCThreadManager;
 import org.apache.excalibur.event.command.ThreadManager;
-import org.apache.excalibur.instrument.InstrumentManageable;
-import org.apache.excalibur.instrument.InstrumentManager;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
 import org.apache.excalibur.source.impl.URLSource;
@@ -86,14 +79,13 @@
 public class Cocoon
         extends AbstractLogEnabled
         implements ThreadSafe,
-                   Component,
                    Initializable,
                    Disposable,
                    Modifiable,
                    Processor,
                    Contextualizable,
-                   Composable,
-                   InstrumentManageable {
+                   Serviceable {
+
     static Cocoon instance;
 
     private ThreadManager threads;
@@ -112,20 +104,14 @@
     /** The logger manager */
     private LoggerManager loggerManager;
 
-    /** The instrument manager */
-    private InstrumentManager instrumentManager;
-
     /** The classpath (null if not available) */
     private String classpath;
 
     /** The working directory (null if not available) */
     private File workDir;
 
-    /** The component manager. */
-    private ExcaliburComponentManager componentManager;
-
-    /** The parent component manager. */
-    private ComponentManager parentComponentManager;
+    /** The parent service manager. */
+    private ServiceManager parentComponentManager;
 
     /** flag for disposed or not */
     private boolean disposed = false;
@@ -142,8 +128,8 @@
     /** The environment helper */
     protected EnvironmentHelper environmentHelper;
 
-    /** A service manager (wrapper) */
-    protected ServiceManager serviceManager;
+    /** A service manager */
+    protected CocoonServiceManager serviceManager;
 
     /** An optional Avalon Component that is called before and after processing all requests. */
     protected RequestListener requestListener;
@@ -163,13 +149,13 @@
     }
 
     /**
-     * Get the parent component manager. For purposes of
+     * Get the parent service manager. For purposes of
      * avoiding extra method calls, the manager parameter may be null.
      *
      * @param manager the parent component manager. May be <code>null</code>
      */
-    public void compose(ComponentManager manager)
-    throws ComponentException {
+    public void service(ServiceManager manager)
+    throws ServiceException {
         this.parentComponentManager = manager;
     }
 
@@ -238,29 +224,21 @@
     }
 
     /**
-     * Set the <code>InstrumentManager</code> for this Cocoon instance.
-     *
-     * @param manager an <code>InstrumentManager</code> instance
-     */
-    public void setInstrumentManager(final InstrumentManager manager) {
-        this.instrumentManager = manager;
-    }
-
-    /**
      * The <code>initialize</code> method
      *
      * @exception Exception if an error occurs
      */
     public void initialize() throws Exception {
         if (parentComponentManager != null) {
-            this.componentManager = new CocoonComponentManager(parentComponentManager,
+            // TODO: wrap parent component manager
+            this.serviceManager = new CocoonServiceManager(null,
                                                                (ClassLoader) this.context.get(Constants.CONTEXT_CLASS_LOADER));
         } else {
-            this.componentManager = new CocoonComponentManager((ClassLoader) this.context.get(Constants.CONTEXT_CLASS_LOADER));
+            this.serviceManager = new CocoonServiceManager(null, 
+                                                           (ClassLoader) this.context.get(Constants.CONTEXT_CLASS_LOADER));
         }
-        ContainerUtil.enableLogging(this.componentManager, getLogger().getChildLogger("manager"));
-        ContainerUtil.contextualize(this.componentManager, this.context);
-        this.componentManager.setInstrumentManager(this.instrumentManager);
+        ContainerUtil.enableLogging(this.serviceManager, getLogger().getChildLogger("manager"));
+        ContainerUtil.contextualize(this.serviceManager, this.context);
 
         if (getLogger().isDebugEnabled()) {
             getLogger().debug("New Cocoon object.");
@@ -278,7 +256,7 @@
             getLogger().debug("Work directory = " + workDir.getCanonicalPath());
         }
 
-        ExcaliburComponentManager startupManager = new ExcaliburComponentManager((ClassLoader) this.context.get(Constants.CONTEXT_CLASS_LOADER));
+        CocoonServiceManager startupManager = new CocoonServiceManager(null,(ClassLoader) this.context.get(Constants.CONTEXT_CLASS_LOADER));
         ContainerUtil.enableLogging(startupManager, getLogger().getChildLogger("startup"));
         ContainerUtil.contextualize(startupManager, this.context);
         startupManager.setLoggerManager(this.loggerManager);
@@ -299,14 +277,11 @@
         startupManager = null;
 
         // add the logger manager to the component locator
-        final ComponentProxyGenerator proxyGenerator = new ComponentProxyGenerator();
-        final Component loggerManagerProxy = proxyGenerator.getProxy(LoggerManager.class.getName(),loggerManager);
-        componentManager.addComponentInstance(LoggerManager.ROLE,loggerManagerProxy);
 
-        ContainerUtil.initialize(this.componentManager);
+        ContainerUtil.initialize(this.serviceManager);
 
         // Get the Processor and keep it if it's ThreadSafe
-        Processor processor = (Processor)this.componentManager.lookup(Processor.ROLE);
+        Processor processor = (Processor)this.serviceManager.lookup(Processor.ROLE);
         if (processor instanceof ThreadSafe) {
             if (getLogger().isDebugEnabled()) {
                 getLogger().debug("Processor of class " + processor.getClass().getName() +
@@ -318,20 +293,18 @@
                 getLogger().debug("Processor of class " + processor.getClass().getName() +
                                   " is NOT ThreadSafe -- will be looked up at each request");
             }
-            this.componentManager.release(processor);
+            this.serviceManager.release(processor);
         }
 
-        this.serviceManager = new ComponentManagerWrapper(this.componentManager);
-
         this.environmentHelper = new EnvironmentHelper(
                 (String) this.context.get(ContextHelper.CONTEXT_ROOT_URL));
         ContainerUtil.enableLogging(this.environmentHelper, getLogger());
         ContainerUtil.service(this.environmentHelper, this.serviceManager);
 
-        this.sourceResolver = (SourceResolver)this.componentManager.lookup(SourceResolver.ROLE);
+        this.sourceResolver = (SourceResolver)this.serviceManager.lookup(SourceResolver.ROLE);
 
-        if (this.componentManager.hasComponent(RequestListener.ROLE)){
-            this.requestListener = (RequestListener) this.componentManager.lookup(RequestListener.ROLE);
+        if (this.serviceManager.hasService(RequestListener.ROLE)){
+            this.requestListener = (RequestListener) this.serviceManager.lookup(RequestListener.ROLE);
         }
     }
 
@@ -359,7 +332,7 @@
      * @exception ConfigurationException if an error occurs
      * @exception ContextException if an error occurs
      */
-    public void configure(ExcaliburComponentManager startupManager) throws ConfigurationException, ContextException {
+    public void configure(CocoonServiceManager startupManager) throws ConfigurationException, ContextException {
         SAXParser p = null;
         Configuration roleConfig = null;
 
@@ -375,10 +348,10 @@
         } catch (Exception e) {
             throw new ConfigurationException("Error trying to load configurations", e);
         } finally {
-            if (p != null) startupManager.release((Component)p);
+            if (p != null) startupManager.release(p);
         }
 
-        DefaultRoleManager drm = new DefaultRoleManager();
+        RoleManager drm = new RoleManager();
         ContainerUtil.enableLogging(drm, getLogger().getChildLogger("roles"));
         ContainerUtil.configure(drm, roleConfig);
         roleConfig = null;
@@ -392,7 +365,7 @@
         } catch (Exception e) {
             throw new ConfigurationException("Error trying to load configurations",e);
         } finally {
-            if (p != null) startupManager.release((Component)p);
+            if (p != null) startupManager.release(p);
         }
 
         Configuration conf = this.configuration;
@@ -427,23 +400,23 @@
             } catch (Exception e) {
                 throw new ConfigurationException("Error trying to load user-roles configuration", e);
             } finally {
-                startupManager.release((Component)p);
+                startupManager.release(p);
             }
 
-            DefaultRoleManager urm = new DefaultRoleManager(drm);
+            RoleManager urm = new RoleManager(drm);
             ContainerUtil.enableLogging(urm, getLogger().getChildLogger("roles").getChildLogger("user"));
             ContainerUtil.configure(urm, roleConfig);
             roleConfig = null;
             drm = urm;
         }
 
-        this.componentManager.setRoleManager(drm);
-        this.componentManager.setLoggerManager(this.loggerManager);
+        this.serviceManager.setRoleManager(drm);
+        this.serviceManager.setLoggerManager(this.loggerManager);
 
         if (getLogger().isDebugEnabled()) {
             getLogger().debug("Setting up components...");
         }
-        ContainerUtil.configure(this.componentManager, conf);
+        ContainerUtil.configure(this.serviceManager, conf);
     }
 
     /**
@@ -494,18 +467,18 @@
         ContainerUtil.dispose(this.threads);
         this.threads = null;
 
-        if (this.componentManager != null) {
+        if (this.serviceManager != null) {
             if (this.requestListener != null) {
-                this.componentManager.release(this.requestListener);
+                this.serviceManager.release(this.requestListener);
             }
-            this.componentManager.release(this.threadSafeProcessor);
+            this.serviceManager.release(this.threadSafeProcessor);
             this.threadSafeProcessor = null;
 
-            this.componentManager.release(this.sourceResolver);
+            this.serviceManager.release(this.sourceResolver);
             this.sourceResolver = null;
 
-            ContainerUtil.dispose(this.componentManager);
-            this.componentManager = null;
+            ContainerUtil.dispose(this.serviceManager);
+            this.serviceManager = null;
         }
 
         this.context = null;
@@ -651,7 +624,7 @@
                     }
                 }
             } else {
-                Processor processor = (Processor)this.componentManager.lookup(Processor.ROLE);
+                Processor processor = (Processor)this.serviceManager.lookup(Processor.ROLE);
                 try {
                     result = processor.process(environment);
                     if (this.requestListener != null) {
@@ -662,7 +635,7 @@
                         }
                     }
                 } finally {
-                    this.componentManager.release(processor);
+                    this.serviceManager.release(processor);
                 }
             }
             // commit response on success
@@ -709,11 +682,11 @@
             if (this.threadSafeProcessor != null) {
                 return this.threadSafeProcessor.buildPipeline(environment);
             } else {
-                Processor processor = (Processor)this.componentManager.lookup(Processor.ROLE);
+                Processor processor = (Processor)this.serviceManager.lookup(Processor.ROLE);
                 try {
                     return processor.buildPipeline(environment);
                 } finally {
-                    this.componentManager.release(processor);
+                    this.serviceManager.release(processor);
                 }
             }
 
@@ -760,7 +733,10 @@
         return this.environmentHelper.getContext();
     }
 
-    public ExcaliburComponentManager getComponentManager() {
-        return this.componentManager;
+    /**
+     * FIXME -  Do we really need this method?
+     */
+    public ServiceManager getServiceManager() {
+        return this.serviceManager;
     }
 }

Modified: cocoon/trunk/src/java/org/apache/cocoon/bean/BeanListener.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/bean/BeanListener.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/bean/BeanListener.java	Thu Oct 21 12:25:56 2004
@@ -15,8 +15,6 @@
  */
 package org.apache.cocoon.bean;
 
-import java.util.List;
-
 /**
  * Interface allowing caller to install a listener so that it can be informed
  * as the bean makes progress through the links to be called.

Modified: cocoon/trunk/src/java/org/apache/cocoon/bean/CocoonBean.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/bean/CocoonBean.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/bean/CocoonBean.java	Thu Oct 21 12:25:56 2004
@@ -98,7 +98,7 @@
             super.initialize();
 
             this.sourceResolver =
-                (SourceResolver) getComponentManager().lookup(
+                (SourceResolver) getServiceManager().lookup(
                     SourceResolver.ROLE);
 
             initialized = true;
@@ -328,7 +328,7 @@
     public void dispose() {
         if (this.initialized) {
             if (this.sourceResolver != null) {
-                getComponentManager().release(this.sourceResolver);
+                getServiceManager().release(this.sourceResolver);
                 this.sourceResolver = null;
             }
             super.dispose();

Modified: cocoon/trunk/src/java/org/apache/cocoon/bean/CocoonWrapper.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/bean/CocoonWrapper.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/bean/CocoonWrapper.java	Thu Oct 21 12:25:56 2004
@@ -29,7 +29,6 @@
 import java.util.Map;
 import java.util.TreeMap;
 
-import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
 import org.apache.avalon.excalibur.logger.LogKitLoggerManager;
 
 import org.apache.avalon.framework.configuration.Configuration;
@@ -38,6 +37,7 @@
 import org.apache.avalon.framework.context.DefaultContext;
 import org.apache.avalon.framework.logger.LogKitLogger;
 import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceManager;
 
 import org.apache.cocoon.Cocoon;
 import org.apache.cocoon.Constants;
@@ -63,7 +63,7 @@
  * @author <a href="mailto:nicolaken@apache.org">Nicola Ken Barozzi</a>
  * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
  * @author <a href="mailto:uv@upaya.co.uk">Upayavira</a>
- * @version CVS $Id: CocoonWrapper.java,v 1.14 2004/07/11 23:02:54 antonio Exp $
+ * @version CVS $Id$
  */
 public class CocoonWrapper {
 
@@ -160,8 +160,8 @@
         initialized = true;
     }
     
-    protected ExcaliburComponentManager getComponentManager() {
-        return cocoon.getComponentManager();
+    protected ServiceManager getServiceManager() {
+        return cocoon.getServiceManager();
     }
 
     /**

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/container/DefaultSitemapConfigurationHolder.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/container/DefaultSitemapConfigurationHolder.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/container/DefaultSitemapConfigurationHolder.java	Thu Oct 21 12:25:56 2004
@@ -19,10 +19,10 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.avalon.excalibur.component.RoleManager;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.cocoon.components.ChainedConfiguration;
 import org.apache.cocoon.components.SitemapConfigurationHolder;
+import org.apache.cocoon.core.container.RoleManager;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 
 /**

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java	Thu Oct 21 12:25:56 2004
@@ -21,9 +21,6 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.avalon.excalibur.component.ExcaliburComponentSelector;
-import org.apache.avalon.excalibur.component.RoleManageable;
-import org.apache.avalon.excalibur.component.RoleManager;
 import org.apache.avalon.excalibur.pool.Recyclable;
 import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.activity.Initializable;
@@ -38,8 +35,7 @@
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.ServiceSelector;
 import org.apache.avalon.framework.service.Serviceable;
-import org.apache.avalon.framework.service.WrapperServiceSelector;
-import org.apache.cocoon.components.ExtendedComponentSelector;
+import org.apache.cocoon.core.container.CocoonServiceSelector;
 import org.apache.cocoon.components.LifecycleHelper;
 import org.apache.cocoon.components.source.SourceUtil;
 import org.apache.cocoon.components.treeprocessor.variables.VariableResolverFactory;
@@ -56,7 +52,7 @@
 public class DefaultTreeBuilder
         extends AbstractLogEnabled
         implements TreeBuilder, Contextualizable, Serviceable,
-                   RoleManageable, Initializable, Recyclable, Disposable {
+                   Initializable, Recyclable, Disposable {
 
     protected Map attributes = new HashMap();
 
@@ -74,12 +70,6 @@
      */
     protected ServiceManager ownManager;
 
-    /**
-     * The parent role manager, set using <code>setRoleManager</code> (implementation of
-     * <code>RoleManageable</code>).
-     */
-    protected RoleManager ownRoleManager;
-
     // -------------------------------------
     
     /**
@@ -158,7 +148,7 @@
         }
         
         // Create the NodeBuilder selector.
-        ExcaliburComponentSelector selector = new ExtendedComponentSelector() {
+        CocoonServiceSelector selector = new CocoonServiceSelector() {
             protected String getComponentInstanceName() {
                 return "node";
             }
@@ -177,19 +167,12 @@
             true
         );
 
-        this.builderSelector = new WrapperServiceSelector("BuilderSelector", selector);
+        this.builderSelector = selector;
         
     }
 
     public void setParentProcessorManager(ServiceManager manager) {
         this.parentProcessorManager = manager;
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.avalon.excalibur.component.RoleManageable#setRoleManager(org.apache.avalon.excalibur.component.RoleManager)
-     */
-    public void setRoleManager(RoleManager rm) {
-        this.ownRoleManager = rm;
     }
 
     /* (non-Javadoc)

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java	Thu Oct 21 12:25:56 2004
@@ -47,7 +47,6 @@
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  * @version CVS $Id$
  */
-
 public class TreeProcessor
     extends AbstractLogEnabled
     implements ThreadSafe,
@@ -147,10 +146,16 @@
         return new TreeProcessor(this, delayedSource, checkReload, prefix);
     }
 
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
+     */
     public void contextualize(Context context) throws ContextException {
         this.context = context;
     }
 
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+     */
     public void service(ServiceManager manager) throws ServiceException {
         this.parentServiceManager = manager;
         this.resolver = (SourceResolver)this.parentServiceManager.lookup(SourceResolver.ROLE);

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ComponentsSelector.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ComponentsSelector.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ComponentsSelector.java	Thu Oct 21 12:25:56 2004
@@ -18,16 +18,14 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.avalon.framework.CascadingRuntimeException;
 import org.apache.avalon.framework.activity.Disposable;
-import org.apache.avalon.framework.component.ComponentException;
-import org.apache.avalon.framework.component.Component;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.configuration.DefaultConfiguration;
+import org.apache.avalon.framework.service.ServiceException;
 import org.apache.cocoon.acting.Action;
-import org.apache.cocoon.components.ExtendedComponentSelector;
 import org.apache.cocoon.components.pipeline.ProcessingPipeline;
+import org.apache.cocoon.core.container.CocoonServiceSelector;
 import org.apache.cocoon.generation.Generator;
 import org.apache.cocoon.generation.GeneratorFactory;
 import org.apache.cocoon.matching.Matcher;
@@ -41,11 +39,9 @@
 /**
  * Component selector for sitemap components.
  *
- * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @author <a href="mailto:uv@upaya.co.uk">Upayavira</a>
  * @version CVS $Id$
  */
-public class ComponentsSelector extends ExtendedComponentSelector {
+public class ComponentsSelector extends CocoonServiceSelector {
 
     public static final int UNKNOWN     = -1;
     public static final int GENERATOR   = 0;
@@ -124,7 +120,7 @@
     /**
      * Add a component in this selector.
      */
-    public void addComponent(Object hint, Class clazz, Configuration config) throws ComponentException {
+    public void addComponent(Object hint, Class clazz, Configuration config) throws ServiceException {
         super.addComponent(hint, clazz, config);
 
         // Add to known hints. This is needed as we cannot call isSelectable() if initialize()
@@ -174,7 +170,7 @@
             // Don't keep known hints (they're no more needed)
             this.knownHints = null;
         } catch (Exception e) {
-            throw new CascadingRuntimeException("Cannot setup default components", e);
+            throw new RuntimeException("Cannot setup default components", e);
         }
     }
 
@@ -183,9 +179,9 @@
      * since it requires to be initialized, and we want to add components, and this must
      * be done before initialization.
      */
-    private void ensureExists(Object hint, Class clazz, Configuration config) throws ComponentException {
+    private void ensureExists(Object hint, Class clazz, Configuration config) throws ServiceException {
         if (!this.knownHints.contains(hint)) {
-            if (this.parentSelector == null || !this.parentSelector.hasComponent(hint)) {
+            if (this.parentSelector == null || !this.parentSelector.isSelectable(hint)) {
                 addComponent(hint, clazz, config);
             }
         }
@@ -195,8 +191,8 @@
      * Override parent to implement support for {@link GeneratorFactory},
      * {@link TransformerFactory}, and {@link SerializerFactory}.
      */
-    public Component select(Object hint) throws ComponentException {
-        final Component component = super.select(hint);
+    public Object select(Object hint) throws ServiceException {
+        final Object component = super.select(hint);
 
         switch (this.roleId) {
             case GENERATOR:
@@ -223,7 +219,7 @@
      * Override parent to implement support for {@link GeneratorFactory},
      * {@link TransformerFactory}, and {@link SerializerFactory}.
      */
-    public void release(Component component) {
+    public void release(Object component) {
 
         // If component is an Instance returned by Factory, get the Factory.
         switch (this.roleId) {

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java	Thu Oct 21 12:25:56 2004
@@ -25,21 +25,18 @@
 import java.util.Set;
 import java.util.StringTokenizer;
 
-import org.apache.avalon.excalibur.logger.LoggerManager;
-import org.apache.avalon.framework.component.WrapperComponentManager;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.configuration.DefaultConfiguration;
 import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.WrapperServiceManager;
 import org.apache.cocoon.acting.Action;
-import org.apache.cocoon.components.container.CocoonComponentManager;
 import org.apache.cocoon.components.pipeline.ProcessingPipeline;
 import org.apache.cocoon.components.treeprocessor.CategoryNode;
 import org.apache.cocoon.components.treeprocessor.CategoryNodeBuilder;
 import org.apache.cocoon.components.treeprocessor.DefaultTreeBuilder;
 import org.apache.cocoon.components.treeprocessor.ProcessorComponentInfo;
 import org.apache.cocoon.components.treeprocessor.variables.VariableResolverFactory;
+import org.apache.cocoon.core.container.CocoonServiceManager;
 import org.apache.cocoon.generation.Generator;
 import org.apache.cocoon.matching.Matcher;
 import org.apache.cocoon.reading.Reader;
@@ -79,15 +76,11 @@
             config = new DefaultConfiguration("", "");
         }
 
-        final LoggerManager loggerManager = (LoggerManager) this.parentProcessorManager.lookup(LoggerManager.ROLE);
-
-        CocoonComponentManager newManager = new CocoonComponentManager(new WrapperComponentManager(this.parentProcessorManager));
+        CocoonServiceManager newManager = new CocoonServiceManager(this.parentProcessorManager, null);
         
         // Go through the component lifecycle
         newManager.enableLogging(getLogger());
-        newManager.setLoggerManager(loggerManager);
         newManager.contextualize(this.context);
-        newManager.setRoleManager(this.ownRoleManager);
         newManager.configure(config);
         newManager.initialize();
 
@@ -112,7 +105,7 @@
         setupMimeTypes(config, Reader.ROLE, "readers");
         
         // Wrap the ComponentManager in a ServiceManager
-        ServiceManager result = new WrapperServiceManager(newManager);
+        ServiceManager result = newManager;
         
         // Register manager and prevent further modifications
         getProcessor().getComponentInfo().setServiceManager(result);

Modified: cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java	Thu Oct 21 12:25:56 2004
@@ -1376,12 +1376,10 @@
             ContainerUtil.enableLogging(c, getCocoonLogger());
             c.setLoggerManager(getLoggerManager());
             ContainerUtil.contextualize(c, this.appContext);
+            // TODO - ServiceManager
             final ComponentManager parent = this.getParentComponentManager();
             if (parent != null) {
                 ContainerUtil.compose(c, parent);
-            }
-            if (this.enableInstrumentation) {
-                c.setInstrumentManager(getInstrumentManager());
             }
             ContainerUtil.initialize(c);
             this.creationTime = System.currentTimeMillis();

Modified: cocoon/trunk/src/test/org/apache/cocoon/transformation/AugmentTransformerTestCase.java
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/AugmentTransformerTestCase.java	(original)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/AugmentTransformerTestCase.java	Thu Oct 21 12:25:56 2004
@@ -19,10 +19,11 @@
 import junit.framework.Test;
 import junit.framework.TestSuite;
 import junit.textui.TestRunner;
+
 import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.WrapperServiceManager;
 import org.apache.cocoon.Processor;
 import org.apache.cocoon.SitemapComponentTestCase;
-import org.apache.cocoon.components.container.ComponentManagerWrapper;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.cocoon.environment.mock.MockEnvironment;
 import org.w3c.dom.Document;
@@ -32,7 +33,7 @@
  * A simple testcase for AugmentTransformer.
  *
  * @author <a href="mailto:huber@apache.org">Bernhard Huber</a>
- * @version CVS $Id: AugmentTransformerTestCase.java,v 1.1 2004/07/04 18:01:39 huber Exp $
+ * @version CVS $Id$
  */
 public class AugmentTransformerTestCase extends SitemapComponentTestCase {
     
@@ -80,7 +81,7 @@
         MockEnvironment env = new MockEnvironment();
         Processor processor = (Processor)this.manager.lookup(Processor.ROLE);
         
-        EnvironmentHelper.enterProcessor(processor, new ComponentManagerWrapper(this.manager), env);
+        EnvironmentHelper.enterProcessor(processor, new WrapperServiceManager(this.manager), env);
         
         Document resultDocument = load(result);
         Document inputDocument = load(input);

Modified: cocoon/trunk/src/test/org/apache/cocoon/transformation/CIncludeTransformerTestCase.java
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/CIncludeTransformerTestCase.java	(original)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/CIncludeTransformerTestCase.java	Thu Oct 21 12:25:56 2004
@@ -22,7 +22,7 @@
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.cocoon.Processor;
 import org.apache.cocoon.SitemapComponentTestCase;
-import org.apache.cocoon.components.container.ComponentManagerWrapper;
+import org.apache.avalon.framework.service.WrapperServiceManager;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.cocoon.environment.mock.MockEnvironment;
 
@@ -30,7 +30,7 @@
  * A simple testcase for FilterTransformer.
  *
  * @author <a href="mailto:stephan@apache.org">Stephan Michels </a>
- * @version CVS $Id: CIncludeTransformerTestCase.java,v 1.3 2004/05/25 07:28:26 cziegeler Exp $
+ * @version CVS $Id$
  */
 public class CIncludeTransformerTestCase extends SitemapComponentTestCase {
     
@@ -78,7 +78,7 @@
         MockEnvironment env = new MockEnvironment();
         Processor processor = (Processor)this.manager.lookup(Processor.ROLE);
         
-        EnvironmentHelper.enterProcessor(processor, new ComponentManagerWrapper(this.manager), env);
+        EnvironmentHelper.enterProcessor(processor, new WrapperServiceManager(this.manager), env);
         
         assertEqual( load(result),
         transform("cinclude", src, parameters, load(input)));
@@ -106,7 +106,7 @@
         MockEnvironment env = new MockEnvironment();
         Processor processor = (Processor)this.manager.lookup(Processor.ROLE);
         
-        EnvironmentHelper.enterProcessor(processor, new ComponentManagerWrapper(this.manager), env);
+        EnvironmentHelper.enterProcessor(processor, new WrapperServiceManager(this.manager), env);
         
         assertEqual( load(result),
         transform("cinclude", src, parameters, load(input)));
@@ -134,7 +134,7 @@
         MockEnvironment env = new MockEnvironment();
         Processor processor = (Processor)this.manager.lookup(Processor.ROLE);
         
-        EnvironmentHelper.enterProcessor(processor, new ComponentManagerWrapper(this.manager), env);
+        EnvironmentHelper.enterProcessor(processor, new WrapperServiceManager(this.manager), env);
         
         assertEqual( load(result),
         transform("cinclude", src, parameters, load(input)));

Modified: cocoon/trunk/src/test/org/apache/cocoon/transformation/EncodeURLTransformerTestCase.java
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/EncodeURLTransformerTestCase.java	(original)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/EncodeURLTransformerTestCase.java	Thu Oct 21 12:25:56 2004
@@ -22,7 +22,7 @@
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.cocoon.Processor;
 import org.apache.cocoon.SitemapComponentTestCase;
-import org.apache.cocoon.components.container.ComponentManagerWrapper;
+import org.apache.avalon.framework.service.WrapperServiceManager;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.cocoon.environment.mock.MockEnvironment;
 import org.apache.cocoon.environment.mock.MockRequest;
@@ -35,7 +35,7 @@
  * A simple testcase for FilterTransformer.
  *
  * @author <a href="mailto:stephan@apache.org">Stephan Michels </a>
- * @version CVS $Id: EncodeURLTransformerTestCase.java,v 1.1 2004/07/04 18:01:39 huber Exp $
+ * @version CVS $Id$
  */
 public class EncodeURLTransformerTestCase extends SitemapComponentTestCase {
     
@@ -84,7 +84,7 @@
         MockEnvironment env = new MockEnvironment();
         Processor processor = (Processor)this.manager.lookup(Processor.ROLE);
         
-        EnvironmentHelper.enterProcessor(processor, new ComponentManagerWrapper(this.manager), env);
+        EnvironmentHelper.enterProcessor(processor, new WrapperServiceManager(this.manager), env);
         
         Document inputDocument = load(input);
         Document resultDocument = load(result);
@@ -127,7 +127,7 @@
         MockEnvironment env = new MockEnvironment();
         Processor processor = (Processor)this.manager.lookup(Processor.ROLE);
         
-        EnvironmentHelper.enterProcessor(processor, new ComponentManagerWrapper(this.manager), env);
+        EnvironmentHelper.enterProcessor(processor, new WrapperServiceManager(this.manager), env);
         
         Document inputDocument = load(input);
         Document resultDocument = load(result);

Modified: cocoon/trunk/src/test/org/apache/cocoon/transformation/I18NTransformerTestCase.java
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/I18NTransformerTestCase.java	(original)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/I18NTransformerTestCase.java	Thu Oct 21 12:25:56 2004
@@ -22,7 +22,7 @@
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.cocoon.Processor;
 import org.apache.cocoon.SitemapComponentTestCase;
-import org.apache.cocoon.components.container.ComponentManagerWrapper;
+import org.apache.avalon.framework.service.WrapperServiceManager;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.cocoon.environment.mock.MockEnvironment;
 
@@ -30,7 +30,7 @@
  * A simple testcase for FilterTransformer.
  *
  * @author <a href="mailto:stephan@apache.org">Stephan Michels </a>
- * @version CVS $Id: I18NTransformerTestCase.java,v 1.3 2004/05/25 07:28:26 cziegeler Exp $
+ * @version CVS $Id$
  */
 public class I18NTransformerTestCase extends SitemapComponentTestCase {
     
@@ -78,7 +78,7 @@
         MockEnvironment env = new MockEnvironment();
         Processor processor = (Processor)this.manager.lookup(Processor.ROLE);
         
-        EnvironmentHelper.enterProcessor(processor, new ComponentManagerWrapper(this.manager), env);
+        EnvironmentHelper.enterProcessor(processor, new WrapperServiceManager(this.manager), env);
         
         assertEqual( load(result),
         transform("i18n", src, parameters, load(input)));
@@ -105,7 +105,7 @@
         MockEnvironment env = new MockEnvironment();
         Processor processor = (Processor)this.manager.lookup(Processor.ROLE);
         
-        EnvironmentHelper.enterProcessor(processor, new ComponentManagerWrapper(this.manager), env);
+        EnvironmentHelper.enterProcessor(processor, new WrapperServiceManager(this.manager), env);
         
         assertEqual( load(result),
         transform("i18n", src, parameters, load(input)));

Modified: cocoon/trunk/src/test/org/apache/cocoon/transformation/XIncludeTransformerTestCase.java
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/XIncludeTransformerTestCase.java	(original)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/XIncludeTransformerTestCase.java	Thu Oct 21 12:25:56 2004
@@ -22,7 +22,7 @@
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.cocoon.Processor;
 import org.apache.cocoon.SitemapComponentTestCase;
-import org.apache.cocoon.components.container.ComponentManagerWrapper;
+import org.apache.avalon.framework.service.WrapperServiceManager;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.cocoon.environment.mock.MockEnvironment;
 
@@ -30,7 +30,7 @@
  * A simple testcase for FilterTransformer.
  *
  * @author <a href="mailto:stephan@apache.org">Stephan Michels </a>
- * @version CVS $Id: XIncludeTransformerTestCase.java,v 1.3 2004/05/25 07:28:26 cziegeler Exp $
+ * @version CVS $Id$
  */
 public class XIncludeTransformerTestCase extends SitemapComponentTestCase {
     
@@ -77,7 +77,7 @@
         MockEnvironment env = new MockEnvironment();
         Processor processor = (Processor)this.manager.lookup(Processor.ROLE);
         
-        EnvironmentHelper.enterProcessor(processor, new ComponentManagerWrapper(this.manager), env);
+        EnvironmentHelper.enterProcessor(processor, new WrapperServiceManager(this.manager), env);
         
         assertEqual( load(result),
         transform("xinclude", src, parameters, load(input)));
@@ -102,7 +102,7 @@
         MockEnvironment env = new MockEnvironment();
         Processor processor = (Processor)this.manager.lookup(Processor.ROLE);
         
-        EnvironmentHelper.enterProcessor(processor, new ComponentManagerWrapper(this.manager), env);
+        EnvironmentHelper.enterProcessor(processor, new WrapperServiceManager(this.manager), env);
         
         assertEqual( load(result),
         transform("xinclude", src, parameters, load(input)));

Mime
View raw message