avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mcconn...@apache.org
Subject cvs commit: avalon-sandbox/assembly/src/test/org/apache/avalon/playground ComplexService.java BasicComponent.java BasicComponent.xinfo BasicComponent.xprofile ComplexComponent.java ComplexComponent.xinfo SimpleComponent.xinfo
Date Sat, 07 Dec 2002 09:34:29 GMT
mcconnell    2002/12/07 01:34:29

  Modified:    assembly build.xml default.properties
               assembly/src/etc demo.mf project.mf
               assembly/src/java/org/apache/avalon/assembly/appliance
                        ApplianceManager.java AssemblyService.java
                        DefaultAppliance.java DefaultApplianceManager.java
                        DefaultAssemblyService.java
               assembly/src/java/org/apache/avalon/assembly/engine
                        Engine.java
               assembly/src/java/org/apache/avalon/assembly/lifecycle
                        ContextHandler.java DefaultDeploymentService.java
               assembly/src/java/org/apache/avalon/assembly/lifecycle/initialization
                        ExtendedInitializationService.java
               assembly/src/java/org/apache/avalon/assembly/lifestyle
                        AbstractLifestyleHandler.java
                        DefaultLifestyleService.java
               assembly/src/java/org/apache/avalon/assembly/profile
                        ProfileManager.java
               assembly/src/java/org/apache/avalon/assembly/service
                        ServiceManager.java
               assembly/src/java/org/apache/avalon/assembly/type
                        TypeManager.java
               assembly/src/test/org/apache/avalon/assembly
                        TestCaseBase.java
               assembly/src/test/org/apache/avalon/assembly/engine
                        EngineTestCase.java
               assembly/src/test/org/apache/avalon/assembly/profile
                        ProfileManagerTestCase.java
               assembly/src/test/org/apache/avalon/assembly/service
                        DefaultServiceManagerTestCase.java
               assembly/src/test/org/apache/avalon/assembly/type
                        TypeManagerTestCase.java
               assembly/src/test/org/apache/avalon/playground
                        BasicComponent.java BasicComponent.xinfo
                        BasicComponent.xprofile ComplexComponent.java
                        ComplexComponent.xinfo SimpleComponent.xinfo
  Added:       assembly/src/java/org/apache/avalon/assembly/appliance
                        ApplianceFactory.java DefaultApplianceFactory.java
                        MappedServiceManager.java TestApplianceFactory.java
                        TestApplianceFactory.xinfo
               assembly/src/java/org/apache/avalon/assembly/engine
                        DefaultRepositoryManager.java
                        EngineClassLoader.java RepositoryManager.java
               assembly/src/java/org/apache/avalon/assembly/engine/model
                        ClasspathDescriptor.java
                        EngineConfigurationHelper.java
                        FilesetDescriptor.java IncludeDescriptor.java
                        LibraryDescriptor.java Resources.properties
                        package.html
               assembly/src/test/org/apache/avalon/playground
                        ComplexService.java
  Removed:     assembly/src/java/org/apache/avalon/assembly/engine
                        DefaultEngine.java
               assembly/src/java/org/apache/avalon/assembly/profile
                        DefaultProfileManager.java
               assembly/src/java/org/apache/avalon/assembly/service
                        DefaultServiceManager.java
               assembly/src/java/org/apache/avalon/assembly/type
                        DefaultTypeManager.java
  Log:
  More progress on refactoring the type/profile/classloading system.
  
  Revision  Changes    Path
  1.5       +5 -3      avalon-sandbox/assembly/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/build.xml,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- build.xml	3 Dec 2002 06:57:25 -0000	1.4
  +++ build.xml	7 Dec 2002 09:34:27 -0000	1.5
  @@ -26,6 +26,7 @@
       <pathelement location="${avalon-meta.jar}"/>
       <pathelement location="${avalon-lifecycle.jar}"/>
       <pathelement location="${excalibur-logger.jar}"/>
  +    <pathelement location="${excalibur-extension.jar}"/>
       <pathelement location="${excalibur-configuration.jar}"/>
       <pathelement location="${excalibur-thread.jar}"/>
       <pathelement location="${excalibur-event.jar}"/>
  @@ -39,6 +40,7 @@
   
     <path id="test.class.path">
       <path refid="project.class.path"/>
  +    <pathelement location="${build.dir}/lib/${jar.name}"/>
       <pathelement location="${build.dir}/lib/${demo.jar}"/>
       <pathelement location="${build.testclasses}"/>
     </path>
  @@ -364,7 +366,7 @@
   
     <target name="test-reports" depends="test" description="Generate Reports for the unit tests">
   
  -    <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkBSF"/>
  +    <!--<ant antfile="${depchecker.prefix}/depchecker.xml" target="checkBSF"/>-->
   
       <mkdir dir="${build.reports}/junit"/>
   
  @@ -382,8 +384,8 @@
   
     <target name="patch">
       <replace dir="src" summary="true"
  -       token="xxxx"
  -       value="yyyy" >
  +       token="ClasspathHelper"
  +       value="EngineConfigurationHelper" >
        <include name="**/*.*"/>
       </replace>
     </target>
  
  
  
  1.4       +5 -0      avalon-sandbox/assembly/default.properties
  
  Index: default.properties
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/default.properties,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- default.properties	1 Dec 2002 06:43:22 -0000	1.3
  +++ default.properties	7 Dec 2002 09:34:27 -0000	1.4
  @@ -43,6 +43,11 @@
   excalibur-i18n.lib=${excalibur-i18n.home}/build/lib
   excalibur-i18n.jar=${excalibur-i18n.lib}/excalibur-i18n-1.0.jar
   
  +# ----- Excalibur Extension -----
  +excalibur-extension.home=${excalibur.home}/extension
  +excalibur-extension.lib=${excalibur-extension.home}/build/lib
  +excalibur-extension.jar=${excalibur-extension.lib}/excalibur-extension-1.0a.jar
  +
   # ----- Excalibur Configuration -----
   excalibur-configuration.home=${excalibur.home}/configuration
   excalibur-configuration.lib=${excalibur-configuration.home}/build/lib
  
  
  
  1.2       +3 -0      avalon-sandbox/assembly/src/etc/demo.mf
  
  Index: demo.mf
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/etc/demo.mf,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- demo.mf	24 Nov 2002 12:50:44 -0000	1.1
  +++ demo.mf	7 Dec 2002 09:34:27 -0000	1.2
  @@ -13,6 +13,9 @@
   i18n-Extension-Name: excalibur-i18n
   i18n-Specification-Version: 1.0
   
  +Name: Avalon-Block
  +Block-Name: Playground
  +
   Name: org/apache/avalon/playground/SimpleComponent.class
   Avalon: Type
   
  
  
  
  1.2       +3 -0      avalon-sandbox/assembly/src/etc/project.mf
  
  Index: project.mf
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/etc/project.mf,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- project.mf	24 Nov 2002 12:50:44 -0000	1.1
  +++ project.mf	7 Dec 2002 09:34:27 -0000	1.2
  @@ -19,3 +19,6 @@
   i18n-Specification-Version: 1.0
   logger-Extension-Name: excalibur-logger
   logger-Specification-Version: 1.0
  +
  +Name: Avalon-Block
  +Block-Name: Assembly
  
  
  
  1.5       +9 -37     avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/ApplianceManager.java
  
  Index: ApplianceManager.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/ApplianceManager.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ApplianceManager.java	3 Dec 2002 06:57:25 -0000	1.4
  +++ ApplianceManager.java	7 Dec 2002 09:34:27 -0000	1.5
  @@ -67,43 +67,8 @@
    * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
    * @version $Revision$ $Date$
    */
  -public interface ApplianceManager
  +public interface ApplianceManager 
   {
  -   /**
  -    * Creation of a new Appliance instance from a profile and configuration.
  -    * @param profile the profile to manager
  -    * @param config the appliance configuration
  -    * @return a non-initialized appliance instance
  -    * @exception ApplianceException if a error occurs during appliance creation
  -    */
  -    Appliance createAppliance( Profile profile, Configuration config )
  -      throws ApplianceException;
  -
  -   /**
  -    * Creation of a new Appliance instance based on a supplied profile, enabled 
  -    * state and activation policy.
  -    * @param profile the component deployment profile
  -    * @param enabled the enabled state of the appliance
  -    * @param activation the activation policy 
  -    * @return the appliance
  -    * @exception ApplianceException if a error occurs during appliance creation
  -    */
  -    Appliance createAppliance( Profile profile, boolean enabled, boolean activation )
  -      throws ApplianceException;
  -
  -   /**
  -    * Creation of a new Appliance instance based on a supplied profile, enabled 
  -    * state and activation policy.
  -    * @param profile the component deployment profile
  -    * @param enabled the enabled state of the appliance
  -    * @param activation the activation policy 
  -    * @param map a map of supplimentary deployment context entries
  -    * @return the appliance
  -    */
  -    public Appliance createAppliance( 
  -      Profile profile, boolean enabled, boolean activation, Map map )
  -      throws ApplianceException;
  -
       /**
        * Add a appliance to the manager.
        * @param appliance the appliance to add to the manager
  @@ -155,5 +120,12 @@
       * @return the selected appliance (possibly null)
       */
       Appliance getAppliance( StageDescriptor stage );
  +
  +   /**
  +    * Return an appliance factory based on a supplied Profile. 
  +    * @param profile a deployment profile
  +    * @return an appliance factory
  +    */
  +    ApplianceFactory getApplianceFactory( Profile profile );
   
   }
  
  
  
  1.2       +2 -3      avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/AssemblyService.java
  
  Index: AssemblyService.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/AssemblyService.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AssemblyService.java	29 Nov 2002 13:17:16 -0000	1.1
  +++ AssemblyService.java	7 Dec 2002 09:34:27 -0000	1.2
  @@ -65,8 +65,7 @@
   {
      /**
       * Assemble the supplied appliance.
  -    * @param appliance the object to contextualize
  -    * @param object the object to contextualize
  +    * @param appliance the object to assembly
       */
       void assemble( Appliance appliance ) throws AssemblyException;
   
  
  
  
  1.6       +22 -24    avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/DefaultAppliance.java
  
  Index: DefaultAppliance.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/DefaultAppliance.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- DefaultAppliance.java	3 Dec 2002 06:57:25 -0000	1.5
  +++ DefaultAppliance.java	7 Dec 2002 09:34:27 -0000	1.6
  @@ -65,6 +65,7 @@
   import org.apache.avalon.framework.service.Serviceable;
   import org.apache.avalon.framework.service.ServiceException;
   
  +import org.apache.avalon.assembly.engine.Engine;
   import org.apache.avalon.assembly.lifestyle.LifestyleException;
   import org.apache.avalon.assembly.lifestyle.LifestyleService;
   import org.apache.avalon.assembly.lifestyle.LifestyleHandler;
  @@ -98,15 +99,10 @@
        */
       private boolean m_activation = true;
   
  -   /**
  -    * The classloader that will be supplied to the lifestyle manager.
  -    */
  -    private ClassLoader m_classloader;
  -
       /**
        * The lifestyle service from which the appliance lifestyle handler is established.
        */
  -    private LifestyleService m_lifestyle;
  +    private Engine m_engine;
   
       /**
        * The lifestyle handler.
  @@ -151,11 +147,6 @@
       *     <td><strong>key</strong></td><td><strong>type</strong></td><td><strong>default</strong></td>
       *   </tr>
       *   <tr>
  -    *     <td>urn:avalon:classloader</td>
  -    *     <td>{@link ClassLoader}</td>
  -    *     <td>The classloader from to be supplied to the lifestyle manager.</td> 
  -    *   </tr>
  -    *   <tr>
       *     <td>urn:assembly:appliance.profile</td>
       *     <td>{@link Profile}</td>
       *     <td>The profile backing this appliance.</td> 
  @@ -166,19 +157,19 @@
       *     <td>The enabled state of the appliance.</td> 
       *   </tr>
       *   <tr>
  +    *     <td>urn:assembly:appliance.base</td>
  +    *     <td>{@link String}</td>
  +    *     <td>The base path.</td> 
  +    *   </tr>
  +    *   <tr>
       *     <td>urn:assembly:appliance.activation</td>
       *     <td>{@link Boolean}</td>
       *     <td>The activation policy for the appliance.</td> 
       *   </tr>
       *   <tr>
  -    *     <td>urn:assembly:appliance.context</td>
  -    *     <td>{@link Context}</td>
  -    *     <td>Supplimentary (option) deployment context.</td> 
  -    *   </tr>
  -    *   <tr>
  -    *     <td>urn:assembly:appliance.base</td>
  -    *     <td>{@link String}</td>
  -    *     <td>The base path.</td> 
  +    *     <td>urn:assembly:appliance.deployment-context</td>
  +    *     <td>{@link Map}</td>
  +    *     <td>Supplimentary context entries.</td> 
       *   </tr>
       * </table>
       * @param context the runtime context
  @@ -186,7 +177,6 @@
       public void contextualize( Context context ) throws ContextException
       {
           m_context = context;
  -        m_classloader = (ClassLoader) context.get( "urn:assembly:appliance.classloader" );
           m_profile = (Profile)context.get( "urn:assembly:appliance.profile" );
   
           try
  @@ -216,8 +206,6 @@
           {
               m_activation = false;
           }
  -
  -
       }
   
       //==============================================================
  @@ -228,10 +216,20 @@
       * Supply of supporting services to this componet by its manager.
       * This includes a deployment service that will assigned to the 
       * lifecycle handler.
  +    * <table>
  +    *   <tr>
  +    *     <td><strong>key</strong></td><td><strong>type</strong></td><td><strong>default</strong></td>
  +    *   </tr>
  +    *   <tr>
  +    *     <td>urn:assembly:engine.classloader</td>
  +    *     <td>{@link Engine}</td>
  +    *     <td>The deployment engine.</td> 
  +    *   </tr>
  +    * </table>
       */
       public void service( ServiceManager manager ) throws ServiceException
       {
  -        m_lifestyle = (LifestyleService) manager.lookup( "urn:assembly:lifestyle-service" );
  +        m_engine = (Engine) manager.lookup( "urn:assembly:engine.classloader" );
       }
   
       //==============================================================
  @@ -259,7 +257,7 @@
   
           try
           {
  -            m_handler = m_lifestyle.createHandler( this, m_classloader, m_context );
  +            m_handler = m_engine.createLifestyleHandler( this, m_context );
           }
           catch( Throwable e )
           {
  
  
  
  1.5       +88 -281   avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/DefaultApplianceManager.java
  
  Index: DefaultApplianceManager.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/DefaultApplianceManager.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DefaultApplianceManager.java	3 Dec 2002 06:57:25 -0000	1.4
  +++ DefaultApplianceManager.java	7 Dec 2002 09:34:27 -0000	1.5
  @@ -55,6 +55,7 @@
   import java.util.Iterator;
   import java.util.ArrayList;
   
  +import org.apache.avalon.framework.Version;
   import org.apache.avalon.framework.activity.Initializable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.service.ServiceManager;
  @@ -71,6 +72,7 @@
   import org.apache.avalon.meta.info.StageDescriptor;
   import org.apache.avalon.meta.info.ReferenceDescriptor;
   import org.apache.avalon.meta.model.Profile;
  +import org.apache.avalon.meta.info.InfoDescriptor;
   import org.apache.avalon.assembly.lifestyle.LifestyleService;
   import org.apache.avalon.assembly.lifestyle.DefaultLifestyleService;
   import org.apache.avalon.assembly.logging.DefaultLoggingManager;
  @@ -89,67 +91,38 @@
   {
   
       //==================================================================
  -    // static
  -    //==================================================================
  -
  -    public static final String ASSEMBLY_SERVICE_KEY = "urn:assembly:assembly-service";
  -
  -    public static final String LOGGING_MANAGER_KEY = "urn:assembly:logging.manager";
  -
  -    //==================================================================
       // state
       //==================================================================
  -
  -   /**
  -    * Flag indicating if contextualization has been performed.
  -    */
  -    private boolean m_contextualized = false;
  -  
  -   /**
  -    * Flag indicating if initalization has been performed.
  -    */
  -    private boolean m_initialized = false;
     
      /**
       * The parent appliance manager.
       */
       private ApplianceManager m_parent;
   
  -   /**
  -    * The classloader.
  -    */
  -    private ClassLoader m_classloader;
  -
       /**
        * Table of registered appliance instances keyed by profile name.
        */
       private final ArrayList m_appliances = new ArrayList();
  +        
  +   /**
  +    * The default appliance factory.
  +    */
  +    private ApplianceFactory m_factory;
   
  -    /**
  -     * The service manager holding the lifestyle service.
  -     */
  -    private ServiceManager m_manager;
  -    
  -    /**
  -     * The supplied context.
  -     */
  -    private Context m_context;
  -    
  -    /**
  -     * The assembly service.
  -     */
  -    private AssemblyService m_assembly;
  -    
  -    /**
  -     * The assembly service.
  -     */
  -    private LoggingManager m_logging;
  -    
  -    /**
  -     * The lifestyle service that will be supplied to appliance instances
  -     * created by this manager.
  -     */
  -    private LifestyleService m_lifestyle;
  +   /**
  +    * The engine.
  +    */
  +    private Engine m_engine;
  +
  +   /**
  +    * Flag holding the contextualized state of the manager.
  +    */
  +    private boolean m_contextualized;
  +
  +   /**
  +    * Flag holding the initialized state of the manager.
  +    */
  +    private boolean m_initialized;
   
       //==============================================================
       // Contextualizable
  @@ -164,11 +137,6 @@
       *     <td>key</td><td>type</td><td>default</td>
       *   </tr>
       *   <tr>
  -    *     <td>urn:assembly:classloader</td>
  -    *     <td>java.lang.ClassLoader</td>
  -    *     <td>The context classloader will be used by default if no value is supplied.</td> 
  -    *   </tr>
  -    *   <tr>
       *     <td>urn:assembly:parent</td>
       *     <td>{@link org.apache.avalon.assembly.appliance.ApplianceManager}</td>
       *     <td>In no value suppled, this appliance manager will be considered as a root manager.</td> 
  @@ -176,9 +144,8 @@
       * </table>
       * @param context the runtime context
       */
  -    public void contextualize( Context context )
  +    public void contextualize( Context context ) throws ContextException
       {
  -        m_context = context;
           try
           {
               m_parent = (ApplianceManager) context.get( "urn:assembly:parent" );
  @@ -187,16 +154,6 @@
           {
               m_parent = null;
           }
  -
  -        try
  -        {
  -            m_classloader = (ClassLoader) context.get( "urn:assembly:classloader" );
  -        }
  -        catch( ContextException e )
  -        {
  -            m_classloader = Thread.currentThread().getContextClassLoader();
  -        }
  -
           m_contextualized = true;
       }
   
  @@ -205,47 +162,28 @@
       //==============================================================
   
      /**
  -    * <p>Application of a supporting service to the appliance manager.</p>
  +    * <p>Application of a supporting service to the deployment service.</p>
       * <table>
       *   <tr>
       *     <td>key</td><td>type</td><td>description</td>
       *   </tr>
       *   <tr>
  -    *     <td>urn:assembly:lifecycle-service</td>
  -    *     <td>{@link org.apache.avalon.assembly.lifestyle.LifestyleService}</td>
  -    *     <td>The lifestyle service to provide to appliance instances created 
  -    *         by this manager.</td> 
  -    *   </tr>
  -    *   <tr>
  -    *     <td>urn:assembly:assembly-service</td>
  -    *     <td>{@link org.apache.avalon.assembly.AssemblyService}</td>
  -    *     <td>The assembly service.</td> 
  +    *     <td>urn:assembly:engine.classloader</td>
  +    *     <td>{@link org.apache.avalon.assembly.engine.Engine}</td>
  +    *     <td>The service management engine.</td> 
       *   </tr>
       * </table>
  -    * @param context the runtime context
  +    * @param manager the service manager
       */
       public void service( ServiceManager manager ) throws ServiceException
       {
  -        m_manager = manager;
  -        m_logging = (LoggingManager) manager.lookup( LOGGING_MANAGER_KEY );
  -        try
  -        {
  -            m_assembly = (AssemblyService) manager.lookup( ASSEMBLY_SERVICE_KEY );
  -        }
  -        catch( ServiceException se )
  +        if( manager == null )
           {
  -            m_assembly = bootstrapAssemblyService();
  +            throw new NullPointerException( "manager" );
           }
   
  -        try
  -        {
  -            m_lifestyle = 
  -             (LifestyleService) manager.lookup( "urn:assembly:lifestyle-service" );
  -        }
  -        catch( ServiceException se )
  -        {
  -            // ignore and handle during initialization
  -        }
  +        final String key = "urn:assembly:engine.classloader";
  +        m_engine = (Engine) manager.lookup( key );
       }
   
       //==============================================================
  @@ -253,48 +191,40 @@
       //==============================================================
   
      /**
  -    * Initialization fo the component by the container.  The implementation
  -    * validates a logger has been assigned and that the context phase has 
  -    * been executed, following which it flags initialization as complete and 
  -    * marks the component as ready to serve requests.
  -    *
  -    * @exception Exception if the manager has not been suppied with a context
  +    * Initialization of the appliance manager during which the default 
  +    * appliance factory is established.
  +    * @exception Exception if an initialization stage error occurs
       */
       public void initialize() throws Exception
       {
           if( getLogger() == null )
           {
  -            throw new IllegalStateException("logger");
  +            throw new IllegalStateException( "logger" );
           }
           if( !m_contextualized )
           {
  -            throw new IllegalStateException("contextualize");
  +            throw new IllegalStateException( "context" );
           }
  -        if( m_manager == null )
  +        if( m_engine == null )
           {
  -            throw new IllegalStateException("service");
  +            throw new IllegalStateException( "service" );
           }
   
  -        if( getLogger().isDebugEnabled() )
  +        try
           {
  -            getLogger().debug( "initialization" );
  +            DefaultApplianceFactory factory = new DefaultApplianceFactory();
  +            factory.enableLogging( getLogger().getChildLogger( "factory" ) );
  +            factory.initialize();
  +            m_factory = factory;
           }
  -
  -        /*
  -        if( m_lifestyle == null )
  +        catch( Throwable e )
           {
  -            m_lifestyle = bootstrapLifestyleService();
  +            final String error = 
  +              "Internal error while establishing the default applaince factory.";
  +            throw new ApplianceRuntimeException( error, e );
           }
  -        */
   
  -        final String key = "urn:assembly:lifestyle-service";
  -        if( !m_manager.hasService( key ) )
  -        {
  -            DefaultServiceManager manager = new DefaultServiceManager( m_manager );
  -            manager.put( key, bootstrapLifestyleService( m_manager ) );
  -            manager.makeReadOnly();
  -            m_manager = manager;
  -        }
  +        m_initialized = true;
       }
   
       //==================================================================
  @@ -302,104 +232,65 @@
       //==================================================================
   
      /**
  -    * Creation of a new Appliance instance from a profile and configuration.
  -    * @param profile the profile to manager
  -    * @param config the appliance configuration
  -    * @return a non-initialized appliance instance
  -    * @exception ApplianceException if an applicate creation error occurs
  +    * Return an appliance factory based on a supplied Profile. 
  +    * @param profile a deployment profile
  +    * @return an appliance factory
       */
  -    public Appliance createAppliance( Profile profile, Configuration config )
  -      throws ApplianceException
  +    public ApplianceFactory getApplianceFactory( Profile profile )
       {
  -        if( profile == null )
  +        if( !m_initialized ) 
           {
  -            throw new NullPointerException( "profile" );
  +            throw new IllegalStateException( "initilization" );
           }
  -        if( config == null )
  +
  +        InfoDescriptor info = profile.getType().getInfo();
  +        String classname = 
  +          info.getAttribute( 
  +            "urn:assembly:appliance.factory-service", null );
  +        if( classname == null )
           {
  -            throw new NullPointerException( "config" );
  +            return m_factory;
           }
   
  -        final boolean enabled = config.getAttributeAsBoolean( "enabled", true );
  -        final boolean activation = getActivationMode( config );
  -        return createAppliance( profile, enabled, activation );
  -    }
  +        //
  +        // we have an explicit factory declaration
  +        //
   
  -   /**
  -    * Creation of a new Appliance instance based on a supplied profile, enabled 
  -    * state and activation policy.
  -    * @param profile the component deployment profile
  -    * @param enabled the enabled state of the appliance
  -    * @param activation the activation policy 
  -    * @return the appliance
  -    */
  -    public Appliance createAppliance( Profile profile, boolean enabled, boolean activation )
  -      throws ApplianceException
  -    {
  -        return createAppliance( profile, enabled, activation, null );
  -    }
  +        final String version = 
  +          info.getAttribute( 
  +            "urn:assembly:appliance.factory-version", "1" );
   
  -   /**
  -    * Creation of a new Appliance instance based on a supplied profile, enabled 
  -    * state and activation policy.
  -    * @param profile the component deployment profile
  -    * @param enabled the enabled state of the appliance
  -    * @param activation the activation policy 
  -    * @param map a map of context entries to be included in the deployment context 
  -    * @return the appliance
  -    */
  -    public Appliance createAppliance( 
  -      Profile profile, boolean enabled, boolean activation, Map map )
  -      throws ApplianceException
  -    {
  -        if( profile == null )
  -        {
  -            throw new NullPointerException( "profile" );
  -        }
  +        final DependencyDescriptor dep = 
  +          new DependencyDescriptor( "factory", classname, Version.getVersion( version ));
   
           if( getLogger().isDebugEnabled() )
           {
  -            getLogger().debug( "create: " + profile.getName() );
  +            getLogger().debug( "factory: " + dep );
           }
   
  +        Appliance appliance;
           try
           {
  -            
  -            DefaultAppliance appliance = new DefaultAppliance();
  -
  -            appliance.enableLogging(
  -              getLogger().getChildLogger( profile.getName() ) );
  -
  -            DefaultContext context;
  -            if( map == null )
  -            {
  -                context = new DefaultContext( m_context );
  -            }
  -            else 
  -            {
  -                context = new DefaultContext( map, m_context );
  -            }
  -            context.put( "urn:assembly:appliance.profile", profile );
  -            context.put( "urn:assembly:appliance.enabled", new Boolean( enabled ) );
  -            context.put( "urn:assembly:appliance.activation", new Boolean( activation ) );
  -            context.put( "urn:assembly:appliance.classloader", m_classloader );
  -            context.makeReadOnly();
  -            appliance.contextualize( context );
  -
  -            appliance.service( m_manager );
  -
  -            appliance.initialize();
  -
  -            m_assembly.assemble( appliance );
  +            appliance = m_engine.resolve( dep );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error =
  +              "Could not resolve a provider for the custom factory: " 
  +              + dep.getReference();
  +            throw new ApplianceRuntimeException( error, e );
  +        }
   
  -            return appliance;
  +        try
  +        {
  +            return (ApplianceFactory) appliance.access( dep );
           }
           catch( Throwable e )
           {
  -            final String error = 
  -              "Build failure while attempting to create appliance from a qualified profile: " 
  -              + profile;
  -            throw new ApplianceException( error, e );
  +            final String error =
  +              "Could not establish custom factory: " 
  +              + dep.getReference();
  +            throw new ApplianceRuntimeException( error, e );
           }
       }
   
  @@ -528,89 +419,5 @@
               throw new DuplicateApplianceException( appliance.toString() );
           }
           m_appliances.add( appliance );
  -    }
  -
  -    //==================================================================
  -    // implemetation
  -    //==================================================================
  -
  -    /**
  -     * Utility method to get the activation mode for the profile.
  -     * If the activation attribute value is equal to "startup"
  -     * TRUE is returned.  If the value if "lazy", FALSE is returned.
  -     * Otherwise the value will be resolved as a boolean.
  -     *
  -     * @param config the profile configuration
  -     * @return boolean TRUE if activation on startup
  -     */
  -    private boolean getActivationMode( Configuration config )
  -    {
  -        String value = config.getAttribute( "activation", "lazy" );
  -        if( value.equalsIgnoreCase( "startup" ) )
  -        {
  -            return true;
  -        }
  -        if( value.equalsIgnoreCase( "lazy" ) )
  -        {
  -            return false;
  -        }
  -        return config.getAttributeAsBoolean( "activation", false );
  -    }
  -
  -   /**
  -    * Utility to create the default lifestyle service.
  -    * @param manager a service manager
  -    * @return the bootstrap lifestyle service
  -    */
  -    private LifestyleService bootstrapLifestyleService( ServiceManager manager ) throws Exception
  -    {
  -        if( getLogger().isDebugEnabled() )
  -        {
  -            getLogger().debug( "bootstrap lifestyle" );
  -        }
  -
  -        DefaultLifestyleService lifestyle = new DefaultLifestyleService();
  -        lifestyle.enableLogging( getLogger().getChildLogger( "lifestyle" ) );
  -        lifestyle.service( manager );
  -        lifestyle.contextualize( m_context );
  -        lifestyle.initialize();
  -        return lifestyle;
  -    }
  -
  -   /**
  -    * Utility to create the default assembly service.
  -    * @param manager a service manager
  -    * @return the bootstrap assembly service
  -    */
  -    private AssemblyService bootstrapAssemblyService() throws ServiceException
  -    {
  -        if( getLogger() == null )
  -        {
  -            throw new IllegalStateException( "logger" );
  -        }
  -        if( m_manager == null )
  -        {
  -            throw new IllegalStateException( "service" );
  -        }
  -
  -        if( getLogger().isDebugEnabled() )
  -        {
  -            getLogger().debug( "bootstrap assembly" );
  -        }
  -
  -        try
  -        {
  -            DefaultAssemblyService assembly = new DefaultAssemblyService();
  -            assembly.enableLogging( getLogger().getChildLogger( "assembly" ) );
  -            assembly.service( m_manager );
  -            assembly.contextualize( m_context );
  -            assembly.initialize();
  -            return assembly;
  -        }
  -        catch( Throwable e )
  -        {
  -            final String error = "Internal error while preparing boostrap assembly service.";
  -            throw new ServiceException( ASSEMBLY_SERVICE_KEY, error, e );
  -        }
       }
   }
  
  
  
  1.3       +25 -19    avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/DefaultAssemblyService.java
  
  Index: DefaultAssemblyService.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/DefaultAssemblyService.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DefaultAssemblyService.java	3 Dec 2002 06:57:25 -0000	1.2
  +++ DefaultAssemblyService.java	7 Dec 2002 09:34:27 -0000	1.3
  @@ -52,6 +52,7 @@
   
   import java.util.List;
   import java.util.ArrayList;
  +import java.util.Map;
   
   import org.apache.avalon.framework.activity.Initializable;
   import org.apache.avalon.framework.service.Serviceable;
  @@ -80,7 +81,7 @@
       // static
       //==============================================================
   
  -    private static final String ENGINE_KEY = "urn:assembly:engine";
  +    private static final String ENGINE_KEY = "urn:assembly:engine.classloader";
   
       //==============================================================
       // state
  @@ -116,16 +117,9 @@
       * </table>
       * @param context the runtime context
       */
  -    public void contextualize( Context context )
  +    public void contextualize( Context context ) throws ContextException
       {
  -        try
  -        {
  -            m_map = (DependencyGraph) context.get( "urn:assembly:dependency-map" );
  -        }
  -        catch( ContextException e )
  -        {
  -            m_map = new DependencyGraph();
  -        }
  +        m_map = (DependencyGraph) context.get( "urn:assembly:dependency-map" );
       }
   
       //==============================================================
  @@ -184,9 +178,8 @@
       //==============================================================
   
      /**
  -    * Contextualize the supplied object.
  -    * @param appliance the object to contextualize
  -    * @param object the object to contextualize
  +    * Assemble the supplied appliance.
  +    * @param appliance the object to assembly
       */
       public void assemble( Appliance appliance ) throws AssemblyException
       {
  @@ -237,9 +230,22 @@
           DependencyGraph map, Appliance appliance, List visited, String pad )
           throws AssemblyException
       {
  +        if( map == null )
  +        {
  +            throw new NullPointerException( "map" );
  +        }
  +        if( appliance == null )
  +        {
  +            throw new NullPointerException( "appliance" );
  +        }
  +        if( visited == null )
  +        {
  +            throw new NullPointerException( "visited" );
  +        }
  +
           String name = appliance.getProfile().getName();
           getLogger().debug( pad + "assemble: " + name );
  -        String pad2 = pad + "  ";
  +        String pad2 = pad + " ";
   
           //
           // for all of the declared dependencies - make sure the
  @@ -327,8 +333,8 @@
                   catch( Throwable e )
                   {
                       final String error =
  -                        "Unable to deploy a supplier for a stage dependency: '"
  -                        + supplier
  +                        "Unable to resolve a supplier for a stage: '"
  +                        + stage
                           + "' within the appliance '" 
                           + appliance + "'.";
                       throw new AssemblyException( error, e );
  @@ -337,8 +343,8 @@
                   if( supplier == null )
                   {
                       final String message =
  -                        "Unresolved supplied for the stage dependency: "
  -                        + stage.getReference() + " in appliance: " + appliance;
  +                        "Unresolved supplied for the stage: "
  +                        + stage + " in appliance: " + appliance;
   
                       appliance.setEnabled( false );
                       final Exception problem = new Exception( message );
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/ApplianceFactory.java
  
  Index: ApplianceFactory.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
  
  */
  
  package org.apache.avalon.assembly.appliance;
  
  import java.util.Map;
  
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.meta.info.DependencyDescriptor;
  import org.apache.avalon.meta.info.StageDescriptor;
  import org.apache.avalon.meta.model.Profile;
  import org.apache.avalon.assembly.logging.LoggingManager;
  import org.apache.avalon.assembly.engine.Engine;
  
  /**
   * An appliance manager implemetation provides support for the 
   * creation and retrival of appliance instances.
   *
   * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:27 $
   */
  public interface ApplianceFactory
  {
     /**
      * Creation of a new Appliance instance from a profile and configuration.
      * @param profile the profile to manager
      * @param config the appliance configuration
      * @return a non-initialized appliance instance
      * @exception ApplianceException if a error occurs during appliance creation
      */
      Appliance createAppliance( Engine engine, Profile profile, Configuration config, Context system )
        throws ApplianceException;
  
     /**
      * Creation of a new Appliance instance based on a supplied profile, enabled 
      * state and activation policy.
      * @param profile the component deployment profile
      * @param enabled the enabled state of the appliance
      * @param activation the activation policy 
      * @return the appliance
      * @exception ApplianceException if a error occurs during appliance creation
      */
      Appliance createAppliance( 
        Engine engine, Profile profile, boolean enabled, boolean activation, Context system )
        throws ApplianceException;
  
     /**
      * Creation of a new Appliance instance based on a supplied profile, enabled 
      * state and activation policy.
      * @param profile the component deployment profile
      * @param enabled the enabled state of the appliance
      * @param activation the activation policy 
      * @param map a map of supplimentary deployment context entries
      * @return the appliance
      */
      public Appliance createAppliance( 
        Engine engine, Profile profile, boolean enabled, boolean activation, Context system, Map map )
        throws ApplianceException;
  
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/DefaultApplianceFactory.java
  
  Index: DefaultApplianceFactory.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
  
  */
  
  package org.apache.avalon.assembly.appliance;
  
  import java.util.Map;
  import java.util.Hashtable;
  import java.util.Iterator;
  import java.util.ArrayList;
  
  import org.apache.avalon.framework.Version;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.service.ServiceManager;
  import org.apache.avalon.framework.service.DefaultServiceManager;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.service.Serviceable;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.DefaultContext;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.meta.info.DependencyDescriptor;
  import org.apache.avalon.meta.info.StageDescriptor;
  import org.apache.avalon.meta.info.ReferenceDescriptor;
  import org.apache.avalon.meta.model.Profile;
  import org.apache.avalon.meta.info.InfoDescriptor;
  import org.apache.avalon.assembly.lifestyle.LifestyleService;
  import org.apache.avalon.assembly.lifestyle.DefaultLifestyleService;
  import org.apache.avalon.assembly.logging.DefaultLoggingManager;
  import org.apache.avalon.assembly.logging.LoggingManager;
  import org.apache.avalon.assembly.engine.Engine;
  
  /**
   * The default appliance manager provides support for {@link Appliance}
   * creation, registration and retrival.
   *
   * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:27 $
   */
  public class DefaultApplianceFactory extends AbstractLogEnabled 
    implements ApplianceFactory, Initializable
  {
  
      //==================================================================
      // state
      //==================================================================
  
     /**
      * Flag indicating if contextualization has been performed.
      */
      private boolean m_contextualized = false;
    
     /**
      * Flag indicating if initalization has been performed.
      */
      private boolean m_initialized = false;
                    
      //==============================================================
      // Initializable
      //==============================================================
  
     /**
      * Initialization fo the component by the container.  The implementation
      * validates a logger has been assigned and that the context phase has 
      * been executed, following which it flags initialization as complete and 
      * marks the component as ready to serve requests.
      *
      * @exception Exception if the manager has not been supplied with a context
      */
      public void initialize() throws Exception
      {
          if( getLogger() == null )
          {
              throw new IllegalStateException("logger");
          }
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "initialization" );
          }
      }
  
      //==================================================================
      // ApplianceFactory
      //==================================================================
  
     /**
      * Creation of a new Appliance instance from a profile and configuration.
      * @param profile the profile to manager
      * @param config the appliance configuration
      * @return a non-initialized appliance instance
      * @exception ApplianceException if an applicate creation error occurs
      */
      public Appliance createAppliance( Engine engine, Profile profile, Configuration config, Context system )
        throws ApplianceException
      {
          if( profile == null )
          {
              throw new NullPointerException( "profile" );
          }
          if( config == null )
          {
              throw new NullPointerException( "config" );
          }
  
          final boolean enabled = config.getAttributeAsBoolean( "enabled", true );
          final boolean activation = getActivationMode( config );
          return createAppliance( engine, profile, enabled, activation, system );
      }
  
     /**
      * Creation of a new Appliance instance based on a supplied profile, enabled 
      * state and activation policy.
      * @param profile the component deployment profile
      * @param enabled the enabled state of the appliance
      * @param activation the activation policy 
      * @return the appliance
      */
      public Appliance createAppliance( Engine engine, Profile profile, boolean enabled, boolean activation, Context system )
        throws ApplianceException
      {
          if( profile == null )
          {
              throw new NullPointerException( "profile" );
          }
  
          return createAppliance( engine, profile, enabled, activation, system, null );
      }
  
     /**
      * Creation of a new Appliance instance based on a supplied profile, enabled 
      * state and activation policy.
      * @param profile the component deployment profile
      * @param enabled the enabled state of the appliance
      * @param activation the activation policy 
      * @param map a map of context entries to be included in the deployment context 
      * @return the appliance
      */
      public Appliance createAppliance( 
        Engine engine, Profile profile, boolean enabled, boolean activation, Context system, Map map )
        throws ApplianceException
      {
          if( profile == null )
          {
              throw new NullPointerException( "profile" );
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "create: " + profile.getName() );
          }
  
          try
          {
              DefaultAppliance appliance = new DefaultAppliance();
  
              appliance.enableLogging(
                getLogger().getChildLogger( profile.getName() ) );
  
              DefaultContext context;
              if( map == null )
              {
                  context = new DefaultContext( system );
              }
              else 
              {
                  context = new DefaultContext( map, system );
              }
              context.put( "urn:assembly:appliance.profile", profile );
              context.put( "urn:assembly:appliance.enabled", new Boolean( enabled ) );
              context.put( "urn:assembly:appliance.activation", new Boolean( activation ) );
              context.makeReadOnly();
              appliance.contextualize( context );
  
              DefaultServiceManager manager = new DefaultServiceManager();
              manager.put( "urn:assembly:engine.classloader", engine );
              manager.makeReadOnly();
              appliance.service( manager );
              appliance.initialize();
              engine.assemble( appliance );
              return appliance;
          }
          catch( Throwable e )
          {
              final String error = 
                "Error while attempting to create standard appliance" 
                + " from the profile: " 
                + profile;
              throw new ApplianceException( error, e );
          }
      }
  
      //==================================================================
      // implemetation
      //==================================================================
  
      /**
       * Utility method to get the activation mode for the profile.
       * If the activation attribute value is equal to "startup"
       * TRUE is returned.  If the value if "lazy", FALSE is returned.
       * Otherwise the value will be resolved as a boolean.
       *
       * @param config the profile configuration
       * @return boolean TRUE if activation on startup
       */
      private boolean getActivationMode( Configuration config )
      {
          String value = config.getAttribute( "activation", "lazy" );
          if( value.equalsIgnoreCase( "startup" ) )
          {
              return true;
          }
          if( value.equalsIgnoreCase( "lazy" ) )
          {
              return false;
          }
          return config.getAttributeAsBoolean( "activation", false );
      }
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/MappedServiceManager.java
  
  Index: MappedServiceManager.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1997-2002 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.avalon.assembly.appliance;
  
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  
  import org.apache.avalon.framework.service.ServiceManager;
  import org.apache.avalon.framework.service.ServiceException;
  
  /**
   * This class is a static implementation of a <code>ServiceManager</code>. Allow ineritance
   * and extension so you can generate a tree of <code>ServiceManager</code> each defining
   * Object scope.
   *
   * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
   * @version 1.0
   */
  public class MappedServiceManager
      implements ServiceManager
  {
      private final Map m_objects;
      private final ServiceManager m_parent;
      private boolean m_readOnly;
  
      /**
       * Construct <code>ServiceManager</code> with no parent.
       *
       */
      public MappedServiceManager()
      {
          this( (ServiceManager) null );
      }
  
      /**
       * Construct <code>ServiceManager</code> with specified parent.
       *
       * @param parent this <code>ServiceManager</code>'s parent
       */
      public MappedServiceManager( final ServiceManager parent )
      {
          this( null, parent );
      }
  
      /**
       * Construct <code>ServiceManager</code> with specified service map.
       *
       * @param map a set of constructed services
       */
      public MappedServiceManager( final Map map )
      {
          this( map, null );
      }
  
      /**
       * Construct <code>ServiceManager</code> with specified parent.
       *
       * @param map a set of constructed services
       * @param parent this <code>ServiceManager</code>'s parent
       */
      public MappedServiceManager( final Map map, final ServiceManager parent )
      {
          m_parent = parent;
          if( map != null )
          {
              m_objects = map;
          }
          else
          {
              m_objects = new HashMap();
          }
      }
  
      /**
       * Retrieve <code>Object</code> by key from <code>ServiceManager</code>.
       *
       * @param key the key
       * @return the <code>Object</code>
       * @throws ServiceException if an error occurs
       */
      public Object lookup( final String key )
          throws ServiceException
      {
          final Object object = m_objects.get( key );
          if( null != object )
          {
              return object;
          }
          else if( null != m_parent )
          {
              return m_parent.lookup( key );
          }
          else
          {
              final String message = "Unable to provide implementation for " + key;
              throw new ServiceException( key, message, null );
          }
      }
  
      /**
       * Check to see if a <code>Object</code> exists for a key.
       *
       * @param key  a string identifying the key to check.
       * @return True if the object exists, False if it does not.
       */
      public boolean hasService( final String key )
      {
          try
          {
              lookup( key );
              return true;
          }
          catch( final Throwable t )
          {
              return false;
          }
      }
  
      /**
       * Place <code>Object</code> into <code>ServiceManager</code>.
       *
       * @param key the object's key
       * @param object an <code>Object</code> value
       */
      public void put( final String key, final Object object )
      {
          checkWriteable();
          m_objects.put( key, object );
      }
  
      /**
       * Build a human readable representation of this
       * <code>ServiceManager</code>.
       *
       * @return the description of this <code>ServiceManager</code>
       */
      public String toString()
      {
          final StringBuffer buffer = new StringBuffer();
          final Iterator objects = m_objects.keySet().iterator();
          buffer.append( "Services:" );
  
          while( objects.hasNext() )
          {
              buffer.append( "[" );
              buffer.append( objects.next() );
              buffer.append( "]" );
          }
  
          return buffer.toString();
      }
  
      /**
       * Helper method for subclasses to retrieve parent.
       *
       * @return the parent <code>ServiceManager</code>
       */
      protected final ServiceManager getParent()
      {
          return m_parent;
      }
  
      /**
       * Helper method for subclasses to retrieve object map.
       *
       * @return the object map
       */
      protected final Map getObjectMap()
      {
          return m_objects;
      }
  
      /**
       * Makes this <code>ServiceManager</code> read-only.
       *
       */
      public void makeReadOnly()
      {
          m_readOnly = true;
      }
  
      /**
       * Checks if this <code>ServiceManager</code> is writeable.
       *
       * @throws IllegalStateException if this <code>ServiceManager</code> is
       * read-only
       */
      protected final void checkWriteable()
          throws IllegalStateException
      {
          if( m_readOnly )
          {
              final String message =
                  "ServiceManager is read only and can not be modified";
              throw new IllegalStateException( message );
          }
      }
  
      /**
       * Release the <code>Object</code>.
       * @param object The <code>Object</code> to release.
       */
      public void release( Object object )
      {
      }
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/TestApplianceFactory.java
  
  Index: TestApplianceFactory.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
  
  */
  
  package org.apache.avalon.assembly.appliance;
  
  
  /**
   * The default appliance manager provides support for {@link Appliance}
   * creation, registration and retrival.
   *
   * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:27 $
   */
  public class TestApplianceFactory extends DefaultApplianceFactory 
  {
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/appliance/TestApplianceFactory.xinfo
  
  Index: TestApplianceFactory.xinfo
  ===================================================================
  <?xml version="1.0"?>
  <!DOCTYPE type
        PUBLIC "-//AVALON/Component Type DTD Version 1.0//EN"
               "http://jakarta.apache.org/avalon/dtds/meta/type_1_0.dtd" >
  
  <!--  
  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.txt file.
  
  @author  Stephen McConnell
  @version 1.0 12/03/2001
  -->
  
  <type>
  
    <info>
      <name>test</name>
      <version>1.0</version>
    </info>
  
    <services>
      <service>
        <reference type="org.apache.avalon.assembly.appliance.ApplianceFactory" version="2.0"/>
      </service>
    </services>
  
  </type>
  
  
  
  1.3       +15 -2     avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/Engine.java
  
  Index: Engine.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/Engine.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Engine.java	30 Nov 2002 14:47:51 -0000	1.2
  +++ Engine.java	7 Dec 2002 09:34:28 -0000	1.3
  @@ -51,11 +51,17 @@
   package org.apache.avalon.assembly.engine;
   
   import java.util.Map;
  +import java.net.URL;
   
   import org.apache.avalon.framework.Version;
   import org.apache.avalon.framework.context.Context;
  +import org.apache.avalon.framework.service.ServiceManager;
   import org.apache.avalon.meta.model.Profile;
   import org.apache.avalon.assembly.appliance.Appliance;
  +import org.apache.avalon.assembly.appliance.AssemblyService;
  +import org.apache.avalon.assembly.engine.model.ClasspathDescriptor;
  +import org.apache.avalon.assembly.lifestyle.LifestyleService;
  +import org.apache.avalon.assembly.lifestyle.LifestyleHandler;
   import org.apache.avalon.meta.info.DependencyDescriptor;
   import org.apache.avalon.meta.info.StageDescriptor;
   
  @@ -65,8 +71,15 @@
    * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
    * @version $Revision$ $Date$
    */
  -public interface Engine
  +public interface Engine extends RepositoryManager, AssemblyService
   {
  +   /**
  +    * Creation of a new lifestyle handler.
  +    * @param appliance the appliance that the handler will manage
  +    * @param context the system context
  +    */
  +    LifestyleHandler createLifestyleHandler( Appliance appliance, Context context );
  +
      /**
       * Register a type and associated profiles with the container.
       * @param path the path to the appliance implementation class
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/DefaultRepositoryManager.java
  
  Index: DefaultRepositoryManager.java
  ===================================================================
  /* ==================================================================== 
   * The Apache Software License, Version 1.1 
   * 
   * Copyright (c) 2002 The Apache Software Foundation. All rights 
   * reserved. 
   * 
   * Redistribution and use in source and binary forms, with or without 
   * modification, are permitted provided that the following conditions 
   * are met: 
   * 
   * 1. Redistributions of source code must retain the above copyright 
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software 
   *    itself, if and wherever such third-party acknowledgments  
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation" 
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see 
   * <http://www.apache.org/>.
   */ 
  
  package org.apache.avalon.assembly.engine;
  
  import java.io.File;
  import java.io.IOException;
  import java.net.JarURLConnection;
  import java.net.URL;
  import java.net.URLClassLoader;
  import java.util.ArrayList;
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.StringTokenizer;
  import java.util.Vector;
  import java.util.jar.Attributes;
  import java.util.jar.Manifest;
  import java.util.jar.JarFile;
  import java.util.zip.ZipEntry;
  import org.apache.avalon.assembly.type.TypeManager;
  import org.apache.avalon.assembly.profile.ProfileManager;
  import org.apache.avalon.assembly.service.ServiceManager;
  import org.apache.avalon.assembly.engine.model.*;
  import org.apache.avalon.excalibur.extension.Extension;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.avalon.excalibur.packagemanager.ExtensionManager;
  import org.apache.avalon.excalibur.packagemanager.OptionalPackage;
  import org.apache.avalon.excalibur.packagemanager.PackageManager;
  import org.apache.avalon.excalibur.packagemanager.impl.DefaultExtensionManager;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.DefaultContext;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.logger.LogEnabled;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.meta.info.ReferenceDescriptor;
  import org.apache.avalon.meta.info.Service;
  import org.apache.avalon.meta.info.Type;
  import org.apache.avalon.meta.model.Profile;
  
  /**
   * A repository for services, types and profiles.
   *
   * @author <a href="mailto:shea@gtsdesign.com">Gary Shea</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:28 $
   */
  public class DefaultRepositoryManager extends AbstractLogEnabled implements Contextualizable, Initializable, RepositoryManager
  {
      //===================================================================
      // static
      //===================================================================
  
      private static final Resources REZ =
          ResourceManager.getPackageResources( DefaultRepositoryManager.class );
  
      /**
       * Optional context key referencing an instance of {@link LibraryDescriptor}
       *   that defines the set of extension directories to use.
       */
      public static final String EXTENSIONS_DESCRIPTOR_KEY = "urn:assembly:extensions.descriptor";
  
      /**
       * Optional classpath key referencing an instance of {@link ClasspathDescriptor}
       *   that defines the set of jar files to install.
       */
      public static final String CLASSPATH_DESCRIPTOR_KEY = "urn:assembly:classpath.descriptor";
  
      private static final String X_INFO = "xinfo";
      private static final String X_TYPE = "xtype";
      private static final String X_SERVICE = "xservice";
  
      private static final String AVALON_BLOCK_KEY = "Avalon-Block";
  
      //===================================================================
      // state
      //===================================================================
  
      /**
       * Parent repository.
       */
      private RepositoryManager m_parent = null;
  
      /**
       * Parent repository.
       */
      private EngineClassLoader m_classloader;
  
      /**
       * The base directory.
       */
      private File m_home;
  
      /**
       * Description of the extension directories.
       */
      private LibraryDescriptor m_extensions;
  
      /**
       * Utility class to manage extension jar files.
       */
      private PackageManager m_manager;
  
      /**
       * The registry of installed component types.
       */
      private TypeManager m_types;
  
      /**
       * The service registry.
       */
      private ServiceManager m_services;
  
      /**
       * The profile registry.
       */
      private ProfileManager m_profiles;
  
      /**
       * The bootstrap flag..
       */
      private Boolean m_bootstrap = new Boolean( false );
  
      //==============================================================
      // Contextualizable
      //==============================================================
  
     /**
      * <p>Application of a runtime context to the lifestyle service.
      * The context value will be passed directly to lifestyle handlers 
      * established by this service.
      * @param context the runtime context
      */
      public void contextualize( Context context ) throws ContextException
      {
          m_classloader = (EngineClassLoader) context.get( "urn:assembly:engine.classloader" );
          m_extensions = (LibraryDescriptor) context.get( "urn:assembly:libraries-descriptor" );
          m_home = (File) context.get( "urn:avalon:home" );
  
          try
          {
              m_bootstrap = (Boolean) context.get( "urn:assembly:engine.bootstrap" );
          }
          catch( ContextException ce )
          {
              // use default value
          }
          catch( Throwable ce )
          {
              throw new IllegalArgumentException( "urn:assembly:engine.bootstrap" );
          }
          
          try
          {
              m_parent = (RepositoryManager) context.get( "urn:assembly:repository.parent" );
              m_types = new TypeManager( m_classloader, m_parent.getTypeManager() );
              m_services = new ServiceManager( m_classloader, m_parent.getServiceManager()  );
              m_profiles = new ProfileManager( m_classloader, m_parent.getProfileManager()  );
          }
          catch( ContextException ce )
          {
              m_services = new ServiceManager( m_classloader, null );
              m_types = new TypeManager( m_classloader, null );
              m_profiles = new ProfileManager( m_classloader, null );
          }
  
          m_services.enableLogging( getLogger().getChildLogger( "services" ) );
          m_types.enableLogging( getLogger().getChildLogger( "types" ) );
          m_profiles.enableLogging( getLogger().getChildLogger( "profiles" ) );
      }
  
      //===================================================================
      // Initialization
      //===================================================================
  
      /**
       * Initialization of the repository.
       * @exception if an initialization error occurs
       */
      public void initialize() throws Exception
      {
          if( getLogger() == null )
          {
             throw new IllegalStateException( "logging" );
          }
  
          ArrayList list = new ArrayList();
          File anchor = new File( m_home, m_extensions.getBaseDirectory() );
          IncludeDescriptor[] includes = m_extensions.getIncludeDescriptors();
          for( int j = 0; j < includes.length; j++ )
          {
              File include = new File( anchor, includes[ j ].getFile() );
              if( include.isDirectory() )
              {
                  list.add( include );
              }
              else
              {
                  final String error = "Invalid include directory: " + include;
                  throw new IllegalArgumentException( error );
              }
          }
  
          File[] files = (File[])list.toArray( new File[ 0 ] );
          ExtensionManager repository = new DefaultExtensionManager( files );
          m_manager = new PackageManager( repository );
  
          //
          // handle the system classpath bootstrap process
          //
  
          if( m_bootstrap.booleanValue() )
          {
              if( getLogger().isDebugEnabled() )
              {
                 getLogger().debug( "bootstraping from classpath" );
              }
  
              String sep = System.getProperty( "path.separator" );
              String classpath = System.getProperty( "java.class.path" );
  
              StringTokenizer tokenizer = new StringTokenizer( classpath, sep );
              while( tokenizer.hasMoreTokens() )
              {
                  String token = tokenizer.nextToken();
                  URL jar = new File( token ).toURL();
                  scan( jar );
              }
          }
      }
  
      //=======================================================================
      // Repository
      //=======================================================================
  
      public TypeManager getTypeManager()
      {
          return m_types;
      }
  
      public ServiceManager getServiceManager()
      {
          return m_services;
      }
  
      public ProfileManager getProfileManager()
      {
          return m_profiles;
      }
  
      /**
       * Add a classpath to the repository.
       * @param base the base directory from which relative classpath entries
       * will be resolved.
       */
      public void addClasspath( ClasspathDescriptor classpath )
      {
          if( classpath == null )
          {
              throw new NullPointerException( "classpath" );
          }
  
          if( getLogger() == null )
          {
              throw new IllegalStateException( "logging" );
          }
  
          if( getLogger().isDebugEnabled() )
          {
             getLogger().debug( "adding classpath" );
          }
  
          List list = new ArrayList();
          Vector stack = new Vector();
          FilesetDescriptor[] dirs = classpath.getFilesetDescriptors();
          for( int i = 0; i < dirs.length; i++ )
          {
              FilesetDescriptor descriptor = dirs[ i ];
              File anchor = new File( m_home, descriptor.getBaseDirectory() );
              if( !anchor.exists() )
              {
                  final String error =
                    "Classpath base directory does not exist: " 
                    + anchor;
                  throw new EngineRuntimeException( error );
              }
  
              IncludeDescriptor[] includes = descriptor.getIncludeDescriptors();
              for( int j = 0; j < includes.length; j++ )
              {
                  String inc = includes[ j ].getFile();
                  try
                  {
                      addLibrary( new File( anchor, inc ).toURL() );
                  }
                  catch( Throwable e )
                  {
                      final String error = 
                        "Error processing a classpath include: " 
                        + inc;
                      throw new EngineRuntimeException( error, e );
                  }
              }
          }
  
          if( getLogger().isDebugEnabled() )
          {
             getLogger().debug( "classpath ok" );
          }
      }
  
      /**
       * Add a URL to the classpath.
       * @param url the URL to add to the classpath
       */
      public void addLibrary( URL url )
      {
          addExtensions( url );
          m_classloader.addLibraryURL( url );
          scan( url );
      }
  
      private void addExtensions( URL url )
      {
          if( isDirectory( url ) )
          {
              return;
          }
  
          try
          {
              String[] path = urlsToStrings( new URL[]{ url } );
              final File[] extensions = getOptionalPackagesFor( path );
              for( int i = 0; i < extensions.length; i++ )
              {
                  File ext = extensions[ i ];
                  try
                  {
                      URL target = ext.toURL();
                      if( getLogger().isDebugEnabled() )
                      {
                          getLogger().debug( "include: " + target );
                      }
                      addLibrary( target );
                  }
                  catch( Throwable e )
                  {
                      final String error = 
                        "Internal error while attempting to add optional package: " + ext;
                      throw new EngineRuntimeException( error, e );
                  }
              } 
          }
          catch( Throwable e )
          {
              final String error = 
               "Internal error while attempting to add extension url: " + url;
              throw new EngineRuntimeException( error, e );
          }
      }
  
      /**
       * Register any components declared in the manifest.
       * @param url pointing to the jar file
       * @exception EngineRuntimeException if an scanning error occurs
       */
      private void scan( URL url ) throws EngineRuntimeException
      {
          if( isDirectory( url ) )
          {
              return;
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "scanning: " + url );
          }
  
          try
          {
              final URL resource = new URL( "jar:" + url.toString() + "!/" );
              final JarURLConnection jar = (JarURLConnection)resource.openConnection();
              Manifest manifest = jar.getManifest();
              if( manifest == null )
              {
                  return;
              }
  
              Attributes attributes = manifest.getAttributes( AVALON_BLOCK_KEY );
              if( attributes == null )
              {
                  return;
              }
  
              //
              // we are dealing with an Avalon Block so we need to scan the classes
              // for service and type defintions
              //
  
              JarFile base = jar.getJarFile();
              loadComponents( base );
  
          }
          catch( IOException e )
          {
              final String error =
                  "IO exception while attempt to read manifest. from the url: "
                  + url;
              throw new EngineRuntimeException( error, e );
          }
          catch( Throwable e )
          {
              final String error = "Unexpected exception while inspecting manifest on file: ";
              throw new EngineRuntimeException( error + url, e );
          }
      }
  
      private void loadComponents( JarFile base ) throws IOException
      {
          List list = new ArrayList();
          Enumeration entries = base.entries();
          while( entries.hasMoreElements() )
          {
              ZipEntry entry = (ZipEntry) entries.nextElement();
              String name = entry.getName();
  
              if( name.endsWith( X_TYPE ) )
              {
                  String classname = parseResourceName( name );
                  try
                  {
                      Type type = m_types.createType( classname );
                      m_types.addType( type );
                      Profile[] profiles = m_profiles.loadProfiles( type );
                      m_profiles.addProfiles( profiles );
                  }
                  catch( Throwable e )
                  {
                      final String warning = 
                        "Ignoring type: " + name;
                      getLogger().warn( warning, e );
                  }
              }
              else if( name.endsWith( X_INFO ) )
              {
                  String classname = parseResourceName( name );
                  try
                  {
                      Type type = m_types.createType( classname );
                      m_types.addType( type );
                      Profile[] profiles = m_profiles.loadProfiles( type );
                      m_profiles.addProfiles( profiles );
                  }
                  catch( Throwable e )
                  {
                      final String warning = 
                        "Ignoring type: " + name;
                      getLogger().warn( warning, e );
                  }
              }
  
              if( name.endsWith( X_SERVICE ) )
              {
                  String classname = parseResourceName( name );
                  try
                  {
                      Service service = m_services.createService( classname );
                      m_services.addService( service );
                  }
                  catch( Throwable e )
                  {
                      final String warning = 
                        "Ignoring type: " + name;
                      getLogger().warn( warning, e );
                  }
              }
          }
      }
  
      private boolean isDirectory( URL url )
      {
          if( url.getProtocol().equals( "file" ) )
          {
              File file = new File( url.toString().substring( 5 ) );
              return file.isDirectory();
          }
          return false;
      }
  
      private String parseResourceName( String resource )
      {
          int i = resource.lastIndexOf(".");
          String name = resource.substring( 0, i );
          return name.replace( '/', '.' );
      }
  
      private String[] urlsToStrings( URL[] urls )
      {
          Vector vector = new Vector();
          for( int i = 0; i < urls.length; i++ )
          {
              vector.add( urls[ i ].toString() );
          }
          return (String[])vector.toArray( new String[ vector.size() ] );
      }
  
      //================================================================================
      // extension libraries
      //================================================================================
  
      /**
       * Retrieve the files for the optional packages required by
       * the jars in ClassPath.
       *
       * @param classPath the Classpath array
       * @return the files that need to be added to ClassLoader
       * @exception Exception if a extension error occurs
       */
      protected File[] getOptionalPackagesFor( final String[] classPath )
          throws Exception
      {
          if( m_manager == null )
          {
              RepositoryManager parent = getParent();
              if( parent != null )
              {
                  if( parent instanceof DefaultRepositoryManager )
                  {
                      return ( (DefaultRepositoryManager)parent).getOptionalPackagesFor( classPath );
                  }
              }
              return new File[ 0 ];
          }
  
          final Manifest[] manifests = getManifests( classPath );
          final Extension[] available = Extension.getAvailable( manifests );
          final Extension[] required = Extension.getRequired( manifests );
  
          final ArrayList dependencies = new ArrayList();
          final ArrayList unsatisfied = new ArrayList();
  
          m_manager.scanDependencies( required,
                                      available,
                                      dependencies,
                                      unsatisfied );
  
          if( 0 != unsatisfied.size() )
          {
              final int size = unsatisfied.size();
              for( int i = 0; i < size; i++ )
              {
                  final Extension extension = (Extension)unsatisfied.get( i );
                  final Object[] params = new Object[]
                  {
                      extension.getExtensionName(),
                      extension.getSpecificationVendor(),
                      extension.getSpecificationVersion(),
                      extension.getImplementationVendor(),
                      extension.getImplementationVendorID(),
                      extension.getImplementationVersion(),
                      extension.getImplementationURL()
                  };
                  final String message = REZ.format( "missing.extension", params );
                  getLogger().warn( message );
              }
  
              final String message =
                  REZ.getString( "unsatisfied.extensions", new Integer( size ) );
              throw new Exception( message );
          }
  
          final OptionalPackage[] packages =
              (OptionalPackage[])dependencies.toArray( new OptionalPackage[ 0 ] );
          return OptionalPackage.toFiles( packages );
      }
  
      private Manifest[] getManifests( final String[] classPath )
          throws Exception
      {
          final ArrayList manifests = new ArrayList();
  
          for( int i = 0; i < classPath.length; i++ )
          {
              final String element = classPath[ i ];
              if( element.endsWith( ".jar" ) )
              {
                  try
                  {
                      final URL url = new URL( "jar:" + element + "!/" );
                      final JarURLConnection connection =
                          (JarURLConnection)url.openConnection();
                      final Manifest manifest = connection.getManifest();
                      manifests.add( manifest );
                  }
                  catch( final IOException ioe )
                  {
                      final String message =
                          REZ.getString( "bad-classpath-entry", element );
                      throw new EngineException(
                          message + ": " + element, ioe );
                  }
              }
          }
          return (Manifest[])manifests.toArray( new Manifest[ 0 ] );
      }
  
      RepositoryManager getParent()
      {
          return m_parent;
      }
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/EngineClassLoader.java
  
  Index: EngineClassLoader.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
  
  */
  
  package org.apache.avalon.assembly.engine;
  
  import java.io.File;
  import java.util.Map;
  import java.util.Hashtable;
  import java.net.URL;
  import java.net.URLClassLoader;
  
  import org.apache.avalon.framework.Version;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.logger.LogEnabled;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.DefaultContext;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.service.ServiceManager;
  import org.apache.avalon.framework.service.DefaultServiceManager;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.service.Serviceable;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.meta.info.DependencyDescriptor;
  import org.apache.avalon.meta.info.StageDescriptor;
  import org.apache.avalon.meta.info.ReferenceDescriptor;
  import org.apache.avalon.meta.info.Type;
  import org.apache.avalon.meta.model.Profile;
  import org.apache.avalon.assembly.type.TypeManager;
  import org.apache.avalon.assembly.profile.ProfileManager;
  import org.apache.avalon.assembly.appliance.Appliance;
  import org.apache.avalon.assembly.appliance.ApplianceManager;
  import org.apache.avalon.assembly.appliance.ApplianceFactory;
  import org.apache.avalon.assembly.appliance.AssemblyService;
  import org.apache.avalon.assembly.appliance.AssemblyException;
  import org.apache.avalon.assembly.appliance.DefaultAssemblyService;
  import org.apache.avalon.assembly.appliance.DefaultApplianceManager;
  import org.apache.avalon.assembly.appliance.DependencyGraph;
  import org.apache.avalon.assembly.appliance.MappedServiceManager;
  import org.apache.avalon.assembly.lifecycle.DeploymentService;
  import org.apache.avalon.assembly.lifecycle.DefaultDeploymentService;
  import org.apache.avalon.assembly.lifestyle.LifestyleException;
  import org.apache.avalon.assembly.lifestyle.LifestyleService;
  import org.apache.avalon.assembly.lifestyle.DefaultLifestyleService;
  import org.apache.avalon.assembly.lifestyle.LifestyleHandler;
  import org.apache.avalon.assembly.logging.LoggingManager;
  import org.apache.avalon.assembly.engine.model.LibraryDescriptor;
  import org.apache.avalon.assembly.engine.model.ClasspathDescriptor;
  import org.apache.excalibur.mpool.DefaultPoolManager;
  import org.apache.excalibur.mpool.PoolManager;
  import org.apache.excalibur.event.command.CommandManager;
  import org.apache.excalibur.event.command.TPCThreadManager;
  
  /**
   * 
   *
   * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:28 $
   */
  public class EngineClassLoader extends URLClassLoader implements Engine, LogEnabled, Configurable, Contextualizable, Serviceable, Initializable
  {
      //==============================================================
      // state
      //==============================================================
  
     /**
      * The supplied configuration.  The configuration may be empty
      * as defaults are provided for all values.
      */
      private DependencyGraph m_graph;
  
     /**
      * The supplied configuration.  The configuration may be empty
      * as defaults are provided for all values.
      */
      private Configuration m_config;
  
     /**
      * The system wide context where system refers to the context that
      * will be propergated by this engine to compoents under it 
      * supervision.
      */
      private Context m_context;
  
     /**
      * The appliance manager for this engine is a repository of the of the 
      * register appliance instances.  Each appliance in the registry is
      * fully assembled and verified.  Appliance instances encapsulte a 
      * component type, profile, lifestyle policy and service supporting 
      * component deployment.
      */
      private ApplianceManager m_appliances;
  
     /**
      * The repository maanger holds the service, types and profiels associated
      * with the class loader.
      */
      private RepositoryManager m_repository;
  
     /**
      * The lifestyle service.
      */
      private LifestyleService m_lifestyle;
  
     /**
      * The assembly service.
      */
      private AssemblyService m_assembly;
  
     /**
      * A map of custom context entries that suppliment the standard system 
      * context at the scope of this engine.  The map is supplied by a client
      * at the time of engine establishment via the engine context.
      */
      private Map m_map;
  
     /**
      * The default logging manager. The manager is supplied under contextualization
      * phase.
      */
      private LoggingManager m_logging;
  
     /**
      * The assigned logging channel.
      */
      private Logger m_logger;
  
     /**
      * The home directory.
      */
      private File m_home;
  
      /**
       * Description of the extension directories.
       */
      private LibraryDescriptor m_extensions;
  
      /**
       * Flag indicating if system classpath based bootstrapping should take place.
       */
      private Boolean m_bootstrap = new Boolean( false );
  
      /**
       * The set of facilities.
       */
      private Map m_facilities = new Hashtable();
  
      //=======================================================================
      // constructor
      //=======================================================================
  
      /**
       * Creation of a new type manager using the supplied parent class loader.
       * @param parent the parent class loader
       */
      public EngineClassLoader()
      {
          super( new URL[ 0 ] );
          m_graph = new DependencyGraph();
      }
  
      //=======================================================================
      // LogEnabled
      //=======================================================================
  
      /**
       * Sets the logging channel to the supplied value.
       * @param logger the logging channel to assign
       */
      public void enableLogging( Logger logger )
      {
          m_logger = logger;
      }
  
      /**
       * Returns the assigned logging channel
       * @return the logging channel
       */
      protected Logger getLogger()
      {
          return m_logger;
      }
  
  
      //==============================================================
      // Configurable
      //==============================================================
  
     /**
      * Supply of the static configuration for the deployment service.
      * @param config the static configuration
      */
      public void configure( Configuration config ) throws ConfigurationException
      {
          if( config == null )
          {
              throw new NullPointerException( "config" );
          }
      }
  
      //==============================================================
      // Contextualizable
      //==============================================================
  
     /**
      * <p>Application of a runtime context to the lifestyle service.
      * The context value will be passed directly to lifestyle handlers 
      * established by this service.
      * @param context the runtime context
      */
      public void contextualize( Context context ) throws ContextException
      {
          m_context = context;
  
          try
          {
              m_map = (Map) context.get( "urn:assembly:system-map" );
          }
          catch( ContextException ce )
          {
              // ignore
          }
  
          try
          {
              m_extensions = (LibraryDescriptor)context.get( "urn:assembly:extensions.descriptor" );
          }
          catch( ContextException e )
          {
              m_extensions = new LibraryDescriptor();
          }
  
          try
          {
              m_home = (File)context.get( "urn:avalon:home" );
          }
          catch( ContextException e )
          {
              m_home = new File( System.getProperty( "user.dir" ) );
          }
  
          try
          {
              m_bootstrap = (Boolean) context.get( "urn:assembly:engine.bootstrap" );
          }
          catch( ContextException e )
          {
              // default already set
          }
      }
  
      //==============================================================
      // Serviceable
      //==============================================================
  
     /**
      * <p>Application of a supporting service to the engine.</p>
      * <table>
      *   <tr>
      *     <td>key</td><td>type</td><td>description</td>
      *   </tr>
      *   <tr>
      *     <td>urn:assembly:logging.manager</td>
      *     <td>{@link org.apache.assembly.logging.LoggingManager}</td>
      *     <td>A logging manager.</td> 
      *   </tr>
      * </table>
      * @param manager the service manager
      */
      public void service( ServiceManager manager ) throws ServiceException
      {
          if( manager == null )
          {
              throw new NullPointerException( "manager" );
          }
  
          String key = "urn:assembly:logging.manager";
          m_logging = (LoggingManager) manager.lookup( key );
      }
  
      //==============================================================
      // Initializable
      //==============================================================
  
     /**
      * Initialization of the engine.
      * @exception if an initialization error occurs
      */
      public void initialize() throws Exception
      {
          if( getLogger() == null )
          {
              throw new IllegalStateException("logger");
          }
  
          if( m_logging == null )
          {
              throw new IllegalStateException("service");
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "initialization" );
          }
           
          m_repository = createRepositoryManager(); 
          m_lifestyle = createLifestyleService( m_facilities );
          m_appliances = createApplianceManager( m_facilities );
          m_assembly = createAssemblyService( m_facilities, m_graph );
                                       
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "ready" );
          }
      }
  
      //==============================================================
      // AssemblyService
      //==============================================================
  
     /**
      * Assemble the supplied appliance.
      * @param appliance the object to assembly
      */
      public void assemble( Appliance appliance ) throws AssemblyException
      {
          m_assembly.assemble( appliance );
      }
  
      //==============================================================
      // RepositoryManager
      //==============================================================
  
     /**
      * Add a URL to a jar file. A repository implementation is responsible for
      * the registration of any declared component services, types and packaged
      * profiles.
      *
      * @param url a url to a jar file
      */
      public void addLibrary( URL url )
      {
          m_repository.addLibrary( url );
      }
  
      /**
       * Add a classpath to the repository.
       * @param base the base directory from which relative classpath entries
       * will be resolved.
       * @param classpath the classpath descriptor
       */
      public void addClasspath( ClasspathDescriptor classpath )
      {
          m_repository.addClasspath( classpath );
      }
  
     /**
      * Returns the type manager.
      * @return the type manager
      */
      public TypeManager getTypeManager()
      {
          return m_repository.getTypeManager();
      }
  
     /**
      * Returns the service manager.
      * @return the service manager
      */
      public org.apache.avalon.assembly.service.ServiceManager getServiceManager()
      {
          return m_repository.getServiceManager();
      }
  
     /**
      * Returns the profile manager.
      * @return the profile manager
      */
      public ProfileManager getProfileManager()
      {
          return m_repository.getProfileManager();
      }
  
      //==============================================================
      // Engine
      //==============================================================
  
     /**
      * Creation of a new lifestyle handler.
      * @param appliance the appliance that the handler will manage
      * @param context the system context
      * @param map supplimentary deployment context
      */
      public LifestyleHandler createLifestyleHandler( Appliance appliance, Context context )
      {
          return m_lifestyle.createHandler( appliance, this, context );
      }
  
      /**
       * Add a URL to the classpath.
       * @param url the URL to add to the classpath
       */
      void addLibraryURL( URL url )
      {
          addURL( url );
      }
  
     /**
      * Register a type and associated profiles with the container.
      * @param path the path to the appliance implementation class
      * @return the appliance
      */
      public void register( String path ) throws EngineRuntimeException
      {
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "register:" + path );
          }
  
          try
          {
              Type type = getTypeManager().createType( path );
              getTypeManager().addType( type );
              Profile[] profiles = getProfileManager().loadProfiles( type );
              getProfileManager().addProfiles( profiles );
          }
          catch( Throwable e )
          {
              final String error = 
                "Failed to register one or more profiles.";
              throw new EngineRuntimeException( error, e );
          }
      }
  
     /**
      * Resolve an appliance capable of supporting a service 
      * referenced.
      *
      * @param dependency a service depedency descriptor
      * @return the appliance
      */
      public Appliance resolve( DependencyDescriptor dependency ) throws Exception
      {
          if( dependency == null )
          {
              throw new IllegalStateException( "dependency" );
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "resolve: " + dependency );
          }
          Appliance appliance = m_appliances.getAppliance( dependency );
          if( appliance == null )
          {
              Profile profile = getProfileManager().getProfile( dependency );
              if( profile == null )
              {
                  final String error = 
                    "No profiles matching the requested dependency: " 
                    + dependency;
                  throw new EngineException( error );
              }
              else
              {
                  return createAppliance( profile );
              }
          }
          return appliance;
      }
  
     /**
      * Resolve an appliance capable of supporting a referenced extension.
      *
      * @param stage a lifecycle stage descriptor
      * @return the appliance
      */
      public Appliance resolve( StageDescriptor stage ) throws Exception
      {
          if( stage == null )
          {
              throw new IllegalStateException( "stage" );
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "resolve: " + stage );
          }
  
          Appliance appliance = m_appliances.getAppliance( stage );
          if( appliance == null )
          {
              Profile profile = getProfileManager().getProfile( stage );
              if( profile == null )
              {
                  final String error = 
                    "No profiles matching the requested stage: " 
                    + stage;
                  throw new EngineException( error );
              }
              else
              {
                  appliance = createAppliance( profile );
              }
          }
          return appliance;
      }
  
     /**
      * Create a new shared appliance.
      * @param profile the component profile
      * @return the appliance
      */
      public Appliance createAppliance( Profile profile ) throws Exception
      {
          return createAppliance( profile, null );
      }
  
  
     /**
      * Create a new shared appliance.
      * @param profile the component profile
      * @param map supplimentary deployment context entries
      * @return the appliance
      */
      public Appliance createAppliance( Profile profile, Map map ) throws Exception
      {
          return createAppliance( profile, map, true );
      }
  
     /**
      * Create a new appliance.
      * @param profile the component profile
      * @param map supplimentary deployment context entries
      * @param shared TRUE if this appliance may be shared
      * @return the appliance
      */
      public Appliance createAppliance( Profile profile, Map map, boolean shared ) throws Exception
      {
          ApplianceFactory factory = m_appliances.getApplianceFactory( profile );
          Appliance appliance = factory.createAppliance( this, profile, true, true, getSystemContext(), map );
          if( shared )
          {
              m_appliances.addAppliance( appliance );
          }
          return appliance;
      }
  
      //==============================================================
      // utilities
      //==============================================================
  
      private RepositoryManager createRepositoryManager() throws Exception
      {
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "creating repository manager" );
          }
  
          DefaultRepositoryManager manager = new DefaultRepositoryManager();
  
          manager.enableLogging( getLogger() );
          DefaultContext context = new DefaultContext( getSystemContext() );
          context.put( "urn:assembly:engine.classloader", this );
          context.put( "urn:assembly:libraries-descriptor", m_extensions );
          context.put( "urn:assembly:engine.bootstrap", m_bootstrap );
          context.put( "urn:avalon:home", m_home );
          context.makeReadOnly();
          manager.contextualize( context );
          manager.initialize();
  
          return manager;
      }
  
      private ApplianceManager createApplianceManager( Map facilities ) 
        throws Exception
      {
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "creating appliance manager" );
          }
  
          DefaultApplianceManager manager = new DefaultApplianceManager();
  
          manager.enableLogging( getLogger() );
          manager.contextualize( new DefaultContext() ); // <-- placeholder for parent manager
          DefaultServiceManager services = new DefaultServiceManager();
          services.put( "urn:assembly:engine.classloader", this );
          services.makeReadOnly();
          manager.service( services );
          manager.initialize();
          return manager;
      }
  
     /**
      * Utility to create the default lifestyle service.
      * @param manager a service manager
      * @return the bootstrap lifestyle service
      */
      private LifestyleService createLifestyleService( Map facilities ) throws Exception
      {
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "creating lifestyle service" );
          }
  
          DeploymentService deployment = bootstrapDeploymentService( facilities );
  
          DefaultLifestyleService lifestyle = new DefaultLifestyleService();
          lifestyle.enableLogging( getLogger().getChildLogger( "lifestyle" ) );
          DefaultServiceManager manager = new DefaultServiceManager();
          manager.put( "urn:assembly:lifecycle.deployment", deployment );
          manager.put( "urn:assembly:engine.classloader", this );
          manager.makeReadOnly();
          lifestyle.service( manager );
          DefaultContext context = new DefaultContext();
          context.put( "urn:assembly:pool-manager", getPoolManager( ) );
          context.makeReadOnly();
          lifestyle.contextualize( context );
          lifestyle.initialize();
          return lifestyle;
      }
  
      private DeploymentService bootstrapDeploymentService( Map facilities ) 
        throws ServiceException
      {
          try
          {
              DefaultDeploymentService deployment = new DefaultDeploymentService();
              deployment.enableLogging( getLogger() );
              MappedServiceManager manager = new MappedServiceManager( facilities );
              manager.put("urn:assembly:logging.manager", m_logging );
              manager.put("urn:assembly:engine.classloader", this );
              deployment.service( manager );
              deployment.contextualize( new DefaultContext() );
              deployment.initialize();
              return deployment;
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while attempting to create bootstrap deployment service.";
              throw new ServiceException( error, e );
          }
      }
  
     /**
      * Utility to create the default assembly service.
      * @param manager a service manager
      * @return the bootstrap assembly service
      */
      private AssemblyService createAssemblyService( Map facilities, DependencyGraph map ) 
        throws ServiceException
      {
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "creating assembly service" );
          }
  
          try
          {
              DefaultAssemblyService assembly = new DefaultAssemblyService();
              assembly.enableLogging( getLogger().getChildLogger( "assembly" ) );
              MappedServiceManager manager = new MappedServiceManager( facilities );
              manager.put("urn:assembly:engine.classloader", this );
              assembly.service( manager );
              DefaultContext context = new DefaultContext();
              if( map != null )
              {
                  context.put( "urn:assembly:dependency-map", map );
              }
              assembly.contextualize( context );
              assembly.initialize();
              return assembly;
          }
          catch( Throwable e )
          {
              final String error = "Internal error while preparing boostrap assembly service.";
              throw new ServiceException( "urn:assembly:assembly-service", error, e );
          }
      }
  
      private Context getSystemContext()
      {
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "bootstrap system context" );
          }
  
          DefaultContext context;
          if( m_map != null )
          {
              context = new DefaultContext( m_map );
          }
          else
          {
              context = new DefaultContext();
          }
  
          try
          {
              context.get( "urn:avalon:home" );
          }
          catch( ContextException ce )
          {
              final File home = new File( System.getProperty( "user.dir" ) );
              context.put( "urn:avalon:home", home );    
          }
          return context;
      }
  
      private PoolManager getPoolManager( )
      {
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "bootstrap pool manager" );
          }
  
          try
          {
              //
              // Set up the ThreadManager that the CommandManager uses
              //
  
              TPCThreadManager threadManager = new TPCThreadManager();
              threadManager.enableLogging( getLogger().getChildLogger( "threads" ) );
              Parameters params = new Parameters();
              params.setParameter( "threads-per-processor", "2" );
              params.setParameter( "sleep-time", "1000" );
              params.setParameter( "block-timeout", "250" );
              threadManager.parameterize( params );
              threadManager.initialize();
  
              //
              // Set up the CommandManager that the PoolManager uses.
              //
  
              CommandManager commandManager = new CommandManager();
              threadManager.register( commandManager );
  
              //
              // Set up the PoolManager that the pooled lifecycle helper needs
              //
  
              DefaultPoolManager poolManager = 
                new DefaultPoolManager( commandManager.getCommandSink() );
              return poolManager;
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error during establishment of the default pool manager.";
              throw new EngineRuntimeException( error, e );
          }
      }
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/RepositoryManager.java
  
  Index: RepositoryManager.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
  
  */
  
  package org.apache.avalon.assembly.engine;
  
  import java.net.URL;
  
  import org.apache.avalon.assembly.profile.ProfileManager;
  import org.apache.avalon.assembly.service.ServiceManager;
  import org.apache.avalon.assembly.type.TypeManager;
  import org.apache.avalon.assembly.engine.model.ClasspathDescriptor;
  
  /**
   * An appliance is a class that encapsulates the deployment criteria
   * for a particular component together with a the state supporting 
   * component assembly and dependency solutions.  The function of an appliace
   * is to server as the aggregation point for the deployment of a component
   * and the access point for services provided by the component implemetation.
   *
   * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:28 $
   */ 
  
  public interface RepositoryManager
  {
     /**
      * Add a URL to a jar file. A repository implementation is responsible for
      * the registration of any declared component services, types and packaged
      * profiles.
      *
      * @param url a url to a jar file
      */
      void addLibrary( URL url );
  
      /**
       * Add a classpath to the repository.
       * @param base the base directory from which relative classpath entries
       * will be resolved.
       * @param classpath the classpath descriptor
       */
      void addClasspath( ClasspathDescriptor classpath );
  
     /**
      * Returns the type manager.
      * @return the type manager
      */
      TypeManager getTypeManager();
  
     /**
      * Returns the service manager.
      * @return the service manager
      */
      ServiceManager getServiceManager();
  
     /**
      * Returns the profile manager.
      * @return the profile manager
      */
      ProfileManager getProfileManager();
  
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/model/ClasspathDescriptor.java
  
  Index: ClasspathDescriptor.java
  ===================================================================
  /* ==================================================================== 
   * The Apache Software License, Version 1.1 
   * 
   * Copyright (c) 2002 The Apache Software Foundation. All rights 
   * reserved. 
   * 
   * Redistribution and use in source and binary forms, with or without 
   * modification, are permitted provided that the following conditions 
   * are met: 
   * 
   * 1. Redistributions of source code must retain the above copyright 
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software 
   *    itself, if and wherever such third-party acknowledgments  
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation" 
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see 
   * <http://www.apache.org/>.
   */ 
  
  package org.apache.avalon.assembly.engine.model;
  
  import java.io.Serializable;
  
  /**
   * <p>A classpath descriptor that describes a scoped set of jar files.
   * A classpath contains 0-n {@link FilesetDescriptor} instances.</p>
   *
   * <p><b>XML</b></p>
   * <p>The XML form for a classpath description is shown below. The classpath element contains
   * no attributes.  The element may contain multiple fileset elements that collectively define
   * the scope of the classpath.
   * </p>
   * <pre>
   *    &lt;classpath&gt;
   *
   *      <font color="gray"><i>&lt;!--
   *      Declaration of multiple filesets.
   *      --&gt;</i></font>
   *
   *      &lt;fileset dir=<font color="darkred">"dist"</font>&gt;
   *        &lt;include name="<font color="darkred">demo.jar</font>"/&gt;
   *        &lt;include name="<font color="darkred">new-application-1.0.jar</font>"/&gt;
   *      &lt;/fileset&gt;
   *
   *      &lt;fileset dir="<font color="darkred">lib</font>"&gt;
   *        &lt;include name="<font color="darkred">avalon-framework.jar</font>"/&gt;
   *      &lt;/fileset&gt;
   *
   *    &lt;/classpath&gt;
   * </pre>
   *
   * @see FilesetDescriptor
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:28 $
   */
  public class ClasspathDescriptor implements Serializable
  {
      /**
       * The collection of filesets.
       */
      private final FilesetDescriptor[] m_filesets;
  
      /**
       * Create an empty ClasspathDescriptor instance.
       *
       */
      public ClasspathDescriptor()
      {
          this( new FilesetDescriptor[ 0 ] );
      }
  
      /**
       * Create a ClasspathDescriptor instance.
       *
       * @param filesets the set of filesets to include in the classpath
       */
      public ClasspathDescriptor( final FilesetDescriptor[] filesets )
      {
          m_filesets = filesets;
      }
  
      /**
       * Return the filesets held within the classpath descriptor.
       *
       * @return the filesets
       */
      public FilesetDescriptor[] getFilesetDescriptors()
      {
          return m_filesets;
      }
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/model/EngineConfigurationHelper.java
  
  Index: EngineConfigurationHelper.java
  ===================================================================
  /* ==================================================================== 
   * The Apache Software License, Version 1.1 
   * 
   * Copyright (c) 2002 The Apache Software Foundation. All rights 
   * reserved. 
   * 
   * Redistribution and use in source and binary forms, with or without 
   * modification, are permitted provided that the following conditions 
   * are met: 
   * 
   * 1. Redistributions of source code must retain the above copyright 
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software 
   *    itself, if and wherever such third-party acknowledgments  
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation" 
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see 
   * <http://www.apache.org/>.
   */ 
  
  package org.apache.avalon.assembly.engine.model;
  
  import java.io.InputStream;
  import java.util.ArrayList;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Array;
  
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.configuration.DefaultConfiguration;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.meta.ConfigurationBuilder;
  import org.apache.avalon.meta.info.Type;
  import org.apache.avalon.meta.model.LoggingDirective;
  import org.apache.avalon.meta.model.Category;
  import org.apache.avalon.meta.model.ContextDirective;
  import org.apache.avalon.meta.model.Entry;
  import org.apache.avalon.meta.model.Import;
  import org.apache.avalon.meta.model.Mode;
  import org.apache.avalon.meta.model.Profile;
  import org.xml.sax.InputSource;
  
  /**
   * Handles internalization of an XML based description of a {@link Profile}
   * from a Configuration object. The format for Configuration object
   * is specified in the <a href="package-summary.html#external">package summary</a>.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:28 $
   */
  public class EngineConfigurationHelper
  {
  
      /**
       * Utility method to create a new classpath descriptor from a
       * configuration instance.
       * @param config a configuration defining the classpath
       * @return the classpath descriptor
       * @exception ConfigurationException if the configuration is
       *   incomplete
       */
      public static ClasspathDescriptor createClasspathDescriptor( Configuration config )
          throws ConfigurationException
      {
          ArrayList list = new ArrayList();
          Configuration[] configs = config.getChildren( "fileset" );
          for( int i = 0; i < configs.length; i++ )
          {
              Configuration c = configs[ i ];
              list.add( createFilesetDescriptor( c ) );
          }
          FilesetDescriptor[] filesets =
              (FilesetDescriptor[])list.toArray( new FilesetDescriptor[ 0 ] );
          return new ClasspathDescriptor( filesets );
      }
  
      /**
       * Utility method to create a new fileset descriptor from a
       * configuration instance.
       * @param config a configuration defining the fileset
       * @return the fileset descriptor
       * @exception ConfigurationException if the configuration is
       *   incomplete
       */
      public static FilesetDescriptor createFilesetDescriptor( Configuration config )
          throws ConfigurationException
      {
          String base = config.getAttribute( "dir" );
          ArrayList list = new ArrayList();
          Configuration[] includeConfigs = config.getChildren( "include" );
          for( int i = 0; i < includeConfigs.length; i++ )
          {
              Configuration includeConfig = includeConfigs[ i ];
              list.add( createIncludeDescriptor( includeConfig ) );
          }
          IncludeDescriptor[] includes =
              (IncludeDescriptor[])list.toArray( new IncludeDescriptor[ 0 ] );
          return new FilesetDescriptor( base, includes );
      }
  
      /**
       * Utility method to create a new include descriptor from a
       * configuration instance.
       * @param config a configuration defining the include descriptor
       * @return the include descriptor
       * @exception ConfigurationException if the configuration is
       *   incomplete
       */
      public static IncludeDescriptor createIncludeDescriptor( Configuration config )
          throws ConfigurationException
      {
          String filename = config.getAttribute( "name" );
          return new IncludeDescriptor( filename );
      }
  
      /**
       * Utility method to create a new jar file extension library
       * descriptor from a configuration instance.
       * @param config a configuration defining the library descriptor
       * @return the library descriptor
       * @exception ConfigurationException if the configuration is
       *   incomplete
       */
      public static LibraryDescriptor createLibraryDescriptor( Configuration config )
          throws ConfigurationException
      {
  
          if( config == null )
          {
              return new LibraryDescriptor();
          }
  
          String base = config.getAttribute( "dir" );
  
          ArrayList list = new ArrayList();
          Configuration[] configs = config.getChildren( "include" );
          for( int i = 0; i < configs.length; i++ )
          {
              Configuration c = configs[ i ];
              list.add( createIncludeDescriptor( c ) );
          }
          IncludeDescriptor[] dirs =
              (IncludeDescriptor[])list.toArray( new IncludeDescriptor[ 0 ] );
          return new LibraryDescriptor( base, dirs );
      }
  
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/model/FilesetDescriptor.java
  
  Index: FilesetDescriptor.java
  ===================================================================
  /* ==================================================================== 
   * The Apache Software License, Version 1.1 
   * 
   * Copyright (c) 2002 The Apache Software Foundation. All rights 
   * reserved. 
   * 
   * Redistribution and use in source and binary forms, with or without 
   * modification, are permitted provided that the following conditions 
   * are met: 
   * 
   * 1. Redistributions of source code must retain the above copyright 
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software 
   *    itself, if and wherever such third-party acknowledgments  
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation" 
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see 
   * <http://www.apache.org/>.
   */ 
  
  package org.apache.avalon.assembly.engine.model;
  
  import java.io.Serializable;
  
  /**
   * <p>A fileset descriptor is a scoped defintion of a set of files.  A fileset
   * a structurally defined as a base directory and a set of relative filenames
   * represented as include directives.</p>
   *
   * <p><b>XML</b></p>
   * <pre>
   *   &lt;fileset dir="<font color="darkred">lib</font>"&gt;
   *     &lt;include name="<font color="darkred">avalon-framework.jar</font>"/&gt;
   *     &lt;include name="<font color="darkred">logkit.jar</font>"/&gt;
   *   &lt;/dirset&gt;
   * </pre>
   *
   * @see IncludeDescriptor
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:28 $
   */
  public class FilesetDescriptor implements Serializable
  {
      /**
       * The base directory from which include directives will be resolved.
       */
      private final String m_base;
  
      /**
       * The set of include directives.
       */
      private final IncludeDescriptor[] m_includes;
  
      /**
       * Create a FilesetDescriptor instance.
       *
       * @param base the base directory path against which includes are evaluated
       * @param includes the set of includes to include in the fileset
       */
      public FilesetDescriptor( final String base, final IncludeDescriptor[] includes )
      {
          m_base = base;
          m_includes = includes;
      }
  
      /**
       * Return the base directory.
       *
       * @return the directory
       */
      public String getBaseDirectory()
      {
          return m_base;
      }
  
      /**
       * Return the filesets held within the classpath descriptor.
       *
       * @return the filesets
       */
      public IncludeDescriptor[] getIncludeDescriptors()
      {
          return m_includes;
      }
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/model/IncludeDescriptor.java
  
  Index: IncludeDescriptor.java
  ===================================================================
  /* ==================================================================== 
   * The Apache Software License, Version 1.1 
   * 
   * Copyright (c) 2002 The Apache Software Foundation. All rights 
   * reserved. 
   * 
   * Redistribution and use in source and binary forms, with or without 
   * modification, are permitted provided that the following conditions 
   * are met: 
   * 
   * 1. Redistributions of source code must retain the above copyright 
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software 
   *    itself, if and wherever such third-party acknowledgments  
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation" 
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see 
   * <http://www.apache.org/>.
   */ 
  
  package org.apache.avalon.assembly.engine.model;
  
  import java.io.Serializable;
  
  /**
   * <p>An file include directive.</p>
   * <p><b>XML</b></p>
   * <p>An include element is normally contained within a scoping structure such as a
   * fileset or directory set. The include element contains the single attribute name
   * which is used to refer to the file or directory (depending on the containing
   * context.</p>
   * <pre>
   *    <font color="gray">&lt;fileset dir="lib"&gt;</font>
   *       &lt;include name="<font color="darkred">avalon-framework.jar</font>" /&gt;
   *    <font color="gray">&lt;/fileset&gt;</font>
   * </pre>
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:28 $
   */
  public class IncludeDescriptor implements Serializable
  {
      /**
       * The base directory
       */
      private final String m_file;
  
      /**
       * Create a FilesetDescriptor instance.
       *
       * @param file the filename
       */
      public IncludeDescriptor( final String file )
      {
          m_file = file;
      }
  
      /**
       * Return the included filename.
       *
       * @return the file
       */
      public String getFile()
      {
          return m_file;
      }
  
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/model/LibraryDescriptor.java
  
  Index: LibraryDescriptor.java
  ===================================================================
  /* ==================================================================== 
   * The Apache Software License, Version 1.1 
   * 
   * Copyright (c) 2002 The Apache Software Foundation. All rights 
   * reserved. 
   * 
   * Redistribution and use in source and binary forms, with or without 
   * modification, are permitted provided that the following conditions 
   * are met: 
   * 
   * 1. Redistributions of source code must retain the above copyright 
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software 
   *    itself, if and wherever such third-party acknowledgments  
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation" 
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see 
   * <http://www.apache.org/>.
   */ 
  
  package org.apache.avalon.assembly.engine.model;
  
  
  /**
   * <p>An descriptor that declares a set of directories to be
   * referenced as the installed extension directories.  An extensions descriptor
   * may contain multiple {@link IncludeDescriptor} instances.</p>
   *
   * <p><b>XML</b></p>
   * <pre>
   *   &lt;library dir="<font color="darkred">sys</font>"&gt;
   *     &lt;include name="<font color="darkred">extensions</font>"/&gt;
   *     &lt;include name="<font color="darkred">lib</font>"/&gt;
   *   &lt;/library&gt;
   * </pre>
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/12/07 09:34:28 $
   */
  public class LibraryDescriptor extends FilesetDescriptor
  {
  
      /**
       * Create a LibraryDescriptor instance.
       */
      public LibraryDescriptor()
      {
          super( ".", new IncludeDescriptor[ 0 ] );
      }
  
      /**
       * Create a LibraryDescriptor instance.
       *
       * @param base the directory path against which include directives will be evaluated
       * @param includes the set of include directives
       */
      public LibraryDescriptor( final String base, final IncludeDescriptor[] includes )
      {
          super( base, includes );
      }
  
  }
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/model/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  key=value: {0}
  
  
  
  
  1.1                  avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/model/package.html
  
  Index: package.html
  ===================================================================
  
  <body>
  <p>
  The <code>model</code> package contains the extensions directory and classpath structures used as parameters with the service management engine.
  </p>
  </body>
  
  
  
  1.3       +146 -8    avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifecycle/ContextHandler.java
  
  Index: ContextHandler.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifecycle/ContextHandler.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ContextHandler.java	3 Dec 2002 06:57:26 -0000	1.2
  +++ ContextHandler.java	7 Dec 2002 09:34:28 -0000	1.3
  @@ -54,12 +54,18 @@
   import java.lang.reflect.Constructor;
   import java.util.HashMap;
   
  +import org.apache.avalon.framework.activity.Initializable;
   import org.apache.avalon.framework.context.Contextualizable;
   import org.apache.avalon.framework.context.Context;
   import org.apache.avalon.framework.context.DefaultContext;
   import org.apache.avalon.framework.context.ContextException;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
  +import org.apache.avalon.framework.service.ServiceManager;
  +import org.apache.avalon.framework.service.DefaultServiceManager;
  +import org.apache.avalon.framework.service.ServiceException;
  +import org.apache.avalon.framework.service.Serviceable;
   import org.apache.avalon.assembly.appliance.Appliance;
  +import org.apache.avalon.assembly.engine.EngineClassLoader;
   import org.apache.avalon.meta.model.Entry;
   import org.apache.avalon.meta.model.Import;
   import org.apache.avalon.meta.model.Profile;
  @@ -76,7 +82,7 @@
    * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
    * @version $Revision$ $Date$
    */
  -public class ContextHandler extends AbstractLogEnabled implements Contextualizable
  +public class ContextHandler extends AbstractLogEnabled implements Contextualizable, Serviceable, Initializable
   {
       //==============================================================
       // state
  @@ -84,7 +90,11 @@
   
       private Context m_context;
   
  -    private ClassLoader m_classloader;
  +    private EngineClassLoader m_classloader;
  +
  +    private ServiceManager m_manager;
  +
  +    private boolean m_initialized = false;
   
       //==============================================================
       // Contextualizable
  @@ -100,7 +110,69 @@
       public void contextualize( Context context ) throws ContextException
       {
           m_context = context;
  -        m_classloader = (ClassLoader) context.get( "urn:assembly:classloader" );
  +        //m_classloader = (ClassLoader) context.get( "urn:assembly:classloader" );
  +    }
  +
  +    //==============================================================
  +    // Serviceable
  +    //==============================================================
  +
  +   /**
  +    * <p>Application of a supporting service to the deployment service.</p>
  +    * <table>
  +    *   <tr>
  +    *     <td>key</td><td>type</td><td>description</td>
  +    *   </tr>
  +    *   <tr>
  +    *     <td>urn:assembly:lifecycle.logging</td>
  +    *     <td>{@link org.apache.avalon.assembly.logging.LoggingService}</td>
  +    *     <td>The logging service to use for the creation of auxiliary logging channels.</td> 
  +    *   </tr>
  +    * </table>
  +    * @param context the runtime context
  +    */
  +    public void service( ServiceManager manager ) throws ServiceException
  +    {
  +        if( manager == null )
  +        {
  +            throw new NullPointerException( "manager" );
  +        }
  +
  +        final String key = "urn:assembly:engine.classloader";
  +        if( !manager.hasService( key ) )
  +        {
  +            throw new ServiceException( key );
  +        }
  +        m_manager = manager;
  +    }
  +
  +    //==============================================================
  +    // Initializable
  +    //==============================================================
  +
  +   /**
  +    * Initialization fo the component by the container.  The implementation
  +    * validates a logger has been assigned and that the contextulization and
  +    * servicing phases have been executed.
  +    *
  +    * @exception Exception if the manager has not been propery established.
  +    */
  +    public void initialize() throws Exception
  +    {
  +        if( getLogger() == null )
  +        {
  +            throw new IllegalStateException("logger");
  +        }
  +        if( m_context == null )
  +        {
  +            throw new IllegalStateException("contextualize");
  +        }
  +        if( m_manager == null )
  +        {
  +            throw new IllegalStateException("service");
  +        }
  +
  +        m_initialized = true;
       }
   
       //==============================================================
  @@ -108,6 +180,37 @@
       //==============================================================
   
       /**
  +     * Returns the assembly engine.
  +     * @return the assembly engine
  +     * @exception IllegalStateException if a client attempts to access
  +     *   the engine prior to completion of initialization.
  +     */
  +     protected EngineClassLoader getClassLoader()
  +     {
  +         if( !m_initialized )
  +         {
  +             throw new IllegalStateException( "initialization" );
  +         }
  +
  +         if( m_classloader != null )
  +         {
  +             return m_classloader;
  +         }
  +
  +         final String key = "urn:assembly:engine.classloader";
  +         try
  +         {
  +             m_classloader = (EngineClassLoader) m_manager.lookup( key );
  +             return m_classloader;
  +         }
  +         catch( ServiceException se )
  +         {
  +             // should not happen
  +             throw new IllegalStateException( key );
  +         }
  +     }
  +
  +    /**
        * Internal utility to construct a context instance using a descriptor, directive and source
        * context instances.
        *
  @@ -126,6 +229,11 @@
                              Context context )
         throws Exception
       {
  +        if( !m_initialized )
  +        {
  +            throw new IllegalStateException( "initialization" );
  +        }
  +
           Map map = new HashMap();
           Context result;
   
  @@ -135,7 +243,7 @@
               Class clazz;
               try
               {
  -                clazz = m_classloader.loadClass( classname );
  +                clazz = getClassLoader().loadClass( classname );
               }
               catch( ClassNotFoundException cnfe )
               {
  @@ -198,7 +306,18 @@
                               final String error =
                                   "Import directive for key: " + key + " via name: " + name
                                   + " cannot be resolved.";
  -                            getLogger().warn( error );
  +
  +                            if( entry.isRequired() )
  +                            {
  +                                throw new ContextException( error );
  +                            }
  +                            else
  +                            {
  +                                if( getLogger().isWarnEnabled() )
  +                                {
  +                                    getLogger().warn( error );
  +                                }
  +                            }
                           }
                       }
   
  @@ -216,7 +335,26 @@
                           Entry ent = directive.getEntry( key );
                           if( ent != null )
                           {
  -                            object = ent.getValue( m_classloader, map );
  +                            object = ent.getValue( getClassLoader(), map );
  +                            if( object == null )
  +                            {
  +                                final String error =
  +                                  "Unable to build a context value for the entry: '" 
  +                                  + key + "' type: "
  +                                  + entry.getType();
  +
  +                                if( entry.isRequired() )
  +                                {
  +                                    throw new ContextException( error );
  +                                }
  +                                else
  +                                {
  +                                    if( getLogger().isWarnEnabled() )
  +                                    {
  +                                        getLogger().warn( error );
  +                                    }
  +                                }
  +                            }
                           }
                       }
                   }
  @@ -334,7 +472,7 @@
           }
   
           final Class clazz = value.getClass();
  -        final Class typeClass = m_classloader.loadClass( type );
  +        final Class typeClass = getClassLoader().loadClass( type );
           return typeClass.isAssignableFrom( clazz );
       }
   }
  
  
  
  1.4       +13 -1     avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifecycle/DefaultDeploymentService.java
  
  Index: DefaultDeploymentService.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifecycle/DefaultDeploymentService.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DefaultDeploymentService.java	3 Dec 2002 06:57:26 -0000	1.3
  +++ DefaultDeploymentService.java	7 Dec 2002 09:34:28 -0000	1.4
  @@ -176,6 +176,12 @@
               throw new NullPointerException( "manager" );
           }
   
  +        final String classloaderkey = "urn:assembly:engine.classloader";
  +        if( !manager.hasService( classloaderkey ) )
  +        {
  +            throw new ServiceException( classloaderkey );
  +        }
  +
           m_manager = manager;
   
           String key = "urn:assembly:lifecycle.logging";
  @@ -435,6 +441,8 @@
               DefaultContextualizationService service = new DefaultContextualizationService();
               service.enableLogging( getLogger().getChildLogger( "context" ) );
               service.contextualize( m_context );
  +            service.service( m_manager );
  +            service.initialize();
               return service;
           }
           catch( Throwable e )
  @@ -470,6 +478,8 @@
                   ExtendedInitializationService service = new ExtendedInitializationService();
                   service.enableLogging( getLogger().getChildLogger( "init" ) );
                   service.contextualize( m_context );
  +                service.service( m_manager );
  +                service.initialize();
                   return service;
               }
               else
  @@ -512,6 +522,8 @@
                   ExtendedDisposalService service = new ExtendedDisposalService();
                   service.enableLogging( getLogger().getChildLogger( "disposal" ) );
                   service.contextualize( m_context );
  +                service.service( m_manager );
  +                service.initialize();
                   return service;
               }
               else
  
  
  
  1.5       +2 -2      avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifecycle/initialization/ExtendedInitializationService.java
  
  Index: ExtendedInitializationService.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifecycle/initialization/ExtendedInitializationService.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ExtendedInitializationService.java	30 Nov 2002 18:12:06 -0000	1.4
  +++ ExtendedInitializationService.java	7 Dec 2002 09:34:28 -0000	1.5
  @@ -169,7 +169,7 @@
                   catch( Throwable e )
                   {
                       final String error = 
  -                      "Extension handler context establiahment error on appliance: '"
  +                      "Extension handler context establishment error on appliance: '"
                         + appliance 
                         + "' under stage: '" + stage
                         + "' for provider: '" + provider;
  
  
  
  1.7       +4 -2      avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifestyle/AbstractLifestyleHandler.java
  
  Index: AbstractLifestyleHandler.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifestyle/AbstractLifestyleHandler.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- AbstractLifestyleHandler.java	3 Dec 2002 06:57:26 -0000	1.6
  +++ AbstractLifestyleHandler.java	7 Dec 2002 09:34:28 -0000	1.7
  @@ -171,7 +171,8 @@
       */
       public void service( ServiceManager manager ) throws ServiceException
       {
  -        m_deployment = (DeploymentService) manager.lookup( "urn:assembly:deployment-service" );
  +        super.service( manager );
  +        m_deployment = (DeploymentService) manager.lookup( "urn:assembly:lifecycle.deployment" );
       }
   
       //==============================================================
  @@ -187,6 +188,7 @@
       */
       public void initialize() throws Exception 
       {
  +        super.initialize();
           if( getLogger() == null )
           {
               throw new LifestyleException("logger");
  
  
  
  1.4       +18 -31    avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifestyle/DefaultLifestyleService.java
  
  Index: DefaultLifestyleService.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifestyle/DefaultLifestyleService.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DefaultLifestyleService.java	3 Dec 2002 06:57:26 -0000	1.3
  +++ DefaultLifestyleService.java	7 Dec 2002 09:34:28 -0000	1.4
  @@ -105,6 +105,11 @@
       */
       private Configuration m_config;
   
  +   /**
  +    * The supplied static configuration.
  +    */
  +    private DeploymentService m_deployment;
  +
       //==============================================================
       // Configurable
       //==============================================================
  @@ -136,7 +141,18 @@
           {
               throw new NullPointerException( "manager" );
           }
  +
  +        final String engineKey = "urn:assembly:engine.classloader";
  +        if( !manager.hasService( engineKey ) )
  +        {
  +            throw new ServiceException( engineKey );
  +        }
  +
           m_manager = manager;
  +
  +        m_deployment = 
  +         (DeploymentService) manager.lookup( "urn:assembly:lifecycle.deployment" );
  +
       }
   
       //==============================================================
  @@ -172,20 +188,11 @@
           {
               throw new IllegalStateException("context");
           }
  -        if( m_manager == null )
  +        if( m_deployment == null )
           {
               throw new IllegalStateException("manager");
           }
   
  -        String key = "urn:assembly:deployment-service";
  -        if( !m_manager.hasService( key ) )
  -        {
  -            DefaultServiceManager manager = new DefaultServiceManager( m_manager );
  -            manager.put( key, bootstrapDeploymentService( m_manager ) );
  -            manager.makeReadOnly();
  -            m_manager = manager;
  -        }
  -
           m_initialized = true;
       }
   
  @@ -298,26 +305,6 @@
                 "Lifestyle policy argument '" + policy + "' within appliance: " 
                 + appliance + "' is not recognized.";
               throw new LifestyleRuntimeException( error );
  -        }
  -    }
  -
  -    private DeploymentService bootstrapDeploymentService( ServiceManager manager ) 
  -      throws ServiceException
  -    {
  -        try
  -        {
  -            DefaultDeploymentService deployment = new DefaultDeploymentService();
  -            deployment.enableLogging( getLogger() );
  -            deployment.service( manager );
  -            deployment.contextualize( m_context );
  -            deployment.initialize();
  -            return deployment;
  -        }
  -        catch( Throwable e )
  -        {
  -            final String error = 
  -              "Internal error while attempting to create bootstrap deployment service.";
  -            throw new ServiceException( error, e );
           }
       }
   }
  
  
  
  1.4       +343 -50   avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/profile/ProfileManager.java
  
  Index: ProfileManager.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/profile/ProfileManager.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ProfileManager.java	29 Nov 2002 13:04:56 -0000	1.3
  +++ ProfileManager.java	7 Dec 2002 09:34:28 -0000	1.4
  @@ -50,31 +50,132 @@
   
   package org.apache.avalon.assembly.profile;
   
  +import java.util.Hashtable;
  +import java.util.ArrayList;
  +import java.util.Enumeration;
  +
  +import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.avalon.framework.configuration.Configuration;
  +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.activity.Initializable;
  +import org.apache.avalon.assembly.type.TypeManager;
   import org.apache.avalon.assembly.type.UnknownTypeException;
  +import org.apache.excalibur.configuration.ConfigurationUtil;
   import org.apache.avalon.meta.model.Profile;
  -import org.apache.avalon.meta.info.Type;
  +import org.apache.avalon.meta.model.builder.ProfileBuilder;
  +import org.apache.avalon.meta.model.verifier.ProfileVerifier;
  +import org.apache.avalon.meta.info.ReferenceDescriptor;
   import org.apache.avalon.meta.info.DependencyDescriptor;
   import org.apache.avalon.meta.info.StageDescriptor;
  +import org.apache.avalon.meta.info.Type;
   
   /**
    * A profile manager implemetation provides support for the creation, 
  - * storage and retrival of component profiles.
  + * storage and retrival of component types.
    *
    * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
    * @version $Revision$ $Date$
    */
  -public interface ProfileManager 
  +public class ProfileManager extends AbstractLogEnabled 
   {
  +    //==============================================================
  +    // static
  +    //==============================================================
  +
  +   /**
  +    * The profile builder.
  +    */
  +    private static final ProfileBuilder PROFILE_BUILDER = new ProfileBuilder();
  +
  +    //==============================================================
  +    // state
  +    //==============================================================
  +
  +   /**
  +    * The classloader supplied to the manager.
  +    */
  +    private ClassLoader m_classloader;
  +
  +   /**
  +    * The parent profile manager (may be null)
  +    */
  +    private ProfileManager m_parent;
  +
  +    /**
  +     * Table of component profiles keyed by profile name.
  +     */
  +    private final Hashtable m_profiles = new Hashtable();
  +
  +   /**
  +    * The default profile selector.
  +    */
  +    private final DefaultProfileSelector m_selector = new DefaultProfileSelector();
  +
  +    //==============================================================
  +    // constructor
  +    //==============================================================
  +
  +   /**
  +    * Creation of a new root profile manager.
  +    * @param classloader the classloder to use
  +    * @exception NullPointerException if the classloader is null
  +    */
  +    public ProfileManager( ClassLoader classloader ) throws NullPointerException
  +    {
  +        this( classloader, null );
  +    }
  +
  +   /**
  +    * Creation of a new profile manager.
  +    * @param classloader the classloder to use
  +    * @param parent the parent type manager
  +    * @exception NullPointerException if the classloader is null
  +    */
  +    public ProfileManager( ClassLoader classloader, ProfileManager parent ) throws NullPointerException
  +    {
  +        if( classloader == null )
  +        {
  +            throw new NullPointerException("classloader");
  +        }
  +        m_classloader = classloader;
  +        m_parent = parent;
  +    }
  +
  +    //==============================================================
  +    // implemetation
  +    //==============================================================
  +
       /**
        * Load a set of packaged profiles associated with the supplied class.
  +     * Profiles returned from this operation are not included within the 
  +     * manager.  To register a profile with the manager use the {@link #addProfile}
  +     * operation.
        *
        * @param type the component type used to locate an packaged profiles
        * @return the set of packaged component profiles
  -     * @exception ProfileException if a error occurs while attempt to
  -     *   load packaged profiles 
  +     * @exception ProfileException if an error occurs while loading package profiles
        */
  -    Profile[] loadProfiles( Type type ) throws ProfileException;
  +    public Profile[] loadProfiles( Type type ) throws ProfileException
  +    {
  +        if( type == null )
  +        {
  +            throw new NullPointerException("type");
  +        }
  +        
  +        try
  +        {
  +            return PROFILE_BUILDER.build( m_classloader, type );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              "Build error while attempting to create packaged profiles for type: " 
  +              + type.getInfo().getClassname();
  +            throw new ProfileException( error, e );
  +        }
  +    }
   
       /**
        * Create a profile from a supplied configuration.
  @@ -82,10 +183,32 @@
        * @param type the component type that the profile qualifies
        * @param config a configuration fragment describing the deployment profile
        * @return the deployment profile
  -     * @exception ProfileException if a profile creation error occurs
  +     * @exception ProfileException if an error occurs while attempting to create a profiles
        */
  -    Profile createProfile( Type type, Configuration config ) 
  -      throws ProfileException;
  +    public Profile createProfile( Type type, Configuration config ) 
  +      throws ProfileException
  +    {
  +        if( type == null )
  +        {
  +            throw new NullPointerException("type");
  +        }
  +        if( config == null )
  +        {
  +            throw new NullPointerException("config");
  +        }
  +
  +        try
  +        {
  +            return PROFILE_BUILDER.build( type, config );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              "Profile build error while constructing a profile from supplied configuration:\n"
  +              + ConfigurationUtil.list( config );
  +            throw new ProfileException( error, e );
  +        }
  +    }
   
      /**
       * Add a set of profiles to the manager.
  @@ -95,93 +218,263 @@
       * @exception ProfileException if a profile verification failure occurs
       * @see #createProfile
       */
  -    public void addProfiles( Profile[] profiles ) throws DuplicateProfileException, ProfileException;
  +    public void addProfiles( Profile[] profiles ) throws DuplicateProfileException, ProfileException
  +    {
  +        for( int i=0; i<profiles.length; i++ )
  +        {
  +            Profile profile = profiles[i];
  +            addProfile( profile );
  +        }
  +    }
   
      /**
       * Add a profile to the manager.
  -    * @param profile the depployment profile to add to the manager
  -    * @exception DuplicateProfileException if the supplied type is already registered
  +    * @param profile the deployment profile to add to the manager
  +    * @exception DuplicateProfileException if a profile of the same name 
  +    *   is already registered with the manager 
       * @exception ProfileException if a profile verification failure occurs
       * @see #createProfile
       */
  -    void addProfile( Profile profile ) 
  -      throws DuplicateProfileException, ProfileException;
  +    public void addProfile( Profile profile ) throws DuplicateProfileException, ProfileException
  +    {
  +        if( profile == null )
  +        {
  +            throw new NullPointerException("profile");
  +        }
  +
  +        if( getLogger() == null )
  +        {
  +            throw new IllegalStateException("logging");
  +        }
  +
  +        try
  +        {
  +            getNamedProfile( profile.getName() );
  +            throw new DuplicateProfileException( 
  +              profile.getType().getInfo().getClassname()
  +              + "/" + profile.getName()  );
  +        }
  +        catch( UnknownProfileException upe )
  +        {
  +            try
  +            {
  +                verify( profile );
  +            }
  +            catch( Throwable e )
  +            {
  +                final String error = 
  +                  "Could not register the profile: " + profile
  +                  + " due to a verification failure.";
  +                throw new ProfileException( error, e );
  +            }
  +
  +            if( getLogger().isDebugEnabled() )
  +            {
  +                getLogger().debug(
  +                  "add: " + profile );
  +            }
  +
  +            m_profiles.put( profile.getName(), profile );
  +        }
  +    }
   
       /**
        * Returns a profile held locally by the manager based on the profile name.
        * @param name the profile name
  -     * @return the profile matching the name
  +     * @return the profile matching the supplied name
        * @exception UnknownProfileException if the profile name is unknown within
        *   the scope of the manager
        */
  -    Profile getNamedProfile( String name ) 
  -      throws UnknownProfileException;
  -
  +    public Profile getNamedProfile( String name ) throws UnknownProfileException
  +    {
  +        Profile profile = (Profile) m_profiles.get( name );
  +        if( profile == null )
  +        {
  +            throw new UnknownProfileException( name );
  +        }
  +        return profile;
  +    }
  +    
       /**
  -     * Locate the set of {@link Profile} instances associated with the 
  -     * supplied component type.
  -     *
  +     * Get the set of profiles declared for a particular type.
        * @param type the component type
  -     * @return the profiles for the supplied classname.
  -     * @exception UnknownTypeException if a matching type cannot be found
  +     * @return the set of profile matching the type.
  +     * @exception UnknownTypeException if the type is unknown to the manager
        */
  -    Profile[] getProfiles( Type type ) 
  -      throws UnknownTypeException;
  +    public Profile[] getProfiles( Type type ) throws UnknownTypeException
  +    {
  +        if( type == null )
  +        {
  +            throw new NullPointerException("type");
  +        }
  +
  +        ArrayList list = new ArrayList();
  +        if( m_parent != null )
  +        {
  +            Profile[] profiles = m_parent.getProfiles( type );
  +            for( int i=0; i<profiles.length; i++ )
  +            {
  +                 list.add( profiles[i] );
  +            }
  +        }
  +        
  +        Enumeration enum = m_profiles.elements();
  +        while( enum.hasMoreElements() )
  +        {
  +            Profile profile = (Profile) enum.nextElement();
  +            if( profile.getType().equals( type ) )
  +            {
  +                list.add( type );
  +            }
  +        }
  +
  +        return (Profile[]) list.toArray( new Profile[0] );
  +    }
   
      /**
       * Locate the set of component profiles capable of services the supplied 
       * dependency.
  -    *
       * @param dependency a service dependency descriptor
       * @return a set of profiles capable of servicing the supplied dependency
       */
  -    Profile[] getProfiles( DependencyDescriptor dependency );
  +    public Profile[] getProfiles( DependencyDescriptor dependency )
  +    {
  +        if( dependency == null )
  +        {
  +            throw new NullPointerException("dependency");
  +        }
  +
  +        ArrayList list = new ArrayList();
  +        if( m_parent != null )
  +        {
  +            Profile[] profiles = m_parent.getProfiles( dependency );
  +            for( int i=0; i<profiles.length; i++ )
  +            {
  +                list.add( profiles[i] );
  +            }
  +        }
  +
  +        ReferenceDescriptor reference = dependency.getReference();
  +        Enumeration enum = m_profiles.elements();
  +        while( enum.hasMoreElements() )
  +        {
  +            Profile profile = (Profile) enum.nextElement();
  +            Object service = profile.getType().getService( reference );
  +            if( service != null )
  +            {
  +                list.add( profile );
  +            }
  +        }
  +
  +        return (Profile[]) list.toArray( new Profile[0] );
  +    }
   
      /**
       * Locate the set of component profiles that provide the supplied extension.
  -    *
       * @param stage a stage descriptor
       * @return a set of types that provide the supplied service
       */
  -    Profile[] getProfiles( StageDescriptor stage );
  +    public Profile[] getProfiles( StageDescriptor stage )
  +    {
  +        if( stage == null )
  +        {
  +            throw new NullPointerException("stage");
  +        }
  +
  +        ArrayList list = new ArrayList();
  +        if( m_parent != null )
  +        {
  +            Profile[] profiles = m_parent.getProfiles( stage );
  +            for( int i=0; i<profiles.length; i++ )
  +            {
  +                list.add( profiles[i] );
  +            }
  +        }
  +
  +        Enumeration enum = m_profiles.elements();
  +        while( enum.hasMoreElements() )
  +        {
  +            Profile profile = (Profile) enum.nextElement();
  +            if( profile.getType().getExtension( stage ) != null )
  +            {
  +                list.add( profile );
  +            }
  +        }
  +
  +        return (Profile[]) list.toArray( new Profile[0] );
  +    }
   
      /**
       * Locate the set of profiles tied to a type capable of supporting a service 
       * referenced by a supplied dependency descriptor using the default selector.
  -    *
       * @param dependency a service depedency descriptor
  -    * @return a set of types capable of servicing the supplied dependency
  -    */
  -    Profile getProfile( DependencyDescriptor dependency );
  -
  -   /**
  -    * Locate a profile tied to a type capable of supporting an extension 
  -    * referenced by a supplied stage descriptor using the default selector.
  -    *
  -    * @param stage a stage descriptor
  -    * @param selector the profile selector
  -    * @return a set of types that provide the supplied service
  +    * @return a set of profiles capable of servicing the supplied dependency
       */
  -    Profile getProfile( StageDescriptor stage );
  +    public Profile getProfile( DependencyDescriptor dependency )
  +    {
  +        return getProfile( dependency, m_selector );
  +    }
   
      /**
       * Locate the set of profiles tied to a type capable of supporting a service 
       * referenced by a supplied dependency descriptor using a supplied selector.
  -    *
       * @param dependency a service depedency descriptor
  -    * @param selector the profile selector
  -    * @return a set of types capable of servicing the supplied dependency
  +    * @param selector a profile selector
  +    * @return a set of profiles capable of servicing the supplied dependency
  +    */
  +    public Profile getProfile( DependencyDescriptor dependency, ProfileSelector selector )
  +    {
  +        Profile[] profiles = getProfiles( dependency );
  +        return selector.select( profiles, dependency );
  +    }
  +
  +   /**
  +    * Locate a profile tied to a type capable of supporting an extension 
  +    * referenced by a supplied stage descriptor usign the default selector.
  +    * @param stage a stage descriptor
  +    * @return a set of types that provide the supplied service
       */
  -    Profile getProfile( DependencyDescriptor dependency, ProfileSelector selector );
  +    public Profile getProfile( StageDescriptor stage )
  +    {
  +        return getProfile( stage, m_selector );
  +    }
   
      /**
       * Locate a profile tied to a type capable of supporting an extension 
       * referenced by a supplied stage descriptor usign the a suplied selector.
  -    *
       * @param stage a stage descriptor
  -    * @param selector the profile selector
  +    * @param selector a profile selector
       * @return a set of types that provide the supplied service
       */
  -    Profile getProfile( StageDescriptor stage, ProfileSelector selector );
  +    public Profile getProfile( StageDescriptor stage, ProfileSelector selector )
  +    {
  +        Profile[] profiles = getProfiles( stage );
  +        return selector.select( profiles, stage );
  +    }
   
  +   /**
  +    * Verify the supplied profile.
  +    * @param profile the profile to verify
  +    * @exception ProfileException if the verification failes
  +    */
  +    private void verify( Profile profile ) throws ProfileException
  +    {
  +        if( profile == null )
  +        {
  +            throw new NullPointerException("profile");
  +        }
  +
  +        ProfileVerifier verifier = new ProfileVerifier();
  +        try
  +        {
  +            verifier.verifyType( profile, m_classloader );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = "Verification failure for profile: " 
  +              + profile.getName() + " from type: "
  +              + profile.getType().getInfo().getClassname();
  +            throw new ProfileException( error, e );
  +        }
  +    }
   }
  
  
  
  1.2       +236 -20   avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/service/ServiceManager.java
  
  Index: ServiceManager.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/service/ServiceManager.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ServiceManager.java	24 Nov 2002 12:50:45 -0000	1.1
  +++ ServiceManager.java	7 Dec 2002 09:34:28 -0000	1.2
  @@ -50,19 +50,84 @@
   
   package org.apache.avalon.assembly.service;
   
  -import org.apache.avalon.framework.Version;
  +import java.util.Map;
  +import java.util.Hashtable;
   
  +import org.apache.avalon.framework.Version;
  +import org.apache.avalon.framework.logger.AbstractLogEnabled;
  +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.activity.Initializable;
   import org.apache.avalon.meta.info.Service;
  +import org.apache.avalon.meta.info.builder.ServiceBuilder;
   
   /**
  - * A service manager implementation provides support for the creation, 
  + * A service manager implemetation provides support for the creation, 
    * storage and retrival of service defintions.
    *
    * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
    * @version $Revision$ $Date$
    */
  -public interface ServiceManager
  +public class ServiceManager extends AbstractLogEnabled
   {
  +    //==============================================================
  +    // state
  +    //==============================================================
  +
  +   /**
  +    * The classloader supplied to the manager.
  +    */
  +    private ClassLoader m_classloader;
  +
  +   /**
  +    * The parent service manager (may be null)
  +    */
  +    private ServiceManager m_parent;
  +
  +   /**
  +    * The service builder.
  +    */
  +    private static final ServiceBuilder DEFAULT_BUILDER = new ServiceBuilder();
  +
  +    /**
  +     * Table of component types keyed by implementation classname.
  +     */
  +    private Hashtable m_services = new Hashtable();
  +
  +    //==============================================================
  +    // constructor
  +    //==============================================================
  +
  +   /**
  +    * Creation of a new root service manager.
  +    * @param classloader the classloder to use
  +    * @exception NullPointerException if the classloader is null
  +    */
  +    public ServiceManager( ClassLoader classloader ) throws NullPointerException
  +    {
  +        this( classloader, null );
  +    }
  +
  +   /**
  +    * Creation of a new service manager.
  +    * @param classloader the classloder to use
  +    * @param parent the parent type manager
  +    * @exception NullPointerException if the classloader is null
  +    */
  +    public ServiceManager( ClassLoader classloader, ServiceManager parent ) throws NullPointerException
  +    {
  +        if( classloader == null )
  +        {
  +            throw new NullPointerException("classloader");
  +        }
  +        m_classloader = classloader;
  +        m_parent = parent;
  +    }
  +
  +    //==============================================================
  +    // implemetation
  +    //==============================================================
   
       /**
        * Create a services associated from a supplied path. 
  @@ -71,36 +136,187 @@
        * @return the service defintions
        * @exception ServiceException if an error occurs during service creation
        */
  -    Service createService( Class clazz ) throws ServiceException;
  +    public Service createService( Class clazz ) throws ServiceException
  +    {
  +        if( clazz == null )
  +        {
  +            throw new NullPointerException("clazz");
  +        }
  +
  +        try
  +        {
  +            return DEFAULT_BUILDER.build( clazz.getName(), clazz.getClassLoader() );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +               "Could not create a service relative to the path: " 
  +               + clazz.getName() + " due to a service build error.";
  +            throw new ServiceException( error, e );
  +        }
  +    }
   
       /**
        * Create a service instance based on a supplied classname.
        *
        * @param classname the component implementation classname
        * @return the service defintion
  -     * @exception ServiceException if an error occurs during creation
  -     *   of a service defintion
  +     * @exception ServiceException if an error occurs during service creation
        */
  -    Service createService( String classname ) throws ServiceException;
  +    public Service createService( String classname ) throws ServiceException
  +    {
  +        if( classname == null )
  +        {
  +            throw new NullPointerException("classname");
  +        }
   
  -    /**
  -     * Add a service to the manager.
  -     *
  -     * @param service the service to add to the repository
  -     * @exception ServiceException if the service definition is invalid
  -     * @exception DuplicateServiceException if the service definition already exists
  -     */
  -    void addService( Service service ) throws ServiceException, DuplicateServiceException;
  +        try
  +        {
  +            Class clazz = m_classloader.loadClass( classname );
  +            return createService( clazz );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              "Unexpected error while attempting to build a service from the classname: " + classname;
  +            throw new ServiceException( error, e );
  +        }
  +    }
   
       /**
        * Locate a {@link Service} instances associated with the 
  -     * supplied classname and version. 
  +     * supplied classname and version. If a service defintion is not
  +     * found locally, the implementation redirects the request to 
  +     * the parent service manager.
  +     *
        * @param classname the service class name
        * @param version the service version
  -     * @return the service matching the supplied classname
  -     *   and version
  +     * @return the service matching the supplied classname and version.
        * @exception UnknownServiceException if a matching service cannot be found
        */
  -    Service getService( String classname, Version version ) throws UnknownServiceException;
  +    public Service getService( String classname, Version version ) throws UnknownServiceException
  +    {
  +        Map map = getServiceMap( classname, false );
  +        if( map != null )
  +        {
  +            Service service = (Service) map.get( version );
  +            if( service != null )
  +            {
  +                return service;
  +            }
  +        }
  +
  +        //
  +        // check the parent first
  +        //
  +
  +        if( m_parent != null )
  +        {
  +            return m_parent.getService( classname, version );
  +        }
  +        else
  +        {
  +            final String error = "Unknown service defintion: " + classname + "/" + version;
  +            throw new UnknownServiceException( error );
  +        }
  +    }
  +
  +    /**
  +     * Add a service to the manager.
  +     *
  +     * @param service the service defintion
  +     * @exception DuplicateServiceException if the service already exists
  +     * @exception ServiceException if the service definition is invalid
  +    */
  +    public void addService( Service service ) throws DuplicateServiceException, ServiceException
  +    {
  +        if( getLogger() == null )
  +        {
  +            throw new IllegalStateException("logging");
  +        }
  +
  +        //
  +        // make sure we are dealing with a service that is verified
  +        //
  +
  +        verifyService( service );
  +
  +        //
  +        // make sure that there is not already a local defintion for 
  +        // this service
  +        //
  +
  +        String classname = service.getClassname();
  +        Version version = service.getVersion();
  +        Map map = getServiceMap( classname, false );
  +        if( map != null )
  +        {
  +            if( map.get( version ) != null )
  +            {
  +                final String error = 
  +                  "Duplicate service defintion: " + service;
  +                throw new ServiceException( error );
  +            }            
  +        }
  +        else
  +        {
  +            map = getServiceMap( classname, true );
  +        }
  + 
  +        if( getLogger().isDebugEnabled() )
  +        {
  +            StringBuffer buffer = new StringBuffer();
  +            buffer.append( "add: " + classname );
  +            buffer.append( "/" + service.getVersion() );
  +            String[] names = service.getAttributeNames();
  +            for( int i = 0; i < names.length; i++ )
  +            {
  +                String name = names[ i ];
  +                String value = service.getAttribute( name );
  +                buffer.append( "\n  attribute " + name + " = " + value );
  +            }
  +            getLogger().debug( buffer.toString() );
  +        }
  +
  +        map.put( version, service );
  +    }
  +
  +   /**
  +    * Internal utility that returns a map of services keyed by version.  The 
  +    * map is resolved from the m_services list based on the classname key.
  +    * @param classname the classname key
  +    * @param create if TRUE create a new map if no map found
  +    * @return the service map for the class
  +    */
  +    private Map getServiceMap( String classname, boolean create )
  +    {
  +        Map map = (Map) m_services.get( classname );
  +        if(( map == null ) && create )
  +        {
  +            map = new Hashtable();
  +            m_services.put( classname, map );
  +        }
  +        return map;
  +    }
  +
   
  +   /**
  +    * Verify that a class exists within the classloader representing the 
  +    * service type.
  +    * @param service the service to verify
  +    * @exception ServiceException if a verification error occurs
  +    */
  +    private void verifyService( Service service ) throws ServiceException
  +    {
  +        Class clazz;
  +        try
  +        {
  +            clazz = m_classloader.loadClass( service.getClassname() );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = "Unresolvable service class.";
  +            throw new ServiceException( error, e );
  +        }
  +    }
   }
  
  
  
  1.2       +339 -12   avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/type/TypeManager.java
  
  Index: TypeManager.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/type/TypeManager.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TypeManager.java	24 Nov 2002 12:50:46 -0000	1.1
  +++ TypeManager.java	7 Dec 2002 09:34:29 -0000	1.2
  @@ -50,9 +50,23 @@
   
   package org.apache.avalon.assembly.type;
   
  +import java.util.Hashtable;
  +import java.util.Iterator;
  +import java.util.Enumeration;
  +import java.util.ArrayList;
  +
  +import org.apache.avalon.framework.logger.AbstractLogEnabled;
  +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.activity.Initializable;
   import org.apache.avalon.meta.info.Type;
  +import org.apache.avalon.meta.info.builder.TypeBuilder;
  +import org.apache.avalon.meta.info.ReferenceDescriptor;
   import org.apache.avalon.meta.info.DependencyDescriptor;
  +import org.apache.avalon.meta.info.ServiceDescriptor;
   import org.apache.avalon.meta.info.StageDescriptor;
  +import org.apache.avalon.meta.verifier.ComponentVerifier;
   
   /**
    * A type manager implemetation provides support for the creation, 
  @@ -61,8 +75,70 @@
    * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
    * @version $Revision$ $Date$
    */
  -public interface TypeManager
  +public class TypeManager extends AbstractLogEnabled
   {
  +    //==============================================================
  +    // static
  +    //==============================================================
  +
  +   /**
  +    * The type builder.
  +    */
  +    private static final TypeBuilder DEFAULT_BUILDER = new TypeBuilder();
  +
  +    //==============================================================
  +    // state
  +    //==============================================================
  +
  +   /**
  +    * The classloader supplied to the manager.
  +    */
  +    private ClassLoader m_classloader;
  +
  +   /**
  +    * The parent type manager (may be null)
  +    */
  +    private TypeManager m_parent;
  +
  +    /**
  +     * Table of component types keyed by implementation classname.
  +     */
  +    private final Hashtable m_types = new Hashtable();
  +
  +    //==============================================================
  +    // constructor
  +    //==============================================================
  +
  +   /**
  +    * Creation of a new root type manager.
  +    * @param classloader the classloder to use
  +    * @exception NullPointerException if the classloader is null
  +    */
  +    public TypeManager( ClassLoader classloader ) throws NullPointerException
  +    {
  +        this( classloader, null );
  +    }
  +
  +   /**
  +    * Creation of a new type manager.
  +    * @param classloader the classloder to use
  +    * @param parent the parent type manager
  +    * @exception NullPointerException if the classloader is null
  +    */
  +    public TypeManager( ClassLoader classloader, TypeManager parent ) throws NullPointerException
  +    {
  +        if( classloader == null )
  +        {
  +            throw new NullPointerException("classloader");
  +        }
  +        m_classloader = classloader;
  +        m_parent = parent;
  +    }
  +
  +    //==============================================================
  +    // TypeManager
  +    //==============================================================
  +
       /**
        * Create a new type instance.  The type instance returned is not 
        * registered with the manager.  To register the type the client 
  @@ -74,7 +150,26 @@
        * @exception TypeException is a type creation error occurs
        * @see #addType
        */
  -    Type createType( Class clazz ) throws TypeException;
  +    public Type createType( Class clazz ) throws TypeException
  +    {
  +        if( clazz == null )
  +        {
  +            throw new NullPointerException("clazz");
  +        }
  +
  +        try
  +        {
  +            return DEFAULT_BUILDER.build( clazz.getName(), clazz.getClassLoader() );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              "Could not register a type relative to the path: " 
  +              + clazz.getName()
  +              + " due to a type build error.";
  +            throw new TypeException( error, e );
  +        }
  +    }
   
       /**
        * Create a type instance based on a supplied classname and classloader.
  @@ -83,7 +178,25 @@
        * @return the component type
        * @exception TypeException is a type creation error occurs
        */
  -    Type createType( String classname ) throws TypeException;
  +    public Type createType( String classname ) throws TypeException
  +    {
  +        if( classname == null )
  +        {
  +            throw new NullPointerException("classname");
  +        }
  +
  +        try
  +        {
  +            Class clazz = m_classloader.loadClass( classname );
  +            return createType( clazz );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              "Unexpected error while attempting to build a type from the classname: " + classname;
  +            throw new TypeException( error, e );
  +        }
  +    }
   
      /**
       * Add a type to the manager.
  @@ -92,7 +205,47 @@
       * @exception TypeException if a type verification failure occurs
       * @see #createType
       */
  -    void addType( Type type ) throws DuplicateTypeException, TypeException;
  +    public void addType( Type type ) throws DuplicateTypeException, TypeException
  +    {
  +        if( type == null )
  +        {
  +            throw new NullPointerException("type");
  +        }
  +
  +        if( getLogger() == null )
  +        {
  +            throw new IllegalStateException("logging");
  +        }
  +
  +        final String classname = type.getInfo().getClassname();
  +
  +        try
  +        {
  +            type = getType( classname );
  +            throw new DuplicateTypeException( classname );
  +        }
  +        catch( UnknownTypeException ute )
  +        {
  +            try
  +            {
  +                verify( type );
  +            }
  +            catch( Throwable e )
  +            {
  +                final String error = 
  +                  "Could not register the type: " + classname
  +                  + " due to a verification failure.";
  +                throw new TypeException( error, e );
  +            }
  +
  +            if( getLogger().isDebugEnabled() )
  +            {
  +                getLogger().debug("add: " + classname );
  +            }
  +
  +            m_types.put( classname, type );
  +        }
  +    }
   
       /**
        * Locate a {@link Type} instances associated with the 
  @@ -101,7 +254,15 @@
        * @return the type matching the supplied implementation classname.
        * @exception UnknownTypeException if a matching type cannot be found
        */
  -    Type getType( Class clazz ) throws UnknownTypeException;
  +    public Type getType( Class clazz ) throws UnknownTypeException
  +    {
  +        if( clazz == null )
  +        {
  +            throw new NullPointerException("clazz");
  +        }
  +
  +        return getType( clazz.getName() );
  +    }
   
       /**
        * Locate a {@link Type} instances associated with the 
  @@ -110,21 +271,187 @@
        * @return the type matching the supplied implementation classname.
        * @exception UnknownTypeException if a matching type cannot be found
        */
  -    Type getType( String classname ) throws UnknownTypeException;
  +    public Type getType( String classname ) throws UnknownTypeException
  +    {
  +        if( classname == null )
  +        {
  +            throw new NullPointerException("classname");
  +        }
  +
  +        Type type = (Type) m_types.get( classname );
  +        if( type == null )
  +        {
  +            if( m_parent != null )
  +            {
  +                return m_parent.getType( classname );
  +            }
  +            else
  +            {
  +                throw new UnknownTypeException( classname );
  +            }
  +        }
  +        return type;
  +    }
   
      /**
  -    * Locate the set of component types capable of servicing the supplied 
  +    * Locate the set of component types capable of services the supplied 
       * dependency.
       * @param dependency a service dependency descriptor
       * @return a set of types capable of servicing the supplied dependency
       */
  -    Type[] getTypes( DependencyDescriptor dependency );
  +    public Type[] getTypes( DependencyDescriptor dependency )
  +    {
  +        if( dependency == null )
  +        {
  +            throw new NullPointerException("dependency");
  +        }
  +
  +        ArrayList list = new ArrayList();
  +        if( m_parent != null )
  +        {
  +            Type[] types = m_parent.getTypes( dependency );
  +            for( int i=0; i<types.length; i++ )
  +            {
  +                list.add( types[i] );
  +            }
  +        }
  +
  +        ReferenceDescriptor reference = dependency.getReference();
  +        Enumeration enum = m_types.elements();
  +        while( enum.hasMoreElements() )
  +        {
  +            Type type = (Type) enum.nextElement();
  +            Object service = type.getService( reference );
  +            if( service != null )
  +            {
  +                list.add( type );
  +            }
  +        }
  +        return (Type[]) list.toArray( new Type[0] );
  +    }
   
      /**
  -    * Locate the set of component types that provide the supplied extension stage.
  +    * Locate the set of component types that provide the supplied extension.
       * @param stage a stage descriptor
  -    * @return a set of types that are capable of supporting the supplied stage
  +    * @return a set of types that support the supplied stage
       */
  -    Type[] getTypes( StageDescriptor stage );
  +    public Type[] getTypes( StageDescriptor stage )
  +    {
  +        if( stage == null )
  +        {
  +            throw new NullPointerException("stage");
  +        }
  +
  +        ArrayList list = new ArrayList();
  +        if( m_parent != null )
  +        {
  +            Type[] types = m_parent.getTypes( stage );
  +            for( int i=0; i<types.length; i++ )
  +            {
  +                list.add( types[i] );
  +            }
  +        }
  +
  +        Iterator iterator = m_types.entrySet().iterator();
  +        while( iterator.hasNext() )
  +        {
  +            Type type = (Type) iterator.next();
  +            if( type.getExtension( stage ) != null )
  +            {
  +                list.add( type );
  +            }
  +        }
   
  +        return (Type[]) list.toArray( new Type[0] );
  +    }
  +
  +   /**
  +    * Verify the intergrity of the supplied type.
  +    * @param type the type to verify
  +    * @exception Exception if an verification failure occurs
  +    */
  +    private void verify( Type type ) throws Exception
  +    {
  +        String name = type.getInfo().getName();
  +        Class clazz = getComponentClass( type );
  +        Class[] classes = getServiceClasses( type );
  +        ComponentVerifier verifier = new ComponentVerifier();
  +        verifier.verifyComponent( name, clazz, classes );
  +    }
  +
  +    /**
  +     * Return the set of interface classes for a given type that are declared
  +     * or default to the "native" service access protocol and where the
  +     * service access model is undefined (i.e. native implementation).
  +     * access mode.
  +     *
  +     * @param type the component type
  +     * @return an array of classes represnting the type's service interfaces
  +     */
  +    private Class[] getServiceClasses( Type type )
  +    {
  +        ArrayList list = new ArrayList();
  +        ServiceDescriptor[] services = type.getServices();
  +        for( int i = 0; i < services.length; i++ )
  +        {
  +            ServiceDescriptor service = services[ i ];
  +            if( ( service.getAttribute( 
  +              "urn:avalon:service.protocol", "native" ).equals( "native" ) )
  +              && ( service.getAttribute( "urn:avalon:service.accessor", null ) == null ) )
  +            {
  +                list.add( getServiceClass( services[ i ] ) );
  +            }
  +        }
  +        return ( Class[]) list.toArray( new Class[0] );
  +    }
  +
  +    /**
  +     * Returns the component type implementation class.
  +     * @param type the component type descriptor
  +     * @return the class implementing the component type
  +     * @exception TypeException if a classloader error occurs
  +     */
  +    private Class getComponentClass( Type type ) throws TypeException
  +    {
  +        if( null == type )
  +        {
  +            throw new NullPointerException( "type" );
  +        }
  +
  +        final String classname = type.getInfo().getClassname();
  +
  +        try
  +        {
  +            return m_classloader.loadClass( classname );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              "Could not load implementation class for component type: "
  +              + classname;
  +            throw new TypeException( error, e );
  +        }
  +    }
  +
  +    /**
  +     * Returns the service type implementation class.
  +     * @param service the service type descriptor
  +     * @return the class implementing the service type
  +     * @exception TypeRuntimeException if a classloader error occurs
  +     */
  +    private Class getServiceClass( ServiceDescriptor service ) throws TypeRuntimeException
  +    {
  +        final String classname = service.getReference().getClassname();
  +        try
  +        {
  +            return m_classloader.loadClass( classname );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              "Could not load implementation class for service type: "
  +              + classname;
  +            throw new TypeRuntimeException( error, e );
  +        }
  +    }
   }
  
  
  
  1.4       +8 -4      avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/TestCaseBase.java
  
  Index: TestCaseBase.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/TestCaseBase.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TestCaseBase.java	3 Dec 2002 06:57:27 -0000	1.3
  +++ TestCaseBase.java	7 Dec 2002 09:34:29 -0000	1.4
  @@ -28,8 +28,8 @@
   public abstract class TestCaseBase extends TestCase
   {
   
  -    protected ClassLoader m_loader;
       protected LoggingManager m_logManager;
  +    protected File m_base;
   
       public TestCaseBase( String name )
       {
  @@ -38,9 +38,12 @@
   
       protected void setUp() throws Exception
       {
  -        m_loader = Thread.currentThread().getContextClassLoader();
  +        setUpLogging();
  +    }
   
  -        final File base = new File( System.getProperty( "user.dir" ) );
  +    protected void setUpLogging() throws Exception
  +    {
  +        m_base = new File( System.getProperty( "user.dir" ) );
           LoggingDescriptor logging = 
              new LoggingDescriptor( 
                "", "DEBUG", null, 
  @@ -48,8 +51,9 @@
                new Category( "logging" ) );
   
           DefaultContext context = new DefaultContext();
  -        context.put( "urn:avalon:home", base );
  +        context.put( "urn:avalon:home", m_base );
           context.put( "urn:assembly:logging.descriptor", logging );
  +        context.makeReadOnly();
   
           DefaultLoggingManager manager = new DefaultLoggingManager();
           manager.contextualize( context );
  
  
  
  1.4       +73 -43    avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/engine/EngineTestCase.java
  
  Index: EngineTestCase.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/engine/EngineTestCase.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- EngineTestCase.java	3 Dec 2002 06:57:27 -0000	1.3
  +++ EngineTestCase.java	7 Dec 2002 09:34:29 -0000	1.4
  @@ -13,14 +13,10 @@
   import org.apache.avalon.framework.Version;
   import org.apache.avalon.framework.context.DefaultContext;
   import org.apache.avalon.framework.service.DefaultServiceManager;
  -import org.apache.avalon.framework.service.ServiceManager;
  -import org.apache.avalon.assembly.type.TypeManager;
  -import org.apache.avalon.assembly.type.DefaultTypeManager;
   import org.apache.avalon.meta.info.*;
   import org.apache.avalon.assembly.TestCaseBase;
   import org.apache.avalon.assembly.engine.Engine;
  -import org.apache.avalon.assembly.engine.DefaultEngine;
  -import org.apache.avalon.assembly.appliance.*;
  +import org.apache.avalon.assembly.appliance.Appliance;
   import org.apache.avalon.assembly.util.ExceptionHelper;
   
   /**
  @@ -31,7 +27,7 @@
   public class EngineTestCase extends TestCaseBase
   {
   
  -    private Engine m_engine;
  +    protected EngineClassLoader m_engine;
   
       public EngineTestCase()
       {
  @@ -46,40 +42,39 @@
       protected void setUp() throws Exception
       {
           super.setUp();
  -        DefaultEngine engine = new DefaultEngine();
  -        engine.enableLogging( getLogger() );
  -        DefaultServiceManager manager = new DefaultServiceManager();
  -        manager.put( "urn:assembly:logging.manager", m_logManager );
  -        manager.makeReadOnly();
  -        engine.service( manager );
  -        engine.contextualize( new DefaultContext() );
  -        engine.initialize();
  -        m_engine = engine;
  +        setUpEngine( true );
       }
   
  -   /**
  -    * Test a component with custom context type and profile based import and 
  -    * entry creation directives and no service dependencies.
  -    */
  -    public void testBasicComponent()
  +    protected void setUpEngine( boolean bootstrap ) throws Exception
       {
  -        //
  -        // register the component types with the engine - this will result in the 
  -        // automatic loading of the type defintion and the any packaged profiles
  -        //
  -
           try
           {
  -            final String classname = "org.apache.avalon.playground.BasicComponent";
  -            m_engine.register( classname );
  -            assertTrue( true );
  +            EngineClassLoader engine = new EngineClassLoader();
  +            engine.enableLogging( getLogger() );
  +            DefaultContext context = new DefaultContext();
  +            context.put( "urn:assembly:engine.bootstrap", new Boolean( bootstrap ) );
  +            context.makeReadOnly();
  +            engine.contextualize( context );
  +            DefaultServiceManager manager = new DefaultServiceManager();
  +            manager.put( "urn:assembly:logging.manager", m_logManager );
  +            manager.makeReadOnly();
  +            engine.service( manager );
  +            engine.initialize();
  +            m_engine = engine;
           }
           catch( Throwable e )
           {
  -            ExceptionHelper.printException( "Registration failure.", e, this, true );
  +            ExceptionHelper.printException( "Engine setup failure.", e, this, true );
               assertTrue( false );
           }
  +    }
   
  +   /**
  +    * Test a component with custom context type and profile based import and 
  +    * entry creation directives and no service dependencies.
  +    */
  +    public void testBasicComponent()
  +    {
           //
           // get a full assembled and verified appliance from the engine using
           // a service classname and version
  @@ -121,8 +116,9 @@
      /**
       * Test a component with service and extension depedencies.
       */
  -    public void testSimpleComponent()
  +    public void testSimpleComponent() throws Throwable
       {
  +        final String complex = "org.apache.avalon.playground.ComplexComponent";
           final String basic = "org.apache.avalon.playground.BasicComponent";
           final String simple = "org.apache.avalon.playground.SimpleComponent";
           final String exploiter = "org.apache.avalon.playground.ExploitationManager";
  @@ -131,43 +127,77 @@
           final String service = "org.apache.avalon.playground.SimpleService";
   
           DependencyDescriptor dependency = 
  -          new DependencyDescriptor( "test", service, Version.getVersion( "1.1" ) );
  +          new DependencyDescriptor( "test", service, Version.getVersion( "1.0" ) );
             
           Appliance appliance = null;
           try
           {
  -            m_engine.register( basic );
  -            m_engine.register( exploiter );
  -            m_engine.register( demo );
  -            m_engine.register( simple );
  -            assertTrue( true );
  -
  +            getLogger().info( "resolving: " + dependency );
               appliance = m_engine.resolve( dependency );
               assertTrue( appliance != null );
           }
           catch( Throwable e )
           {
  -            System.out.println("failed to resolve : " + dependency );
  -            ExceptionHelper.printException( "Resolution failure.", e, appliance, true );
  +            final String reason = "Resolution failure.";
  +            String error = ExceptionHelper.packException( reason, e );
  +            getLogger().error( error );
               assertTrue( false );
           }
   
           try
           {
  +            getLogger().info( "accessing: " + dependency );
               Object object = appliance.access( dependency );
               assertTrue( true );
           }
           catch( Throwable e )
           {
  -            System.out.println("appliance access failure : " + dependency );
  -            ExceptionHelper.printException( "Access failure.", e, appliance, true );
  +            final String reason = "Access failure.";
  +            String error = ExceptionHelper.packException( reason, e );
  +            getLogger().error( error );
               assertTrue( false );
           }
       }
   
  -    protected void tearDown() throws Exception
  +   /**
  +    * Test a component with service and extension depedencies.
  +    */
  +    public void testComplexService()
       {
  -        m_loader = null;
  +        final String service = "org.apache.avalon.playground.ComplexService";
  +
  +        DependencyDescriptor dependency = 
  +          new DependencyDescriptor( "test-complex", service, Version.getVersion( "1.0" ) );
  +          
  +        Appliance appliance = null;
  +        try
  +        {
  +            getLogger().info( "resolving: " + dependency );
  +            appliance = m_engine.resolve( dependency );
  +            assertTrue( appliance != null );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String reason = "Resolution failure.";
  +            String error = ExceptionHelper.packException( reason, e );
  +            getLogger().error( error );
  +            assertTrue( false );
  +        }
  +
  +        try
  +        {
  +            getLogger().info( "accesing: " + dependency );
  +            Object object = appliance.access( dependency );
  +            assertTrue( true );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String reason = "Access failure.";
  +            String error = ExceptionHelper.packException( reason, e );
  +            getLogger().error( error );
  +            assertTrue( false );
  +        }
  +
       }
   
   }
  
  
  
  1.6       +3 -12     avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/profile/ProfileManagerTestCase.java
  
  Index: ProfileManagerTestCase.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/profile/ProfileManagerTestCase.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ProfileManagerTestCase.java	3 Dec 2002 06:57:27 -0000	1.5
  +++ ProfileManagerTestCase.java	7 Dec 2002 09:34:29 -0000	1.6
  @@ -30,6 +30,7 @@
   
       private ProfileManager m_manager;
       private TypeManager m_types;
  +    protected ClassLoader m_loader = Thread.currentThread().getContextClassLoader();
   
       public ProfileManagerTestCase()
       {
  @@ -196,25 +197,15 @@
   
       private TypeManager createTypeManager() throws Exception
       {
  -        DefaultTypeManager manager = new DefaultTypeManager();
  +        TypeManager manager = new TypeManager( m_loader );
           manager.enableLogging( getLogger().getChildLogger("types") );
  -        DefaultContext context = new DefaultContext();
  -        context.put( "urn:assembly:classloader", m_loader );
  -        context.makeReadOnly();
  -        manager.contextualize( context );
  -        manager.initialize();
           return manager;
       }
   
       private ProfileManager createProfileManager() throws Exception
       {
  -        DefaultProfileManager manager = new DefaultProfileManager();
  +        ProfileManager manager = new ProfileManager( m_loader );
           manager.enableLogging( getLogger().getChildLogger("profiles") );
  -        DefaultContext context = new DefaultContext();
  -        context.put( "urn:assembly:classloader", m_loader );
  -        context.makeReadOnly();
  -        manager.contextualize( context );
  -        manager.initialize();
           return manager;
       }
   
  
  
  
  1.3       +2 -6      avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/service/DefaultServiceManagerTestCase.java
  
  Index: DefaultServiceManagerTestCase.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/service/DefaultServiceManagerTestCase.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DefaultServiceManagerTestCase.java	3 Dec 2002 06:57:27 -0000	1.2
  +++ DefaultServiceManagerTestCase.java	7 Dec 2002 09:34:29 -0000	1.3
  @@ -27,6 +27,7 @@
   {
   
       private ServiceManager m_manager;
  +    protected ClassLoader m_loader = Thread.currentThread().getContextClassLoader();
   
       public DefaultServiceManagerTestCase()
       {
  @@ -41,13 +42,8 @@
       protected void setUp() throws Exception
       {
           super.setUp();
  -        DefaultServiceManager manager = new DefaultServiceManager();
  +        ServiceManager manager = new ServiceManager( m_loader );
           manager.enableLogging( getLogger().getChildLogger("services") );
  -        DefaultContext context = new DefaultContext();
  -        context.put( "urn:assembly:classloader", m_loader );
  -        context.makeReadOnly();
  -        manager.contextualize( context );
  -        manager.initialize();
           m_manager = manager;
       }
   
  
  
  
  1.3       +2 -6      avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/type/TypeManagerTestCase.java
  
  Index: TypeManagerTestCase.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/type/TypeManagerTestCase.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- TypeManagerTestCase.java	3 Dec 2002 06:57:27 -0000	1.2
  +++ TypeManagerTestCase.java	7 Dec 2002 09:34:29 -0000	1.3
  @@ -26,6 +26,7 @@
   {
   
       private TypeManager m_manager;
  +    protected ClassLoader m_loader = Thread.currentThread().getContextClassLoader();
   
       public TypeManagerTestCase()
       {
  @@ -40,13 +41,8 @@
       protected void setUp() throws Exception
       {
           super.setUp();
  -        DefaultTypeManager manager = new DefaultTypeManager();
  +        TypeManager manager = new TypeManager( m_loader );
           manager.enableLogging( getLogger().getChildLogger("types") );
  -        DefaultContext context = new DefaultContext();
  -        context.put( "urn:assembly:classloader", m_loader );
  -        context.makeReadOnly();
  -        manager.contextualize( context );
  -        manager.initialize();
           m_manager = manager;
       }
   
  
  
  
  1.2       +5 -1      avalon-sandbox/assembly/src/test/org/apache/avalon/playground/BasicComponent.java
  
  Index: BasicComponent.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/playground/BasicComponent.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BasicComponent.java	24 Nov 2002 12:50:46 -0000	1.1
  +++ BasicComponent.java	7 Dec 2002 09:34:29 -0000	1.2
  @@ -72,12 +72,16 @@
    * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
    */
   public class BasicComponent extends AbstractLogEnabled
  -    implements Contextualizable, Configurable, Initializable, Startable, BasicService, NullService, Disposable
  +    implements Contextualizable, Configurable, Initializable, Startable, Disposable, BasicService, NullService
   {
   
       private String m_location;
       private String m_message;
       private File m_home;
  +
  +    //=======================================================================
  +    // Contextualizable
  +    //=======================================================================
   
       /**
        * Supply of the the component context to the component type.
  
  
  
  1.2       +1 -1      avalon-sandbox/assembly/src/test/org/apache/avalon/playground/BasicComponent.xinfo
  
  Index: BasicComponent.xinfo
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/playground/BasicComponent.xinfo,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BasicComponent.xinfo	24 Nov 2002 12:50:46 -0000	1.1
  +++ BasicComponent.xinfo	7 Dec 2002 09:34:29 -0000	1.2
  @@ -19,7 +19,7 @@
       <name>basic</name>
     </info>
   
  -  <context>
  +  <context type="org.apache.avalon.playground.BasicContextInterface">
       <entry key="location"/>
       <entry key="home" type="java.io.File"/>
     </context>
  
  
  
  1.3       +1 -1      avalon-sandbox/assembly/src/test/org/apache/avalon/playground/BasicComponent.xprofile
  
  Index: BasicComponent.xprofile
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/playground/BasicComponent.xprofile,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- BasicComponent.xprofile	3 Dec 2002 06:57:27 -0000	1.2
  +++ BasicComponent.xprofile	7 Dec 2002 09:34:29 -0000	1.3
  @@ -21,7 +21,7 @@
    
      <component name="basic">
        <context class="org.apache.avalon.playground.BasicContext">
  -       <import key="home" name="urn:avalon:home"/>
  +       <import name="urn:avalon:home" key="home" />
          <entry key="location">Paris</entry>
        </context>
      </component>
  
  
  
  1.2       +1 -1      avalon-sandbox/assembly/src/test/org/apache/avalon/playground/ComplexComponent.java
  
  Index: ComplexComponent.java
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/playground/ComplexComponent.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ComplexComponent.java	24 Nov 2002 12:50:46 -0000	1.1
  +++ ComplexComponent.java	7 Dec 2002 09:34:29 -0000	1.2
  @@ -71,7 +71,7 @@
    */
   
   public class ComplexComponent extends AbstractLogEnabled
  -    implements Serviceable, Initializable, Startable, Disposable
  +    implements ComplexService, Serviceable, Initializable, Startable, Disposable
   {
   
       private ServiceManager m_manager;
  
  
  
  1.2       +6 -0      avalon-sandbox/assembly/src/test/org/apache/avalon/playground/ComplexComponent.xinfo
  
  Index: ComplexComponent.xinfo
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/playground/ComplexComponent.xinfo,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ComplexComponent.xinfo	24 Nov 2002 12:50:46 -0000	1.1
  +++ ComplexComponent.xinfo	7 Dec 2002 09:34:29 -0000	1.2
  @@ -23,6 +23,12 @@
        <logger name="init"/>
     </loggers>
   
  +  <services>
  +    <service> 
  +      <reference type="org.apache.avalon.playground.ComplexService"/>
  +    </service> 
  +  </services>
  +
     <dependencies>
         <dependency>
           <role>basic</role>
  
  
  
  1.3       +6 -0      avalon-sandbox/assembly/src/test/org/apache/avalon/playground/SimpleComponent.xinfo
  
  Index: SimpleComponent.xinfo
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/playground/SimpleComponent.xinfo,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SimpleComponent.xinfo	3 Dec 2002 06:57:27 -0000	1.2
  +++ SimpleComponent.xinfo	7 Dec 2002 09:34:29 -0000	1.3
  @@ -17,6 +17,12 @@
   
     <info>
       <name>simple</name>
  +    <attributes>
  +      <attribute key="urn:assembly:appliance.factory-service" 
  +        value="org.apache.avalon.assembly.appliance.ApplianceFactory"/>
  +      <attribute key="urn:assembly:appliance.factory-version" 
  +        value="2.0"/>
  +    </attributes>
     </info>
   
     <services>
  
  
  
  1.1                  avalon-sandbox/assembly/src/test/org/apache/avalon/playground/ComplexService.java
  
  Index: ComplexService.java
  ===================================================================
  /* ==================================================================== 
   * The Apache Software License, Version 1.1 
   * 
   * Copyright (c) 2002 The Apache Software Foundation. All rights 
   * reserved. 
   * 
   * Redistribution and use in source and binary forms, with or without 
   * modification, are permitted provided that the following conditions 
   * are met: 
   * 
   * 1. Redistributions of source code must retain the above copyright 
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software 
   *    itself, if and wherever such third-party acknowledgments  
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation" 
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see 
   * <http://www.apache.org/>.
   */ 
  
  package org.apache.avalon.playground;
  
  /**
   * The <code>ComplexService</code> does do anything.
   *
   * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
   */
  public interface ComplexService
  {
  }
  
  
  

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


Mime
View raw message