You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by le...@apache.org on 2002/02/20 07:26:42 UTC
cvs commit: jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component ComponentHandler.java DefaultComponentFactory.java DefaultComponentHandler.java ExcaliburComponentManager.java PoolableComponentHandler.java ThreadSafeComponentHandler.java
leif 02/02/19 22:26:42
Modified: src/java/org/apache/avalon/excalibur/component
ComponentHandler.java DefaultComponentFactory.java
DefaultComponentHandler.java
ExcaliburComponentManager.java
PoolableComponentHandler.java
ThreadSafeComponentHandler.java
Log:
Add patch by Ryan Shaw to fix the problems with the Component
Manager disposing components in the wrong order.
Revision Changes Path
1.5 +77 -3 jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/ComponentHandler.java
Index: ComponentHandler.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/ComponentHandler.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ComponentHandler.java 11 Dec 2001 09:53:27 -0000 1.4
+++ ComponentHandler.java 20 Feb 2002 06:26:42 -0000 1.5
@@ -24,12 +24,15 @@
* of the ComponentHandler that you need.
*
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
- * @version CVS $Revision: 1.4 $ $Date: 2001/12/11 09:53:27 $
+ * @author <a href="mailto:ryan@silveregg.co.jp">Ryan Shaw</a>
+ * @version CVS $Revision: 1.5 $ $Date: 2002/02/20 06:26:42 $
* @since 4.0
*/
public abstract class ComponentHandler extends AbstractLoggable
implements Initializable, Disposable {
+ private int m_references = 0;
+
public static ComponentHandler getComponentHandler(
final Class componentClass,
final Configuration config,
@@ -119,7 +122,78 @@
return new ThreadSafeComponentHandler(componentInstance);
}
- public abstract Component get() throws Exception;
+ /**
+ * Get an instance of the type of component handled by this handler.
+ * <p>
+ * Subclasses should not extend this method but rather the doGet method below otherwise
+ * reference counts will not be supported.
+ * <p>
+ * This method is not final to make the class backwards compatible.
+ *
+ * @return a <code>Component</code>
+ * @exception Exception if an error occurs
+ */
+ public Component get() throws Exception
+ {
+ Component component = doGet();
+
+ m_references++;
+
+ return component;
+ }
+
+ /**
+ * Put back an instance of the type of component handled by this handler.
+ * <p>
+ * Subclasses should not extend this method but rather the doPut method below otherwise
+ * reference counts will not be supported.
+ * <p>
+ * This method is not final to make the class backwards compatible.
+ *
+ * @param component a <code>Component</code>
+ * @exception Exception if an error occurs
+ */
+ public void put(Component component) throws Exception
+ {
+ doPut( component );
+
+ m_references--;
+ }
+
+ /**
+ * Concrete implementation of getting a component.
+ *
+ * @return a <code>Component</code> value
+ * @exception Exception if an error occurs
+ */
+ protected Component doGet() throws Exception
+ {
+ // This method is not abstract to make the class backwards compatible.
+ throw new IllegalStateException("This method must be overridden.");
+ }
+
+ /**
+ * Concrete implementation of putting back a component.
+ *
+ * @param component a <code>Component</code> value
+ * @exception Exception if an error occurs
+ */
+ protected void doPut(Component component) throws Exception
+ {
+ // This method is not abstract to make the class backwards compatible.
+ throw new IllegalStateException("This method must be overridden.");
+ }
- public abstract void put(Component component) throws Exception;
+ /**
+ * Returns <code>true</code> if this component handler can safely be
+ * disposed; i.e. none of the components it is handling are still
+ * being used.
+ *
+ * @return <code>true</code> if this component handler can safely be
+ * disposed; <code>false</code> otherwise
+ */
+ public final boolean canBeDisposed()
+ {
+ return ( m_references == 0 );
+ }
}
1.11 +101 -7 jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/DefaultComponentFactory.java
Index: DefaultComponentFactory.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/DefaultComponentFactory.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- DefaultComponentFactory.java 11 Dec 2001 09:53:27 -0000 1.10
+++ DefaultComponentFactory.java 20 Feb 2002 06:26:42 -0000 1.11
@@ -23,21 +23,31 @@
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.avalon.framework.component.ComponentManager;
+import org.apache.avalon.framework.component.ComponentException;
+import org.apache.avalon.framework.component.Component;
+
import org.apache.avalon.excalibur.pool.ObjectFactory;
import org.apache.avalon.excalibur.logger.LogKitManager;
import org.apache.avalon.excalibur.logger.LogKitManageable;
+import org.apache.avalon.excalibur.collections.BucketMap;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
/**
* 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.10 $ $Date: 2001/12/11 09:53:27 $
+ * @author <a href="mailto:ryan@silveregg.co.jp">Ryan Shaw</a>
+ * @version CVS $Revision: 1.11 $ $Date: 2002/02/20 06:26:42 $
* @since 4.0
*/
public class DefaultComponentFactory
extends AbstractLoggable
- implements ObjectFactory, ThreadSafe
+ implements ObjectFactory, Disposable, ThreadSafe
{
/** The class which this <code>ComponentFactory</code>
* should create.
@@ -68,6 +78,11 @@
*/
private org.apache.avalon.framework.logger.Logger m_logEnabledLogger;
+ /** Components created by this factory, and their associated ComponentManager
+ * proxies, if they are Composables.
+ */
+ private final BucketMap m_components = new BucketMap();
+
/**
* Construct a new component factory for the specified component.
*
@@ -151,12 +166,15 @@
{
((Contextualizable)component).contextualize( m_context );
}
-
+
+ ComponentManager proxy = null;
+
if( component instanceof Composable )
{
- ((Composable)component).compose( m_componentManager );
+ proxy = new ComponentManagerProxy( m_componentManager );
+ ((Composable)component).compose( proxy );
}
-
+
if ( component instanceof RoleManageable )
{
((RoleManageable)component).setRoleManager( m_roles );
@@ -187,7 +205,9 @@
{
((Startable)component).start();
}
-
+
+ m_components.put( component, proxy );
+
return component;
}
@@ -196,6 +216,29 @@
return m_componentClass;
}
+ public final void dispose()
+ {
+ Component[] components = new Component[ m_components.keySet().size() ];
+
+ m_components.keySet().toArray( components );
+
+ for( int i = 0; i < components.length; i++ )
+ {
+ try
+ {
+ decommission( components[i] );
+ }
+ catch ( final Exception e )
+ {
+ if (getLogger().isWarnEnabled())
+ {
+ getLogger().warn( "Error decommissioning component: " +
+ getCreatedClass().getName(), e);
+ }
+ }
+ }
+ }
+
public final void decommission( final Object component )
throws Exception
{
@@ -204,7 +247,7 @@
getLogger().debug( "ComponentFactory decommissioning instance of " +
m_componentClass.getName() + "." );
}
-
+
if( component instanceof Startable )
{
((Startable)component).stop();
@@ -214,6 +257,13 @@
{
((Disposable)component).dispose();
}
+
+ if( component instanceof Composable )
+ {
+ ( (ComponentManagerProxy) m_components.get( component ) ).releaseAll();
+ }
+
+ m_components.remove( component );
}
protected org.apache.avalon.framework.logger.Logger getLogEnabledLogger()
@@ -224,5 +274,49 @@
}
return m_logEnabledLogger;
+ }
+
+ private static class ComponentManagerProxy implements ComponentManager
+ {
+ private final ComponentManager m_realManager;
+ private final Collection m_unreleased = new ArrayList();
+
+ ComponentManagerProxy( ComponentManager manager )
+ {
+ m_realManager = manager;
+ }
+
+ public Component lookup( String role ) throws ComponentException
+ {
+ Component component = m_realManager.lookup( role );
+
+ m_unreleased.add( component );
+
+ return component;
+ }
+
+ public boolean hasComponent( String role )
+ {
+ return m_realManager.hasComponent( role );
+ }
+
+ public void release( Component component )
+ {
+ m_unreleased.remove( component );
+
+ m_realManager.release( component );
+ }
+
+ private void releaseAll()
+ {
+ Component[] unreleased = new Component[ m_unreleased.size() ];
+
+ m_unreleased.toArray( unreleased );
+
+ for( int i = 0; i < unreleased.length; i++ )
+ {
+ release( unreleased[i] );
+ }
+ }
}
}
1.8 +6 -5 jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/DefaultComponentHandler.java
Index: DefaultComponentHandler.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/DefaultComponentHandler.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- DefaultComponentHandler.java 11 Dec 2001 09:53:27 -0000 1.7
+++ DefaultComponentHandler.java 20 Feb 2002 06:26:42 -0000 1.8
@@ -21,7 +21,8 @@
* and destroyed correctly.
*
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
- * @version CVS $Revision: 1.7 $ $Date: 2001/12/11 09:53:27 $
+ * @author <a href="mailto:ryan@silveregg.co.jp">Ryan Shaw</a>
+ * @version CVS $Revision: 1.8 $ $Date: 2002/02/20 06:26:42 $
* @since 4.0
*/
class DefaultComponentHandler
@@ -82,7 +83,7 @@
/**
* Get a reference of the desired Component
*/
- public Component get()
+ protected Component doGet()
throws Exception
{
if( ! m_initialized )
@@ -95,13 +96,13 @@
throw new IllegalStateException( "You cannot get a component from a disposed holder" );
}
- return (Component)m_factory.newInstance();
+ return (Component) m_factory.newInstance();
}
/**
* Return a reference of the desired Component
*/
- public void put( final Component component )
+ protected void doPut( final Component component )
{
if( !m_initialized )
{
@@ -130,7 +131,7 @@
try
{
// do nothing here
-
+
if( m_factory instanceof Disposable )
{
((Disposable)m_factory).dispose();
1.18 +64 -31 jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/ExcaliburComponentManager.java
Index: ExcaliburComponentManager.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/ExcaliburComponentManager.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- ExcaliburComponentManager.java 15 Feb 2002 20:12:10 -0000 1.17
+++ ExcaliburComponentManager.java 20 Feb 2002 06:26:42 -0000 1.18
@@ -35,7 +35,8 @@
*
* @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.17 $ $Date: 2002/02/15 20:12:10 $
+ * @author <a href="mailto:ryan@silveregg.co.jp">Ryan Shaw</a>
+ * @version CVS $Revision: 1.18 $ $Date: 2002/02/20 06:26:42 $
* @since 4.0
*/
public class ExcaliburComponentManager
@@ -183,32 +184,57 @@
{
synchronized( this )
{
- Iterator keys = m_componentHandlers.keySet().iterator();
- final List keyList = new ArrayList();
+ boolean forceDisposal = false;
- while( keys.hasNext() )
+ final List disposed = new ArrayList();
+
+ while ( m_componentHandlers.size() > 0 )
{
- final Object key = keys.next();
- final ComponentHandler handler =
- (ComponentHandler)m_componentHandlers.get( key );
-
- handler.dispose();
-
- keyList.add( key );
- }
-
- keys = keyList.iterator();
-
- while( keys.hasNext() )
- {
- m_componentHandlers.remove( keys.next() );
- }
-
- keyList.clear();
+ for ( Iterator iterator = m_componentHandlers.keySet().iterator();
+ iterator.hasNext(); )
+ {
+ final Object role = iterator.next();
+
+ final ComponentHandler handler =
+ (ComponentHandler) m_componentHandlers.get( role );
+
+ if ( forceDisposal || handler.canBeDisposed() )
+ {
+ if ( forceDisposal && getLogger().isWarnEnabled() )
+ {
+ getLogger().warn
+ ( "disposing of handler for unreleased component"
+ + " (role: " + role + ")" );
+ }
+
+ handler.dispose();
+ disposed.add( role );
+ }
+ }
+
+ if ( disposed.size() > 0 )
+ {
+ removeDisposedHandlers( disposed );
+ }
+ else
+ { // no more disposable handlers!
+ forceDisposal = true;
+ }
+ }
m_disposed = true;
}
}
+
+ private void removeDisposedHandlers( List disposed ) {
+
+ for( Iterator iterator = disposed.iterator(); iterator.hasNext(); )
+ {
+ m_componentHandlers.remove( iterator.next() );
+ }
+
+ disposed.clear();
+ }
/**
* Return an instance of a component based on a Role. The Role is usually the Interface's
@@ -277,12 +303,12 @@
final Configuration configuration = new DefaultConfiguration( "", "-" );
handler =
- ComponentHandler.getComponentHandler( componentClass,
- configuration,
- this,
- m_context,
- m_roles,
- m_logkit);
+ ComponentHandler.getComponentHandler( componentClass,
+ configuration,
+ this,
+ m_context,
+ m_roles,
+ m_logkit);
handler.setLogger( getLogger() );
handler.initialize();
@@ -413,7 +439,7 @@
if (getLogger().isErrorEnabled())
{
getLogger().error( message + className + " for role " + role +
- " on configuration element " + configurations[ i ].getName(), cnfe );
+ " on configuration element " + configurations[ i ].getName(), cnfe );
}
throw new ConfigurationException( message, cnfe );
@@ -425,7 +451,7 @@
if (getLogger().isErrorEnabled())
{
getLogger().error( message + className + " for role " + role +
- " on configuration element " + configurations[ i ].getName(), ce );
+ " on configuration element " + configurations[ i ].getName(), ce );
}
throw new ConfigurationException( message, ce );
@@ -492,8 +518,15 @@
getLogger().debug("Error trying to release component.", e);
}
}
-
- m_componentMapping.remove( component );
+
+ // RBS: I don't think we should be removing component-->handler
+ // mappings here, because if the Component is threadsafe, and
+ // it has had multiple lookups, then the first release will
+ // remove the component from the mapping, and subsequent releases
+ // will never call handler.put(), which is bad for keeping track
+ // of whether components are being used.
+ //
+ // m_componentMapping.remove( component );
}
else if ( null != m_parentManager)
{
1.9 +4 -3 jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/PoolableComponentHandler.java
Index: PoolableComponentHandler.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/PoolableComponentHandler.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- PoolableComponentHandler.java 18 Feb 2002 10:14:44 -0000 1.8
+++ PoolableComponentHandler.java 20 Feb 2002 06:26:42 -0000 1.9
@@ -79,7 +79,8 @@
*
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
- * @version CVS $Revision: 1.8 $ $Date: 2002/02/18 10:14:44 $
+ * @author <a href="mailto:ryan@silveregg.co.jp">Ryan Shaw</a>
+ * @version CVS $Revision: 1.9 $ $Date: 2002/02/20 06:26:42 $
* @since 4.0
*/
public class PoolableComponentHandler extends ComponentHandler {
@@ -157,7 +158,7 @@
/**
* Get a reference of the desired Component
*/
- public Component get()
+ protected Component doGet()
throws Exception
{
if( ! m_initialized )
@@ -178,7 +179,7 @@
/**
* Return a reference of the desired Component
*/
- public void put( final Component component )
+ protected void doPut( final Component component )
{
if( !m_initialized )
{
1.9 +4 -3 jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/ThreadSafeComponentHandler.java
Index: ThreadSafeComponentHandler.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/src/java/org/apache/avalon/excalibur/component/ThreadSafeComponentHandler.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- ThreadSafeComponentHandler.java 11 Dec 2001 09:53:27 -0000 1.8
+++ ThreadSafeComponentHandler.java 20 Feb 2002 06:26:42 -0000 1.9
@@ -21,7 +21,8 @@
* and destroyed correctly.
*
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
- * @version CVS $Revision: 1.8 $ $Date: 2001/12/11 09:53:27 $
+ * @author <a href="mailto:ryan@silveregg.co.jp">Ryan Shaw</a>
+ * @version CVS $Revision: 1.9 $ $Date: 2002/02/20 06:26:42 $
* @since 4.0
*/
public class ThreadSafeComponentHandler extends ComponentHandler {
@@ -102,7 +103,7 @@
/**
* Get a reference of the desired Component
*/
- public final Component get()
+ protected final Component doGet()
throws Exception
{
if( ! m_initialized )
@@ -121,7 +122,7 @@
/**
* Return a reference of the desired Component
*/
- public void put( final Component component )
+ protected void doPut( final Component component )
{
if( !m_initialized )
{
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>