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/12 10:11:09 UTC

cvs commit: jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource AbstractExtension.java AbstractLifestyleHandler.java DefaultComponentManager.java DefaultManager.java DefaultResource.java DefaultServiceManager.java Extension.java LifecycleException.java LifecycleHelper.java LifestyleHandler.java ResourceException.java ResourceProvider.java ResourceRuntimeException.java Resources.properties SingletonLifestyleHandler.java TransientLifestyleHandler.java package.html

mcconnell    2002/08/12 01:11:09

  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 ProfileRegistry.java
               assembly/src/java/org/apache/excalibur/merlin/container
                        StructuralExtension.java
  Added:       assembly/src/java/org/apache/excalibur/merlin/resource
                        AbstractExtension.java
                        AbstractLifestyleHandler.java
                        DefaultComponentManager.java DefaultManager.java
                        DefaultResource.java DefaultServiceManager.java
                        Extension.java LifecycleException.java
                        LifecycleHelper.java LifestyleHandler.java
                        ResourceException.java ResourceProvider.java
                        ResourceRuntimeException.java Resources.properties
                        SingletonLifestyleHandler.java
                        TransientLifestyleHandler.java package.html
  Removed:     assembly/src/java/org/apache/excalibur/merlin/assembly/resource
                        AbstractExtension.java DefaultComponentManager.java
                        DefaultManager.java DefaultResource.java
                        DefaultServiceManager.java Extension.java
                        LifecycleException.java LifecycleHelper.java
                        LifestyleHandler.java ResourceException.java
                        ResourceProvider.java ResourceRuntimeException.java
                        Resources.properties SingletonLifestyleHandler.java
                        package.html
  Log:
  Upgrading support for lifecycle and lifestyle management.
  
  Revision  Changes    Path
  1.40      +4 -4      jakarta-avalon-excalibur/assembly/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/build.xml,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- build.xml	12 Aug 2002 06:08:54 -0000	1.39
  +++ build.xml	12 Aug 2002 08:11:08 -0000	1.40
  @@ -295,10 +295,10 @@
     </target>
   
     <target name="patch">
  -    <replace dir="${src.dir}/java" 
  -       token="ProfileDesignator"
  -       value="DefaultResource" >
  -     <include name="org/apache/excalibur/merlin/**/*.*"/>
  +    <replace dir="demo" 
  +       token="org.apache.excalibur.merlin.assembly.resource"
  +       value="org.apache.excalibur.merlin.resource" >
  +     <include name="**/*.*"/>
       </replace>
     </target>
   
  
  
  
  1.3       +2 -2      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.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DemoManager.java	2 Aug 2002 06:29:20 -0000	1.2
  +++ DemoManager.java	12 Aug 2002 08:11:08 -0000	1.3
  @@ -4,8 +4,8 @@
   
   import org.apache.avalon.framework.context.Context;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
  -import org.apache.excalibur.merlin.assembly.resource.Extension;
  -import org.apache.excalibur.merlin.assembly.resource.AbstractExtension;
  +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;
   
  
  
  
  1.5       +2 -2      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.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ExploitationManager.java	2 Aug 2002 06:29:20 -0000	1.4
  +++ ExploitationManager.java	12 Aug 2002 08:11:08 -0000	1.5
  @@ -4,8 +4,8 @@
   
   import org.apache.avalon.framework.context.Context;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
  -import org.apache.excalibur.merlin.assembly.resource.Extension;
  -import org.apache.excalibur.merlin.assembly.resource.AbstractExtension;
  +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;
   
  
  
  
  1.12      +25 -9     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.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- ContainerManager.java	12 Aug 2002 06:08:54 -0000	1.11
  +++ ContainerManager.java	12 Aug 2002 08:11:08 -0000	1.12
  @@ -34,16 +34,17 @@
   import org.apache.avalon.excalibur.i18n.ResourceManager;
   import org.apache.avalon.excalibur.i18n.Resources;
   import org.apache.excalibur.configuration.ConfigurationUtil;
  -import org.apache.excalibur.merlin.assembly.resource.LifecycleHelper;
  -import org.apache.excalibur.merlin.assembly.resource.ResourceProvider;
  -import org.apache.excalibur.merlin.assembly.resource.ResourceException;
  -import org.apache.excalibur.merlin.assembly.resource.DefaultResource;
  -import org.apache.excalibur.merlin.assembly.resource.LifestyleHandler;
  -import org.apache.excalibur.merlin.assembly.resource.SingletonLifestyleHandler;
  -import org.apache.excalibur.merlin.model.ContainerDescriptor;
  -import org.apache.excalibur.merlin.model.ClasspathDescriptor;
  +import org.apache.excalibur.merlin.resource.ResourceException;
  +import org.apache.excalibur.merlin.resource.DefaultResource;
   import org.apache.excalibur.merlin.container.Container;
   import org.apache.excalibur.merlin.container.DefaultContainer;
  +import org.apache.excalibur.merlin.resource.LifestyleHandler;
  +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.model.ContainerDescriptor;
  +import org.apache.excalibur.merlin.model.ClasspathDescriptor;
   import org.apache.excalibur.merlin.model.LoggingDescriptor;
   import org.apache.excalibur.merlin.model.builder.XMLContainerUtil;
   import org.apache.excalibur.merlin.model.Category;
  @@ -728,7 +729,7 @@
       }
   
      /**
  -    * Returns an existing or new resource using the supplied local profile and context.
  +    * Returns a new or existing resource using the supplied local profile and context.
       *
       * @param profile the profile
       * @param the deployment context
  @@ -746,6 +747,21 @@
           // ## assemble it before supplying it to the default resource instance. #
           // ##                                                                   #
           // ######################################################################
  +
  +        String policy = profile.getType().getInfo().getAttribute("avalon:lifestyle", "transient" );
  +        if( policy.equals( "transient" ) )
  +        {
  +        }
  +        else if( policy.equalsIgnoreCase( "singleton" ) ) 
  +        {
  +        }
  +        else if( policy.equalsIgnoreCase( "per-thread" ) ) 
  +        {
  +        }
  +        else if( policy.equalsIgnoreCase( "pooled" ) ) 
  +        {
  +        }
  +
   
           SingletonLifestyleHandler handler = 
              new SingletonLifestyleHandler( this, m_provider, m_helper, profile, context );
  
  
  
  1.11      +3 -17     jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ProfileRegistry.java
  
  Index: ProfileRegistry.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ProfileRegistry.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- ProfileRegistry.java	12 Aug 2002 06:08:54 -0000	1.10
  +++ ProfileRegistry.java	12 Aug 2002 08:11:08 -0000	1.11
  @@ -32,10 +32,8 @@
   import org.apache.excalibur.meta.info.Facility;
   import org.apache.excalibur.merlin.model.Profile;
   import org.apache.excalibur.merlin.model.Resource;
  -import org.apache.excalibur.merlin.assembly.resource.LifecycleHelper;
  -import org.apache.excalibur.merlin.assembly.resource.ResourceProvider;
  -import org.apache.excalibur.merlin.assembly.resource.ResourceException;
  -import org.apache.excalibur.merlin.assembly.resource.DefaultResource;
  +import org.apache.excalibur.merlin.resource.ResourceException;
  +import org.apache.excalibur.merlin.resource.DefaultResource;
   
   /**
    * Internal table that holds available component type keyed relative
  @@ -61,18 +59,6 @@
       * The dependency map that is populated during the assembly process.
       */
       private DependencyGraph m_map;
  -
  -   /**
  -    * The lifecycle helper.
  -    */
  -    private LifecycleHelper m_helper;
  -
  -   /**
  -    * Utility class that manages supply of context, config, services, etc. during
  -    * startup of a profile.
  -    */
  -    private ResourceProvider m_provider;
  -
   
       //=======================================================================
       // constructor
  
  
  
  1.2       +5 -5      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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- StructuralExtension.java	12 Aug 2002 01:56:37 -0000	1.1
  +++ StructuralExtension.java	12 Aug 2002 08:11:09 -0000	1.2
  @@ -6,16 +6,16 @@
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.avalon.framework.context.ContextException;
   import org.apache.avalon.framework.configuration.Configuration;
  -import org.apache.excalibur.merlin.container.Container;
  -import org.apache.excalibur.merlin.container.Structural;
   import org.apache.excalibur.merlin.assembly.TypeException;
   import org.apache.excalibur.merlin.assembly.ContainerManager;
  -import org.apache.excalibur.merlin.assembly.resource.Extension;
  -import org.apache.excalibur.merlin.assembly.resource.AbstractExtension;
  +import org.apache.excalibur.merlin.container.Container;
  +import org.apache.excalibur.merlin.container.Structural;
  +import org.apache.excalibur.merlin.resource.Extension;
  +import org.apache.excalibur.merlin.resource.AbstractExtension;
   import org.apache.excalibur.merlin.model.builder.XMLContainerUtil;
   import org.apache.excalibur.merlin.model.ContainerDescriptor;
  -import org.apache.excalibur.meta.info.Type;
   import org.apache.excalibur.merlin.model.Profile;
  +import org.apache.excalibur.meta.info.Type;
   
   /**
    * Extension that supplorts the assembly of a container structure.
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/AbstractExtension.java
  
  Index: AbstractExtension.java
  ===================================================================
  
  
  package org.apache.excalibur.merlin.resource;
  
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.activity.Disposable;
  
  /**
   * Definition of an extension type.
   * @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
   */
  public class AbstractExtension extends AbstractLogEnabled implements Extension
  {
  
      //=======================================================================
      // 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
      {
          if( getLogger().isDebugEnabled() )
            getLogger().debug(
               "extending " + object.getClass().getName() 
               + "#" + System.identityHashCode( object ) 
               + " for stage " + stageToString( stage ) );
      }
  
     /**
      * Utility method to return a string representation of the lifecycle stage.
      * @param stage the lifecycle stage
      * @return the string representation of the stage
      */
      public static String stageToString( int stage )
      {
         if( stage == CREATE )
         {
             return "CREATE";
         }
         else if( stage == ACCESS )
         {
             return "ACCESS";
         }
         else if( stage == RELEASE )
         {
             return "RELEASE";
         }
         else if( stage == DESTROY )
         {
             return "DESTROY";
         }
         else
         {
             throw new IllegalArgumentException( "stage: " + stage );
         }
      }
  
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/AbstractLifestyleHandler.java
  
  Index: AbstractLifestyleHandler.java
  ===================================================================
  /*
   * 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.
   *
   * Original contribution by OSM SARL, http://www.osm.net
   */
  package org.apache.excalibur.merlin.resource;
  
  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.merlin.assembly.ContainerManager;
  import org.apache.excalibur.merlin.resource.ResourceException;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.Resource;
  import org.apache.excalibur.meta.info.PhaseDescriptor;
  import org.apache.excalibur.meta.info.ExtensionDescriptor;
  import org.apache.excalibur.meta.info.Facility;
  
  
  /**
   * Lifestyle implementation that provides suppport for the singleton
   * policy.  Request for a single instance will allways return the 
   * same instance for each request.
   *
   * @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
   */
  public abstract class AbstractLifestyleHandler extends AbstractLogEnabled 
    implements LifestyleHandler, Disposable
  {
       private Profile m_profile;
       private ContainerManager m_manager;
       private ResourceProvider m_provider;
       private LifecycleHelper m_helper;
       private Context m_context;
  
      /**
       * Creation of a new singleton lifecycle manager.
       * @param manager the type manager 
       * @param provider the resource provider 
       * @param helper the lifecycle helper 
       * @param profile the profile defining the object type
       * @param context the establishment context
       */
       public AbstractLifestyleHandler( 
                             final ContainerManager manager, 
                             final ResourceProvider provider, 
                             final LifecycleHelper helper,
                             final Profile profile, 
                             final Context context )
       {
           if( profile == null )
             throw new NullPointerException("profile");
  
           if( manager == null )
             throw new NullPointerException("manager");
  
           m_profile = profile;
           m_manager = manager;
           m_provider = provider;
           m_helper = helper;
           m_context = context;
       }
  
      /**
       * Returns an instance of the object type supported by the 
       * manager to the client.
       * 
       * @return an instance of the type defined by the profile
       */
      public abstract Object get() throws Exception;
  
      /**
       * Invoked by a client to return an instance of the object type previously 
       * supported by the manager.  The singleton manager does nothing as the 
       * object may be used across an arbitary number of clients.
       * 
       * @param object the object to return
       */
       public abstract void put( Object object ) throws Exception;
  
      /**
       * Handle the access phase extensions as declared by the profile type.
       * @param object the object to process
       * @param Exception if a stage procesing exception occurs
       */
       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 );
          }
       }
  
      /**
       * Handle the access phase extensions as declared by the profile type.
       * @param object the object to process
       * @param Exception if a stage procesing exception occurs
       */
       protected void processReleaseStage( Object object ) throws Exception
       {
          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 );
          }
       }
  
      private void processExtension( int stage, PhaseDescriptor phase, Object object, Context context ) throws Exception
      {
          final Facility facility = m_profile.getFacility( phase );
          final ExtensionDescriptor ext = facility.getExtension( phase );
          if( ext.isApplicable( stage ) )
          {
              Resource resource = m_profile.getExtension( phase );
              Extension extension = (Extension) resource.access();
              try
              {
                  extension.extend( stage, object, context );
              }
              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 );
              }
          }
      }
  
      /**
       * Instantiate an instance of the type.
       * 
       * @return an instance of the type defined by the profile
       */
       protected Object createInstance() throws Exception
       {
          getLogger().debug("create");
  
          //
          // 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();
          }
          catch( Throwable e )
          {
              final String error = 
                "Unexpected exception while attempting to instantiate an instance from profile: " 
                   + m_profile;
               throw new ResourceException( error, e );
          }
  
          final String path = m_manager.getPath() + "/" + m_profile.getName();
          m_helper.startup( object, path, m_profile, m_provider, m_context );
  
          return object;
  
       }
  
  
      /**
       * Request for disposal of the manager.  This operation is normally invoked
       * by the client that initialy instantiated the manager.  The implementation
       * handles the disposal of the associated profile.
       */
       public void dispose()
       {
           m_profile = null;
           m_manager = null;
           m_provider = null;
           m_helper = null;
       }
  }
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultComponentManager.java
  
  Index: DefaultComponentManager.java
  ===================================================================
  /*
   * 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.
   *
   * Original contribution by OSM SARL, http://www.osm.net
   */
  package org.apache.excalibur.merlin.resource;
  
  import java.util.Map;
  import org.apache.avalon.framework.component.Component;
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  
  /**
   * Internal helper class the implements the <code>ComponentLocator</code> interface and
   * is supplied to dynamically created componets during lifecycle pipeline processing.
   * @author Stephen McConnell <mc...@osm.net>
   */
  class DefaultComponentManager
      extends DefaultManager
      implements ComponentManager
  {
      public DefaultComponentManager( Map providers )
      {
          super( providers );
      }
  
      public boolean hasComponent( String role )
      {
          return super.has( role );
      }
  
      public Component lookup( String role ) throws ComponentException
      {
          Object object = null;
          try
          {
              object = super.get( role );
              if( object instanceof Component )
              {
                  return (Component)object;
              }
              throw new ComponentException( role, "Service provider returned a non-Component." );
          }
          catch( ResourceException e )
          {
              final String error = "Provider related error during service resolution.";
              throw new ComponentException( role, error, e );
          }
      }
  
      /**
       * Release a pooled object.
       *
       * @param component a pooled object
       */
      public void release( Component component )
      {
          super.put( component );
      }
  }
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultManager.java
  
  Index: DefaultManager.java
  ===================================================================
  /*
   * 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.
   *
   * Original contribution by OSM SARL, http://www.osm.net
   */
  package org.apache.excalibur.merlin.resource;
  
  import java.util.Map;
  import java.util.Hashtable;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.excalibur.merlin.model.Resource;
  
  
  /**
   * Internal helper class the handles the functional requirements of
   * both ComponetManager and ComponentLocator.
   * @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
   */
  class DefaultManager
  {
      /**
       * A map of resources keyed by lookup role.
       */
      private Map m_providers;
  
      /**
       * A mappiong of resource instances keyed by the object is provided
       * and to which the object should be released.
       */
      private Hashtable m_mapping = new Hashtable();
  
     /**
      * Creation of a new manager.
      * @param providers the resource map
      */
      public DefaultManager( Map providers )
      {
          m_providers = providers;
      }
  
     /**
      * Return TRUE is the manager has a resoruce for the role.
      * @param role the role name to look for in the resource map
      * @return TRUE is a resource exists for the role
      */
      public boolean has( String role )
      {
          return ( m_providers.get( role ) != null );
      }
  
     /**
      * Returns the service object.
      * @return the service instance
      */
      public Object get( String role ) throws ResourceException
      {
          Resource resource = (Resource) m_providers.get( role );
          if( resource == null )
          {
              throw new ResourceException(
                  "Could not locate a provider for the role: " + role );
          }
          else
          {
              try
              {
                  Object object = resource.access();
                  m_mapping.put( object, resource );
                  return object;
              }
              catch( Throwable e )
              {
                  final String error = "Unexpected exception while resolving the service from " 
                  + resource.getPath() + " for the role: " + role;
                  throw new ResourceException( error, e );
              }
          }
      }
  
      /**
       * Release a pooled object.
       * @param object a pooled object
       * @exception ResourceRuntimeException is an error occurs during release
       */
      public void put( Object object ) throws ResourceRuntimeException
      {
         final Resource resource = (Resource) m_mapping.get( object );
         try
         {
             resource.release( object );
             m_mapping.remove( object );
         }
         catch( Throwable e )
         {
             final String error = "Unexpected error while attempting to release resource: " + resource;
             throw new ResourceRuntimeException( error, e );
         }
      }
  
  }
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultResource.java
  
  Index: DefaultResource.java
  ===================================================================
  /*
   * 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.
   */
  package org.apache.excalibur.merlin.resource;
  
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.DefaultContext;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.excalibur.merlin.resource.LifecycleHelper;
  import org.apache.excalibur.merlin.resource.LifestyleHandler;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.Resource;
  import org.apache.excalibur.meta.info.ServiceDescriptor;
  import org.apache.excalibur.meta.info.PhaseDescriptor;
  import org.apache.excalibur.meta.info.ExtensionDescriptor;
  import org.apache.excalibur.meta.info.Facility;
  
  /**
   * Opaque type that maps a path to a profile.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
   */
  public class DefaultResource extends AbstractLogEnabled implements Resource
  {
  
      public static final String HEADER = "service:";
  
      /**
       * The path of the profile designator.
       */
      private final String m_path;
  
      /**
       * The profile that disignator refers to.
       */
      private final Profile m_profile;
  
      /**
       * The deployment context.
       */
      private final Context m_context;
  
      /**
       * The lifestyle manager.
       */
      private LifestyleHandler m_handler;
  
      /**
       * Create a new resoruce instance.
       *
       * @param path the container path
       * @param profile the resource's profile
       * @param context the deployment context
       * @param factory the lifestyle manager
       */
      public DefaultResource( final String path,
                             final Profile profile,
                             final Context context,
                             final LifestyleHandler handler )
      {
          if( null == path )
              throw new NullPointerException( "path" );
  
          if( null == profile )
              throw new NullPointerException( "profile" );
  
          if( null == context )
              throw new NullPointerException( "context" );
  
          if( null == handler )
              throw new NullPointerException( "handler" );
  
          m_path = path;
          m_profile = profile;
          m_context = context;
          m_handler = handler;
      }
  
      /**
       * Returns the path of the resource.
       *
       * @return the symbolic path of the resource
       */
      public String getPath()
      {
          return HEADER + m_path;
      }
  
      /**
       * Returns the service descriptor.
       *
       * @return the service descriptor
       */
      public ServiceDescriptor[] getServices()
      {
          return m_profile.getType().getServices();
      }
  
      /**
       * Access an instance.
       *
       * @return the service instance.
       * @exception Exception if an error occurs while establishing the object
       */
      public Object access() throws Exception
      {
          getLogger().debug("access");
          return m_handler.get();
      }
  
      /**
       * Release a service instance.
       */
      public void release( Object object ) throws Exception
      {
          getLogger().debug("release");
          m_handler.put( object );
      }
  
      /**
       * Dispose of the reference and any consumed resources.
       */
      public void dispose()
      {
          getLogger().debug("dispose");
          if( m_handler instanceof Disposable )
          {
              ((Disposable)m_handler).dispose();
          }
          m_handler = null;
      }
  
     /**
      * Return the profile.
      *
      * @return the profile
      */
      public Profile getProfile()
      {
          return m_profile;
      }
  
      public String toString()
      {
          return "DefaultResource - profile:" + m_profile;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultServiceManager.java
  
  Index: DefaultServiceManager.java
  ===================================================================
  /*
   * 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.
   *
   * Original contribution by OSM SARL, http://www.osm.net
   */
  package org.apache.excalibur.merlin.resource;
  
  import java.util.Map;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.service.ServiceManager;
  
  /**
   * Internal helper class the implements the <code>ServiceManager</code> interface and
   * is supplied to dynamically created componets during lifecyle pipeline processing.
   * @author Stephen McConnell <mc...@osm.net>
   */
  class DefaultServiceManager
      extends DefaultManager
      implements ServiceManager
  {
      /**
       * Construct a new ServiceManager.
       */
      public DefaultServiceManager( Map providers )
      {
          super( providers );
      }
  
      /**
       * Returns true if a provider exists for the supplied role.
       * @param role the service identifier
       * @return boolean TRUE if the service is available else FALSE
       */
      public boolean hasService( String role )
      {
          return super.has( role );
      }
  
      /**
       * Retrieve Object by role from ComponentLocator.
       * @param role the role
       * @return the Object
       * @throws ServiceException if an error occurs
       */
      public Object lookup( String role ) throws ServiceException
      {
          try
          {
              return super.get( role );
          }
          catch( ResourceException e )
          {
              final String error = "Service resolution failure for role: " + role;
              throw new ServiceException( error, e );
          }
      }
  
      /**
       * Release a pooled object.
       * @param object a pooled object
       */
      public void release( Object object )
      {
          super.put( object );
      }
  }
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/Extension.java
  
  Index: Extension.java
  ===================================================================
  /*
  * 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.
  */
  package org.apache.excalibur.merlin.resource;
  
  import org.apache.avalon.framework.context.Context;
  
  /**
   * <code>PhaseExtension</code> interface. This interface defines the methods that
   * a container can invoke on a phase handler extension.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @author <a href="mailto:crafterm@apache.org">Marcus Crafter</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
   */
  public interface Extension
  {
      public static final int CREATE = 0;
      public static final int ACCESS = 1;
      public static final int RELEASE = 2;
      public static final int DESTROY = 3;
  
      /**
       * Apply lifecycle phase extension.
       *
       * @param stage the lifecycle stage
       * @param object the object to apply the extension to
       * @param context the context
       * @exception Exception if an error occurs
       */
      void extend( int stage, Object object, Context context )
          throws Exception;
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifecycleException.java
  
  Index: LifecycleException.java
  ===================================================================
  /*
   * 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.
   */
  package org.apache.excalibur.merlin.resource;
  
  import org.apache.avalon.framework.CascadingException;
  import org.apache.excalibur.meta.verifier.VerifyException;
  
  /**
   * Exception to indicate error processing a component through its lifecycle.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
   */
  public final class LifecycleException
      extends CascadingException
  {
      /**
       * Construct a new <code>VerifyException</code> instance.
       *
       * @param message The detail message for this exception.
       */
      public LifecycleException( final String message )
      {
          this( message, null );
      }
  
      /**
       * Construct a new <code>VerifyException</code> instance.
       *
       * @param message The detail message for this exception.
       * @param throwable the root cause of the exception
       */
      public LifecycleException( final String message, final Throwable throwable )
      {
          super( message, throwable );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifecycleHelper.java
  
  Index: LifecycleHelper.java
  ===================================================================
  /*
   * 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.
   */
  package org.apache.excalibur.merlin.resource;
  
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.framework.component.ComponentManager;
  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.container.ContainerUtil;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.context.DefaultContext;
  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.framework.parameters.Parameterizable;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.service.ServiceManager;
  import org.apache.avalon.framework.service.Serviceable;
  
  import org.apache.excalibur.merlin.container.Container;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.Resource;
  import org.apache.excalibur.merlin.model.ContextDirective;
  import org.apache.excalibur.meta.info.ContextDescriptor;
  import org.apache.excalibur.meta.info.PhaseDescriptor;
  import org.apache.excalibur.meta.info.ExtensionDescriptor;
  import org.apache.excalibur.meta.info.Facility;
  
  /**
   * This is a class to help an Application manage the lifecycle of a component.
   * The implementation provides support for the processing of a component through
   * each lifecycle stage, and manage errors in a consistent way.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   */
  public class LifecycleHelper
      extends AbstractLogEnabled
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( LifecycleHelper.class );
  
      //Constants to designate stages
      private static final int STAGE_CREATE = 0;
      private static final int STAGE_LOGGER = 1;
      private static final int STAGE_CONTEXT = 2;
      private static final int STAGE_COMPOSE = 3;
      private static final int STAGE_CONFIG = 4;
      private static final int STAGE_PARAMETER = 5;
      private static final int STAGE_EXTENSION_PRE = 6;
      private static final int STAGE_INIT = 7;
      private static final int STAGE_START = 8;
      private static final int STAGE_STOP = 9;
      private static final int STAGE_DISPOSE = 10;
      private static final int STAGE_EXTENSION_POST = 11;
      private static final int STAGE_DESTROY = 12;
  
     /**
      * Method to run a component through it's startup phase.
      * Errors that occur during startup will be logged appropriately and
      * cause exceptions with useful messages to be raised.
      *
      * @param name the name of the component
      * @param profile representing the instance criteria
      * @param provider the resource provider
      * @param phaseContext the phase context 
      *
      * @throws LifecycleException if an error occurs when the component passes
      *     through a specific lifecycle stage
      */
      public Object startup( final Object object,
                             final String path,
                             final Profile profile,
                             final ResourceProvider provider,
                             final Context phaseContext )
          throws LifecycleException
      {
  
          if( object == null )
            throw new NullPointerException("object");
  
          if( path == null )
            throw new NullPointerException("path");
  
          if( profile == null )
            throw new NullPointerException("profile");
  
          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 );
                  ContainerUtil.enableLogging( object, logger );
              }
  
              //Contextualize stage
              stage = STAGE_CONTEXT;
              if( object instanceof Contextualizable )
              {
                  notice( path, stage );
                  final Context context = provider.createContext( profile, phaseContext );
                  ContainerUtil.contextualize( object, context );
              }
  
              //Composition stage
              stage = STAGE_COMPOSE;
              if( object instanceof Serviceable )
              {
                  notice( path, stage );
                  final ServiceManager manager =
                      provider.createServiceManager( profile );
                  ContainerUtil.service( object, manager );
              }
              else if( object instanceof Composable )
              {
                  notice( path, stage );
                  final ComponentManager componentManager =
                      provider.createComponentManager( profile );
                  ContainerUtil.compose( object, componentManager );
              }
  
              //Configuring stage
              stage = STAGE_CONFIG;
              if( object instanceof Configurable )
              {
                  notice( path, stage );
                  final Configuration configuration =
                      provider.createConfiguration( profile );
                  ContainerUtil.configure( object, configuration );
              }
  
              //Parameterizing stage
              stage = STAGE_PARAMETER;
              if( object instanceof Parameterizable )
              {
                  notice( path, stage );
                  final Parameters parameters =
                      provider.createParameters( profile );
                  ContainerUtil.parameterize( object, parameters );
              }
  
              //
              // apply creation phase extensions
              //
  
              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 Facility 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 );
                      }
                      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 );
                      }
                  }
              }
  
              //Initialize stage
              stage = STAGE_INIT;
              if( object instanceof Initializable )
              {
                  notice( path, stage );
                  ContainerUtil.initialize( object );
              }
  
              //Start stage
              stage = STAGE_START;
              if( !(object instanceof Container) )
              {
                  if( object instanceof Startable )
                  {
                      notice( path, stage );
                      ContainerUtil.start( object );
                  }
              }
  
              return object;
          }
          catch( final Throwable t )
          {
              fail( path, stage, t );
  
              //fail() throws an exception so next
              //line will never be executed
              return null;
          }
      }
  
      /**
       * Method to run a component through it's shutdown phase.
       * Errors that occur during shutdown will be logged appropriately.
       *
       * @param name the name of the component
       * @param object the component to shutdown
       */
      public void shutdown( final String name,
                            final Profile profile,
                            final Object object )
          throws LifecycleException
      {
  
          getLogger().info("shutdown initiated for '" + name + "'." );
  
          //Stage at which failure occured
          int stage = 0;
  
          //Failure exception
          Throwable failure = null;
  
          //Stoppable stage
  
          if( object instanceof Startable )
          {
              notice( name, STAGE_STOP );
              try
              {
                  ContainerUtil.stop( object );
              }
              catch( final Throwable t )
              {
                  safeFail( name, STAGE_STOP, t );
                  failure = t;
                  stage = STAGE_STOP;
              }
          }
  
          //
          // 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-- )
          {
              PhaseDescriptor phase = phases[i];
              final Facility 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() );
                  }
                  catch( Throwable e )
                  {
                      safeFail( name, STAGE_EXTENSION_POST, e );
                      failure = e;
                      stage = STAGE_EXTENSION_POST;
                  }
              }
          }
  
          //Disposable stage
          if( object instanceof Disposable )
          {
              notice( name, STAGE_DISPOSE );
              try
              {
                  ContainerUtil.dispose( object );
              }
              catch( final Throwable t )
              {
                  safeFail( name, STAGE_DISPOSE, t );
                  failure = t;
                  stage = STAGE_DISPOSE;
              }
          }
  
          notice( name, STAGE_DESTROY );
  
          if( null != failure )
          {
              fail( name, stage, failure );
          }
      }
  
      /**
       * Utility method to report that a lifecycle stage is about to be processed.
       *
       * @param name the name of component that is the subject of the notice
       * @param stage the lifecycle processing stage
       */
      private void notice( final String name, final int stage )
      {
          if( getLogger().isDebugEnabled() )
          {
              final String message =
                  REZ.getString( "lifecycle.stage.notice",
                                 name,
                                 new Integer( stage ) );
              getLogger().debug( message );
          }
      }
  
      /**
       * Utility method to report that there was an error processing
       * specified lifecycle stage.
       *
       * @param name the name of component that caused failure
       * @param stage the lefecycle stage
       * @param t the exception thrown
       */
      private void safeFail( final String name,
                             final int stage,
                             final Throwable t )
      {
          final String reason = t.toString();
          final String message =
              REZ.getString( "lifecycle.fail.error",
                             name,
                             new Integer( stage ),
                             reason );
          getLogger().error( message );
      }
  
      /**
       * Utility method to report that there was an error processing
       * specified lifecycle stage. It will also re-throw an exception
       * with a better error message.
       *
       * @param name the name of block that caused failure
       * @param stage the stage
       * @param t the exception thrown
       * @throws LifecycleException containing error
       */
      private void fail( final String name,
                         final int stage,
                         final Throwable t )
          throws LifecycleException
      {
          //final String reason = t.getMessage();
          final String reason = t.toString();
          final String message =
              REZ.getString( "lifecycle.fail.error",
                             name,
                             new Integer( stage ), reason );
          getLogger().error( message );
          throw new LifecycleException( message, t );
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifestyleHandler.java
  
  Index: LifestyleHandler.java
  ===================================================================
  /*
   * 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.
   *
   * Original contribution by OSM SARL, http://www.osm.net
   */
  package org.apache.excalibur.merlin.resource;
  
  import java.util.Map;
  import java.util.Hashtable;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.excalibur.merlin.model.Resource;
  
  
  /**
   * Interface implemented by a component lifestyle handler. 
   *
   * @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
   */
  public interface LifestyleHandler
  {
      /**
       * 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;
  
      /**
       * Invoked by a client to return an instance of the object type previously 
       * supplied by a manager implementation.
       * 
       * @param object the object to return
       * @exception Exception if an error occurs during object release
       */
       public void put( Object object ) throws Exception;
  
  }
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/ResourceException.java
  
  Index: ResourceException.java
  ===================================================================
  /*
   * 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.
   */
  package org.apache.excalibur.merlin.resource;
  
  import java.util.Enumeration;
  import java.util.Dictionary;
  import java.util.Hashtable;
  
  import org.apache.avalon.framework.CascadingException;
  
  /**
   * Exception to indicate that there was an error relating to resource management.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
   */
  public final class ResourceException
      extends CascadingException
  {
  
      /**
       * Construct a new <code>ResourceException</code> instance.
       *
       * @param message The detail message for this exception.
       */
      public ResourceException( final String message )
      {
          this( message, null );
      }
  
      /**
       * Construct a new <code>ResourceException</code> instance.
       *
       * @param message The detail message for this exception.
       * @param throwable the root cause of the exception
       */
      public ResourceException( final String message, final Throwable throwable )
      {
          super( message, throwable );
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/ResourceProvider.java
  
  Index: ResourceProvider.java
  ===================================================================
  /*
   * 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.
   */
  
  package org.apache.excalibur.merlin.resource;
  
  import java.io.InputStream;
  import java.io.File;
  import java.io.IOException;
  import java.net.URL;
  import java.net.JarURLConnection;
  import java.net.URLClassLoader;
  import java.util.Map;
  import java.util.List;
  import java.util.LinkedList;
  import java.util.Hashtable;
  import java.util.Properties;
  import java.util.Vector;
  import java.util.Iterator;
  import java.util.jar.Attributes;
  import java.util.jar.Manifest;
  import java.security.Policy;
  import java.io.FileInputStream;
  import java.util.HashMap;
  import java.lang.reflect.Constructor;
  
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.avalon.framework.Version;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.logger.AvalonFormatter;
  import org.apache.avalon.framework.logger.LogKitLogger;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Executable;
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.framework.CascadingRuntimeException;
  import org.apache.avalon.framework.service.ServiceManager;
  import org.apache.avalon.framework.component.Component;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.DefaultConfiguration;
  import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.context.DefaultContext;
  import org.apache.avalon.framework.service.Serviceable;
  import org.apache.avalon.framework.service.ServiceManager;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.excalibur.configuration.ConfigurationUtil;
  import org.apache.excalibur.meta.verifier.VerifyException;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.meta.info.ServiceDescriptor;
  import org.apache.excalibur.meta.info.DependencyDescriptor;
  import org.apache.excalibur.meta.info.ReferenceDescriptor;
  import org.apache.excalibur.meta.info.ContextDescriptor;
  import org.apache.excalibur.meta.info.EntryDescriptor;
  import org.apache.excalibur.meta.info.ExtensionDescriptor;
  import org.apache.excalibur.merlin.resource.ResourceException;
  import org.apache.excalibur.merlin.assembly.KernelManager;
  import org.apache.excalibur.merlin.assembly.ContainerManager;
  import org.apache.excalibur.merlin.assembly.DefaultLoggerManager;
  import org.apache.excalibur.merlin.resource.DefaultComponentManager;
  import org.apache.excalibur.merlin.resource.DefaultServiceManager;
  import org.apache.excalibur.merlin.model.ContainerDescriptor;
  import org.apache.excalibur.merlin.model.ContextDirective;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.Association;
  import org.apache.excalibur.merlin.model.Resource;
  import org.apache.excalibur.merlin.model.Import;
  import org.apache.excalibur.merlin.model.Entry;
  
  
  /**
   * Internal class that handles the establishment of component instances based on a supplied
   * type profile.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
   */
  public class ResourceProvider extends AbstractLogEnabled
  {
  
      //=======================================================================
      // state
      //=======================================================================
  
      private final static Resources REZ =
          ResourceManager.getPackageResources( ResourceProvider.class );
  
      //=======================================================================
      // state
      //=======================================================================
     /**
      * The log manager.
      */
      private DefaultLoggerManager m_logging;
  
     /**
      * The classloader to use when servicing object creation requests.
      */
      private ContainerManager m_classloader;
  
     /**
      * Context object containing system level values that is used 
      * as a sources for import directives.
      */
      private DefaultContext m_dictionary;
  
      //=======================================================================
      // constructor
      //=======================================================================
  
     /**
      * 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();
      }
  
      //=======================================================================
      // ResourceProvider
      //=======================================================================
  
      /**
       * 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_classloader instanceof KernelManager )
          {
              root = m_classloader.getPath().replace('/','.').substring(1);
          }
          else
          {
              root = m_classloader.getPath().replace('/','.').substring(1) + "." + profile.getName();
          }
  
          m_logging.addCategories( root, profile.getCategories() );
          return m_logging.getLoggerForCategory( root );
      }
  
      /**
       * 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 Exception if unable to create context
       */
      public Context createContext( Profile profile, Context  context )
          throws Exception
      {
          ContextDescriptor descriptor = profile.getType().getContext();
          ContextDirective directive = profile.getContext();
          return buildContext( descriptor, directive, context );
      }
  
      /**
       * 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
       */
      public 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_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;
          }
      }
  
      /**
       * 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_classloader );
          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;
      }
  
      /**
       * 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 );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/ResourceRuntimeException.java
  
  Index: ResourceRuntimeException.java
  ===================================================================
  /*
   * 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.
   */
  package org.apache.excalibur.merlin.resource;
  
  import java.util.Enumeration;
  import java.util.Dictionary;
  import java.util.Hashtable;
  
  import org.apache.avalon.framework.CascadingRuntimeException;
  
  /**
   * Exception to indicate that there was an error relating to resource management.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
   */
  public final class ResourceRuntimeException
      extends CascadingRuntimeException
  {
  
      /**
       * Construct a new <code>ResourceRuntimeException</code> instance.
       *
       * @param message The detail message for this exception.
       */
      public ResourceRuntimeException( final String message )
      {
          this( message, null );
      }
  
      /**
       * Construct a new <code>ResourceRuntimeException</code> instance.
       *
       * @param message The detail message for this exception.
       * @param throwable the root cause of the exception
       */
      public ResourceRuntimeException( final String message, final Throwable throwable )
      {
          super( message, throwable );
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  lifecycle.stage.notice=Component named "{0}" is passing through the {1,choice,0#Creation|1#Logger initialization|2#Contextualization|3#Composing|4#Configuration|5#Parameterizing|6#Extension-CREATE|7#Initialization|8#Starting|9#Stopping|10#Extension-DESTROY|11#Disposing|12#Destruction} stage.
  lifecycle.fail.error=Component named "{0}" failed to pass through the {1,choice,0#Creation|1#Logger initialization|2#Contextualization|3#Composing|4#Configuration|5#Parameterizing|6#Extension-CREATE|7#Initialization|8#Starting|9#Stopping|10#Extension-DESTROY|11#Disposing|12#Destruction} stage. (Reason: {2}).
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/SingletonLifestyleHandler.java
  
  Index: SingletonLifestyleHandler.java
  ===================================================================
  /*
   * 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.
   *
   * Original contribution by OSM SARL, http://www.osm.net
   */
  package org.apache.excalibur.merlin.resource;
  
  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.merlin.assembly.ContainerManager;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.Resource;
  import org.apache.excalibur.meta.info.PhaseDescriptor;
  import org.apache.excalibur.meta.info.ExtensionDescriptor;
  import org.apache.excalibur.meta.info.Facility;
  
  
  /**
   * Lifestyle implementation that provides suppport for the singleton
   * policy.  Request for a single instance will allways return the 
   * same instance for each request.
   *
   * @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
   */
  public class SingletonLifestyleHandler extends AbstractLifestyleHandler 
  {
       private Profile m_profile;
       private ContainerManager m_manager;
       private LifecycleHelper m_helper;
  
       private Object m_object;
  
      /**
       * Creation of a new singleton lifecycle manager.
       * @param manager the type manager 
       * @param provider the resource provider 
       * @param helper the lifecycle helper 
       * @param profile the profile defining the object type
       * @param context the establishment context
       */
       public SingletonLifestyleHandler( 
                             final ContainerManager manager, 
                             final ResourceProvider provider,
                             final LifecycleHelper helper,
                             final Profile profile,
                             final Context context )
       {
           super( manager, provider, helper, profile, context );
           m_profile = profile;
           m_manager = manager;
           m_helper = helper;
       }
  
      /**
       * Returns an instance of the object type supported by the 
       * manager to the client.
       * 
       * @return an instance of the type defined by the profile
       */
       public Object get() throws Exception
       {
          getLogger().debug("get");
          if( m_object == null )
              m_object = super.createInstance();
          super.processAccessStage( m_object );
          return m_object;
  
       }
  
      /**
       * Invoked by a client to return an instance of the object type previously 
       * supported by the manager.  The singleton manager does nothing as the 
       * object may be used across an arbitary number of clients.
       * 
       * @param object the object to return
       */
       public void put( Object object ) throws Exception
       {
          getLogger().debug("put");
          super.processReleaseStage( m_object );
       }
  
      /**
       * Request for disposal of the manager.  This operation is normally invoked
       * by the client that initialy instantiated the manager.  The implementation
       * handles the disposal of the singleton resoruce and release of associated
       * references.
       */
       public void 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 );
               }
           }
           m_object = null;
           m_profile = null;
           m_manager = null;
           m_helper = null;
  
           super.dispose();
  
       }
  }
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/TransientLifestyleHandler.java
  
  Index: TransientLifestyleHandler.java
  ===================================================================
  /*
   * 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.
   *
   * Original contribution by OSM SARL, http://www.osm.net
   */
  package org.apache.excalibur.merlin.resource;
  
  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.merlin.assembly.ContainerManager;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.Resource;
  import org.apache.excalibur.meta.info.PhaseDescriptor;
  import org.apache.excalibur.meta.info.ExtensionDescriptor;
  import org.apache.excalibur.meta.info.Facility;
  
  
  /**
   * Lifestyle implementation that provides suppport for the transient
   * lifestyle policy.  Request for a single instance will return 
   * an new instance for each request.
   *
   * @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
   */
  public class TransientLifestyleHandler extends AbstractLifestyleHandler 
  {
       private Profile m_profile;
       private ContainerManager m_manager;
       private LifecycleHelper m_helper;
  
       private ArrayList m_objects = new ArrayList();
  
      /**
       * Creation of a new singleton lifecycle manager.
       * @param manager the type manager 
       * @param provider the resource provider 
       * @param helper the lifecycle helper 
       * @param profile the profile defining the object type
       * @param context the establishment context
       */
       public TransientLifestyleHandler( 
                             final ContainerManager manager, 
                             final ResourceProvider provider,
                             final LifecycleHelper helper,
                             final Profile profile,
                             final Context context )
       {
           super( manager, provider, helper, profile, context );
           m_profile = profile;
           m_manager = manager;
           m_helper = helper;
       }
  
      /**
       * Returns an instance of the object type supported by the 
       * manager to the client.
       * 
       * @return an instance of the type defined by the profile
       */
       public Object get() throws Exception
       {
          getLogger().debug("get");
          Object object = super.createInstance();
          m_objects.add( object );
          super.processAccessStage( object );
          return object;
       }
  
      /**
       * Invoked by a client to return an instance of the object type previously 
       * supported by the manager.  The singleton manager does nothing as the 
       * object may be used across an arbitary number of clients.
       * 
       * @param object the object to return
       */
       public void put( Object object ) throws Exception
       {
           getLogger().debug("put");
           if( m_objects.contains( 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 );
               }
           }
           super.processReleaseStage( object );
       }
  
      /**
       * Request for disposal of the manager.  This operation is normally invoked
       * by the client that initialy instantiated the manager.  The implementation
       * handles the disposal of the singleton resoruce and release of associated
       * references.
       */
       public void dispose()
       {
           Object[] objects = m_objects.toArray();
           for( int i=0; i<objects.length; i++ )
           {
               try
               {
                   put( objects[i] );
               }
               catch( Throwable e )
               {
                   //
               }
           }
           m_profile = null;
           m_manager = null;
           m_helper = null;
           m_objects = null;
  
           super.dispose();
  
       }
  }
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/package.html
  
  Index: package.html
  ===================================================================
  <body>
  Interfaces and classes supporting component lifecycle management.
  </body>
  
  
  

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