bloritsch 01/04/05 12:40:46 Added: proposal/4.0/src/java/org/apache/avalon/pool HardResourceLimitingPool.java Resizable.java SingleThreadedPool.java SoftResourceLimitingPool.java proposal/4.0/src/java/org/apache/framework/component DefaultComponentFactory.java DefaultComponentHandler.java DefaultComponentPool.java DefaultComponentPoolController.java DefaultRoleInfo.java RoleInfo.java src/java/org/apache/avalon/component DefaultComponentFactory.java DefaultComponentHandler.java DefaultComponentManager.java DefaultComponentPool.java DefaultComponentPoolController.java DefaultComponentSelector.java DefaultRoleInfo.java RoleInfo.java Removed: proposal/4.0/src/java/org/apache/avalon/pool ThreadSafePool.java Log: Many fixes to 4.0 tree, and backporting Cocoon's ComponentManagement Infrastructure. Revision Changes Path 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/pool/HardResourceLimitingPool.java Index: HardResourceLimitingPool.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.pool; import org.apache.framework.lifecycle.Initializable; import org.apache.framework.thread.ThreadSafe; /** * This is a implementation of <code>Pool</code> that is thread safe. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a> * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class HardResourceLimitingPool extends SoftResourceLimitingPool implements ThreadSafe, Initializable { public final static int DEFAULT_POOL_SIZE = 8; public HardResourceLimitingPool( final ObjectFactory factory, final PoolController controller ) throws Exception { super( factory, controller, DEFAULT_POOL_SIZE, DEFAULT_POOL_SIZE ); } public HardResourceLimitingPool( final ObjectFactory factory ) throws Exception { this( factory, null ); } public HardResourceLimitingPool( final ObjectFactory factory, final int initial, final int maximum ) throws Exception { super( factory, null, initial, maximum ); } public HardResourceLimitingPool( final ObjectFactory factory, final int initial ) throws Exception { this( factory, initial, initial ); } public HardResourceLimitingPool( final Class clazz, final int initial, final int maximum ) throws NoSuchMethodException, Exception { this( new DefaultObjectFactory( clazz ), initial, maximum ); } public HardResourceLimitingPool( final Class clazz, final int initial ) throws NoSuchMethodException, Exception { this( clazz, initial, initial ); } public void init() { try { super.init(); } catch (Exception e) { getLogger().debug("Caught init exception", e); } } /** * Retrieve an object from pool. * * @return an object from Pool */ public final synchronized Poolable get() throws Exception { while ( this.m_ready.size() == 0 || this.m_currentCount > this.m_max ) { try { wait(); } catch( final InterruptedException ie ) { } } return super.get(); } /** * Place an object in pool. * * @param poolable the object to be placed in pool */ public final synchronized void put( final Poolable poolable ) { super.put( poolable ); notify(); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/pool/Resizable.java Index: Resizable.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.pool; /** * This is the interface for Pools that are not a fixed size. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> */ public interface Resizable { void grow(int amount); void shrink(int amount); } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/pool/SingleThreadedPool.java Index: SingleThreadedPool.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.pool; import org.apache.framework.lifecycle.Initializable; import org.apache.framework.thread.SingleThreaded; /** * This is an <code>Pool</code> that caches Poolable objects for reuse. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a> * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class SingleThreadedPool implements Pool, SingleThreaded, Resizable { protected int m_count; protected Poolable[] m_pool; protected ObjectFactory m_factory; protected PoolController m_controller; protected int m_maximum; protected int m_initial; public SingleThreadedPool( final ObjectFactory factory, final PoolController controller, final int initial, final int maximum ) throws Exception { m_count = 0; m_factory = factory; m_controller = controller; m_maximum = maximum; m_initial = initial; if( !(this instanceof Initializable) ) { init(); } } public void init() throws Exception { grow( m_maximum ); fill( m_initial ); } /** * Retrieve an object from pool. * * @return an object from Pool */ public Poolable get() throws Exception { if( null == m_pool && null != m_controller ) { final int increase = m_controller.grow(); if( increase > 0 ) grow( increase ); } if( 0 == m_count ) { return (Poolable)m_factory.newInstance(); } m_count--; final Poolable poolable = m_pool[ m_count ]; m_pool[ m_count ] = null; return poolable; } /** * Place an object in pool. * * @param poolable the object to be placed in pool */ public void put( final Poolable poolable ) { if( poolable instanceof Recyclable ) { ((Recyclable)poolable).recycle(); } if( m_pool.length == (m_count + 1) && null != m_controller ) { final int decrease = m_controller.shrink(); if( decrease > 0 ) shrink( decrease ); } if ( m_pool.length > m_count + 1 ) { m_pool[ m_count++ ] = poolable; } } /** * Return the total number of slots in Pool * * @return the total number of slots */ public final int getCapacity() { return m_pool.length; } /** * Get the number of used slots in Pool * * @return the number of used slots */ public final int getSize() { return m_count; } /** * This fills the pool to the size specified in parameter. */ public final void fill( final int fillSize ) throws Exception { final int size = Math.min( m_pool.length, fillSize ); for( int i = m_count; i < size; i++ ) { m_pool[i] = (Poolable)m_factory.newInstance(); } m_count = size; } /** * This fills the pool by the size specified in parameter. */ public final void grow( final int increase ) { if( null == m_pool ) { m_pool = new Poolable[ increase ]; return; } final Poolable[] poolables = new Poolable[ increase + m_pool.length ]; System.arraycopy( m_pool, 0, poolables, 0, m_pool.length ); m_pool = poolables; } /** * This shrinks the pool by parameter size. */ public final void shrink( final int decrease ) { final Poolable[] poolables = new Poolable[ m_pool.length - decrease ]; System.arraycopy( m_pool, 0, poolables, 0, poolables.length ); m_pool = poolables; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/pool/SoftResourceLimitingPool.java Index: SoftResourceLimitingPool.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.pool; import org.apache.avalon.pool.Poolable; import org.apache.framework.lifecycle.Initializable; /** * This is an <code>Pool</code> that caches Poolable objects for reuse. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> */ public class SoftResourceLimitingPool extends AbstractPool implements Resizable { protected final PoolController m_controller; /** * Create an SoftResourceLimitingPool. The pool requires a factory, * and can optionally have a controller. */ public SoftResourceLimitingPool( final ObjectFactory factory, final int min ) throws Exception { super(factory, min, min * 2); this.m_controller = null; } /** * Create an SoftResourceLimitingPool. The pool requires a factory, * and can optionally have a controller. */ public SoftResourceLimitingPool( final ObjectFactory factory, final int min, final int max ) throws Exception { super(factory, min, max); this.m_controller = null; } /** * Create an SoftResourceLimitingPool. The pool requires a factory, * and can optionally have a controller. */ public SoftResourceLimitingPool( final ObjectFactory factory, final PoolController controller, final int min, final int max ) throws Exception { super(factory, min, max); m_controller = controller; } public void init() { this.grow(this.m_min); } public synchronized void grow(final int amount) { for (int i = 0; i < amount; i++) { try { m_ready.push( this.m_factory.newInstance() ); this.m_currentCount++; } catch (Exception e) { if (getLogger() != null) getLogger().debug( m_factory.getCreatedClass().getName() + ": could not be instantiated.", e ); } } notify(); } public synchronized void shrink(final int amount) { for (int i = 0; i < amount; i++) { if (this.m_ready.size() > this.m_min) { try { this.m_factory.decommission( this.m_ready.pop() ); this.m_currentCount--; } catch (Exception e) { if (getLogger() != null) getLogger().debug( m_factory.getCreatedClass().getName() + ": improperly decommissioned.", e ); } } } } public Poolable get() throws Exception { if (this.m_ready.size() == 0) { this.grow((this.m_controller == null) ? this.m_max - this.m_min : this.m_controller.grow()); } return super.get(); } public void put(Poolable obj) { if (this.m_ready.size() > this.m_max) { this.shrink((this.m_controller == null) ? this.m_ready.size() - (this.m_max + 1) : this.m_controller.shrink()); } super.put(obj); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/framework/component/DefaultComponentFactory.java Index: DefaultComponentFactory.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.framework.component; import org.apache.avalon.pool.ObjectFactory; import org.apache.avalon.pool.Pool; import org.apache.avalon.pool.Poolable; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.Configurable; import org.apache.framework.thread.ThreadSafe; import org.apache.framework.context.Contextualizable; import org.apache.framework.context.Context; import org.apache.framework.lifecycle.Initializable; import org.apache.framework.lifecycle.Disposable; import org.apache.framework.lifecycle.Stoppable; import org.apache.framework.lifecycle.Startable; import org.apache.framework.logger.AbstractLoggable; import org.apache.framework.logger.Loggable; /** * Factory for Avalon components. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> * @author <a href="mailto:[EMAIL PROTECTED]">Paul Russell</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:43 $ */ public class DefaultComponentFactory extends AbstractLoggable implements ObjectFactory, ThreadSafe { /** The class which this <code>ComponentFactory</code> * should create. */ private Class componentClass; /** The configuration for this component. */ private Configuration conf; /** The component manager for this component. */ private ComponentManager manager; /** The Context for the component */ private Context context; /** Construct a new component factory for the specified component. * @param componentClass the class to instantiate (must have a default constructor). * @param config the <code>Configuration</code> object to pass to new instances. * @param manager the component manager to pass to <code>Composer</code>s. */ public DefaultComponentFactory(Class componentClass, Configuration config, ComponentManager manager, Context context) { this.componentClass = componentClass; this.conf = config; this.manager = manager; this.context = context; } public Object newInstance() throws Exception { Object comp = componentClass.newInstance(); getLogger().debug("ComponentFactory creating new instance of " + componentClass.getName() + "." ); if ( comp instanceof Loggable) { ((Loggable)comp).setLogger(getLogger()); } if ( comp instanceof Contextualizable ) { ((Contextualizable)comp).contextualize(this.context); } if ( comp instanceof Composer) { ((Composer)comp).compose(this.manager); } if ( comp instanceof Configurable ) { ((Configurable)comp).configure(this.conf); } if ( comp instanceof Initializable ) { ((Initializable)comp).init(); } if ( comp instanceof Startable ) { ((Startable)comp).start(); } return comp; } public final Class getCreatedClass() { return componentClass; } public final void decommission(Object comp) throws Exception { getLogger().debug("ComponentFactory decommissioning instance of " + componentClass.getName() + "." ); if ( comp instanceof Stoppable ) { ((Stoppable)comp).stop(); } if ( comp instanceof Disposable ) { ((Disposable)comp).dispose(); } comp = null; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/framework/component/DefaultComponentHandler.java Index: DefaultComponentHandler.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.framework.component; import org.apache.framework.configuration.Configuration; import org.apache.framework.context.Context; import org.apache.framework.lifecycle.Disposable; import org.apache.framework.lifecycle.Initializable; import org.apache.framework.logger.AbstractLoggable; import org.apache.framework.lifecycle.Stoppable; import org.apache.avalon.pool.Poolable; import org.apache.log.Logger; /** * The DefaultComponentHandler to make sure components are initialized * and destroyed correctly. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:44 $ */ class DefaultComponentHandler extends AbstractLoggable implements Initializable, Disposable { /** Indicates that the Handler is holding a <code>ThreadSafe</code> Component */ final static int THREADSAFE = 0; /** Indicates that the Handler is holding a <code>Poolable</code> Component */ final static int POOLABLE = 1; /** Indicates that the Handler is holding a <code>SingleThreaded</code> Component */ final static int SINGLETHREADED = 2; /** The instance of the ComponentFactory that creates and disposes of the Component */ private DefaultComponentFactory factory; /** The pool of components for <code>Poolable</code> Components */ private DefaultComponentPool pool; /** The instance of the Component for <code>ThreadSafe</code> Components */ private Component instance; /** The type of the Component: THREADSAFE, POOLABLE, or SINGLETHREADED */ private final int type; /** State management boolean stating whether the Handler is initialized or not */ private boolean initialized = false; /** State management boolean stating whether the Handler is disposed or not */ private boolean disposed = false; /** * Create a ComponentHandler that takes care of hiding the details of * whether a Component is ThreadSafe, Poolable, or SingleThreaded. * It falls back to SingleThreaded if not specified. */ DefaultComponentHandler(Class componentClass, Configuration config, ComponentManager manager, Context context) throws Exception { this.factory = new DefaultComponentFactory(componentClass, config, manager, context); if (org.apache.avalon.pool.Poolable.class.isAssignableFrom(componentClass)) { this.pool = new DefaultComponentPool(this.factory); this.type = DefaultComponentHandler.POOLABLE; } else if (org.apache.framework.thread.ThreadSafe.class.isAssignableFrom(componentClass)) { this.type = DefaultComponentHandler.THREADSAFE; } else { this.type = DefaultComponentHandler.SINGLETHREADED; } } /** * Create a ComponentHandler that takes care of hiding the details of * whether a Component is ThreadSafe, Poolable, or SingleThreaded. * It falls back to SingleThreaded if not specified. */ DefaultComponentHandler(Component comp) throws Exception { this.type = DefaultComponentHandler.THREADSAFE; this.instance = comp; } /** * Sets the logger that the ComponentHandler will use. */ public void setLogger(Logger log) { if (this.factory != null) { this.factory.setLogger(log); } if (this.pool != null) { this.pool.setLogger(log); } super.setLogger(log); } /** * Initialize the ComponentHandler. */ public void init() { if (this.initialized) return; switch (this.type) { case DefaultComponentHandler.THREADSAFE: try { if (this.instance == null) { this.instance = (Component)this.factory.newInstance(); } } catch (Exception e) { getLogger().error("Cannot use component: " + this.factory.getCreatedClass().getName(), e); } break; case DefaultComponentHandler.POOLABLE: try { this.pool.init(); } catch (Exception e) { getLogger().error("Cannot use component: " + this.factory.getCreatedClass().getName(), e); } break; default: // Nothing to do for SingleThreaded Components break; } this.initialized = true; } /** * Get a reference of the desired Component */ public Component get() throws Exception { if (! this.initialized) { throw new IllegalStateException("You cannot get a component from an uninitialized holder."); } if (this.disposed) { throw new IllegalStateException("You cannot get a component from a disposed holder"); } Component comp = null; switch (this.type) { case DefaultComponentHandler.THREADSAFE: comp = this.instance; break; case DefaultComponentHandler.POOLABLE: comp = (Component)this.pool.get(); break; default: comp = (Component)this.factory.newInstance(); break; } return comp; } /** * Return a reference of the desired Component */ public void put(Component comp) { if (! this.initialized) { throw new IllegalStateException("You cannot put a component in an uninitialized holder."); } if (this.disposed) { throw new IllegalStateException("You cannot put a component in a disposed holder"); } switch (this.type) { case DefaultComponentHandler.THREADSAFE: // Nothing to do for ThreadSafe Components break; case DefaultComponentHandler.POOLABLE: this.pool.put((Poolable) comp); break; default: try { this.factory.decommission(comp); } catch (Exception e) { getLogger().warn("Error decommissioning component: " + this.factory.getCreatedClass().getName(), e); } break; } } /** * Dispose of the ComponentHandler and any associated Pools and Factories. */ public void dispose() { this.disposed = true; try { switch (this.type) { case DefaultComponentHandler.THREADSAFE: if (this.factory != null) { this.factory.decommission(this.instance); } else { if ( this.instance instanceof Stoppable ) { ((Stoppable) this.instance).stop(); } if ( this.instance instanceof Disposable ) { ((Disposable) this.instance).dispose(); } } this.instance = null; break; case DefaultComponentHandler.POOLABLE: if (this.pool instanceof Disposable) { ((Disposable) this.pool).dispose(); } this.pool = null; break; default: // do nothing here break; } if (this.factory instanceof Disposable) { ((Disposable) this.factory).dispose(); } this.factory = null; } catch (Exception e) { getLogger().warn("Error decommissioning component: " + this.factory.getCreatedClass().getName(), e); } } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/framework/component/DefaultComponentPool.java Index: DefaultComponentPool.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.framework.component; import java.util.List; import java.util.ArrayList; import org.apache.avalon.pool.Poolable; import org.apache.framework.thread.ThreadSafe; import org.apache.framework.lifecycle.Initializable; import org.apache.framework.lifecycle.Disposable; import org.apache.framework.logger.AbstractLoggable; import org.apache.avalon.pool.Pool; import org.apache.avalon.pool.ObjectFactory; import org.apache.avalon.pool.Recyclable; import org.apache.avalon.aut.Lock; import org.apache.avalon.aut.LockException; /** * This is a implementation of <code>Pool</code> for SitemapComponents * that is thread safe. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> * @author <a href="mailto:[EMAIL PROTECTED]">Giacomo Pati</a> */ public class DefaultComponentPool extends AbstractLoggable implements Pool, Initializable, Disposable, Runnable, ThreadSafe { public final static int DEFAULT_POOL_SIZE = 8; /** The resources that are currently free */ protected List availableResources = new ArrayList(); /** Resources that have been allocated out of the pool */ protected List usedResources = new ArrayList(); private boolean initialized = false; private boolean disposed = false; private Lock lock = new Lock(); private Thread initializationThread; protected ObjectFactory factory = null; protected int initial = DEFAULT_POOL_SIZE/2; protected int maximum = DEFAULT_POOL_SIZE; public DefaultComponentPool(final ObjectFactory factory) throws Exception { init(factory, DEFAULT_POOL_SIZE/2, DEFAULT_POOL_SIZE); } public DefaultComponentPool(final ObjectFactory factory, final int initial) throws Exception { init(factory, initial, initial); } public DefaultComponentPool(final ObjectFactory factory, final int initial, final int maximum) throws Exception { init(factory, initial, maximum); } private void init(final ObjectFactory factory, final int initial, final int maximum) throws Exception { this.factory = factory; this.initial = initial; this.maximum = maximum; } public void init() throws Exception { this.initializationThread = new Thread(this); this.initializationThread.start(); } public void run() { this.lock.lock(this.availableResources); for( int i = 0; i < this.initial; i++ ) { try { this.availableResources.add(this.factory.newInstance()); } catch (Exception e) { getLogger().warn("Could not create poolable resource", e); } } if (this.availableResources.size() > 0) { this.initialized = true; } this.lock.unlock(this.availableResources); } public void dispose() { this.lock.lock(this.availableResources); this.disposed = true; while ( ! this.availableResources.isEmpty() ) { this.availableResources.remove(0); } this.lock.unlock(this.availableResources); } /** * Allocates a resource when the pool is empty. By default, this method * returns null, indicating that the requesting. This * allows a thread pool to expand when necessary, allowing for spikes in * activity. * * @return A new resource */ protected Poolable getOverflowResource() throws Exception { Poolable poolable = (Poolable) this.factory.newInstance(); getLogger().debug("Component Pool - creating Overflow Resource:" + " Resource=" + poolable + " Available=" + availableResources.size() + " Used=" + usedResources.size() ); return poolable; } /** Requests a resource from the pool. * No extra information is associated with the allocated resource. * @return The allocated resource */ public Poolable get() throws Exception { if (! this.initialized) { if (this.initializationThread == null) { throw new IllegalStateException("You cannot get a resource before the pool is initialized"); } else { this.initializationThread.join(); } } if (this.disposed) { throw new IllegalStateException("You cannot get a resource after the pool is disposed"); } this.lock.lock(this.availableResources); // See if there is a resource in the pool already Poolable resource = null; if (this.availableResources.size() > 0) { resource = (Poolable)this.availableResources.remove(0); this.lock.lock(this.usedResources); this.usedResources.add(resource); this.lock.unlock(this.usedResources); } else { resource = this.getOverflowResource(); if (resource != null) { this.lock.lock(this.usedResources); this.usedResources.add(resource); this.lock.unlock(this.usedResources); } } this.lock.unlock(this.availableResources); if (resource == null) { throw new RuntimeException("Could not get the component from the pool"); } return resource; } /** Releases a resource back to the pool of available resources * @param resource The resource to be returned to the pool */ public void put(Poolable resource) { int pos = -1; this.lock.lock(this.usedResources); // Make sure the resource is in the used list pos = usedResources.indexOf(resource); if (resource instanceof Recyclable) { ((Recyclable)resource).recycle(); } // If the resource was in the used list, remove it from the used list and // add it back to the free list if (pos >= 0) { this.usedResources.remove(pos); this.lock.lock(this.availableResources); if (this.availableResources.size() < this.maximum) { // If the available resources are below the maximum add this back. this.availableResources.add(resource); } else { // If the available are above the maximum destroy this resource. try { this.factory.decommission(resource); getLogger().debug("Component Pool - decommissioning Overflow Resource:" + " Resource=" + resource + " Available=" + availableResources.size() + " Used=" + usedResources.size() ); resource = null; } catch (Exception e) { throw new RuntimeException("caught exception decommissioning resource: " + resource); } } this.lock.unlock(this.availableResources); } this.lock.unlock(this.usedResources); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/framework/component/DefaultComponentPoolController.java Index: DefaultComponentPoolController.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.framework.component; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.Configurable; import org.apache.framework.thread.ThreadSafe; import org.apache.avalon.pool.PoolController; /** * This class holds a sitemap component which is not specially marked as having * a spezial behaviour or treatment. * * @author <a href="mailto:[EMAIL PROTECTED]">Giacomo Pati</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:44 $ */ public class DefaultComponentPoolController implements PoolController, ThreadSafe, Component { /** Initial increase/decrease amount */ public final static int DEFAULT_AMOUNT = 8; /** Current increase/decrease amount */ protected int amount = DEFAULT_AMOUNT; /** The last direction to increase/decrease >0 means increase, <0 decrease */ protected int sizing_direction = 0; /** Creates a PoolController */ public DefaultComponentPoolController() { super(); } /** * Called when a Pool reaches it's minimum. * Return the number of elements to increase minimum and maximum by. * @return the element increase */ public int grow() { /* if (sizing_direction < 0 && amount > 1) amount /= 2; sizing_direction = 1; */ return amount; } /** * Called when a pool reaches it's maximum. * Returns the number of elements to decrease mi and max by. * @return the element decrease */ public int shrink() { /* if (sizing_direction > 0 && amount > 1) amount /= 2; sizing_direction = -1; */ return amount; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/framework/component/DefaultRoleInfo.java Index: DefaultRoleInfo.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.framework.component; import java.util.Map; import java.util.Iterator; import java.util.Hashtable; import java.util.Collections; import org.apache.framework.configuration.Configurable; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.ConfigurationException; import org.apache.framework.logger.AbstractLoggable; /** * Default RoleInfo implementation * * @author <a href="mailto:ricardo@apache,org">Ricardo Rocha</a> * @author <a href="mailto:giacomo@apache,org">Giacomo Pati</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:44 $ */ public class DefaultRoleInfo extends AbstractLoggable implements RoleInfo, Configurable { private Map shorthands = new Hashtable(); private Map classNames = new Hashtable(); public String lookup(String shorthandName) { getLogger().debug("looking up role " + shorthandName + ", returning " + (String) this.shorthands.get(shorthandName)); return (String) this.shorthands.get(shorthandName); } public Iterator shorthandNames() { return Collections.unmodifiableMap(this.shorthands).keySet().iterator(); } public String defaultClass(String role) { return (String) this.classNames.get(role); } public void addRole(String name, String shorthand, String defaultClassName) { this.shorthands.put(shorthand, name); if (defaultClassName != null) { this.classNames.put(name, defaultClassName); } } public void configure(Configuration conf) throws ConfigurationException { Configuration[] roles = conf.getChildren("role"); for (int i = 0; i < roles.length; i++) { String name = roles[i].getAttribute("name"); String shorthand = roles[i].getAttribute("shorthand"); String defaultClassName = roles[i].getAttribute("default-class", null); this.addRole(name, shorthand, defaultClassName); getLogger().debug("added Role " + name + " with shorthand " + shorthand + " for " + defaultClassName); } } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/framework/component/RoleInfo.java Index: RoleInfo.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.framework.component; import java.util.Iterator; /** * RoleInfo Interface * * @author <a href="mailto:ricardo@apache,org">Ricardo Rocha</a> * @author <a href="mailto:giacomo@apache,org">Giacomo Pati</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:44 $ */ public interface RoleInfo { /** * Find Role name based on shorthand name */ public String lookup(String shorthandName); /** * Get a list of shorthand names that correspond to a role */ public Iterator shorthandNames(); /** * Get the default classname for a given role */ public String defaultClass(String role); } 1.1 jakarta-avalon/src/java/org/apache/avalon/component/DefaultComponentFactory.java Index: DefaultComponentFactory.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.avalon.component; import org.apache.avalon.util.pool.ObjectFactory; import org.apache.avalon.util.pool.Pool; import org.apache.avalon.configuration.Configuration; import org.apache.avalon.ComponentManager; import org.apache.avalon.configuration.Configurable; import org.apache.avalon.Composer; import org.apache.avalon.ThreadSafe; import org.apache.avalon.Contextualizable; import org.apache.avalon.Context; import org.apache.avalon.Poolable; import org.apache.avalon.Initializable; import org.apache.avalon.Disposable; import org.apache.avalon.Stoppable; import org.apache.avalon.Startable; import org.apache.avalon.AbstractLoggable; import org.apache.avalon.Loggable; /** * Factory for Avalon components. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> * @author <a href="mailto:[EMAIL PROTECTED]">Paul Russell</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:45 $ */ public class DefaultComponentFactory extends AbstractLoggable implements ObjectFactory, ThreadSafe { /** The class which this <code>ComponentFactory</code> * should create. */ private Class componentClass; /** The configuration for this component. */ private Configuration conf; /** The component manager for this component. */ private ComponentManager manager; /** The Context for the component */ private Context context; /** Construct a new component factory for the specified component. * @param componentClass the class to instantiate (must have a default constructor). * @param config the <code>Configuration</code> object to pass to new instances. * @param manager the component manager to pass to <code>Composer</code>s. */ public DefaultComponentFactory(Class componentClass, Configuration config, ComponentManager manager, Context context) { this.componentClass = componentClass; this.conf = config; this.manager = manager; this.context = context; } public Object newInstance() throws Exception { Object comp = componentClass.newInstance(); getLogger().debug("ComponentFactory creating new instance of " + componentClass.getName() + "." ); if ( comp instanceof Loggable) { ((Loggable)comp).setLogger(getLogger()); } if ( comp instanceof Contextualizable ) { ((Contextualizable)comp).contextualize(this.context); } if ( comp instanceof Composer) { ((Composer)comp).compose(this.manager); } if ( comp instanceof Configurable ) { ((Configurable)comp).configure(this.conf); } if ( comp instanceof Initializable ) { ((Initializable)comp).init(); } if ( comp instanceof Startable ) { ((Startable)comp).start(); } return comp; } public final Class getCreatedClass() { return componentClass; } public final void decommission(Object comp) throws Exception { getLogger().debug("ComponentFactory decommissioning instance of " + componentClass.getName() + "." ); if ( comp instanceof Stoppable ) { ((Stoppable)comp).stop(); } if ( comp instanceof Disposable ) { ((Disposable)comp).dispose(); } comp = null; } } 1.1 jakarta-avalon/src/java/org/apache/avalon/component/DefaultComponentHandler.java Index: DefaultComponentHandler.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.avalon.component; import org.apache.avalon.Component; import org.apache.avalon.ComponentManager; import org.apache.avalon.configuration.Configuration; import org.apache.avalon.Context; import org.apache.avalon.Disposable; import org.apache.avalon.Initializable; import org.apache.avalon.AbstractLoggable; import org.apache.avalon.Poolable; import org.apache.avalon.Stoppable; import org.apache.log.Logger; /** * The DefaultComponentHandler to make sure components are initialized * and destroyed correctly. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:45 $ */ class DefaultComponentHandler extends AbstractLoggable implements Initializable, Disposable { /** Indicates that the Handler is holding a <code>ThreadSafe</code> Component */ final static int THREADSAFE = 0; /** Indicates that the Handler is holding a <code>Poolable</code> Component */ final static int POOLABLE = 1; /** Indicates that the Handler is holding a <code>SingleThreaded</code> Component */ final static int SINGLETHREADED = 2; /** The instance of the ComponentFactory that creates and disposes of the Component */ private DefaultComponentFactory factory; /** The pool of components for <code>Poolable</code> Components */ private DefaultComponentPool pool; /** The instance of the Component for <code>ThreadSafe</code> Components */ private Component instance; /** The type of the Component: THREADSAFE, POOLABLE, or SINGLETHREADED */ private final int type; /** State management boolean stating whether the Handler is initialized or not */ private boolean initialized = false; /** State management boolean stating whether the Handler is disposed or not */ private boolean disposed = false; /** * Create a ComponentHandler that takes care of hiding the details of * whether a Component is ThreadSafe, Poolable, or SingleThreaded. * It falls back to SingleThreaded if not specified. */ DefaultComponentHandler(Class componentClass, Configuration config, ComponentManager manager, Context context) throws Exception { this.factory = new DefaultComponentFactory(componentClass, config, manager, context); if (org.apache.avalon.Poolable.class.isAssignableFrom(componentClass)) { this.pool = new DefaultComponentPool(this.factory); this.type = DefaultComponentHandler.POOLABLE; } else if (org.apache.avalon.ThreadSafe.class.isAssignableFrom(componentClass)) { this.type = DefaultComponentHandler.THREADSAFE; } else { this.type = DefaultComponentHandler.SINGLETHREADED; } } /** * Create a ComponentHandler that takes care of hiding the details of * whether a Component is ThreadSafe, Poolable, or SingleThreaded. * It falls back to SingleThreaded if not specified. */ DefaultComponentHandler(Component comp) throws Exception { this.type = DefaultComponentHandler.THREADSAFE; this.instance = comp; } /** * Sets the logger that the ComponentHandler will use. */ public void setLogger(Logger log) { if (this.factory != null) { this.factory.setLogger(log); } if (this.pool != null) { this.pool.setLogger(log); } super.setLogger(log); } /** * Initialize the ComponentHandler. */ public void init() { if (this.initialized) return; switch (this.type) { case DefaultComponentHandler.THREADSAFE: try { if (this.instance == null) { this.instance = (Component)this.factory.newInstance(); } } catch (Exception e) { getLogger().error("Cannot use component: " + this.factory.getCreatedClass().getName(), e); } break; case DefaultComponentHandler.POOLABLE: try { this.pool.init(); } catch (Exception e) { getLogger().error("Cannot use component: " + this.factory.getCreatedClass().getName(), e); } break; default: // Nothing to do for SingleThreaded Components break; } this.initialized = true; } /** * Get a reference of the desired Component */ public Component get() throws Exception { if (! this.initialized) { throw new IllegalStateException("You cannot get a component from an uninitialized holder."); } if (this.disposed) { throw new IllegalStateException("You cannot get a component from a disposed holder"); } Component comp = null; switch (this.type) { case DefaultComponentHandler.THREADSAFE: comp = this.instance; break; case DefaultComponentHandler.POOLABLE: comp = (Component)this.pool.get(); break; default: comp = (Component)this.factory.newInstance(); break; } return comp; } /** * Return a reference of the desired Component */ public void put(Component comp) { if (! this.initialized) { throw new IllegalStateException("You cannot put a component in an uninitialized holder."); } if (this.disposed) { throw new IllegalStateException("You cannot put a component in a disposed holder"); } switch (this.type) { case DefaultComponentHandler.THREADSAFE: // Nothing to do for ThreadSafe Components break; case DefaultComponentHandler.POOLABLE: this.pool.put((Poolable) comp); break; default: try { this.factory.decommission(comp); } catch (Exception e) { getLogger().warn("Error decommissioning component: " + this.factory.getCreatedClass().getName(), e); } break; } } /** * Dispose of the ComponentHandler and any associated Pools and Factories. */ public void dispose() { this.disposed = true; try { switch (this.type) { case DefaultComponentHandler.THREADSAFE: if (this.factory != null) { this.factory.decommission(this.instance); } else { if ( this.instance instanceof Stoppable ) { ((Stoppable) this.instance).stop(); } if ( this.instance instanceof Disposable ) { ((Disposable) this.instance).dispose(); } } this.instance = null; break; case DefaultComponentHandler.POOLABLE: if (this.pool instanceof Disposable) { ((Disposable) this.pool).dispose(); } this.pool = null; break; default: // do nothing here break; } if (this.factory instanceof Disposable) { ((Disposable) this.factory).dispose(); } this.factory = null; } catch (Exception e) { getLogger().warn("Error decommissioning component: " + this.factory.getCreatedClass().getName(), e); } } } 1.1 jakarta-avalon/src/java/org/apache/avalon/component/DefaultComponentManager.java Index: DefaultComponentManager.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.avalon.component; import java.util.HashMap; import java.util.Map; import java.util.Collections; import java.util.Iterator; import java.util.ArrayList; import java.util.List; import org.apache.avalon.ComponentManager; import org.apache.avalon.Component; import org.apache.avalon.ComponentManagerException; import org.apache.avalon.Context; import org.apache.avalon.Contextualizable; import org.apache.avalon.configuration.Configurable; import org.apache.avalon.configuration.Configuration; import org.apache.avalon.Composer; import org.apache.avalon.configuration.ConfigurationException; import org.apache.avalon.configuration.DefaultConfiguration; import org.apache.avalon.Disposable; import org.apache.avalon.Initializable; import org.apache.avalon.AbstractLoggable; /** * Default component manager for Avalon's components. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> * @author <a href="mailto:[EMAIL PROTECTED]">Paul Russell</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:45 $ */ public class DefaultComponentManager extends AbstractLoggable implements ComponentManager, Configurable, Contextualizable, Disposable { /** The application context for components */ private Context context; /** Static component mapping handlers. */ private Map componentMapping; /** Static component handlers. */ private Map componentHandlers; /** RoleInfos. */ private RoleInfo roles; /** Is the Manager disposed or not? */ private boolean disposed = false; /** Construct a new default component manager. */ public DefaultComponentManager() { // Setup the maps. componentHandlers = Collections.synchronizedMap(new HashMap()); componentMapping = Collections.synchronizedMap(new HashMap()); } /** Set up the Component's Context. */ public void contextualize(Context context) { if (this.context == null) { this.context = context; } } /** Properly dispose of the Child handlers. */ public synchronized void dispose() { this.disposed = true; Iterator keys = this.componentHandlers.keySet().iterator(); List keyList = new ArrayList(); while (keys.hasNext()) { Object key = keys.next(); DefaultComponentHandler handler = (DefaultComponentHandler) this.componentHandlers.get(key); handler.dispose(); keyList.add(key); } keys = keyList.iterator(); while (keys.hasNext()) { this.componentHandlers.remove(keys.next()); } keyList.clear(); } /** * Return an instance of a component based on a Role. The Role is usually the Interface's * Fully Qualified Name(FQN)--unless there are multiple Components for the same Role. In that * case, the Role's FQN is appended with "Selector", and we return a ComponentSelector. */ public Component lookup( String role ) throws ComponentManagerException { if (disposed) throw new IllegalStateException("You cannot lookup components on a disposed ComponentManager"); DefaultComponentHandler handler = null; Component component = null; if ( role == null ) { getLogger().error("ComponentManager Attempted to retrieve component with null role."); throw new ComponentManagerException("Attempted to retrieve component with null role."); } handler = (DefaultComponentHandler) this.componentHandlers.get(role); // Retrieve the instance of the requested component if ( handler == null ) { getLogger().debug("Could not find ComponentHandler, attempting to create one for role: " + role); Class componentClass = null; Configuration config = new DefaultConfiguration("", "-"); try { componentClass = this.getClass().getClassLoader().loadClass(roles.defaultClass(role)); handler = new DefaultComponentHandler(componentClass, config, this, this.context); handler.setLogger(getLogger()); handler.init(); } catch (Exception e) { getLogger().error("ComponentManager Could not find component for role: " + role, e); throw new ComponentManagerException("Could not find component for role: " + role, e); } this.componentHandlers.put(role, handler); } try { component = handler.get(); } catch (IllegalStateException ise) { handler.init(); try { component = handler.get(); } catch (Exception ee) { throw new ComponentManagerException("Could not access the Component for you", ee); } } catch (Exception e) { throw new ComponentManagerException("Could not access the Component for you", e); } this.componentMapping.put(component, handler); return component; } /** * Configure the ComponentManager. */ public void configure(Configuration conf) throws ConfigurationException { DefaultRoleInfo role_info = new DefaultRoleInfo(); role_info.setLogger(getLogger()); role_info.configure(conf); roles = role_info; // Set components Configuration[] e = conf.getChildren("component"); for (int i = 0; i < e.length; i++) { String type = e[i].getAttribute("type", ""); String role = e[i].getAttribute("role", ""); String className = e[i].getAttribute("class", ""); if (! "".equals(type)) { role = roles.lookup(type); } if ("".equals(className)) { className = roles.defaultClass(role); } try { getLogger().debug("Adding component (" + role + " = " + className + ")"); this.addComponent(role, this.getClass().getClassLoader().loadClass(className),e[i]); } catch ( Exception ex ) { getLogger().error("Could not load class " + className, ex); throw new ConfigurationException("Could not get class " + className + " for role " + role, ex); } } Iterator r = roles.shorthandNames(); while (r.hasNext()) { Configuration co = conf.getChild((String) r.next(), false); if (co != null) { String role = roles.lookup(co.getName()); String className = co.getAttribute("class", ""); if ("".equals(className)) { className = roles.defaultClass(role); } try { getLogger().debug("Adding component (" + role + " = " + className + ")"); this.addComponent(role, this.getClass().getClassLoader().loadClass(className), co); } catch ( Exception ex ) { getLogger().error("Could not load class " + className, ex); throw new ConfigurationException("Could not get class " + className + " for role " + role, ex); } } } } /** * Release a Component. This implementation makes sure it has a handle on the propper * ComponentHandler, and let's the ComponentHandler take care of the actual work. */ public void release(Component component) { if (component == null) return; DefaultComponentHandler handler = (DefaultComponentHandler) this.componentMapping.get(component); if (handler == null) return; handler.put(component); this.componentMapping.remove(component); } /** 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(String role, Class component, Configuration config) throws ComponentManagerException { try { DefaultComponentHandler handler = new DefaultComponentHandler(component, config, this, this.context); handler.setLogger(getLogger()); this.componentHandlers.put(role, handler); } catch (Exception e) { throw new ComponentManagerException ("Could not set up Component for role: " + role, e); } } /** Add a static instance of a component to the manager. * @param role the role name for the component. * @param instance the instance of the component. */ public void addComponentInstance(String role, Object instance) { try { DefaultComponentHandler handler = new DefaultComponentHandler((Component) instance); handler.setLogger(getLogger()); this.componentHandlers.put(role, handler); } catch (Exception e) { getLogger().warn("Could not set up Component for role: " + role, e); } } } 1.1 jakarta-avalon/src/java/org/apache/avalon/component/DefaultComponentPool.java Index: DefaultComponentPool.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.component; import java.util.List; import java.util.ArrayList; import org.apache.avalon.Poolable; import org.apache.avalon.ThreadSafe; import org.apache.avalon.Initializable; import org.apache.avalon.Disposable; import org.apache.avalon.util.pool.Pool; import org.apache.avalon.util.pool.ObjectFactory; import org.apache.avalon.util.Lock; import org.apache.avalon.util.LockException; import org.apache.avalon.Recyclable; import org.apache.avalon.AbstractLoggable; /** * This is a implementation of <code>Pool</code> for SitemapComponents * that is thread safe. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> * @author <a href="mailto:[EMAIL PROTECTED]">Giacomo Pati</a> */ public class DefaultComponentPool extends AbstractLoggable implements Pool, Initializable, Disposable, Runnable, ThreadSafe { public final static int DEFAULT_POOL_SIZE = 8; /** The resources that are currently free */ protected List availableResources = new ArrayList(); /** Resources that have been allocated out of the pool */ protected List usedResources = new ArrayList(); private boolean initialized = false; private boolean disposed = false; private Lock lock = new Lock(); private Thread initializationThread; protected ObjectFactory factory = null; protected int initial = DEFAULT_POOL_SIZE/2; protected int maximum = DEFAULT_POOL_SIZE; public DefaultComponentPool(final ObjectFactory factory) throws Exception { init(factory, DEFAULT_POOL_SIZE/2, DEFAULT_POOL_SIZE); } public DefaultComponentPool(final ObjectFactory factory, final int initial) throws Exception { init(factory, initial, initial); } public DefaultComponentPool(final ObjectFactory factory, final int initial, final int maximum) throws Exception { init(factory, initial, maximum); } private void init(final ObjectFactory factory, final int initial, final int maximum) throws Exception { this.factory = factory; this.initial = initial; this.maximum = maximum; } public void init() throws Exception { this.initializationThread = new Thread(this); this.initializationThread.start(); } public void run() { this.lock.lock(this.availableResources); for( int i = 0; i < this.initial; i++ ) { try { this.availableResources.add(this.factory.newInstance()); } catch (Exception e) { getLogger().warn("Could not create poolable resource", e); } } if (this.availableResources.size() > 0) { this.initialized = true; } this.lock.unlock(this.availableResources); } public void dispose() { this.lock.lock(this.availableResources); this.disposed = true; while ( ! this.availableResources.isEmpty() ) { this.availableResources.remove(0); } this.lock.unlock(this.availableResources); } /** * Allocates a resource when the pool is empty. By default, this method * returns null, indicating that the requesting. This * allows a thread pool to expand when necessary, allowing for spikes in * activity. * * @return A new resource */ protected Poolable getOverflowResource() throws Exception { Poolable poolable = (Poolable) this.factory.newInstance(); getLogger().debug("Component Pool - creating Overflow Resource:" + " Resource=" + poolable + " Available=" + availableResources.size() + " Used=" + usedResources.size() ); return poolable; } /** Requests a resource from the pool. * No extra information is associated with the allocated resource. * @return The allocated resource */ public Poolable get() throws Exception { if (! this.initialized) { if (this.initializationThread == null) { throw new IllegalStateException("You cannot get a resource before the pool is initialized"); } else { this.initializationThread.join(); } } if (this.disposed) { throw new IllegalStateException("You cannot get a resource after the pool is disposed"); } this.lock.lock(this.availableResources); // See if there is a resource in the pool already Poolable resource = null; if (this.availableResources.size() > 0) { resource = (Poolable)this.availableResources.remove(0); this.lock.lock(this.usedResources); this.usedResources.add(resource); this.lock.unlock(this.usedResources); } else { resource = this.getOverflowResource(); if (resource != null) { this.lock.lock(this.usedResources); this.usedResources.add(resource); this.lock.unlock(this.usedResources); } } this.lock.unlock(this.availableResources); if (resource == null) { throw new RuntimeException("Could not get the component from the pool"); } return resource; } /** Releases a resource back to the pool of available resources * @param resource The resource to be returned to the pool */ public void put(Poolable resource) { int pos = -1; this.lock.lock(this.usedResources); // Make sure the resource is in the used list pos = usedResources.indexOf(resource); if (resource instanceof Recyclable) { ((Recyclable)resource).recycle(); } // If the resource was in the used list, remove it from the used list and // add it back to the free list if (pos >= 0) { this.usedResources.remove(pos); this.lock.lock(this.availableResources); if (this.availableResources.size() < this.maximum) { // If the available resources are below the maximum add this back. this.availableResources.add(resource); } else { // If the available are above the maximum destroy this resource. try { this.factory.decommission(resource); getLogger().debug("Component Pool - decommissioning Overflow Resource:" + " Resource=" + resource + " Available=" + availableResources.size() + " Used=" + usedResources.size() ); resource = null; } catch (Exception e) { throw new RuntimeException("caught exception decommissioning resource: " + resource); } } this.lock.unlock(this.availableResources); } this.lock.unlock(this.usedResources); } } 1.1 jakarta-avalon/src/java/org/apache/avalon/component/DefaultComponentPoolController.java Index: DefaultComponentPoolController.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.avalon.component; import org.apache.avalon.Component; import org.apache.avalon.ComponentManager; import org.apache.avalon.Composer; import org.apache.avalon.configuration.Configuration; import org.apache.avalon.configuration.Configurable; import org.apache.avalon.ThreadSafe; import org.apache.avalon.util.pool.PoolController; /** * This class holds a sitemap component which is not specially marked as having * a spezial behaviour or treatment. * * @author <a href="mailto:[EMAIL PROTECTED]">Giacomo Pati</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:45 $ */ public class DefaultComponentPoolController implements PoolController, ThreadSafe, Component { /** Initial increase/decrease amount */ public final static int DEFAULT_AMOUNT = 8; /** Current increase/decrease amount */ protected int amount = DEFAULT_AMOUNT; /** The last direction to increase/decrease >0 means increase, <0 decrease */ protected int sizing_direction = 0; /** Creates a PoolController */ public DefaultComponentPoolController() { super(); } /** * Called when a Pool reaches it's minimum. * Return the number of elements to increase minimum and maximum by. * @return the element increase */ public int grow() { /* if (sizing_direction < 0 && amount > 1) amount /= 2; sizing_direction = 1; */ return amount; } /** * Called when a pool reaches it's maximum. * Returns the number of elements to decrease mi and max by. * @return the element decrease */ public int shrink() { /* if (sizing_direction > 0 && amount > 1) amount /= 2; sizing_direction = -1; */ return amount; } } 1.1 jakarta-avalon/src/java/org/apache/avalon/component/DefaultComponentSelector.java Index: DefaultComponentSelector.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.avalon.component; import java.util.HashMap; import java.util.Map; import java.util.Collections; import java.util.Iterator; import java.util.ArrayList; import java.util.List; import org.apache.avalon.ComponentManager; import org.apache.avalon.ComponentSelector; import org.apache.avalon.Component; import org.apache.avalon.ComponentManagerException; import org.apache.avalon.Context; import org.apache.avalon.Contextualizable; import org.apache.avalon.configuration.Configurable; import org.apache.avalon.configuration.Configuration; import org.apache.avalon.Composer; import org.apache.avalon.configuration.ConfigurationException; import org.apache.avalon.configuration.DefaultConfiguration; import org.apache.avalon.AbstractLoggable; import org.apache.avalon.Disposable; import org.apache.avalon.ThreadSafe; /** * Default component manager for Avalon's components. * * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a> * @author <a href="mailto:[EMAIL PROTECTED]">Paul Russell</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:45 $ */ public class DefaultComponentSelector extends AbstractLoggable implements Contextualizable, ComponentSelector, Composer, Configurable, ThreadSafe, Disposable { /** The application context for components */ protected Context context; /** The application context for components */ private ComponentManager manager; /** Dynamic component handlers mapping. */ private Map componentMapping; /** Static configuraiton object. */ private Configuration conf = null; /** Static component handlers. */ private Map componentHandlers; /** Flag for if this is disposed or not. */ private boolean disposed = false; /** Shorthand for hints */ private Map hints; /** Construct a new default component manager. */ public DefaultComponentSelector() { // Setup the maps. componentHandlers = Collections.synchronizedMap(new HashMap()); componentMapping = Collections.synchronizedMap(new HashMap()); } /** Provide the application Context. */ public void contextualize(Context context) { if (this.context == null) { this.context = context; } } /** Compose the ComponentSelector so that we know what the parent ComponentManager is. */ public void compose(ComponentManager manager) throws ComponentManagerException { if (this.manager == null) { this.manager = manager; } } /** * Properly dispose of all the ComponentHandlers. */ public synchronized void dispose() { this.disposed = true; Iterator keys = this.componentHandlers.keySet().iterator(); List keyList = new ArrayList(); while (keys.hasNext()) { Object key = keys.next(); DefaultComponentHandler handler = (DefaultComponentHandler) this.componentHandlers.get(key); handler.dispose(); keyList.add(key); } keys = keyList.iterator(); while (keys.hasNext()) { this.componentHandlers.remove(keys.next()); } keyList.clear(); } /** * Return an instance of a component based on a hint. The Composer has already selected the * role, so the only part left it to make sure the Component is handled. */ public Component select( Object hint ) throws ComponentManagerException { if (disposed) throw new IllegalStateException("You cannot select a Component from a disposed ComponentSelector"); DefaultComponentHandler handler = null; Component component = null; if ( hint == null ) { getLogger().error(this.getName() + ": ComponentSelector Attempted to retrieve component with null hint."); throw new ComponentManagerException("Attempted to retrieve component with null hint."); } handler = (DefaultComponentHandler) this.componentHandlers.get(hint); // Retrieve the instance of the requested component if ( handler == null ) { throw new ComponentManagerException(this.getName() + ": ComponentSelector could not find the component for hint: " + hint); } try { component = handler.get(); } catch (Exception e) { throw new ComponentManagerException(this.getName() + ": ComponentSelector could not access the Component for you", e); } if (component == null) { throw new ComponentManagerException(this.getName() + ": ComponentSelector could not find the component for hint: " + hint); } this.componentMapping.put(component, handler); return component; } /** * Default Configuration handler for ComponentSelector. */ public void configure(Configuration conf) throws ConfigurationException { this.conf = conf; getLogger().debug("ComponentSelector setting up with root element: " + conf.getName()); Configuration[] hints = conf.getChildren("hint"); HashMap hintMap = new HashMap(); for (int i = 0; i < hints.length; i++) { hintMap.put(hints[i].getAttribute("short-hand").trim(), hints[i].getAttribute("class").trim()); } this.hints = Collections.unmodifiableMap(hintMap); Iterator shorthand = this.hints.keySet().iterator(); Configuration[] instances = null; while (shorthand.hasNext()) { String type = (String) shorthand.next(); Class clazz = null; try { clazz = this.getClass().getClassLoader().loadClass((String) this.hints.get(type)); } catch (Exception e) { getLogger().error("ComponentSelector The component instance for \"" + type + "\" has an invalid class name.", e); throw new ConfigurationException("The component instance for '" + type + "' has an invalid class name.", e); } instances = conf.getChildren(type); for (int i = 0; i < instances.length; i++) { Object hint = instances[i].getAttribute("name").trim(); try { this.addComponent(hint, clazz, instances[i]); } catch (Exception e) { getLogger().error("ComponentSelector The component instance for \"" + hint + "\" has an invalid class name.", e); throw new ConfigurationException("The component instance for '" + hint + "' has an invalid class name.", e); } } } instances = conf.getChildren("component-instance"); for (int i = 0; i < instances.length; i++) { Object hint = instances[i].getAttribute("name").trim(); String className = (String) instances[i].getAttribute("class").trim(); try { this.addComponent(hint, this.getClass().getClassLoader().loadClass(className), instances[i]); } catch (Exception e) { getLogger().error("ComponentSelector The component instance for \"" + hint + "\" has an invalid class name.", e); throw new ConfigurationException("The component instance for '" + hint + "' has an invalid class name.", e); } } } /** * Release the Component to the propper ComponentHandler. */ public void release(Component component) { if (component == null) return; DefaultComponentHandler handler = (DefaultComponentHandler) this.componentMapping.get(component); if (handler == null) return; handler.put(component); this.componentMapping.remove(component); } /** 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(Object hint, Class component, Configuration config) throws ComponentManagerException { try { DefaultComponentHandler handler = new DefaultComponentHandler(component, config, this.manager, this.context); handler.setLogger(getLogger()); handler.init(); this.componentHandlers.put(hint, handler); getLogger().debug("Adding " + component.getName() + " for " + hint.toString()); } catch (Exception e) { getLogger().error("Could not set up Component for hint: " + hint, e); throw new ComponentManagerException ("Could not set up Component for hint: " + hint, e); } } /** Add a static instance of a component to the manager. * @param hint the hint name for the component. * @param instance the instance of the component. */ public void addComponentInstance(String hint, Object instance) { try { DefaultComponentHandler handler = new DefaultComponentHandler((Component) instance); handler.setLogger(getLogger()); handler.init(); this.componentHandlers.put(hint, handler); getLogger().debug("Adding " + instance.getClass().getName() + " for " + hint.toString()); } catch (Exception e) { getLogger().error("Could not set up Component for hint: " + hint, e); } } private static final String DEFAULT_NAME = "UnnamedSelector"; /** * Return this selector's configuration name or a default name if no such * configuration was provided. This accounts for the case when a static * component instance has been added through * <code>addComponentInstance</code> with no associated configuration */ private String getName() { if (this.conf != null) { return this.conf.getName(); } return DEFAULT_NAME; } } 1.1 jakarta-avalon/src/java/org/apache/avalon/component/DefaultRoleInfo.java Index: DefaultRoleInfo.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.avalon.component; import java.util.Map; import java.util.Iterator; import java.util.Hashtable; import java.util.Collections; import org.apache.avalon.configuration.Configurable; import org.apache.avalon.configuration.Configuration; import org.apache.avalon.AbstractLoggable; import org.apache.avalon.configuration.ConfigurationException; /** * Default RoleInfo implementation * * @author <a href="mailto:ricardo@apache,org">Ricardo Rocha</a> * @author <a href="mailto:giacomo@apache,org">Giacomo Pati</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:45 $ */ public class DefaultRoleInfo extends AbstractLoggable implements RoleInfo, Configurable { private Map shorthands = new Hashtable(); private Map classNames = new Hashtable(); public String lookup(String shorthandName) { getLogger().debug("looking up role " + shorthandName + ", returning " + (String) this.shorthands.get(shorthandName)); return (String) this.shorthands.get(shorthandName); } public Iterator shorthandNames() { return Collections.unmodifiableMap(this.shorthands).keySet().iterator(); } public String defaultClass(String role) { return (String) this.classNames.get(role); } public void addRole(String name, String shorthand, String defaultClassName) { this.shorthands.put(shorthand, name); if (defaultClassName != null) { this.classNames.put(name, defaultClassName); } } public void configure(Configuration conf) throws ConfigurationException { Configuration[] roles = conf.getChildren("role"); for (int i = 0; i < roles.length; i++) { String name = roles[i].getAttribute("name"); String shorthand = roles[i].getAttribute("shorthand"); String defaultClassName = roles[i].getAttribute("default-class", null); this.addRole(name, shorthand, defaultClassName); getLogger().debug("added Role " + name + " with shorthand " + shorthand + " for " + defaultClassName); } } } 1.1 jakarta-avalon/src/java/org/apache/avalon/component/RoleInfo.java Index: RoleInfo.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.avalon.component; import java.util.Iterator; /** * RoleInfo Interface * * @author <a href="mailto:ricardo@apache,org">Ricardo Rocha</a> * @author <a href="mailto:giacomo@apache,org">Giacomo Pati</a> * @version CVS $Revision: 1.1 $ $Date: 2001/04/05 19:40:46 $ */ public interface RoleInfo { /** * Find Role name based on shorthand name */ public String lookup(String shorthandName); /** * Get a list of shorthand names that correspond to a role */ public Iterator shorthandNames(); /** * Get the default classname for a given role */ public String defaultClass(String role); } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]