mcconnell    2002/12/16 20:46:05

  Modified:    merlin/src/java/org/apache/avalon/merlin/container
                        Container.java ContainerLoader.java
                        DefaultContainer.java DefaultContainer.xinfo
  Log:
  Completed container based startup and shutdown of contained components.
  
  Revision  Changes    Path
  1.2       +22 -1     
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/Container.java
  
  Index: Container.java
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/Container.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Container.java    12 Dec 2002 00:34:49 -0000      1.1
  +++ Container.java    17 Dec 2002 04:46:04 -0000      1.2
  @@ -70,4 +70,25 @@
   {
       public static final String KEY = Container.class.getName();
       public static final Version VERSION = Version.getVersion( "1.0" );
  +
  +   /**
  +    * Assemble all of the componets in this container and invoke assembly on 
  +    * all subsidiary containers.
  +    * @exception Exception if a assembly error occurs
  +    */
  +    void assemble() throws Exception;
  +
  +   /**
  +    * Startup the components in this container and startup all subsidiary 
  +    * containers.
  +    * @exception Exception if a startup error occurs
  +    */
  +    void startup() throws Exception;
  +
  +   /**
  +    * Shutdown all subsidiary containers and all components in this 
container.
  +    * @exception Exception if a shutdown error occurs
  +    */
  +    void shutdown() throws Exception;
  +
   }
  
  
  
  1.3       +64 -16    
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/ContainerLoader.java
  
  Index: ContainerLoader.java
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/ContainerLoader.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ContainerLoader.java      16 Dec 2002 01:09:47 -0000      1.2
  +++ ContainerLoader.java      17 Dec 2002 04:46:04 -0000      1.3
  @@ -55,6 +55,8 @@
   import java.io.FileInputStream;
   import java.io.InputStream;
   import java.net.URL;
  +import java.util.Map;
  +import java.util.Hashtable;
   import java.util.ArrayList;
   import java.util.Enumeration;
   import java.util.jar.JarFile;
  @@ -95,6 +97,7 @@
   import org.apache.avalon.assembly.engine.model.LibraryDescriptor;
   import org.apache.avalon.assembly.engine.model.ClasspathDescriptor;
   import org.apache.avalon.assembly.util.ExceptionHelper;
  +import org.apache.excalibur.configuration.ConfigurationUtil;
   
   /**
    * An abstract utility class that provides support for  
  @@ -127,7 +130,7 @@
         EngineClassLoader engine, String name, File home, Configuration 
config, Logger logger )
         throws Exception
       {
  -        return createContainer( engine, name, home, config, logger, false );
  +        return createContainer( engine, name, home, config, logger, null );
       }
   
      /**
  @@ -138,12 +141,13 @@
       *    will be resolved
       * @param config the container configuration
       * @param logger the logging channel to assign to the container
  +    * @param partition if null, this is a root container of a block in which 
case 
  +    *   the block's engine, logging channel, and name are applied to the 
container
       */
       protected Appliance createContainer( 
  -      EngineClassLoader engine, String name, File home, Configuration 
config, Logger logger, boolean flag )
  +      EngineClassLoader engine, String name, File home, Configuration 
config, Logger logger, String partition )
         throws Exception
       {
  -
           String classname = config.getAttribute( "class", 
DefaultContainer.class.getName() );
           Type type = engine.getRepository().getTypeManager().getType( 
classname );
           ContainerDescriptor descriptor = CREATOR.createContainerDescriptor( 
type, config, name );
  @@ -152,46 +156,90 @@
           for( int i=0; i<components.length; i++ )
           {
               Profile profile = createProfile( name, engine, components[i] );
  +            engine.getRepository().getProfileManager().addProfile( profile );
               descriptor.addComponent( profile );
  -            Appliance appliance = engine.createAppliance( 
  -              new ApplianceContext( profile ), true );
           }
   
  +        ArrayList list = new ArrayList();
           Configuration[] containers = config.getChildren( "container" );
           for( int i=0; i<containers.length; i++ )
           {
  -            Configuration childConfig = containers[i];
  -
               // 
               // create a classloader that will be supplied to the 
               // container (including resolution of the container level 
classpath
  -            // and extension path additions)
  +            // and extension path additions), logger, and container name
               //
   
  +            Configuration childConfig = containers[i];
               Configuration engineConfig = childConfig.getChild( "engine" );
               String childName;
               Logger childLogger;
               EngineClassLoader childEngine;
  -            if( flag )
  +            String childPartition;
  +
  +            if( partition == null )
               {
                   childName = name;
                   childLogger = logger;
                   childEngine = engine;
  +                childPartition = name;
               }
               else
               {
                   childName = childConfig.getAttribute( "name", "untitled" );
                   childLogger = logger.getChildLogger( childName );
                   childEngine = childEngine = createChildEngine( engine, home, 
childConfig, childLogger );
  +                childPartition = partition + "/" + name;
               }
   
  -            Appliance container = createContainer( childEngine, childName, 
home, childConfig, childLogger );
  -            ContainerDescriptor containerDescriptor = (ContainerDescriptor) 
container.getProfile();
  -            descriptor.addContainer( containerDescriptor );
  -            Appliance appliance = engine.createAppliance( 
  -              new ApplianceContext( containerDescriptor ), true );
  +            //
  +            // recursively call this method to create the subsidiary 
containers
  +            //
  +
  +            Appliance container = 
  +              createContainer( 
  +                childEngine, childName, home, childConfig, childLogger, 
childPartition );
  +            list.add( container );
  +        }
  +
  +        //
  +        // create the appliance context for the container
  +        //
  +
  +        Map map = new Hashtable();
  +        map.put("urn:assembly:engine.classloader", engine );
  +        map.put("urn:merlin:container.containers", list );
  +        map.put("urn:merlin:container.descriptor", descriptor );
  +        if( partition != null )
  +        {
  +            map.put("urn:merlin:container.partition", partition );
  +        }
  +        else
  +        {
  +            map.put("urn:merlin:container.partition", "" );
  +        }
  +        ApplianceContext context = new ApplianceContext( descriptor );
  +        context.setDeploymentContext( map );
  +
  +        if( partition != null )
  +        {
  +            context.setPartitionName( partition );
  +        }
  +
  +        //
  +        // create the containement appliance
  +        //
  +
  +        try
  +        {
  +            return engine.createAppliance( context, false );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              "Unable to create containment appliance: " + name;
  +            throw new ContainerException( error, e );
           }
  -        return engine.createAppliance( new ApplianceContext( descriptor ), 
false );
       }
   
       protected Profile createProfile( String name, EngineClassLoader engine, 
Configuration config )
  
  
  
  1.2       +342 -4    
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/DefaultContainer.java
  
  Index: DefaultContainer.java
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/DefaultContainer.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultContainer.java     12 Dec 2002 00:34:49 -0000      1.1
  +++ DefaultContainer.java     17 Dec 2002 04:46:04 -0000      1.2
  @@ -55,12 +55,24 @@
   
   package org.apache.avalon.merlin.container;
   
  +import java.util.List;
  +import java.util.Iterator;
  +import java.util.ArrayList;
  +import java.util.Map;
  +import java.util.Hashtable;
  +
  +import org.apache.avalon.assembly.engine.EngineClassLoader;
  +import org.apache.avalon.assembly.appliance.Appliance;
  +import org.apache.avalon.assembly.appliance.ApplianceContext;
  +import org.apache.avalon.assembly.appliance.ApplianceException;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.avalon.framework.context.Context;
   import org.apache.avalon.framework.context.Contextualizable;
   import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.framework.activity.Disposable;
   import org.apache.avalon.framework.activity.Initializable;
  -import org.apache.avalon.assembly.engine.EngineClassLoader;
  +import org.apache.avalon.merlin.container.ContainerDescriptor;
  +import org.apache.avalon.meta.model.Profile;
   
   /**
    * <p>A container is node in a containment heirachy. It defines a scope 
  @@ -71,7 +83,8 @@
    * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
    * @version $Revision$ $Date$
    */
  -public class DefaultContainer extends AbstractLogEnabled implements 
Container, Contextualizable, Initializable
  +public class DefaultContainer extends AbstractLogEnabled 
  +  implements Container, Contextualizable, Initializable, Disposable
   {
       //==============================================================
       // state
  @@ -79,6 +92,40 @@
   
       private EngineClassLoader m_engine;
   
  +    private ContainerDescriptor m_descriptor;
  +
  +   /**
  +    * List of the appliance instances that the container is 
  +    * holding.  Each appliance instance is a contained component.
  +    */
  +    private List m_components = new ArrayList();
  +
  +   /**
  +    * List of the containment appliance instances that the container is 
  +    * holding.  Each appliance instance is a subsidiary container.
  +    */
  +    private List m_containers;
  +
  +   /**
  +    * Map of container objects keyed by containment appliance.
  +    */
  +    private Map m_containerMap = new Hashtable();
  +
  +   /**
  +    * Map of components keyed by appliance.
  +    */
  +    private Map m_componentMap = new Hashtable();
  +
  +   /**
  +    * Container partition name.
  +    */
  +    private String m_partition;
  +
  +   /**
  +    * Container path name.
  +    */
  +    private String m_path;
  +
       //==============================================================
       // Contextualizable
       //==============================================================
  @@ -92,6 +139,9 @@
       public void contextualize( Context context ) throws ContextException
       {
           m_engine = (EngineClassLoader) context.get( 
"urn:assembly:engine.classloader" );
  +        m_containers = (List) context.get( "urn:merlin:container.containers" 
);
  +        m_descriptor = (ContainerDescriptor) context.get( 
"urn:merlin:container.descriptor" );
  +        m_partition = (String) context.get( "urn:merlin:container.partition" 
);
       }
   
       //==============================================================
  @@ -100,7 +150,295 @@
   
       public void initialize() throws Exception
       {
  -        getLogger().debug( "initialization" );
  +        if( getLogger() == null )
  +        {
  +            throw new IllegalStateException("logger");
  +        }
  +        if( m_engine == null )
  +        {
  +            throw new IllegalStateException("context");
  +        }
  +
  +        if( m_partition != null )
  +        {
  +            m_path = m_partition + "/" + m_descriptor.getName();
  +        }
  +        else
  +        {
  +            m_path = "/" + m_descriptor.getName();
  +        }
  +
  +        if( getLogger().isDebugEnabled() )
  +        {
  +            getLogger().debug( "initialization: " + m_path );
  +        }
  +
  +        Profile[] profiles = m_descriptor.getComponents();
  +        for( int i=0; i<profiles.length; i++ )
  +        {
  +            Profile profile = profiles[i];
  +            getLogger().debug( "creating appliance: " + profile );
  +            ApplianceContext context = new ApplianceContext( profile );
  +            context.setPartitionName( m_path );
  +            Appliance appliance = createAppliance( context, true );
  +            m_components.add( appliance );
  +        }
  +
  +        Iterator iterator = m_containers.iterator();
  +        while( iterator.hasNext() )
  +        {
  +            Appliance appliance = (Appliance) iterator.next();
  +
  +            if( getLogger().isDebugEnabled() )
  +            {
  +                final String message =
  +                  "activating container: [" + 
appliance.getProfile().getName() + "]"; 
  +                getLogger().debug( message );
  +            }
  +
  +            try
  +            {
  +                Container container = (Container) appliance.access();
  +                m_containerMap.put( appliance, container );
  +            }
  +            catch( Throwable e )
  +            {
  +                final String error =
  +                  "Could not establish a sub-container: " 
  +                     + appliance.getProfile().getName() 
  +                     + " in container: " + this;
  +                throw new ContainerException( error, e );
  +            }
  +        }
  +    }
  +
  +   /**
  +    * Interception point in the component deployment process where 
specilization of 
  +    * this class can modify the criteria supplied under the appliance 
context.  The
  +    * default implementation invokes appliance creation on the service 
management 
  +    * engine and returns the non-assembled appliance result.
  +    *
  +    * @param context the appliance context
  +    * @param shared boolean value indicating if the appliance is to be shared
  +    *   (i.e. available to other components as a depedency solution 
condidate)
  +    * @return the new appliance
  +    * @exception ApplianceException if an appliance creation error occurs
  +    */
  +    protected Appliance createAppliance( ApplianceContext context, boolean 
shared )
  +       throws ApplianceException
  +    {
  +        return m_engine.createAppliance( context, shared );
  +    }
  +
  +   /**
  +    * Assemble all of the componets in this container and invoke assembly on 
  +    * all subsidiary containers.
  +    * @exception Exception if a assembly error occurs
  +    */
  +    public void assemble() throws Exception
  +    {
  +        if( getLogger().isDebugEnabled() )
  +        {
  +            getLogger().debug( "assembly" );
  +        }
  +        assembleComponents();
  +        assembleContainers();
  +    }
  +
  +   /**
  +    * Startup the components in this container.
  +    * @exception Exception if a startup error occurs
  +    */
  +    protected void assembleComponents() throws Exception
  +    {
  +        Iterator iterator = m_components.iterator();
  +        while( iterator.hasNext() )
  +        {
  +            Appliance appliance = (Appliance) iterator.next();
  +            m_engine.assemble( appliance );
  +        }
       }
   
  +   /**
  +    * Invoke assembly on the nested containers in this container.
  +    * @exception Exception if an assembly error occurs
  +    */
  +    protected void assembleContainers() throws Exception
  +    {
  +        Iterator iterator = m_containers.iterator();
  +        while( iterator.hasNext() )
  +        {
  +            Appliance appliance = (Appliance) iterator.next();
  +            Container container = (Container) m_containerMap.get( appliance 
);
  +            container.assemble();
  +        }
  +    }
  +
  +   /**
  +    * Startup the components in this container and startup all subsidiary 
  +    * containers.
  +    * @exception Exception if a startup error occurs
  +    */
  +    public void startup() throws Exception
  +    {
  +        if( getLogger().isDebugEnabled() )
  +        {
  +            getLogger().debug( "startup" );
  +        }
  +        startupComponents();
  +        startupContainers();
  +    }
  +
  +   /**
  +    * Startup the components in this container.
  +    * @exception Exception if a startup error occurs
  +    */
  +    protected void startupComponents() throws Exception
  +    {
  +        Iterator iterator = m_components.iterator();
  +        while( iterator.hasNext() )
  +        {
  +            Appliance appliance = (Appliance) iterator.next();
  +
  +            if( getLogger().isDebugEnabled() )
  +            {
  +                final String message =
  +                  "activating component: [" + 
appliance.getProfile().getName() + "]"; 
  +                getLogger().debug( message );
  +            }
  +
  +            try
  +            {
  +                Object object = appliance.access();
  +                m_componentMap.put( appliance, object );
  +            }
  +            catch( Throwable e )
  +            {
  +                final String error =
  +                  "Could not establish a component: " 
  +                     + appliance.getProfile().getName() 
  +                     + " in container: " + this;
  +                throw new ContainerException( error, e );
  +            }
  +        }
  +    }
  +
  +   /**
  +    * Startup the containers in this container.
  +    * @exception Exception if a startup error occurs
  +    */
  +    protected void startupContainers() throws Exception
  +    {
  +        Iterator iterator = m_containers.iterator();
  +        while( iterator.hasNext() )
  +        {
  +            Appliance appliance = (Appliance) iterator.next();
  +            Container container = (Container) m_containerMap.get( appliance 
);
  +            try
  +            {
  +                container.startup();
  +            }
  +            catch( Throwable e )
  +            {
  +                final String error =
  +                  "Could not start a subsidiary container: " 
  +                     + appliance.getProfile().getName() 
  +                     + " in container: " + this;
  +                throw new ContainerException( error, e );
  +            }
  +        }
  +    }
  +
  +   /**
  +    * Shutdown all subsidiary containers and all components in this 
container.
  +    * @exception Exception if a shutdown error occurs
  +    */
  +    public void shutdown() throws Exception
  +    {
  +        if( getLogger().isDebugEnabled() )
  +        {
  +            getLogger().debug( "shutdown" );
  +        }
  +        shutdownContainers();
  +        shutdownComponents();
  +    }
  +
  +   /**
  +    * Shutdown all subsidiary containers and all components in this 
container.
  +    * @exception Exception if a shutdown error occurs
  +    */
  +    protected void shutdownComponents() throws Exception
  +    {
  +        Iterator iterator = m_components.iterator();
  +        while( iterator.hasNext() )
  +        {
  +            Appliance appliance = (Appliance) iterator.next();
  +            Object object = m_componentMap.get( appliance );
  +            if( object != null )
  +            {
  +                if( getLogger().isDebugEnabled() )
  +                {
  +                    final String message =
  +                      "stopping: " + appliance;
  +                    getLogger().debug( message );
  +                }
  +
  +                m_componentMap.remove( appliance );
  +                appliance.release( object );
  +                appliance.terminate();
  +            }
  +        }
  +    }
  +
  +   /**
  +    * Shutdown the containers in this container.
  +    * @exception Exception if a startup error occurs
  +    */
  +    protected void shutdownContainers() throws Exception
  +    {
  +        Iterator iterator = m_containers.iterator();
  +        while( iterator.hasNext() )
  +        {
  +            Appliance appliance = (Appliance) iterator.next();
  +            Container container = (Container) m_containerMap.get( appliance 
);
  +            try
  +            {
  +                container.shutdown();
  +                m_containerMap.remove( appliance );
  +                appliance.release( container );
  +                appliance.terminate();
  +            }
  +            catch( Throwable e )
  +            {
  +                final String error =
  +                  "Could not shutdown a subsidiary container: " 
  +                     + appliance.getProfile().getName() 
  +                     + " in container: " + this;
  +                throw new ContainerException( error, e );
  +            }
  +        }
  +    }
  +
  +   /**
  +    * Disposal of the container.
  +    */
  +    public void dispose()
  +    {
  +        if( getLogger().isDebugEnabled() )
  +        {
  +            getLogger().debug( "disposal" );
  +        }
  +        m_engine = null;
  +        m_descriptor = null;
  +        m_componentMap.clear();
  +        m_components.clear();
  +        m_componentMap = null;
  +        m_components = null;
  +        m_containerMap.clear();
  +        m_containers.clear();
  +        m_containerMap = null;
  +        m_containers = null;
  +        m_partition = null;
  +        m_path = null;
  +    }
   }
  
  
  
  1.2       +5 -0      
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/DefaultContainer.xinfo
  
  Index: DefaultContainer.xinfo
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/DefaultContainer.xinfo,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultContainer.xinfo    12 Dec 2002 00:34:49 -0000      1.1
  +++ DefaultContainer.xinfo    17 Dec 2002 04:46:04 -0000      1.2
  @@ -23,6 +23,11 @@
     <context>
       <entry key="urn:assembly:engine.classloader"
         type="org.apache.avalon.assembly.engine.EngineClassLoader"/>
  +    <entry key="urn:merlin:container.containers"
  +      type="java.util.List"/>
  +    <entry key="urn:merlin:container.descriptor"
  +      type="org.apache.avalon.merlin.container.ContainerDescriptor"/>
  +    <entry key="urn:merlin:container.partition"/>
     </context>
   
   </type>
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to