avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject cvs commit: avalon-excalibur/fortress/container-impl/src/java/org/apache/avalon/fortress/impl/handler ComponentFactory.java
Date Fri, 02 Apr 2004 10:29:03 GMT
cziegeler    2004/04/02 02:29:03

  Modified:    fortress/container-impl/src/java/org/apache/avalon/fortress/impl/handler
                        ComponentFactory.java
  Log:
  Add dynamic creation/instantiation of objects (currently turned off)
  
  Revision  Changes    Path
  1.29      +294 -21   avalon-excalibur/fortress/container-impl/src/java/org/apache/avalon/fortress/impl/handler/ComponentFactory.java
  
  Index: ComponentFactory.java
  ===================================================================
  RCS file: /home/cvs/avalon-excalibur/fortress/container-impl/src/java/org/apache/avalon/fortress/impl/handler/ComponentFactory.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- ComponentFactory.java	28 Feb 2004 15:16:25 -0000	1.28
  +++ ComponentFactory.java	2 Apr 2004 10:29:03 -0000	1.29
  @@ -17,22 +17,31 @@
   
   package org.apache.avalon.fortress.impl.handler;
   
  +import java.lang.reflect.Constructor;
  +import java.lang.reflect.Method;
  +
   import org.apache.avalon.excalibur.logger.LoggerManager;
   import org.apache.avalon.fortress.util.LifecycleExtensionManager;
   import org.apache.avalon.framework.CascadingException;
   import org.apache.avalon.framework.component.Composable;
   import org.apache.avalon.framework.component.WrapperComponentManager;
  +import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.container.ContainerUtil;
   import org.apache.avalon.framework.context.Context;
   import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.framework.context.Contextualizable;
   import org.apache.avalon.framework.context.DefaultContext;
  +import org.apache.avalon.framework.logger.LogEnabled;
   import org.apache.avalon.framework.logger.LogKit2AvalonLoggerAdapter;
   import org.apache.avalon.framework.logger.Loggable;
   import org.apache.avalon.framework.logger.Logger;
   import org.apache.avalon.framework.parameters.Parameterizable;
   import org.apache.avalon.framework.parameters.Parameters;
   import org.apache.avalon.framework.service.ServiceManager;
  +import org.apache.avalon.framework.service.Serviceable;
  +import org.apache.commons.beanutils.BeanUtils;
  +import org.apache.commons.beanutils.MethodUtils;
   import org.apache.excalibur.instrument.AbstractLogEnabledInstrumentable;
   import org.apache.excalibur.instrument.CounterInstrument;
   import org.apache.excalibur.mpool.ObjectFactory;
  @@ -81,6 +90,14 @@
       private final Logger m_componentLogger;
   
       /**
  +     * The class info for creating the component
  +     */
  +    private ClassInfo m_classinfo;
  +    
  +    /** Use the dynamic configuration */
  +    private boolean m_useDynamicCreation = false;
  +    
  +    /**
        * Construct a new component factory for the specified component.
        *
        * @param componentClass the class to instantiate (must have a default constructor).
  @@ -126,6 +143,7 @@
   
           addInstrument( m_newInstance );
           addInstrument( m_dispose );
  +        
       }
   
       /**
  @@ -143,7 +161,7 @@
   
           try
           {
  -            component = m_componentClass.newInstance();
  +            component = this.createComponent();
   
               if ( getLogger().isDebugEnabled() )
               {
  @@ -153,27 +171,13 @@
                   getLogger().debug( message );
               }
   
  -            ContainerUtil.enableLogging( component, m_componentLogger );
  -
  -            if ( component instanceof Loggable )
  -            {
  -                final org.apache.log.Logger logkitLogger =
  -                    LogKit2AvalonLoggerAdapter.createLogger( m_componentLogger );
  -                ( (Loggable) component ).setLogger( logkitLogger );
  -            }
  +            this.enabledComponentLogging(component);
   
  -            ContainerUtil.contextualize( component, m_context );
  -            if ( component instanceof Composable )
  -            {
  -                ContainerUtil.compose( component, new WrapperComponentManager( m_serviceManager
) );
  -            }
  -            ContainerUtil.service( component, m_serviceManager );
  -            ContainerUtil.configure( component, m_configuration );
  +            this.contextualizeComponent(component);
   
  -            if ( component instanceof Parameterizable )
  -            {
  -                ContainerUtil.parameterize( component, Parameters.fromConfiguration( m_configuration
) );
  -            }
  +            this.serviceComponent(component);
  +            
  +            this.configureComponent(component);
   
               m_extManager.executeCreationExtensions( component, m_context );
   
  @@ -260,6 +264,275 @@
               final String message = "The object given to be disposed does " +
                   "not come from this ObjectFactory";
               throw new IllegalArgumentException( message );
  +        }
  +    }
  +    
  +    /**
  +     * Create a new component
  +     */
  +    protected Object createComponent() throws Exception
  +    {
  +        if ( !m_useDynamicCreation ) 
  +        {
  +            return m_componentClass.newInstance();
  +        }
  +        
  +        if ( m_classinfo == null )
  +        {
  +            m_classinfo = new ClassInfo();            
  +        }
  +        
  +        return m_classinfo.m_constructor.newInstance(m_classinfo.m_constructorArguments);
  +    }
  +
  +    /**
  +     * Enable logging for the component
  +     */
  +    protected void enabledComponentLogging(Object component) throws Exception 
  +    {
  +        ContainerUtil.enableLogging( component, m_componentLogger );
  +
  +        if ( component instanceof Loggable )
  +        {
  +            final org.apache.log.Logger logkitLogger =
  +                LogKit2AvalonLoggerAdapter.createLogger( m_componentLogger );
  +            ( (Loggable) component ).setLogger( logkitLogger );
  +        }
  +
  +        if ( m_useDynamicCreation ) 
  +        {
  +
  +            if ( m_classinfo.m_setLoggerMethod != null ) {
  +                m_classinfo.m_setLoggerMethod.invoke( component, new Object[] {m_componentLogger});
  +            }
  +        }
  +    }
  +    
  +    /**
  +     * Contextualize the component
  +     */
  +    protected void contextualizeComponent(Object component) throws Exception 
  +    {
  +        ContainerUtil.contextualize( component, m_context );
  +        if ( !(component instanceof Contextualizable ) ) 
  +        {
  +            try 
  +            {
  +                MethodUtils.invokeMethod(component, "setContext", m_context);
  +            }
  +            catch (Exception ignore) {}
  +        }
  +
  +        if ( m_useDynamicCreation ) 
  +        {
  +            if ( m_classinfo.m_setContextMethod != null ) {
  +                m_classinfo.m_setContextMethod.invoke( component, new Object[] {m_context});
  +            }
  +        }
  +    }
  +    
  +    /**
  +     * Service the component
  +     */
  +    protected void serviceComponent(Object component) throws Exception
  +    {
  +        if ( component instanceof Composable )
  +        {
  +            ContainerUtil.compose( component, new WrapperComponentManager( m_serviceManager
) );
  +        }                
  +        ContainerUtil.service( component, m_serviceManager );
  +
  +        if ( m_useDynamicCreation ) 
  +        {
  +            if ( m_classinfo.m_setServiceManagerMethod != null ) {
  +                m_classinfo.m_setServiceManagerMethod.invoke( component, new Object[] {m_serviceManager});
  +            }
  +        }
  +    }
  +    
  +    /**
  +     * Configure the component
  +     */
  +    protected void configureComponent(Object component) throws Exception
  +    {
  +        ContainerUtil.configure( component, m_configuration );
  +
  +        if ( component instanceof Parameterizable )
  +        {
  +            ContainerUtil.parameterize( component, Parameters.fromConfiguration( m_configuration
) );
  +        }        
  +
  +        if ( m_useDynamicCreation ) 
  +        {
  +            if ( m_classinfo.m_setParametersMethod!= null ) {
  +                m_classinfo.m_setParametersMethod.invoke( component, new Object[] {Parameters.fromConfiguration(
m_configuration )});
  +            }
  +            if ( m_classinfo.m_setConfigurationMethod != null ) {
  +                m_classinfo.m_setConfigurationMethod.invoke( component, new Object[] {m_configuration});
  +            }
  +    
  +            // if the component has a configuration, but does not implement the
  +            // interfaces, try to set the parameters using reflection
  +            if ( m_classinfo.m_dynamicConfiguration ) 
  +            {
  +                if ( m_configuration != null && m_configuration.getChildren().length
> 0) 
  +                {
  +                    final Parameters p = Parameters.fromConfiguration( m_configuration
);
  +                    String[] names = p.getNames();
  +                    for( int i = 0; i < names.length; i++ ) 
  +                    {
  +                        try 
  +                        {
  +                            BeanUtils.setProperty( component, names[i], p.getParameter(names[i]));
  +                        } 
  +                        catch (Exception ignore)                    
  +                        {
  +                            if ( this.getLogger() != null && this.getLogger().isWarnEnabled()
) 
  +                            {
  +                                this.getLogger().warn("Error while trying to configure
" + component 
  +                                           + " with parameter: " + names[i], ignore); 
 
  +                            }
  +                        }
  +                    }
  +                }
  +            }
  +        }
  +    }
  +    
  +    /**
  +     * This class collects all information about the components class:
  +     * - the constructor to use
  +     * 
  +     */
  +    protected class ClassInfo {
  +        
  +        public Constructor m_constructor;
  +        public Object[]    m_constructorArguments;
  +        public Method      m_setLoggerMethod;
  +        public Method      m_setConfigurationMethod;
  +        public Method      m_setParametersMethod;
  +        public Method      m_setContextMethod;
  +        public boolean     m_dynamicConfiguration = false;
  +        public Method      m_setServiceManagerMethod;
  +        
  +        /** Constructor */
  +        public ClassInfo() 
  +        throws Exception {
  +            // let's see which constructors are available
  +            Constructor[] constructors = m_componentClass.getConstructors();
  +            
  +            if( constructors.length < 1 ) 
  +            {
  +                throw new Exception("Class " + m_componentClass + " does not have a public
constructor.");
  +            }
  +
  +            if( constructors.length > 1 )
  +            {
  +                // if we have more than one constructor, we first search for
  +                // an empty argument constructor
  +                // if that is not available we simply take the first constructor
  +                // we find
  +                try
  +                {
  +                    m_constructor = m_componentClass.getConstructor( new Class[0] );
  +                }
  +                catch( NoSuchMethodException e )
  +                {
  +                    // we ignore the exception and take the first one
  +                    m_constructor = constructors[0];
  +                }
  +            }
  +            else
  +            {
  +                m_constructor = constructors[0];
  +            }
  +
  +            // now test the parameters for the constructor
  +            final Class[] classes = m_constructor.getParameterTypes();
  +            m_constructorArguments = new Object[ classes.length ];
  +            for( int i=0; i<classes.length; i++ )
  +            {
  +                final Class current = classes[i];
  +                if( Logger.class.isAssignableFrom( current ) )
  +                {
  +                    if ( m_componentLogger == null ) 
  +                    {
  +                        throw new IllegalArgumentException("Logger is null.");
  +                    }
  +                    m_constructorArguments[i] = m_componentLogger;
  +                }
  +                else if( Context.class.isAssignableFrom( current ) )
  +                {
  +                    if ( m_context == null ) 
  +                    {
  +                        throw new IllegalArgumentException("Context is null.");
  +                    }
  +                    m_constructorArguments[i] = m_context;
  +                }
  +                else if( Configuration.class.isAssignableFrom( current ) )
  +                {
  +                    if ( m_configuration == null ) 
  +                    {
  +                        throw new IllegalArgumentException("Configuration is null.");
  +                    }
  +                    m_constructorArguments[i] = m_configuration;
  +                }
  +                else if( Parameters.class.isAssignableFrom( current ) )
  +                {
  +                    if ( m_configuration == null ) 
  +                    {
  +                        throw new IllegalArgumentException("Configuration is null.");
  +                    }
  +                    m_constructorArguments[i] = Parameters.fromConfiguration( m_configuration
);
  +                }
  +                else if( ServiceManager.class.isAssignableFrom( current ) )
  +                {
  +                    m_constructorArguments[i] = m_serviceManager;
  +                }
  +                else
  +                {
  +                    throw new Exception("Unknown parameter type for constructor of component:
" + current);
  +                }
  +            }
  +            
  +            // now test for some setter methods
  +            if ( !Loggable.class.isAssignableFrom( m_componentClass)
  +                    && !LogEnabled.class.isAssignableFrom(m_componentClass)) 
  +            {
  +                m_setLoggerMethod = this.getMethod("setLogger", Logger.class);
  +            }
  +
  +            if ( !Contextualizable.class.isAssignableFrom( m_componentClass)) 
  +            {
  +                m_setContextMethod = this.getMethod("setContext", Context.class);
  +            }
  +
  +            if ( !Parameterizable.class.isAssignableFrom( m_componentClass)
  +                  && !Configurable.class.isAssignableFrom(m_componentClass)) 
  +            {
  +                m_setConfigurationMethod = this.getMethod("setConfiguration", Configuration.class);
  +                m_setParametersMethod = this.getMethod("setParameters", Parameters.class);
  +                if ( m_setConfigurationMethod == null && m_setParametersMethod
== null )
  +                {
  +                    m_dynamicConfiguration = true;
  +                }
  +            }
  +            
  +            if ( !Composable.class.isAssignableFrom(m_componentClass)
  +                 && !Serviceable.class.isAssignableFrom(m_componentClass))
  +            {
  +                m_setServiceManagerMethod = this.getMethod("setServiceManager", ServiceManager.class);
               
  +            }
  +        }
  +        
  +        protected Method getMethod(String name, Class clazz) throws Exception
  +        {
  +            try 
  +            {
  +                return m_componentClass.getMethod(name, new Class[] {clazz});         
  
  +            }
  +            catch (NoSuchMethodException ignore) {}
  +            return null;
           }
       }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe@avalon.apache.org
For additional commands, e-mail: cvs-help@avalon.apache.org


Mime
View raw message