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>