You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by mc...@apache.org on 2002/08/14 12:46:30 UTC

cvs commit: jakarta-avalon-excalibur/assembly/src/xdocs faq.xml

mcconnell    2002/08/14 03:46:30

  Modified:    assembly build.xml
               assembly/demo/src/java/org/apache/excalibur/playground
                        DemoManager.java ExploitationManager.java
               assembly/src/java/org/apache/excalibur/merlin/assembly
                        ContainerManager.java
               assembly/src/java/org/apache/excalibur/merlin/container
                        StructuralExtension.java
               assembly/src/java/org/apache/excalibur/merlin/model
                        Resource.java
               assembly/src/java/org/apache/excalibur/merlin/resource
                        AbstractLifestyleHandler.java
                        DefaultLifestyleManager.java DefaultResource.java
                        DeploymentHelper.java LifecycleHelper.java
                        LifestyleHandler.java LifestyleManager.java
                        ResourceProvider.java
                        SingletonLifestyleHandler.java
                        TransientLifestyleHandler.java
               assembly/src/xdocs faq.xml
  Log:
  Implemetation of the common lifecycle extension management model.
  
  Revision  Changes    Path
  1.41      +3 -2      jakarta-avalon-excalibur/assembly/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/build.xml,v
  retrieving revision 1.40
  retrieving revision 1.41
  diff -u -r1.40 -r1.41
  --- build.xml	12 Aug 2002 08:11:08 -0000	1.40
  +++ build.xml	14 Aug 2002 10:46:29 -0000	1.41
  @@ -104,6 +104,7 @@
       <uptodate property="uptodate" targetfile="${dist.dir}/${merlin.jar}">
         <srcfiles dir="${src.dir}/java">
            <include name="**/merlin/**/*.*"/>
  +         <include name="**/excalibur/container/**/*.*"/>
         </srcfiles>
         <srcfiles dir="${etc}">
            <include name="${project.manifest}"/>
  @@ -115,7 +116,7 @@
         <echo message="Building Merlin"/>
         <mkdir dir="${build}/main"/>
         <javac debug="off" destdir="${build}/main" deprecation="false"
  -        includes="org/apache/excalibur/merlin/**">
  +        excludes="org/apache/excalibur/meta/**">
           <classpath>
   	    <path refid="project.class.path" />
             <pathelement path="${dist.dir}/${meta.jar}" />
  @@ -223,7 +224,7 @@
         use="true"
   	windowtitle="Merlin" 
         additionalparam="-breakiterator -J-Xmx128m"
  -      packagenames="org.apache.excalibur.merlin.*" 
  +      packagenames="org.apache.excalibur.merlin.*,org.apache.excalibur.container.*" 
         overview="${merlin.page}"
         >
           <sourcepath path="${src.dir}/java"/>
  
  
  
  1.6       +26 -9     jakarta-avalon-excalibur/assembly/demo/src/java/org/apache/excalibur/playground/DemoManager.java
  
  Index: DemoManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/demo/src/java/org/apache/excalibur/playground/DemoManager.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- DemoManager.java	14 Aug 2002 03:03:34 -0000	1.5
  +++ DemoManager.java	14 Aug 2002 10:46:29 -0000	1.6
  @@ -4,16 +4,17 @@
   
   import org.apache.avalon.framework.context.Context;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
  -import org.apache.excalibur.merlin.resource.Extension;
  -import org.apache.excalibur.merlin.resource.AbstractExtension;
   import org.apache.avalon.framework.activity.Initializable;
   import org.apache.avalon.framework.activity.Disposable;
  +import org.apache.excalibur.container.lifecycle.Creator;
  +import org.apache.excalibur.container.lifecycle.Accessor;
   
   /**
    * Definition of an extension type.
    * @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
    */
  -public class DemoManager extends AbstractExtension implements Initializable, Disposable
  +public class DemoManager extends AbstractLogEnabled 
  +  implements Creator, Accessor, Initializable, Disposable
   {
   
       //=======================================================================
  @@ -22,19 +23,35 @@
   
       public void initialize()
       {
  -        getLogger().info("initialize");
  +        getLogger().debug("initializing extension");
       }
   
       //=======================================================================
  -    // Extension
  +    // Creator
       //=======================================================================
   
  -    public void extend( int stage, Object target, Context context ) throws Exception
  +    public void create( Object target, Context context ) throws Exception
       {
  -        super.extend( stage, target, context );
           if( target instanceof Demonstratable )
  -          ((Demonstratable)target).demo( "demonstratable, stage: " + stageToString( stage ).toLowerCase() 
  -             + ", instance: " + System.identityHashCode( this ) );
  +          ((Demonstratable)target).demo( "create id: " + System.identityHashCode( this ) );
  +    }
  +
  +    public void destroy( Object target, Context context )
  +    {
  +        if( target instanceof Demonstratable )
  +          ((Demonstratable)target).demo( "destroy id: " + System.identityHashCode( this ) );
  +    }
  +
  +    public void access( Object target, Context context ) throws Exception
  +    {
  +        if( target instanceof Demonstratable )
  +          ((Demonstratable)target).demo( "access id: " + System.identityHashCode( this ) );
  +    }
  +
  +    public void release( Object target, Context context )
  +    {
  +        if( target instanceof Demonstratable )
  +          ((Demonstratable)target).demo( "release id: " + System.identityHashCode( this ) );
       }
   
       //=======================================================================
  
  
  
  1.6       +11 -30    jakarta-avalon-excalibur/assembly/demo/src/java/org/apache/excalibur/playground/ExploitationManager.java
  
  Index: ExploitationManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/demo/src/java/org/apache/excalibur/playground/ExploitationManager.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ExploitationManager.java	12 Aug 2002 08:11:08 -0000	1.5
  +++ ExploitationManager.java	14 Aug 2002 10:46:29 -0000	1.6
  @@ -4,8 +4,7 @@
   
   import org.apache.avalon.framework.context.Context;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
  -import org.apache.excalibur.merlin.resource.Extension;
  -import org.apache.excalibur.merlin.resource.AbstractExtension;
  +import org.apache.excalibur.container.lifecycle.Creator;
   import org.apache.avalon.framework.activity.Initializable;
   import org.apache.avalon.framework.activity.Disposable;
   
  @@ -13,7 +12,7 @@
    * Definition of an extension type.
    * @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
    */
  -public class ExploitationManager extends AbstractExtension implements Initializable, Disposable
  +public class ExploitationManager extends AbstractLogEnabled implements Creator, Initializable, Disposable
   {
   
       //=======================================================================
  @@ -38,33 +37,15 @@
       // Extension
       //=======================================================================
   
  -    /**
  -     * Invoked by a container to request the application of a custom lifecycle
  -     * phase on the supplied object.
  -     *
  -     * @param int lifecycle stage
  -     * @param object the object to apply the extension to
  -     * @param context the context
  -     * @exception Exception if an error occurs
  -     */
  -    public void extend( int stage, Object object, Context context )
  -        throws Exception
  -     {
  +    public void create( Object object, Context context ) throws Exception
  +    {
  +        if( object instanceof Exploitable )
  +          ((Exploitable)object).incarnate();
  +    }
  +
  +    public void destroy( Object object, Context context )
  +    {
           if( object instanceof Exploitable )
  -        {
  -            super.extend( stage, object, context );
  -            if( stage == CREATE )
  -            {
  -                ((Exploitable)object).incarnate();
  -            }
  -            else if( stage == DESTROY )
  -            {
  -                ((Exploitable)object).etherialize();
  -            }
  -        }
  -        else
  -        {
  -            getLogger().warn( "Invalid target - object does not implement Exploitable" );
  -        }
  +          ((Exploitable)object).etherialize();
       }
   }
  
  
  
  1.19      +9 -7      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ContainerManager.java
  
  Index: ContainerManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ContainerManager.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- ContainerManager.java	14 Aug 2002 03:03:35 -0000	1.18
  +++ ContainerManager.java	14 Aug 2002 10:46:29 -0000	1.19
  @@ -43,7 +43,6 @@
   import org.apache.excalibur.merlin.resource.SingletonLifestyleHandler;
   import org.apache.excalibur.merlin.resource.TransientLifestyleHandler;
   import org.apache.excalibur.merlin.resource.LifecycleHelper;
  -import org.apache.excalibur.merlin.resource.ResourceProvider;
   import org.apache.excalibur.merlin.resource.DeploymentHelper;
   import org.apache.excalibur.merlin.model.ContainerDescriptor;
   import org.apache.excalibur.merlin.model.ClasspathDescriptor;
  @@ -141,7 +140,6 @@
       * Utility class that manages supply of context, config, services, etc. during
       * startup of a profile.
       */
  -    private ResourceProvider m_provider;
   
      /**
       * The manager name from which the manager path is resolved.
  @@ -294,15 +292,19 @@
             + "' " + System.identityHashCode( this ) 
             + " with parent: " + System.identityHashCode( getParent() ) );
   
  +        //
  +        // setup the default profile selector
  +        //
  +
           m_selector.enableLogging( getLocalLogger().getChildLogger("selector") );
           m_helper.enableLogging( getLocalLogger().getChildLogger("lifecycle") );
   
           //
  -        // setup the resource provider
  +        // setup the deployment helper
           //
   
  -        m_provider = new ResourceProvider( this, m_context, getLoggingManager() );
  -        m_provider.enableLogging( getLocalLogger().getChildLogger("provider") );
  +        m_deployment = new DeploymentHelper( getLoggingManager(), this );
  +        m_deployment.enableLogging( getLocalLogger().getChildLogger("deployment") );
   
           //
           // setup the assembly sub-system
  @@ -810,7 +812,7 @@
           {
               LifestyleManager lifestyles = getLifestyleManager();
               LifestyleHandler handler =
  -              lifestyles.getHandler( this, m_deployment, m_helper, m_provider, profile, context );
  +              lifestyles.getHandler( this, m_deployment, m_helper, profile, context );
               DefaultResource res = 
                 new DefaultResource( getPath(), profile, context, handler );
               res.enableLogging( getLocalLogger().getChildLogger( "resource" ) );
  
  
  
  1.4       +4 -10     jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/StructuralExtension.java
  
  Index: StructuralExtension.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/StructuralExtension.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- StructuralExtension.java	13 Aug 2002 03:57:56 -0000	1.3
  +++ StructuralExtension.java	14 Aug 2002 10:46:29 -0000	1.4
  @@ -3,13 +3,13 @@
   package org.apache.excalibur.merlin.container;
   
   import org.apache.avalon.framework.context.Context;
  -import org.apache.excalibur.merlin.resource.AbstractExtension;
  +import org.apache.excalibur.container.lifecycle.AbstractCreator;
   
   /**
    * Extension that supplorts the assembly of a container structure.
    * @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
    */
  -public class StructuralExtension extends AbstractExtension
  +public class StructuralExtension extends AbstractCreator
   {
   
       //=======================================================================
  @@ -17,24 +17,18 @@
       //=======================================================================
   
       /**
  -     * Invoked by a container to request the application of the assembly
  +     * Invoked by a container to request the application of an assembly
        * phase on the supplied object.
        *
  -     * @param int lifecycle stage
        * @param object the object to apply the extension to
        * @param context the context
        * @exception Exception if an error occurs
        */
  -    public void extend( int stage, Object object, Context context )
  +    public void create( Object object, Context context )
           throws Exception
        {
           if( !( object instanceof Structural ) )
             return;
  -
  -        if( !( stage == CREATE ) )
  -          return;
  -
  -        super.extend( stage, object, context );
   
           ((Structural)object).assemble( );
       }
  
  
  
  1.6       +8 -1      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/Resource.java
  
  Index: Resource.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/Resource.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Resource.java	12 Aug 2002 06:08:54 -0000	1.5
  +++ Resource.java	14 Aug 2002 10:46:29 -0000	1.6
  @@ -28,6 +28,13 @@
       String getPath();
   
       /**
  +     * Returns the component class.
  +     *
  +     * @return the class
  +     */
  +    Class getImplementationClass();
  +
  +    /**
        * Returns the resource descriptor.
        *
        * @return the descriptor
  
  
  
  1.5       +109 -53   jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/AbstractLifestyleHandler.java
  
  Index: AbstractLifestyleHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/AbstractLifestyleHandler.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- AbstractLifestyleHandler.java	14 Aug 2002 03:03:35 -0000	1.4
  +++ AbstractLifestyleHandler.java	14 Aug 2002 10:46:29 -0000	1.5
  @@ -9,12 +9,15 @@
    */
   package org.apache.excalibur.merlin.resource;
   
  +import java.util.Map;
   import java.util.ArrayList;
   
   import org.apache.avalon.framework.activity.Disposable;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.avalon.framework.context.DefaultContext;
   import org.apache.avalon.framework.context.Context;
  +import org.apache.excalibur.container.lifecycle.Creator;
  +import org.apache.excalibur.container.lifecycle.Accessor;
   import org.apache.excalibur.merlin.assembly.ContainerManager;
   import org.apache.excalibur.merlin.resource.ResourceException;
   import org.apache.excalibur.merlin.model.Profile;
  @@ -39,10 +42,12 @@
        private Profile m_profile;
        private ContainerManager m_manager;
        private DeploymentHelper m_deployment;
  -     private ResourceProvider m_provider;
        private LifecycleHelper m_helper;
        private Context m_context;
   
  +     private ResourceProvider m_provider;
  +     private Class m_class;
  +
        private boolean m_initialized = false;
        protected boolean m_disposed = false;
   
  @@ -57,7 +62,6 @@
        public AbstractLifestyleHandler( 
                              final ContainerManager manager,
                              final DeploymentHelper deployment, 
  -                           final ResourceProvider provider, 
                              final LifecycleHelper helper,
                              final Profile profile, 
                              final Context context )
  @@ -68,9 +72,6 @@
            if( deployment == null )
              throw new NullPointerException("deployment");
   
  -         if( provider == null )
  -           throw new NullPointerException("provider");
  -
            if( helper == null )
              throw new NullPointerException("helper");
   
  @@ -83,12 +84,33 @@
            m_profile = profile;
            m_manager = manager;
            m_deployment = deployment;
  -         m_provider = provider;
            m_helper = helper;
            m_context = context;
        }
   
       /**
  +     * Returns the service class.
  +     * 
  +     * @return the service class
  +     */
  +     public Class getImplementationClass()
  +     {
  +         if( m_class != null )
  +           return m_class;
  +         try
  +         {
  +             m_class = m_deployment.createImplementationClass( m_profile );
  +             return m_class;
  +         }
  +         catch( Throwable e )
  +         {
  +             final String error =
  +               "Unexpected error while attempting to get an implemetation class";
  +             throw new ResourceRuntimeException( error, e );
  +         }
  +     }
  +
  +    /**
        * Returns an instance of the object type supported by the 
        * manager to the client.
        * 
  @@ -112,11 +134,12 @@
        */
        protected void processAccessStage( Object object ) throws Exception
        {
  -        DefaultContext context = new DefaultContext();
           PhaseDescriptor[] phases = m_profile.getType().getPhases();
           for( int i=0; i<phases.length; i++ )
           {
  -            processExtension( ExtensionDescriptor.RELEASE, phases[i], object, context );
  +            PhaseDescriptor stage = phases[i];
  +            Context context = (Context) m_provider.createContext( stage );
  +            processExtension( stage, object, true );
           }
        }
   
  @@ -125,48 +148,76 @@
        * @param object the object to process
        * @param Exception if a stage procesing exception occurs
        */
  -     protected void processReleaseStage( Object object ) throws Exception
  +     protected void processReleaseStage( Object object )
        {
  -        DefaultContext context = new DefaultContext();
           PhaseDescriptor[] phases = m_profile.getType().getPhases();
           for( int i=(phases.length-1); i>-1; i-- )
           {
  -            processExtension( ExtensionDescriptor.RELEASE, phases[i], object, context );
  +            PhaseDescriptor stage = phases[i];
  +            try
  +            {
  +                processExtension( stage, object, false );
  +            }
  +            catch( Throwable e )
  +            {
  +                final String warning = 
  +                  "Ignoring release exception.";
  +                getLogger().warn( warning, e );
  +            }
           }
  -     }
  +    }
   
  -    private void processExtension( int stage, PhaseDescriptor phase, Object object, Context context ) throws Exception
  +   /**
  +    * Invoke an extension handler for a lifecycle stage.
  +    *
  +    * @param stage the lifecycle stage (one of ACCESS or RELEASE )
  +    * @param phase the phase descriptor describing the stage dependency
  +    * @param object the object to be processed
  +    * @param context the extension context
  +    *
  +    * @exception Exception if an error occurs during stage execution
  +    */ 
  +    private void processExtension( 
  +                         PhaseDescriptor stage, 
  +                         Object object, 
  +                         boolean access ) 
  +      throws Exception
       {
  -        final Type facility = m_profile.getFacility( phase );
  -        final ExtensionDescriptor ext = facility.getExtension( phase );
  -        if( ext.isApplicable( stage ) )
  +        Resource resource = m_profile.getExtension( stage );
  +        if( Accessor.class.isAssignableFrom( resource.getImplementationClass() ) )
           {
  -            Resource resource = m_profile.getExtension( phase );
  -            Extension extension = (Extension) resource.access();
  +            Accessor extension = (Accessor) resource.access();
               try
               {
  -                extension.extend( stage, object, context );
  -                resource.release( extension );
  +                 Context context = m_provider.createContext( stage );
  +                 if( access )
  +                 {
  +                     extension.access( object, context );
  +                 }
  +                 else
  +                 {
  +                     extension.release( object, context );
  +                 }
  +                 resource.release( extension );
               }
               catch( Throwable e )
               {
  -                final String error =
  -                  "Extension " + extension.getClass().getName() 
  -                  + " raised an exception " + e.getClass().getName()
  -                  + " while processing the " 
  -                  + ExtensionDescriptor.stageToString( stage ) 
  -                  + " phase for the component " 
  -                  + m_profile.getName();
  -
  -                throw new LifecycleException( error, e );
  +                 final String error =
  +                   "Extension " + resource.getClass().getName() 
  +                   + " raised an exception while processing an inner stage for the component " 
  +                   + m_profile.getName();
  +                 throw new LifecycleException( error, e );
               }
           }
       }
   
       /**
  -     * Instantiate an instance of the type.
  +     * Instantiate an instance of the type.  If this is the first invocation
  +     * of this method, the implemetation will trigger profile deployment in 
  +     * advance of instance creation.
        * 
        * @return an instance of the type defined by the profile
  +     * @see DeploymentHelper
        */
        protected Object createInstance() throws Exception
        {
  @@ -174,37 +225,21 @@
   
           if( !m_initialized )
           {
  -            m_deployment.deploy( m_profile );
  +            m_deployment.createLoggingCategories( m_profile );
  +            Context context = m_deployment.createStandardContext( m_profile, m_context );
  +            Map map = m_deployment.createExtensionContextMap( m_profile, m_context );
  +            m_provider = new ResourceProvider( m_deployment, m_profile, context, map );            
               m_initialized = true;
           }
   
           //
  -        // load the class
  -        //
  -
  -        Class clazz = null;
  -        String classname = null;
  -        try
  -        {
  -            classname = m_profile.getType().getInfo().getImplementationKey();
  -            clazz = m_manager.loadClass( classname );
  -        }
  -        catch( Throwable e )
  -        {
  -            final String error = 
  -              "Unexpected exception while attempting to load class '" 
  -              + classname + "' for the profile: " + m_profile;
  -            throw new ResourceException( error, e );
  -        }
  -
  -        //
           // create a new instance of the class
           //
   
           Object object;
           try
           {
  -            object = clazz.newInstance();
  +            object = getImplementationClass().newInstance();
           }
           catch( Throwable e )
           {
  @@ -215,12 +250,33 @@
           }
   
           final String path = m_manager.getPath() + "/" + m_profile.getName();
  -        m_helper.startup( object, path, m_profile, m_provider, m_context );
  -
  +        m_helper.startup( path, m_profile, object, m_provider );
           return object;
   
        }
   
  +    /**
  +     * Handle the orderly shutdown of a supplied component.
  +     * @param object the object to process through the shutdown phase
  +     */
  +     public void handleShutdown( Object object )
  +     {
  +         if( object == null )
  +           throw new NullPointerException("object");
  +
  +         if( m_provider == null )
  +           throw new NullPointerException("provider");
  +
  +         final String path = m_manager.getPath() + "/" + m_profile.getName();
  +         try
  +         {
  +             m_helper.shutdown( path, m_profile, object, m_provider );
  +         }
  +         catch( Throwable e )
  +         {
  +             getLogger().warn("Ignoring shutdown error from resource: " + path, e );
  +         }
  +     }
   
       /**
        * Request for disposal of the manager.  This operation is normally invoked
  
  
  
  1.3       +2 -3      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultLifestyleManager.java
  
  Index: DefaultLifestyleManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultLifestyleManager.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DefaultLifestyleManager.java	14 Aug 2002 03:03:35 -0000	1.2
  +++ DefaultLifestyleManager.java	14 Aug 2002 10:46:29 -0000	1.3
  @@ -79,7 +79,6 @@
                               ContainerManager manager, 
                               DeploymentHelper deployment,
                               LifecycleHelper helper, 
  -                            ResourceProvider provider, 
                               Profile profile, 
                               Context context ) 
        throws Exception
  @@ -95,7 +94,7 @@
               //
   
               SingletonLifestyleHandler handler = 
  -              new SingletonLifestyleHandler( manager, deployment, provider, helper, profile, context );
  +              new SingletonLifestyleHandler( manager, deployment, helper, profile, context );
               handler.enableLogging( getLogger() );
               return handler;
           }
  @@ -106,7 +105,7 @@
               //
   
               TransientLifestyleHandler handler = 
  -              new TransientLifestyleHandler( manager, deployment, provider, helper, profile, context );
  +              new TransientLifestyleHandler( manager, deployment, helper, profile, context );
               handler.enableLogging( getLogger() );
               return handler;
           }
  
  
  
  1.4       +11 -1     jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultResource.java
  
  Index: DefaultResource.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultResource.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DefaultResource.java	14 Aug 2002 03:03:35 -0000	1.3
  +++ DefaultResource.java	14 Aug 2002 10:46:29 -0000	1.4
  @@ -93,6 +93,16 @@
       }
   
       /**
  +     * Returns the component class.
  +     *
  +     * @return the class
  +     */
  +    public Class getImplementationClass()
  +    {
  +        return m_handler.getImplementationClass();
  +    }
  +
  +    /**
        * Returns the service descriptor.
        *
        * @return the service descriptor
  
  
  
  1.2       +466 -7    jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DeploymentHelper.java
  
  Index: DeploymentHelper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DeploymentHelper.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DeploymentHelper.java	14 Aug 2002 03:03:35 -0000	1.1
  +++ DeploymentHelper.java	14 Aug 2002 10:46:29 -0000	1.2
  @@ -8,6 +8,10 @@
   package org.apache.excalibur.merlin.resource;
   
   import java.util.ArrayList;
  +import java.util.Map;
  +import java.util.Hashtable;
  +import java.util.HashMap;
  +import java.lang.reflect.Constructor;
   
   import org.apache.avalon.excalibur.i18n.ResourceManager;
   import org.apache.avalon.excalibur.i18n.Resources;
  @@ -18,8 +22,10 @@
   import org.apache.avalon.framework.component.Composable;
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
  +import org.apache.avalon.framework.configuration.DefaultConfiguration;
   import org.apache.avalon.framework.container.ContainerUtil;
   import org.apache.avalon.framework.context.Context;
  +import org.apache.avalon.framework.context.ContextException;
   import org.apache.avalon.framework.context.Contextualizable;
   import org.apache.avalon.framework.context.DefaultContext;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
  @@ -39,6 +45,12 @@
   import org.apache.excalibur.merlin.model.ContextDirective;
   import org.apache.excalibur.merlin.model.CategoriesDescriptor;
   import org.apache.excalibur.merlin.model.Category;
  +import org.apache.excalibur.merlin.model.Import;
  +import org.apache.excalibur.merlin.model.Entry;
  +import org.apache.excalibur.merlin.model.Association;
  +import org.apache.excalibur.meta.info.DependencyDescriptor;
  +import org.apache.excalibur.meta.info.ContextDescriptor;
  +import org.apache.excalibur.meta.info.EntryDescriptor;
   import org.apache.excalibur.meta.info.ContextDescriptor;
   import org.apache.excalibur.meta.info.PhaseDescriptor;
   import org.apache.excalibur.meta.info.ExtensionDescriptor;
  @@ -51,9 +63,6 @@
    * executed on deployment of a profile.  This includes actions such as 
    * the establishment of logging channels, preparation of context instances, 
    * and other once-only actions scoped relative to a specific profile.
  - * Clients will normally deploy a profile prior to one or more creation of 
  - * instances relative to the profile type.  In other words, deployment should
  - * should be invoked once, prior to any subsequent instantiations of the type.
    *
    * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
    */
  @@ -71,8 +80,14 @@
       // state
       //=======================================================================
   
  +   /**
  +    * The logging system used to establish logging categories.
  +    */
       private DefaultLoggerManager m_logging;
   
  +   /**
  +    * The container type manager.
  +    */
       private ContainerManager m_manager;
   
       //=======================================================================
  @@ -100,16 +115,43 @@
       //=======================================================================
   
      /**
  +    * Returns the implememntation class for the type.
  +    *
  +    * @param profile the profile 
  +    *
  +    * @throws DeploymentException if an errors
  +    */
  +    public Class createImplementationClass( final Profile profile )
  +        throws DeploymentException
  +    {
  +        String classname = null;
  +        try
  +        {
  +            classname = profile.getType().getInfo().getImplementationKey();
  +            return m_manager.loadClass( classname );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              "Unexpected exception while attempting to load class '" 
  +              + classname + "' for the profile: " 
  +              + m_manager.getPath() + "/" + profile.getName();
  +            throw new DeploymentException( error, e );
  +        }
  +    }
  +
  +   /**
       * Method to initiate profile deployment. Th default implementation
       * handles the once only establishment of the logging categories declared
       * under the profile type, qualified by the priority and target criteria
       * declared under the profile categories descriptor.
       *
       * @param profile the profile to deploy
  +    * @param context the deployment context
       *
       * @throws DeploymentException if an error during deployment
       */
  -    public void deploy( final Profile profile )
  +    public void createLoggingCategories( final Profile profile )
           throws DeploymentException
       {
           if( profile == null )
  @@ -117,8 +159,13 @@
   
           getLogger().info("deployment initiated for '" + profile.getName() + "'." );
   
  +        //
  +        // handle the declaration of the logging categories based on the type 
  +        // and profile information
  +        //
  +
           String root;
  -        CategoriesDescriptor categories = createLoggingCategories( profile );
  +        CategoriesDescriptor categories = buildLoggingCategories( profile );
           if( m_manager instanceof KernelManager )
           {
               root = m_manager.getPath().replace('/','.').substring(1);
  @@ -140,9 +187,8 @@
       *   information
       * @return a new fully populated <code>CategoriesDescriptor</code>
       */
  -    private CategoriesDescriptor createLoggingCategories( Profile profile )
  +    private CategoriesDescriptor buildLoggingCategories( Profile profile )
       {
  -
           CategoriesDescriptor categories = profile.getCategories();
           LoggerDescriptor[] loggers = profile.getType().getLoggers();
           ArrayList list = new ArrayList();
  @@ -166,4 +212,417 @@
             (Category[]) list.toArray( new Category[0] )
           );
       }
  +
  +   /**
  +    * Handles creation of a map of context entries keyed by phase. Context
  +    * entries are built using the supplied deployment context argument together
  +    * with profile directives relative to type constraints.
  +    *
  +    * @param profile the profile 
  +    * @param context the deployment context
  +    */
  +    public Map createExtensionContextMap( Profile profile, Context context )
  +      throws DeploymentException
  +    {
  +        //
  +        // build the set of extension context instances
  +        //
  +
  +        Hashtable table = new Hashtable();
  +        PhaseDescriptor[] stages = profile.getType().getPhases();
  +        for( int i=0; i<stages.length; i++ )
  +        {
  +            PhaseDescriptor stage = stages[i];
  +            Type type = profile.getFacility( stage );
  +
  +            if( type == null )
  +              throw new NullPointerException("extension");
  +
  +            final ExtensionDescriptor ext = type.getExtension( stage );
  +            try
  +            {
  +                Context extensionContext = createContext( ext, context );
  +                table.put( stage, extensionContext );
  +            }
  +            catch( Throwable e )
  +            {
  +                final String error = "Unexpected error while context for extension: " 
  +                  + ext.getName() 
  +                  + " in profile " + m_manager.getPath() 
  +                  + "/" + profile.getName();
  +                throw new DeploymentException( error, e );
  +            }
  +        }
  +        return table;
  +    }
  +
  +    /**
  +     * Create a new Context for component.
  +     *
  +     * @param profile the profile
  +     * @param a supplimentary context usable during import resolution
  +     * @return a new Context for service
  +     * @throws DeploymentException if an error occurs in standard 
  +     *   context creation
  +     */
  +    public Context createStandardContext( Profile profile, Context  context )
  +        throws DeploymentException
  +    {
  +        try
  +        {
  +            ContextDescriptor descriptor = profile.getType().getContext();
  +            ContextDirective directive = profile.getContext();
  +            return buildContext( descriptor, directive, context );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = "Unexpected error while preparing standard context.";
  +            throw new DeploymentException( error, e );
  +        }
  +    }
  +
  +    /**
  +     * Create a new Context for an extension.
  +     *
  +     * @param profile the profile
  +     * @param a supplimentary context usable during import resolution
  +     * @return a new Context for service
  +     * @throws Exception if unable to create context
  +     */
  +    private Context createContext( ExtensionDescriptor extension, Context  context )
  +        throws Exception
  +    {
  +        ContextDescriptor descriptor = extension.getContext();
  +        return buildContext( descriptor, null, context );
  +    }
  +
  +   /**
  +    * Internal utility to construct a context instance using a descriptor, directive and source
  +    * context instances.
  +    *
  +    * @param descriptor the descriptor containing the context dependency declarations
  +    * @param directive an optional context directive containing import and context value 
  +    *    creation parameters
  +    * @param context a supplimentary context object to used during value resolution
  +    * @return a context object containing only those context entries desribed under the 
  +    *   supplied descriptor
  +    * @exception Exception if a required context value cannot be resolved or an error 
  +    *   occurs during context value creation
  +    */
  +    private Context buildContext( 
  +                           ContextDescriptor descriptors, 
  +                           ContextDirective directive, 
  +                           Context context ) 
  +      throws Exception
  +    {
  +        Map map = new HashMap();
  +        Context result;
  +
  +        if( directive != null )
  +        {
  +            final String classname = directive.getClassname();
  +            Class clazz;
  +            try
  +            {
  +                 clazz = m_manager.loadClass( classname );
  +            }
  +            catch( ClassNotFoundException cnfe )
  +            {
  +                 throw new ResourceException(
  +                   "Could not find context class " + classname, cnfe );
  +            }
  +
  +            try
  +            {
  +                Constructor constructor = clazz.getConstructor(
  +                   new Class[]{ Map.class, Context.class } );
  +                result = (Context)constructor.newInstance( new Object[]{ map, null } );
  +            }
  +            catch( Throwable e )
  +            {
  +                throw new ResourceException(
  +                  "Unexpected exception while creating context form "
  +                  + classname, e );
  +            }
  +        }
  +        else
  +        {
  +            result = new DefaultContext( map );
  +        }
  +
  +        EntryDescriptor[] entries = descriptors.getEntrys();
  +        for( int i=0; i<entries.length; i++ )
  +        {
  +            EntryDescriptor entry = entries[i];
  +            String key = entry.getKey();
  +             
  +            //
  +            // if the entry is already in the supplied context then use it
  +            //
  +
  +            Object object = getContextValue( context, key );
  +
  +            //
  +            // If the context value is unresolved, try to handle resolution
  +            // using an import directive supplied under the directive
  +            //
  +
  +            if( object == null )
  +            {
  +
  +                //
  +                // check if the profile declares an import directive
  +                // for the context
  +                //
  +
  +                if( directive != null )
  +                {
  +                    Import imp = directive.getImport( key );
  +                    if( imp != null )
  +                    {
  +                        String name = imp.getImportName();
  +                        object = getContextValue( context, name );
  +                        if( object == null )
  +                        {
  +                            final String error = 
  +                             "Import directive for key: " + key + " via name: " + name 
  +                             + " cannot be resolved.";
  +                            getLogger().warn( error );
  +                        }
  +                    }
  +
  +                    //
  +                    // if the context value is unresolved, try to construct a context 
  +                    // value using an entry constructor directive
  +                    //
  +
  +                    if( object == null )
  +                    {
  +                        //
  +                        // check if the directive declares a context value constructor
  +                        //
  +
  +                        Entry ent = directive.getEntry( key );
  +                        if( ent != null )
  +                        {
  +                            object = ent.getValue( m_manager, map );
  +                        }
  +                    }
  +                }
  +            }
  +
  +            //
  +            // finally, if the object is still null, and its not optional, then
  +            // throw an exception, otherwise, add the object to the context
  +            //
  +
  +            if( object != null )
  +            {
  +                try
  +                {
  +                    boolean ok = objectImplementsType( object, entry.getType() );
  +                    if( ok )
  +                    {
  +                         map.put( key, object );
  +                    }
  +                    else
  +                    {
  +                        final String error = 
  +                          "Object resolved for the key '" + key + "' of class '"
  +                          + object.getClass().getName() + "' does not implement the type '"
  +                          + entry.getType();
  +                        throw new ResourceException( error );
  +                    }
  +                }
  +                catch( ClassNotFoundException cnfe )
  +                {
  +                    final String error =
  +                      "Context criteria for the key '" + key + "' specifies an unknown type '" 
  +                      + entry.getType() + "'.";
  +                    throw new ResourceException( error );
  +                }
  +            }
  +            else
  +            {
  +                if( entry.isRequired() )
  +                {
  +                    final String error = 
  +                      "Unable to resolve a context value for the entry: " + key;
  +                    throw new ResourceException( error );
  +                }
  +            }
  +        }
  +
  +        if( result instanceof DefaultContext )
  +        {
  +            ((DefaultContext)result).makeReadOnly();
  +        }
  +
  +        return result;
  +    }
  +
  +   /**
  +    * Internal utility to get a context value or null if the context key
  +    * is unknown.
  +    * @param context the context object
  +    * @param key the context key to lookup
  +    * @return the context value derived from the key or null if the key is unknown
  +    */
  +    private Object getContextValue( Context context, String key )
  +    {
  +        if( context == null ) return null;
  +        try
  +        {
  +            return context.get( key );
  +        }
  +        catch( ContextException e )
  +        {
  +            return null;
  +        }
  +    }
  +
  +    /**
  +     * Check whether the specified value is compatible with specified type.
  +     *
  +     * @param value the value
  +     * @param type the desired type
  +     * @return true if value is compatible with type, false otherwise
  +     */
  +    private boolean objectImplementsType( final Object value, final String type ) 
  +      throws ClassNotFoundException
  +    {
  +        if( type == null )
  +          throw new NullPointerException("type");
  +
  +        if( value == null )
  +          throw new NullPointerException("value");
  +
  +        final Class clazz = value.getClass();
  +        final Class typeClass = m_manager.loadClass( type );
  +        return typeClass.isAssignableFrom( clazz );
  +    }
  +
  +    /**
  +     * Create a new Logger for component.
  +     *
  +     * @param profile the profile
  +     * @return a new Logger for service
  +     * @throws Exception if unable to create the logger
  +     */
  +    public Logger createLogger( Profile profile )
  +        throws Exception
  +    {
  +        String root;
  +        if( m_manager instanceof KernelManager )
  +        {
  +            root = m_manager.getPath().replace('/','.').substring(1);
  +        }
  +        else
  +        {
  +            root = m_manager.getPath().replace('/','.').substring(1) 
  +              + "." + profile.getName();
  +        }
  +        return m_logging.getLoggerForCategory( root );
  +    }
  +
  +    /**
  +     * Create a new ComponentManager for component.
  +     *
  +     * @param profile the profile
  +     * @return a new ComponentManager for component
  +     * @throws Exception if unable to create the component manager
  +     */
  +    public ComponentManager createComponentManager( Profile profile )
  +        throws Exception
  +    {
  +        final Map services = getServices( profile );
  +        final DefaultComponentManager componentManager = new DefaultComponentManager( services );
  +        return componentManager;
  +    }
  +
  +    /**
  +     * Create a new ServiceManager for component.
  +     *
  +     * @param entry the entry
  +     * @return a new ServiceManager for component
  +     * @throws Exception if unable to create resource
  +     */
  +    public ServiceManager createServiceManager( Profile profile )
  +        throws Exception
  +    {
  +        final Map services = getServices( profile );
  +        final DefaultServiceManager serviceManager = new DefaultServiceManager( services );
  +        return serviceManager;
  +    }
  +
  +    /**
  +     * Create a new Configuration object for component.
  +     *
  +     * @param entry the entry
  +     * @return a new Configuration object for component
  +     * @throws Exception if unable to create resource
  +     */
  +    public Configuration createConfiguration( Profile profile )
  +        throws Exception
  +    {
  +        Configuration config = profile.getConfiguration( m_manager );
  +        if( config == null ) 
  +          config = new DefaultConfiguration("configuration", null );
  +        return config;
  +    }
  +
  +    /**
  +     * Create a new Parameters object for component.
  +     *
  +     * @param entry the entry
  +     * @return a new Parameters object for component
  +     * @throws Exception if unable to create resource
  +     */
  +    public Parameters createParameters( Profile profile )
  +        throws Exception
  +    {
  +        final Parameters parameters = profile.getParameters();
  +        if( null == parameters )
  +        {
  +            final String message =
  +                REZ.getString( "resource.missing-parameters.error",
  +                               profile.getName() );
  +            throw new Exception( message );
  +        }
  +        parameters.makeReadOnly();
  +        return parameters;
  +    }
  +
  +   /**
  +    * Prepare a map of the dependent services keyed by role name.
  +    * @param profile the profile referencing a type declaring dependecies
  +    * @return a map of the services
  +    */
  +    private Map getServices( Profile profile ) throws Exception
  +    {
  +        getLogger().debug("preparing services for profile: " + profile );
  +        final Type type = profile.getType();
  +        final DependencyDescriptor[] dependencies = type.getDependencies();
  +        final HashMap services = new HashMap();
  +        for( int i = 0; i < dependencies.length; i++ )
  +        {
  +            DependencyDescriptor dependency = dependencies[i];
  +            final String role = dependency.getRole();
  +            try
  +            {
  +                final Association association = profile.getAssociation( role );
  +                Object resource = association.getProvider();
  +                services.put( role, resource );
  +            }
  +            catch( Throwable e )
  +            {
  +                final String error = 
  +  "Unexpected exception while attempting to locate a service to fulfill a dependency for "
  +                  + "the role: " + role + " in profile: " + profile.getName() + ".";
  +                throw new ResourceException( error, e );
  +            }
  +        }
  +        return services;
  +    }
  +
   }
  
  
  
  1.5       +59 -78    jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifecycleHelper.java
  
  Index: LifecycleHelper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifecycleHelper.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- LifecycleHelper.java	14 Aug 2002 03:03:35 -0000	1.4
  +++ LifecycleHelper.java	14 Aug 2002 10:46:29 -0000	1.5
  @@ -7,6 +7,8 @@
    */
   package org.apache.excalibur.merlin.resource;
   
  +import java.util.Map;
  +
   import org.apache.avalon.excalibur.i18n.ResourceManager;
   import org.apache.avalon.excalibur.i18n.Resources;
   import org.apache.avalon.framework.activity.Disposable;
  @@ -28,6 +30,8 @@
   import org.apache.avalon.framework.service.ServiceManager;
   import org.apache.avalon.framework.service.Serviceable;
   
  +import org.apache.excalibur.container.lifecycle.Creator;
  +import org.apache.excalibur.container.lifecycle.Accessor;
   import org.apache.excalibur.merlin.container.Container;
   import org.apache.excalibur.merlin.model.Profile;
   import org.apache.excalibur.merlin.model.Resource;
  @@ -79,11 +83,10 @@
       * @throws LifecycleException if an error occurs when the component passes
       *     through a specific lifecycle stage
       */
  -    public Object startup( final Object object,
  -                           final String path,
  +    public Object startup( final String path,
                              final Profile profile,
  -                           final ResourceProvider provider,
  -                           final Context phaseContext )
  +                           final Object object,
  +                           final ResourceProvider provider )
           throws LifecycleException
       {
   
  @@ -99,25 +102,17 @@
           if( provider == null )
             throw new NullPointerException("provider");
   
  -        if( phaseContext == null )
  -          throw new NullPointerException("phaseContext");
  -
           getLogger().info("startup initiated for '" + path + "'." );
   
           int stage = 0;
           try
           {
  -            //Creation stage
  -            //stage = STAGE_CREATE;
  -            //notice( path, stage );
  -            //final Object object = provider.createObject( profile );
  -
               //LogEnabled stage
               stage = STAGE_LOGGER;
               if( object instanceof LogEnabled )
               {
                   notice( path, stage );
  -                final Logger logger = provider.createLogger( profile );
  +                final Logger logger = provider.createLogger();
                   ContainerUtil.enableLogging( object, logger );
               }
   
  @@ -126,7 +121,7 @@
               if( object instanceof Contextualizable )
               {
                   notice( path, stage );
  -                final Context context = provider.createContext( profile, phaseContext );
  +                final Context context = provider.createContext();
                   ContainerUtil.contextualize( object, context );
               }
   
  @@ -136,14 +131,14 @@
               {
                   notice( path, stage );
                   final ServiceManager manager =
  -                    provider.createServiceManager( profile );
  +                    provider.createServiceManager();
                   ContainerUtil.service( object, manager );
               }
               else if( object instanceof Composable )
               {
                   notice( path, stage );
                   final ComponentManager componentManager =
  -                    provider.createComponentManager( profile );
  +                    provider.createComponentManager();
                   ContainerUtil.compose( object, componentManager );
               }
   
  @@ -153,7 +148,7 @@
               {
                   notice( path, stage );
                   final Configuration configuration =
  -                    provider.createConfiguration( profile );
  +                    provider.createConfiguration();
                   ContainerUtil.configure( object, configuration );
               }
   
  @@ -163,7 +158,7 @@
               {
                   notice( path, stage );
                   final Parameters parameters =
  -                    provider.createParameters( profile );
  +                    provider.createParameters();
                   ContainerUtil.parameterize( object, parameters );
               }
   
  @@ -172,36 +167,8 @@
               //
   
               stage = STAGE_EXTENSION_PRE;
  -            PhaseDescriptor[] phases = profile.getType().getPhases();
  -            if( phases.length > 0 )
  -              notice( path, stage );
  -            for( int i=0; i<phases.length; i++ )
  -            {
  -                PhaseDescriptor phase = phases[i];
  -                final Type facility = profile.getFacility( phase );
  -                final ExtensionDescriptor ext = facility.getExtension( phase );
  -                if( ext.isApplicable( ExtensionDescriptor.CREATE ) )
  -                {
  -                    Resource resource = profile.getExtension( phase );
  -                    Extension extension = (Extension) resource.access();
  -                    try
  -                    {
  -                        getLogger().info("applying phase " + phase.getReference() + " to " + path );
  -                        Context extContext = provider.createContext( ext, phaseContext );
  -                        extension.extend( Extension.CREATE, object, extContext );
  -                        resource.release( extension );
  -                    }
  -                    catch( Throwable e )
  -                    {
  -                        final String error =
  -                          "Extension " + extension.getClass().getName() 
  -                          + " raised an exception " + e.getClass().getName()
  -                          + " while processing the creation phase for the component " 
  -                          + path;
  -                        throw new LifecycleException( error, e );
  -                    }
  -                }
  -            }
  +
  +            handleStageExtensions( profile, provider, object, true );
   
               //Initialize stage
               stage = STAGE_INIT;
  @@ -239,11 +206,14 @@
        * Errors that occur during shutdown will be logged appropriately.
        *
        * @param name the name of the component
  -     * @param object the component to shutdown
  +     * @param profile the profile used to establish the object
  +     * @param object the object to process through the shutdown phase
  +     * @param map the set of context entries for extension stages
        */
       public void shutdown( final String name,
                             final Profile profile,
  -                          final Object object )
  +                          final Object object,
  +                          final ResourceProvider provider )
           throws LifecycleException
       {
   
  @@ -274,36 +244,17 @@
   
           //
           // apply disposal extensions
  -        // ### TO-DO context ###
           //
   
           stage = STAGE_EXTENSION_POST;
  -        PhaseDescriptor[] phases = profile.getType().getPhases();
  -        if( phases.length > 0 )
  -          notice( name, stage );
  -        for( int i=(phases.length-1); i>-1; i-- )
  +        try
           {
  -            PhaseDescriptor phase = phases[i];
  -            final Type facility = profile.getFacility( phase );
  -            final ExtensionDescriptor ext = facility.getExtension( phase );
  -            if( ext.isApplicable( ExtensionDescriptor.DESTROY ) )
  -            {
  -                try
  -                {
  -                    Resource resource = profile.getExtension( phase );        
  -                    Extension extension = (Extension) resource.access();
  -                    getLogger().info("applying '" + phase.getReference() 
  -                      + "' to '" + name + "'.");
  -                    extension.extend( Extension.DESTROY, object, new DefaultContext() );
  -                    resource.release( extension );
  -                }
  -                catch( Throwable e )
  -                {
  -                    safeFail( name, STAGE_EXTENSION_POST, e );
  -                    failure = e;
  -                    stage = STAGE_EXTENSION_POST;
  -                }
  -            }
  +            handleStageExtensions( profile, provider, object, false );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String warning = "Ignoring extension error during shutdown phase.";
  +            getLogger().warn( warning, e );
           }
   
           //Disposable stage
  @@ -330,6 +281,37 @@
           }
       }
   
  +    private void handleStageExtensions( Profile profile, ResourceProvider provider, Object object, boolean create ) throws Exception
  +    {
  +        PhaseDescriptor[] stages = profile.getType().getPhases();
  +        for( int i=0; i<stages.length; i++ )
  +        {
  +            PhaseDescriptor stage = stages[i];
  +            handleStageExtension( profile, stage, provider, object, create );
  +        }
  +    }
  +
  +    private void handleStageExtension( 
  +      Profile profile, PhaseDescriptor stage, ResourceProvider provider, Object object, boolean create )
  +      throws Exception
  +    {
  +        Resource resource = profile.getExtension( stage );
  +        if( Creator.class.isAssignableFrom( resource.getImplementationClass() ) )
  +        {
  +            Creator extension = (Creator) resource.access();
  +            Context context = provider.createContext( stage );
  +            if( create )
  +            {
  +                 extension.create( object, context );
  +            }
  +            else
  +            {
  +                 extension.destroy( object, context );
  +            }
  +            resource.release( extension );
  +        }
  +    }
  +
       /**
        * Utility method to report that a lifecycle stage is about to be processed.
        *
  @@ -353,7 +335,7 @@
        * specified lifecycle stage.
        *
        * @param name the name of component that caused failure
  -     * @param stage the lefecycle stage
  +     * @param stage the lifecycle stage
        * @param t the exception thrown
        */
       private void safeFail( final String name,
  @@ -384,7 +366,6 @@
                          final Throwable t )
           throws LifecycleException
       {
  -        //final String reason = t.getMessage();
           final String reason = t.toString();
           final String message =
               REZ.getString( "lifecycle.fail.error",
  
  
  
  1.2       +9 -2      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifestyleHandler.java
  
  Index: LifestyleHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifestyleHandler.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LifestyleHandler.java	12 Aug 2002 08:11:09 -0000	1.1
  +++ LifestyleHandler.java	14 Aug 2002 10:46:29 -0000	1.2
  @@ -24,13 +24,20 @@
   public interface LifestyleHandler
   {
       /**
  +     * Returns the service class.
  +     * 
  +     * @return the service class
  +     */
  +     Class getImplementationClass();
  +
  +    /**
        * Returns an instance of the object type supported by the 
        * manager to the client.
        * 
        * @return an instance
        * @exception Exception if an error occurs during object aquisition
        */
  -     public Object get() throws Exception;
  +     Object get() throws Exception;
   
       /**
        * Invoked by a client to return an instance of the object type previously 
  @@ -39,6 +46,6 @@
        * @param object the object to return
        * @exception Exception if an error occurs during object release
        */
  -     public void put( Object object ) throws Exception;
  +     void put( Object object ) throws Exception;
   
   }
  
  
  
  1.3       +0 -2      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifestyleManager.java
  
  Index: LifestyleManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifestyleManager.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- LifestyleManager.java	14 Aug 2002 03:03:35 -0000	1.2
  +++ LifestyleManager.java	14 Aug 2002 10:46:29 -0000	1.3
  @@ -77,7 +77,6 @@
        * @param manager the container type manager
        * @param deployment a profile deployment helper
        * @param helper a lifecycle helper
  -     * @param provider a resource provider
        * @param profile the profies containing the lifestyle policy
        *
        * @return a lifecycle handler supporting the requested policy
  @@ -88,7 +87,6 @@
                               ContainerManager manager, 
                               DeploymentHelper deployment, 
                               LifecycleHelper helper, 
  -                            ResourceProvider provider, 
                               Profile profile, 
                               Context context ) 
        throws Exception;
  
  
  
  1.3       +87 -316   jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/ResourceProvider.java
  
  Index: ResourceProvider.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/ResourceProvider.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ResourceProvider.java	14 Aug 2002 03:03:35 -0000	1.2
  +++ ResourceProvider.java	14 Aug 2002 10:46:29 -0000	1.3
  @@ -66,6 +66,7 @@
   import org.apache.excalibur.meta.info.EntryDescriptor;
   import org.apache.excalibur.meta.info.ExtensionDescriptor;
   import org.apache.excalibur.meta.info.LoggerDescriptor;
  +import org.apache.excalibur.meta.info.PhaseDescriptor;
   import org.apache.excalibur.merlin.resource.ResourceException;
   import org.apache.excalibur.merlin.assembly.KernelManager;
   import org.apache.excalibur.merlin.assembly.ContainerManager;
  @@ -101,21 +102,51 @@
       //=======================================================================
       // state
       //=======================================================================
  +
  +   /**
  +    * The deployment helper
  +    */
  +    private DeploymentHelper m_helper;
  +
  +   /**
  +    * The profile.
  +    */
  +    private Profile m_profile;
  +
  +   /**
  +    * The standard context.
  +    */
  +    private Context m_context;
  +
      /**
  -    * The log manager.
  +    * The extension context map.
       */
  -    private DefaultLoggerManager m_logging;
  +    private Map m_map;
   
      /**
  -    * The classloader to use when servicing object creation requests.
  +    * The logger to apply.
       */
  -    private ContainerManager m_classloader;
  +    private Logger m_logger;
   
      /**
  -    * Context object containing system level values that is used 
  -    * as a sources for import directives.
  +    * The component manager.
       */
  -    private DefaultContext m_dictionary;
  +    private ComponentManager m_componentManager;
  +
  +   /**
  +    * The service manager.
  +    */
  +    private ServiceManager m_serviceManager;
  +
  +   /**
  +    * The configuration.
  +    */
  +    private Configuration m_config;
  +
  +   /**
  +    * The parameters.
  +    */
  +    private Parameters m_params;
   
       //=======================================================================
       // constructor
  @@ -124,17 +155,18 @@
      /**
       * Creation of a new resource provider.
       * 
  -    * @param logger the parent logger to use when creating loggers for services.
  -    * @param loader the class loader
  -    * @param dictionary the parent dictionary
  -    */
  -    public ResourceProvider( ContainerManager loader, Context dictionary, DefaultLoggerManager logging )
  -    {
  -        m_classloader = loader;
  -        m_logging = logging;
  -        m_dictionary = new DefaultContext( dictionary );
  -        m_dictionary.put( "classloader", loader );
  -        m_dictionary.makeReadOnly();
  +    * @param helper the deployment helper that is resonsible for establishing
  +    *    initial values
  +    * @param profile the subject profile
  +    * @param context the standard context to apply
  +    * @param map a map of the extension context instances keyed by stage
  +    */
  +    public ResourceProvider( DeploymentHelper helper, Profile profile, Context context, Map map )
  +    {
  +        m_helper = helper;
  +        m_profile = profile;
  +        m_context = context;
  +        m_map = map;
       }
   
       //=======================================================================
  @@ -144,272 +176,70 @@
       /**
        * Create a new Logger for component.
        *
  -     * @param profile the profile
  -     * @return a new Logger for service
  +     * @return a new Logger for the service
        * @throws Exception if unable to create the logger
        */
  -    public Logger createLogger( Profile profile )
  +    public Logger createLogger()
           throws Exception
       {
  -        String root;
  -        if( m_classloader instanceof KernelManager )
  -        {
  -            root = m_classloader.getPath().replace('/','.').substring(1);
  -        }
  -        else
  -        {
  -            root = m_classloader.getPath().replace('/','.').substring(1) 
  -              + "." + profile.getName();
  -        }
  -        return m_logging.getLoggerForCategory( root );
  +        if( m_logger != null )
  +          return m_logger;
  +        m_logger = m_helper.createLogger( m_profile );
  +        return m_logger;
       }
   
       /**
  -     * Create a new Context for component.
  +     * Create a new Context for the service.
        *
  -     * @param profile the profile
  -     * @param a supplimentary context usable during import resolution
        * @return a new Context for service
  -     * @throws Exception if unable to create context
  +     * @throws Exception if an error occurs in standard context creation
        */
  -    public Context createContext( Profile profile, Context  context )
  +    public Context createContext( )
           throws Exception
       {
  -        ContextDescriptor descriptor = profile.getType().getContext();
  -        ContextDirective directive = profile.getContext();
  -        return buildContext( descriptor, directive, context );
  +        return m_context;
       }
   
       /**
  -     * Create a new Context for an extension.
  +     * Create the context for a extension stage.
        *
  -     * @param profile the profile
  -     * @param a supplimentary context usable during import resolution
        * @return a new Context for service
  -     * @throws Exception if unable to create context
  +     * @throws Exception if an error occurs in standard context creation
        */
  -    public Context createContext( ExtensionDescriptor extension, Context  context )
  +    public Context createContext( PhaseDescriptor stage )
           throws Exception
       {
  -        ContextDescriptor descriptor = extension.getContext();
  -        return buildContext( descriptor, null, context );
  -    }
  -
  -   /**
  -    * Internal utility to construct a context instance using a descriptor, directive and source
  -    * context instances.
  -    *
  -    * @param descriptor the descriptor containing the context dependency declarations
  -    * @param directive an optional context directive containing import and context value 
  -    *    creation parameters
  -    * @param context a supplimentary context object to used during value resolution
  -    * @return a context object containing only those context entries desribed under the 
  -    *   supplied descriptor
  -    * @exception Exception if a required context value cannot be resolved or an error 
  -    *   occurs during context value creation
  -    */
  -    private Context buildContext( 
  -                           ContextDescriptor descriptors, 
  -                           ContextDirective directive, 
  -                           Context context ) 
  -      throws Exception
  -    {
  -        Map map = new HashMap();
  -        Context result;
  -
  -        if( directive != null )
  -        {
  -            final String classname = directive.getClassname();
  -            Class clazz;
  -            try
  -            {
  -                 clazz = m_classloader.loadClass( classname );
  -            }
  -            catch( ClassNotFoundException cnfe )
  -            {
  -                 throw new ResourceException(
  -                   "Could not find context class " + classname, cnfe );
  -            }
  -
  -            try
  -            {
  -                Constructor constructor = clazz.getConstructor(
  -                   new Class[]{ Map.class, Context.class } );
  -                result = (Context)constructor.newInstance( new Object[]{ map, null } );
  -            }
  -            catch( Throwable e )
  -            {
  -                throw new ResourceException(
  -                  "Unexpected exception while creating context form "
  -                  + classname, e );
  -            }
  -        }
  -        else
  -        {
  -            result = new DefaultContext( map );
  -        }
  -
  -        Context dictionary = m_dictionary;
  -        EntryDescriptor[] entries = descriptors.getEntrys();
  -        for( int i=0; i<entries.length; i++ )
  -        {
  -            EntryDescriptor entry = entries[i];
  -            String key = entry.getKey();
  -             
  -            //
  -            // if the entry is already in the supplied context then use it
  -            //
  -
  -            Object object = getContextValue( context, key );
  -            if( object == null )
  -            {
  -                object = getContextValue( dictionary, key );
  -            }
  -
  -            //
  -            // If the context value is unresolved, try to handle resolution
  -            // using an import directive supplied under the directive
  -            //
  -
  -            if( object == null )
  -            {
  -
  -                //
  -                // check if the profile declares an import directive
  -                // for the context
  -                //
  -
  -                if( directive != null )
  -                {
  -                    Import imp = directive.getImport( key );
  -                    if( imp != null )
  -                    {
  -                        String name = imp.getImportName();
  -                        object = getContextValue( context, name );
  -                        if( object == null )
  -                        {
  -                            object = getContextValue( dictionary, name );
  -                        }
  -                        if( object == null )
  -                        {
  -                            final String error = 
  -                             "Import directive for key: " + key + " via name: " + name 
  -                             + " cannot be resolved.";
  -                            getLogger().warn( error );
  -                        }
  -                    }
  -
  -                    //
  -                    // if the context value is unresolved, try to construct a context 
  -                    // value using an entry constructor directive
  -                    //
  -
  -                    if( object == null )
  -                    {
  -                        //
  -                        // check if the directive declares a context value constructor
  -                        //
  -
  -                        Entry ent = directive.getEntry( key );
  -                        if( ent != null )
  -                        {
  -                            object = ent.getValue( m_classloader, map );
  -                        }
  -                    }
  -                }
  -            }
  -
  -            //
  -            // finally, if the object is still null, and its not optional, then
  -            // throw an exception, otherwise, add the object to the context
  -            //
  -
  -            if( object != null )
  -            {
  -                try
  -                {
  -                    boolean ok = objectImplementsType( object, entry.getType() );
  -                    if( ok )
  -                    {
  -                         map.put( key, object );
  -                    }
  -                    else
  -                    {
  -                        final String error = 
  -                          "Object resolved for the key '" + key + "' of class '"
  -                          + object.getClass().getName() + "' does not implement the type '"
  -                          + entry.getType();
  -                        throw new ResourceException( error );
  -                    }
  -                }
  -                catch( ClassNotFoundException cnfe )
  -                {
  -                    final String error =
  -                      "Context criteria for the key '" + key + "' specifies an unknown type '" 
  -                      + entry.getType() + "'.";
  -                    throw new ResourceException( error );
  -                }
  -            }
  -            else
  -            {
  -                if( entry.isRequired() )
  -                {
  -                    final String error = 
  -                      "Unable to resolve a context value for the entry: " + key;
  -                    throw new ResourceException( error );
  -                }
  -            }
  -        }
  -
  -        if( result instanceof DefaultContext )
  -        {
  -            ((DefaultContext)result).makeReadOnly();
  -        }
  -
  -        return result;
  -    }
  -
  -    private Object getContextValue( Context context, String key )
  -    {
  -        if( context == null ) return null;
  -        try
  -        {
  -            return context.get( key );
  -        }
  -        catch( ContextException e )
  -        {
  -            return null;
  -        }
  +        return (Context) m_map.get( stage );
       }
   
       /**
  -     * Create a new ComponentManager for component.
  +     * Create a new ComponentManager for the service.
        *
  -     * @param profile the profile
  -     * @return a new ComponentManager for component
  +     * @return a new ComponentManager 
        * @throws Exception if unable to create the component manager
        */
  -    public ComponentManager createComponentManager( Profile profile )
  +    public ComponentManager createComponentManager( )
           throws Exception
       {
  -        final Map services = getServices( profile );
  -        final DefaultComponentManager componentManager = new DefaultComponentManager( services );
  -        return componentManager;
  +        if( m_componentManager != null )
  +          return m_componentManager;
  +        m_componentManager = m_helper.createComponentManager( m_profile );
  +        return m_componentManager;
       }
   
       /**
        * Create a new ServiceManager for component.
        *
  -     * @param entry the entry
        * @return a new ServiceManager for component
        * @throws Exception if unable to create resource
        */
  -    public ServiceManager createServiceManager( Profile profile )
  +    public ServiceManager createServiceManager( )
           throws Exception
       {
  -        final Map services = getServices( profile );
  -        final DefaultServiceManager serviceManager = new DefaultServiceManager( services );
  -        return serviceManager;
  +        if( m_serviceManager != null )
  +          return m_serviceManager ;
  +        m_serviceManager = m_helper.createServiceManager( m_profile );
  +        return m_serviceManager ;
       }
   
       /**
  @@ -419,13 +249,13 @@
        * @return a new Configuration object for component
        * @throws Exception if unable to create resource
        */
  -    public Configuration createConfiguration( Profile profile )
  +    public Configuration createConfiguration( )
           throws Exception
       {
  -        Configuration config = profile.getConfiguration( m_classloader );
  -        if( config == null ) 
  -          config = new DefaultConfiguration("configuration", null );
  -        return config;
  +        if( m_config != null )
  +          return m_config;
  +        m_config = m_helper.createConfiguration( m_profile );
  +        return m_config;
       }
   
       /**
  @@ -435,71 +265,12 @@
        * @return a new Parameters object for component
        * @throws Exception if unable to create resource
        */
  -    public Parameters createParameters( Profile profile )
  +    public Parameters createParameters( )
           throws Exception
       {
  -        final Parameters parameters = profile.getParameters();
  -        if( null == parameters )
  -        {
  -            final String message =
  -                REZ.getString( "resource.missing-parameters.error",
  -                               profile.getName() );
  -            throw new Exception( message );
  -        }
  -        parameters.makeReadOnly();
  -        return parameters;
  -    }
  -
  -   /**
  -    * Prepare a map of the dependent services keyed by role name.
  -    * @param profile the profile referencing a type declaring dependecies
  -    * @return a map of the services
  -    */
  -    private Map getServices( Profile profile ) throws Exception
  -    {
  -        getLogger().debug("preparing services for profile: " + profile );
  -        final Type type = profile.getType();
  -        final DependencyDescriptor[] dependencies = type.getDependencies();
  -        final HashMap services = new HashMap();
  -        for( int i = 0; i < dependencies.length; i++ )
  -        {
  -            DependencyDescriptor dependency = dependencies[i];
  -            final String role = dependency.getRole();
  -            try
  -            {
  -                final Association association = profile.getAssociation( role );
  -                Object resource = association.getProvider();
  -                services.put( role, resource );
  -            }
  -            catch( Throwable e )
  -            {
  -                final String error = 
  -  "Unexpected exception while attempting to locate a service to fulfill a dependency for "
  -                  + "the role: " + role + " in profile: " + profile.getName() + ".";
  -                throw new ResourceException( error, e );
  -            }
  -        }
  -        return services;
  -    }
  -
  -    /**
  -     * Check whether the specified value is compatible with specified type.
  -     *
  -     * @param value the value
  -     * @param type the desired type
  -     * @return true if value is compatible with type, false otherwise
  -     */
  -    private boolean objectImplementsType( final Object value, final String type ) 
  -      throws ClassNotFoundException
  -    {
  -        if( type == null )
  -          throw new NullPointerException("type");
  -
  -        if( value == null )
  -          throw new NullPointerException("value");
  -
  -        final Class clazz = value.getClass();
  -        final Class typeClass = m_classloader.loadClass( type );
  -        return typeClass.isAssignableFrom( clazz );
  +        if( m_params != null )
  +          return m_params;
  +        m_params = m_helper.createParameters( m_profile );
  +        return m_params;
       }
   }
  
  
  
  1.4       +4 -16     jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/SingletonLifestyleHandler.java
  
  Index: SingletonLifestyleHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/SingletonLifestyleHandler.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SingletonLifestyleHandler.java	14 Aug 2002 03:03:35 -0000	1.3
  +++ SingletonLifestyleHandler.java	14 Aug 2002 10:46:29 -0000	1.4
  @@ -31,7 +31,6 @@
   {
        private Profile m_profile;
        private ContainerManager m_manager;
  -     private LifecycleHelper m_helper;
   
        private Object m_object;
   
  @@ -46,15 +45,13 @@
        public SingletonLifestyleHandler( 
                              final ContainerManager manager, 
                              final DeploymentHelper deployment, 
  -                           final ResourceProvider provider,
                              final LifecycleHelper helper,
                              final Profile profile,
                              final Context context )
        {
  -         super( manager, deployment, provider, helper, profile, context );
  +         super( manager, deployment, helper, profile, context );
            m_profile = profile;
            m_manager = manager;
  -         m_helper = helper;
        }
   
       /**
  @@ -112,24 +109,15 @@
        */
        public void dispose()
        {
  -         super.dispose();
  -
            if( m_object != null )
            {
  -             final String path = m_manager.getPath() + "/" + m_profile.getName();
  -             try
  -             {
  -                 m_helper.shutdown( path, m_profile, m_object );
  -             }
  -             catch( Throwable e )
  -             {
  -                 getLogger().warn("Ignoring shutdown error raised by resource: " + path );
  -             }
  +             handleShutdown( m_object );
            }
            m_object = null;
            m_profile = null;
            m_manager = null;
  -         m_helper = null;
  +
  +         super.dispose();
   
   
        }
  
  
  
  1.3       +3 -15     jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/TransientLifestyleHandler.java
  
  Index: TransientLifestyleHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/TransientLifestyleHandler.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- TransientLifestyleHandler.java	14 Aug 2002 03:03:35 -0000	1.2
  +++ TransientLifestyleHandler.java	14 Aug 2002 10:46:29 -0000	1.3
  @@ -33,7 +33,6 @@
   {
        private Profile m_profile;
        private ContainerManager m_manager;
  -     private LifecycleHelper m_helper;
   
        private ArrayList m_objects = new ArrayList();
   
  @@ -48,15 +47,13 @@
        public TransientLifestyleHandler( 
                              final ContainerManager manager, 
                              final DeploymentHelper deployment, 
  -                           final ResourceProvider provider,
                              final LifecycleHelper helper,
                              final Profile profile,
                              final Context context )
        {
  -         super( manager, deployment, provider, helper, profile, context );
  +         super( manager, deployment, helper, profile, context );
            m_profile = profile;
            m_manager = manager;
  -         m_helper = helper;
        }
   
       /**
  @@ -86,18 +83,10 @@
            getLogger().debug("put");
            if( m_objects.contains( object ) )
            {
  +             super.processReleaseStage( object );
                m_objects.remove( object );
  -             final String path = m_manager.getPath() + "/" + m_profile.getName();
  -             try
  -             {
  -                 m_helper.shutdown( path, m_profile, object );
  -             }
  -             catch( Throwable e )
  -             {
  -                 getLogger().warn("Ignoring shutdown error raised by transient resource: " + path );
  -             }
  +             handleShutdown( object );
            }
  -         super.processReleaseStage( object );
        }
   
       /**
  @@ -122,7 +111,6 @@
            }
            m_profile = null;
            m_manager = null;
  -         m_helper = null;
            m_objects = null;
   
            super.dispose();
  
  
  
  1.5       +3 -3      jakarta-avalon-excalibur/assembly/src/xdocs/faq.xml
  
  Index: faq.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/xdocs/faq.xml,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- faq.xml	6 Aug 2002 07:32:23 -0000	1.4
  +++ faq.xml	14 Aug 2002 10:46:30 -0000	1.5
  @@ -19,11 +19,11 @@
   
       <subsection name="What's the difference between Merlin and Phoenix?">
   
  -<p>Merlin and Phoenix can be considered to be derived from the same family in terms of architecture and notions of "what a component is".  Both Merlin and Phoenix leverage meta-information about a type of component (the .xinfo resource).  Meta information used by Phoenix is described as a &lt;block&gt; whereas Merlin uses the more general &lt;component-info&gt; model.  Both models are relatively equivalent and it is expected that Phoenix will be migrating to a common &lt;component-info&gt; schema in the near future.  With this in place, Phoenix based components will be usable within Merlin providing the components do not use Phoenix specific interfaces or classes.  Typically, the two aspect to watch for on Phoenix based components that limit portability are (a) references to the class BlockContext (which can be eliminated by using the context key instead of Phoenix specific context accessors), and (b), the usage of the BlockListener and ApplicationListener interfaces (both representing Phoenix specific extensions).</p>
  +<p>Merlin and Phoenix can be considered to be derived from the same family in terms of architecture and notions of "what a component is".  Both Merlin and Phoenix leverage meta-information about a type of component (the .xinfo resource).  Meta information used by Phoenix is described in a &lt;blockinfo&gt; whereas Merlin uses the more advanced &lt;type&gt; DTD. Plans for Merlin development include addition of support for the block-info DTD (enabling execution of Phoenix style components inside Merlin).  Both models share many of the same DTD features and it is expected that Phoenix will migrate to or at least support the &lt;type&gt; schema in the future.  With this in place, Phoenix based components will be interoperable within Merlin providing the components do not use Phoenix specific interfaces or classes.  Typically, the two aspect to watch for on Phoenix based components that limit portability are (a) references to the class BlockContext (which can be eliminated by using the context key instead of Phoenix specific context accessors), and (b), the usage of the BlockListener and ApplicationListener interfaces (both representing Phoenix specific extensions).</p>
   
   <p>Aside from these differences, Phoenix and Merlin are very similar - they both handle service assembly, activation, and decommissioning.  Differences appear with respect to the approaches used and the overhead implied on a user. Merlin makes every attempt to minimise that level of information required to assemble a service model.  For example, Merlin does not require explicit linking of components under an assembly file.  Furthermore, Merlin provides a framework for defaults management enabling automatic service establishment.  Perhaps most significant is the design objective of Merlin to provide simple programmatic embedding of kernels and containers into other components and foreign systems.  Relative to Merlin, Phoenix is much more static in that it requires a significantly higher level of engagement in the establishment of a service model.  On the other-hand, Phoenix contains additional features not present in Merlin - in particular JMX support.</p>
   
  -<p>At the overall architecture level Phoenix provides support for pluggable facilities (cut-down components) to provide support for core services towards a set of applications.  Merlin's goes further by providing the ability for real "component" based facilities model via embedded <a href="api/assembly/org/apache/excalibur/merlin/kernel/Kernel.html">kernels</a> that export services backed by a flexible hierarchical <a href="api/assembly/org/apache/excalibur/merlin/container/Container.html">container</a> structure.  Based simply on available functionality, Phoenix, it's the choice when selecting an app-server. Merlin on the other-hand demands substantially less engagement by the end-user and delivers a commensurate reduction in support overhead.</p>
  +<p>At the overall architecture level Phoenix provides support for pluggable facilities (cut-down components) to provide support for core services towards a set of applications.  Merlin's goes further by providing the ability for real "component" based facilities model via embedded <a href="api/assembly/org/apache/excalibur/merlin/kernel/Kernel.html">kernels</a> that export services backed by a flexible hierarchical <a href="api/assembly/org/apache/excalibur/merlin/container/Container.html">container</a> structure.  Based simply on available functionality, Phoenix, is the choice when selecting an app-server. Merlin on the other-hand demands substantially less engagement by the end-user and delivers a commensurate reduction in support overhead.</p>
   
         </subsection>
   
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>