You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by bl...@apache.org on 2001/04/05 21:40:46 UTC
cvs commit: jakarta-avalon/src/java/org/apache/avalon/component DefaultComponentFactory.java DefaultComponentHandler.java DefaultComponentManager.java DefaultComponentPool.java DefaultComponentPoolController.java DefaultComponentSelector.java DefaultRoleInfo.java RoleInfo.java
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:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
* @author <a href="mailto:donaldp@apache.org">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:bloritsch@apache.org">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:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
* @author <a href="mailto:donaldp@apache.org">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:bloritsch@apache.org">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:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:paul@luminas.co.uk">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:bloritsch@apache.org">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:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:Giacomo.Pati@pwr.ch">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:Giacomo.Pati@pwr.ch">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:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:paul@luminas.co.uk">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:bloritsch@apache.org">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:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:paul@luminas.co.uk">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:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:Giacomo.Pati@pwr.ch">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:Giacomo.Pati@pwr.ch">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:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:paul@luminas.co.uk">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: avalon-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: avalon-dev-help@jakarta.apache.org