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/07/08 11:57:37 UTC

cvs commit: jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/doc-files LifecycleHelper.gif ResourceProvider.gif lifecycle.gif

mcconnell    2002/07/08 02:57:37

  Modified:    assembly README.TXT build.xml
               assembly/src/etc kernel.xml merlin.html
               assembly/src/java/org/apache/excalibur/merlin/kernel
                        Container.java DefaultContainer.java
                        DefaultKernel.java Resources.properties
               assembly/src/java/org/apache/excalibur/merlin/registry
                        ProfileRegistry.java Registry.java
                        TypeRegistry.java
  Added:       assembly/src/java/org/apache/excalibur/merlin/kernel
                        ContainerException.java
                        ContainerRuntimeException.java DefaultProvider.java
                        DependencyGraph.java
               assembly/src/java/org/apache/excalibur/meta/lifecycle
                        LifecycleException.java LifecycleHelper.java
                        ResourceProvider.java Resources.properties
                        package.html
               assembly/src/java/org/apache/excalibur/meta/lifecycle/doc-files
                        LifecycleHelper.gif ResourceProvider.gif
                        lifecycle.gif
  Removed:     assembly/src/java/org/apache/excalibur/merlin/kernel
                        Map.java
  Log:
  component instantiation and lifecycle processing in place and validated
  against inital test suite
  
  Revision  Changes    Path
  1.8       +11 -1     jakarta-avalon-excalibur/assembly/README.TXT
  
  Index: README.TXT
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/README.TXT,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- README.TXT	7 Jul 2002 05:02:21 -0000	1.7
  +++ README.TXT	8 Jul 2002 09:57:35 -0000	1.8
  @@ -12,6 +12,9 @@
   Status
   ------
   
  +08-JUL-2002.
  +Instantion of components based on profile criteria in place and operational.
  +
   07-JUL-2002.
   Added support for the resolution of dependency solutions using the container hierarchy. Forked a sub-set of the containerkit model to provide support for more dynamic style resolution of association at the meta data level.  Improved API and class naming. Expanded complexity of the test case (component declarations across multiple containers, cross container dependency resolution, and resolution of conflicting candidate supplier components).
   
  @@ -21,6 +24,8 @@
   To-Do
   -----
   
  +Addition of pooled support under a service manager variant as part Merlin 1.
  +
   The kernel should take advantage of Excalibur LogKit extensions (logging configuration etc.). Functional operation of the container as a node in a container hierarchy is still very much work-in-progress.  
   
   The component instantiation and lifecycle management is not included at this stage.  Before proceeding with actual component instantiation - more playing around is required with the containerkit abstractions.
  @@ -29,8 +34,13 @@
   
   Management of defaults using the CascadingConfiguration need to be included.  The original Merlin approach was to include the default configuration information inside the .xinfo file.  The approach taken here will be to separate default information into a <classname>.xconfig for default information and a <classname>.xprofile containing default deployment descriptors.  
   
  -Introduction of component factories will be required as a complement to the <component/> directive.
  +Introduction of component factories will be required as a complement to the <component/> directive - e.g <factory/>.
  +
  +Addition of support for compoents that are not declared in the manifest.
  +
  +Upgrading of error handling against classic fail scenarios (class not in classpath, manafest errors, informative configuration errors).
   
  +Gentle degrade of service deployment profile on error - if a component cannot be deployed, disable the activation of all of the dependent but continue on with deployment of the rest.
   
   Stephen McConnell
   mcconnell@apache.org
  
  
  
  1.14      +1 -1      jakarta-avalon-excalibur/assembly/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/build.xml,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- build.xml	8 Jul 2002 01:14:01 -0000	1.13
  +++ build.xml	8 Jul 2002 09:57:36 -0000	1.14
  @@ -253,7 +253,7 @@
     </target>
   
     <target name="patch">
  -    <replace token="getServiceDesignator" value="getService" dir="src/java">
  +    <replace token="AssociationMap" value="DependencyGraph" dir="src/java">
           <include name="**/*.*"/>
       </replace>
     </target>
  
  
  
  1.5       +4 -1      jakarta-avalon-excalibur/assembly/src/etc/kernel.xml
  
  Index: kernel.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/etc/kernel.xml,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- kernel.xml	7 Jul 2002 04:27:31 -0000	1.4
  +++ kernel.xml	8 Jul 2002 09:57:36 -0000	1.5
  @@ -93,8 +93,10 @@
          Declaration of an embedded container.  A container will be instantiated, initialized
          and a validation request will be invoked.  In the container is an instance of Container, 
          the reference to parent container will be supplied.
  +       ## pending context inport from container ##
          -->
   
  +       <!--
          <component name="test" class="org.apache.excalibur.merlin.kernel.DefaultContainer">
            <configuration>
             <container>
  @@ -105,7 +107,8 @@
              </classpath>
             </container>
           </configuration>
  -      </component>
  +       </component>
  +       -->
   
         <!--
         including the next entry demonstrates the resolution of a dependency via a profile
  
  
  
  1.2       +1 -1      jakarta-avalon-excalibur/assembly/src/etc/merlin.html
  
  Index: merlin.html
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/etc/merlin.html,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- merlin.html	7 Jul 2002 23:09:09 -0000	1.1
  +++ merlin.html	8 Jul 2002 09:57:36 -0000	1.2
  @@ -67,7 +67,7 @@
   
   <h3>Current Status</h3>
   <p>
  -The implementation provides full support for hierachical containers and profiles management including resolution of dependecies cross containers. The implemetation does not support instantation of componets at this time (expect this soon).
  +The implementation provides full support for hierachical containers and profiles management including resolution of dependecies cross containers. Processing of singleton components throught the component lifecycle is in place and will be expanded to included adaptive managers in the near future.  For a list of TO-DO items, please refer to the README document.
   </p>
   
   </body>
  
  
  
  1.7       +1 -12     jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Container.java
  
  Index: Container.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Container.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Container.java	7 Jul 2002 23:15:42 -0000	1.6
  +++ Container.java	8 Jul 2002 09:57:36 -0000	1.7
  @@ -25,17 +25,6 @@
    */
   public interface Container extends Manageable, Verifiable
   {
  - 
  -   /**
  -    * Return the profile of an installed component matching a dependency.
  -    * @param type a component exposing the depenency
  -    * @param dependency a consumer component dependecy declaration
  -    * @return the supplier profile
  -    * @exception UnresolvedProviderException if no provider available
  -    */
  -    //Profile getProvider( Type type, DependencyDescriptor dependency ) 
  -    //  throws UnresolvedProviderException;
  -
      /**
       * Return the set of potential profiles of installed component matching a dependency.
       * @param dependency a consumer component dependecy declaration
  
  
  
  1.9       +50 -27    jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultContainer.java
  
  Index: DefaultContainer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultContainer.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- DefaultContainer.java	7 Jul 2002 23:20:45 -0000	1.8
  +++ DefaultContainer.java	8 Jul 2002 09:57:36 -0000	1.9
  @@ -68,7 +68,7 @@
   import org.apache.log.output.io.StreamTarget;
   
   import org.apache.excalibur.merlin.registry.UnresolvedProviderException;
  -import org.apache.excalibur.merlin.kernel.Map;
  +import org.apache.excalibur.merlin.kernel.DependencyGraph;
   
   /**
    * Default container implementation that manages a registry of componet providers and 
  @@ -104,7 +104,9 @@
   
       private Logger m_logger;
   
  -    private Map m_map;
  +    private DependencyGraph m_map;
  +
  +    private DefaultProvider m_provider;
   
       //=======================================================================
       // Contextualizable
  @@ -120,15 +122,21 @@
           try
           {
               m_parent = (Container) context.get( CONTAINER_KEY );
  -            m_map = (Map) context.get( MAP_KEY );
  +            m_map = (DependencyGraph) context.get( MAP_KEY );
  +            m_provider = (DefaultProvider) context.get( PROVIDER_KEY );
               super.contextualize( context );
           }
           catch( ContextException e )
           {
  -            // root container
  +            // this is root container - setup the context for the supertype
  +            // (which includes a null container)
  +
               DefaultContext c = new DefaultContext( context );
  -            m_map = new Map();
  +            m_map = new DependencyGraph();
  +            m_provider = new DefaultProvider( m_classloader );
  +            m_provider.enableLogging( getLogger().getChildLogger( "provider" ) );
               c.put( MAP_KEY, m_map );
  +            c.put( PROVIDER_KEY, m_provider );
               c.makeReadOnly();
               super.contextualize( c );
           }
  @@ -200,6 +208,7 @@
           // before starting up any of the nested containers
           //
   
  +        getLogger().debug("startup");
           start();
           Iterator iterator = m_containers.iterator();
           while( iterator.hasNext() )
  @@ -226,15 +235,6 @@
       }
   
       //=======================================================================
  -    // DefaultContainer
  -    //=======================================================================
  -
  -    public Container[] getContainers()
  -    {
  -        return (Container[]) m_containers.toArray( new Container[0] );
  -    }
  -
  -    //=======================================================================
       // private
       //=======================================================================
   
  @@ -249,18 +249,41 @@
             loaderLogger
           );
   
  -        DefaultContext context = new DefaultContext();
  -        context.put( CLASSLOADER_KEY, loader );
  -        context.put( CONTAINER_KEY, this );
  -        Map map = new Map( m_map );
  -        m_map.addChild( map );
  -        context.put( MAP_KEY, map );
  -
  +        String name = conf.getAttribute("name","untitled");
           DefaultContainer container = new DefaultContainer();
  -        container.enableLogging( logger );
  -        container.contextualize( context );
  -        container.configure( conf );
  -        container.initialize( );
  -        return container;
  +        try
  +        {
  +            DependencyGraph map = new DependencyGraph( m_map );
  +            m_map.addChild( map );
  +            DefaultProvider provider = new DefaultProvider( m_provider, m_classloader );
  +            provider.enableLogging( getLogger().getChildLogger( "provider" ) );
  +            DefaultContext context = new DefaultContext();
  +            context.put( CLASSLOADER_KEY, loader );
  +            context.put( CONTAINER_KEY, this );
  +            context.put( MAP_KEY, map );
  +            context.put( PROVIDER_KEY, provider );
  +
  +            container.enableLogging( logger );
  +            container.contextualize( context );
  +            container.configure( conf );
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              "Unexpected exception while creating subsidiary container '" + name + "'.";
  +            throw new ContainerException( error, e );
  +        }
  +
  +        try
  +        {
  +            container.initialize( );
  +            return container;
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error =
  +              "Unexpected exception while creating subsidiary container '" + name + "'.";
  +            throw new ContainerException( error, e );
  +        }
       }
   }
  
  
  
  1.8       +1 -5      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.java
  
  Index: DefaultKernel.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- DefaultKernel.java	7 Jul 2002 23:18:17 -0000	1.7
  +++ DefaultKernel.java	8 Jul 2002 09:57:36 -0000	1.8
  @@ -63,7 +63,6 @@
   import org.apache.excalibur.meta.info.DependencyDescriptor;
   import org.apache.excalibur.meta.info.ServiceDesignator;
   import org.apache.excalibur.meta.data.Profile;
  -import org.apache.excalibur.merlin.kernel.Map;
   import org.apache.log.Hierarchy;
   import org.apache.log.Priority;
   import org.apache.log.output.io.StreamTarget;
  @@ -89,8 +88,6 @@
   
       private boolean m_verified = false;
   
  -    private Map m_map = new Map();
  -
       //=======================================================================
       // Configurable
       //=======================================================================
  @@ -124,7 +121,6 @@
   
           DefaultContext context = new DefaultContext();
           context.put( DefaultContainer.CLASSLOADER_KEY, loader );
  -        context.put( DefaultContainer.MAP_KEY, m_map );
           m_container.enableLogging( getLogger().getChildLogger("container") );
           m_container.contextualize( context );
           m_container.configure( m_config.getChild("container" ) );
  
  
  
  1.5       +9 -0      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Resources.properties,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Resources.properties	7 Jul 2002 04:28:31 -0000	1.4
  +++ Resources.properties	8 Jul 2002 09:57:36 -0000	1.5
  @@ -18,3 +18,12 @@
   required-extensions=The list of required extensions for application includes: {0}
   optional-packages-added=The list of "Optional Packages" added to the application include: {0}
   classpath-entries=The list of classpath entrys for the application include: {0}
  +
  +resource.missing-context-value.error=Missing {0,choice,1#Optional|2#Required} Context Entry with key "{1}" for component named "{2}".
  +resource.bad-value-type.error=Bad value retrieved for {0,choice,1#Optional|2#Required} Context Entry with key "{1}" for component named "{2}". Expected to be of type "{3}" but was of type "{4}".
  +resource.bad-context-type.error=The class of Contex object for component named "{2}" was expected to be of type {0} but was of tpye {1}.
  +resource.service-not-a-component.error=The service with role "0" and implemenation class "{1}" does not implement the Component interface but is being exposed via ComponentManager.
  +resource.missing-dependency.error=Missing {0,choice,1#Optional|2#Required} dependency with role "{1}" for component named {2}.
  +resource.missing-parameters.error=Missing Parameters object for component named "{0}".
  +resource.missing-parameters.error=Missing Configuration for component named "{0}".
  +
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/ContainerException.java
  
  Index: ContainerException.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.kernel;
  
  import org.apache.avalon.framework.CascadingException;
  
  /**
   * Exception to indicate that there was a repository related error.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/08 09:57:36 $
   */
  public final class ContainerException
      extends CascadingException
  {
  
      /**
       * Construct a new <code>ContainerException</code> instance.
       *
       * @param message The detail message for this exception.
       */
      public ContainerException( final String message )
      {
          this( message, null );
      }
  
      /**
       * Construct a new <code>ContainerException</code> instance.
       *
       * @param message The detail message for this exception.
       * @param throwable the root cause of the exception
       */
      public ContainerException( final String message, final Throwable throwable )
      {
          super( message, throwable );
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/ContainerRuntimeException.java
  
  Index: ContainerRuntimeException.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.kernel;
  
  import org.apache.avalon.framework.CascadingRuntimeException;
  
  /**
   * Exception to indicate that there was a repository related runtime error.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/08 09:57:36 $
   */
  public final class ContainerRuntimeException
      extends CascadingRuntimeException
  {
  
      /**
       * Construct a new <code>RegistryRuntimeException</code> instance.
       *
       * @param message The detail message for this exception.
       */
      public ContainerRuntimeException( final String message )
      {
          this( message, null );
      }
  
      /**
       * Construct a new <code>ContainerRuntimeException</code> instance.
       *
       * @param message The detail message for this exception.
       * @param throwable the root cause of the exception
       */
      public ContainerRuntimeException( final String message, final Throwable throwable )
      {
          super( message, throwable );
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultProvider.java
  
  Index: DefaultProvider.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.kernel;
  
  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 org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.excalibur.configuration.ConfigurationUtil;
  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.component.DefaultComponentManager;
  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.DefaultServiceManager;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.Version;
  import org.apache.avalon.framework.ExceptionUtil;
  import org.apache.avalon.excalibur.extension.PackageRepository;
  import org.apache.avalon.excalibur.extension.Extension;
  import org.apache.avalon.excalibur.extension.OptionalPackage;
  import org.apache.avalon.excalibur.extension.DefaultPackageRepository;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.meta.info.DefaultType;
  import org.apache.excalibur.meta.info.ServiceDescriptor;
  import org.apache.excalibur.meta.info.DependencyDescriptor;
  import org.apache.excalibur.meta.info.ServiceDesignator;
  import org.apache.excalibur.meta.data.Profile;
  import org.apache.excalibur.meta.data.Association;
  import org.apache.excalibur.meta.lifecycle.ResourceProvider;
  import org.apache.excalibur.meta.verifier.VerifyException;
  import org.apache.excalibur.merlin.registry.Registry;
  import org.apache.log.Hierarchy;
  import org.apache.log.Priority;
  import org.apache.log.output.io.StreamTarget;
  
  
  /**
   * 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/07/08 09:57:36 $
   */
  public class DefaultProvider extends AbstractLogEnabled implements ResourceProvider
  {
      //=======================================================================
      // state
      //=======================================================================
  
      private final static Resources REZ =
          ResourceManager.getPackageResources( DefaultProvider.class );
  
      //=======================================================================
      // state
      //=======================================================================
  
     /**
      * The container that this provider is assigned to.
      */
      private final ClassLoader m_classloader;
  
     /**
      * The parent provider.
      */
      private final DefaultProvider m_parent;
  
     /**
      * A hashtable of service implemenentation object references keyed by profile.
      */
      private final Hashtable m_singletons = new Hashtable();
  
      //=======================================================================
      // constructor
      //=======================================================================
  
      DefaultProvider( ClassLoader loader )
      {
          this( null, loader );
      }
  
      DefaultProvider( DefaultProvider parent, ClassLoader loader )
      {
          m_parent = parent;
          m_classloader = loader;
      }
  
      //=======================================================================
      // ResourceProvider
      //=======================================================================
  
      /**
       * Create an object specified by profile.
       *
       * @param profile the profile
       * @return the new object
       * @throws Exception if unable to resolve resource
       */
      public Object createObject( Profile profile )
          throws Exception
      {
          Object object = getSingletonInstance( profile );
          if( object == null )
          {
              Class clazz = null;
              String classname = null;
              try
              {
                  classname = profile.getType().getInfo().getImplementationKey();
                  clazz = m_classloader.loadClass( classname );
              }
              catch( Throwable e )
              {
                  final String error = 
                    "Unexpected exception while attempting to load class '" 
                    + classname + "' for the profile: " + profile;
                  throw new ContainerException( error, e );
              }
  
              try
              {
                  object = clazz.newInstance();
                  putSingletonInstance( profile, object );
              }
              catch( Throwable e )
              {
                  final String error = 
                    "Unexpected exception while attempting to instantiate an instance from profile: " + profile;
                  throw new ContainerException( error, e );
              }
          }
          return object;
      }
  
      /**
       * 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
      {
          return getLogger().getChildLogger( profile.getName() );
      }
  
      /**
       * Create a new Context for component.
       *
       * @param profile the profile
       * @return a new Context for service
       * @throws Exception if unable to create context
       */
      public Context createContext( Profile profile )
          throws Exception
      {
          return profile.getContext();
      }
  
      /**
       * 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();
          final Iterator keys = services.keySet().iterator();
          while( keys.hasNext() )
          {
              final String key = (String)keys.next();
              final Object service = services.get( key );
              if( !Component.class.isInstance( service ) )
              {
                  final String message =
                      REZ.getString( "resource.service-not-a-component.error",
                                     key,
                                     service.getClass().getName() );
                  throw new Exception( message );
              }
              componentManager.put( key, (Component)service );
          }
          componentManager.makeReadOnly();
          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();
          final Iterator keys = services.keySet().iterator();
          while( keys.hasNext() )
          {
              final String key = (String)keys.next();
              final Object service = services.get( key );
              serviceManager.put( key, service );
          }
          serviceManager.makeReadOnly();
          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();
          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;
      }
  
      public Object getSingletonInstance( Profile profile )
      {
          return m_singletons.get( profile );
      }
  
      private void putSingletonInstance( Profile profile, Object object )
      {
          m_singletons.put( profile, object );
      }
  
     /**
      * Requests to release all references to a profile and associated 
      * service instances.
      * @param profile the profile to release
      */
      public void release( Profile profile )
      {
          m_singletons.remove( profile );
      }
  
     /**
      * 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
      {
          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();
              final Association association = profile.getAssociation( role );
              final Profile provider = association.getProvider();
              final boolean required = type.getDependency( role ).isRequired();
              final String classname = type.getDependency( role ).getService().getClassname();
  
              final Object service = getServiceInstance( provider, classname );
              if(( null == service ) && ( required ))
              {
                  final String message =
                      REZ.getString( "resource.missing-dependency.error",
                                     !required ? "1" : "2",
                                     role,
                                     profile.getName() );
                  throw new Exception( message );
              }
              services.put( role, service );
          }
          return services;
      }
  
     /**
      * Get a service instance from the instance tables using the supplied
      * provider as the key, and validate that the returned service instance 
      * implements the supplied service classname.
      * @param provider the key to the provider instance
      * @param service the classname of the service requested
      */
      private Object getServiceInstance( Profile provider, String service ) throws Exception
      {
          Object object = lookupInstance( provider );
          if( objectImplementsType( object, service ) )
            return object;
  
          final String error = 
            "Unable to locate an instantiated service instance implementing the interface: "
            + service + ", from the provider: " + provider;
          throw new ContainerException( error );
      }
  
      private Object lookupInstance( Profile provider )
      {
          Object object = getSingletonInstance( provider );
          if( object != null )
            return object;
          if( m_parent != null )
            return m_parent.lookupInstance( provider );
          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 Exception
      {
          if( value == null ) 
            return false;
          try
          {
              final Class clazz = value.getClass();
              final ClassLoader classLoader = clazz.getClassLoader();
              final Class typeClass = classLoader.loadClass( type );
              if( typeClass.isAssignableFrom( clazz ) )
              {
                  return true;
              }
          }
          catch( final ClassNotFoundException cnfe )
          {
          }
          return false;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DependencyGraph.java
  
  Index: DependencyGraph.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.kernel;
  
  import java.util.ArrayList;
  import org.apache.excalibur.meta.data.Profile;
  import org.apache.excalibur.meta.data.Association;
  import org.apache.excalibur.meta.info.DependencyDescriptor;
  
  /**
   * <p>Utility class to help aquire a ordered graph of
   * consumers and providers for specific components.</p>
   * <p><b>UML</b></p>
   * <p><image src="doc-files/Map.gif" border="0"/></p>
   *
   * @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/07/08 09:57:36 $
   */
  public class DependencyGraph
  {
      /**
       * Parent Map. Components in parent
       * Map are potential Providers for services
       * if no profile in current assembly satisfies dependency.
       */
      private final DependencyGraph m_parent;
  
      /**
       * The container providing the componenent.
       */ 
      private Container m_container;
  
      /**
       * The set of components declared by the container as available.,
       * Used when searching for providers/consumers.
       */
      private final ArrayList m_components = new ArrayList();
  
      /**
       * The child {@link DependencyGraph} objects.
       * Possible consumers of services in this assembly.
       */
      private final ArrayList m_children = new ArrayList();
  
  
      public DependencyGraph()
      {
          this( null );
      }
  
      public DependencyGraph( final DependencyGraph parent )
      {
          m_parent = parent;
      }
  
      /**
       * Add child dependency graph.
       *
       * @param child the child map
       */
      public void addChild( final DependencyGraph child )
      {
          m_children.add( child );
      }
  
      /**
       * Remove child dependency graph.
       *
       * @param child the child map
       */
      public void removeChild( final DependencyGraph child )
      {
          m_children.remove( child );
      }
  
      /**
       * Add a profile to current dependency graph.
       *
       * @param profile the profile
       */
      public void add( final Profile profile )
      {
          if( !m_components.contains( profile ) )
            m_components.add( profile );
      }
  
      /**
       * Get the serilized graph of {@link Profile} objects
       * required when starting up all the components. This makes sure
       * that all providers occur before their coresponding
       * consumers in graph.
       *
       * @return the ordered list of components
       */
      public Profile[] getStartupGraph()
      {
          return walkGraph( true );
      }
  
      /**
       * Get the serilized graph of {@link Profile} objects
       * required when shutting down all the components. This makes
       * sure that all consumers occur before their coresponding
       * providers in graph.
       *
       * @return the ordered list of components
       */
      public Profile[] getShutdownGraph()
      {
          return walkGraph( false );
      }
  
      /**
       * Get the serilized graph of {@link Profile} objects
       * that use services of specified profile.
       *
       * @param profile the profile
       * @return the ordered list of consumers
       */
      public Profile[] getConsumerGraph( final Profile profile )
      {
          return referencedProfiles( profile, getComponentGraph( profile, false ));
      }
  
      /**
       * Get the serilized graph of {@link Profile} objects
       * that provide specified profile with services.
       *
       * @param profile the profile
       * @return the ordered list of providers
       */
      public Profile[] getProviderGraph( final Profile profile )
      {
          return referencedProfiles( profile, getComponentGraph( profile, true ));
      }
  
      /**
       * Return a profile array that does not include the provided profile.
       */
      private Profile[] referencedProfiles( final Profile profile, Profile[] profiles )
      {
          ArrayList list = new ArrayList();
          for( int i=0; i<profiles.length; i++ )
          {
              if( !profiles[i].equals( profile ) )
                list.add( profiles[i] );
          }
          return (Profile[]) list.toArray( new Profile[0] );
      }
  
      /**
       * Get the graph of a single profile.
       *
       * @param profile the profile
       * @param providers true if traversing providers, false if consumers
       * @return the list of components in graph
       */
      private Profile[] getComponentGraph( final Profile profile, final boolean providers )
      {
          final ArrayList result = new ArrayList();
          visitcomponent( profile,
                          providers,
                          new ArrayList(),
                          result );
  
          final Profile[] returnValue = new Profile[ result.size() ];
          return (Profile[])result.toArray( returnValue );
      }
  
      /**
       * Method to generate an ordering of nodes to traverse.
       * It is expected that the specified components have passed
       * verification tests and are well formed.
       *
       * @param providers true if forward dependencys traced, false if dependencies reversed
       * @return the ordered node names
       */
      private Profile[] walkGraph( final boolean providers )
      {
          final ArrayList result = new ArrayList();
          final ArrayList done = new ArrayList();
  
          final int size = m_components.size();
          for( int i = 0; i < size; i++ )
          {
              final Profile profile =
                  (Profile)m_components.get( i );
  
              visitcomponent( profile,
                              providers,
                              done,
                              result );
          }
  
          final Profile[] returnValue = new Profile[ result.size() ];
          return (Profile[])result.toArray( returnValue );
      }
  
      /**
       * Visit a profile when traversing dependencies.
       *
       * @param profile the profile
       * @param providers true if walking tree looking for providers, else false
       * @param done those nodes already traversed
       * @param order the order in which nodes have already been
       *             traversed
       */
      private void visitcomponent( final Profile profile,
                                   final boolean providers,
                                   final ArrayList done,
                                   final ArrayList order )
      {
          //If already visited this profile then bug out early
          if( done.contains( profile ) )
          {
              return;
          }
          done.add( profile );
  
          if( providers )
          {
              visitProviders( profile, done, order );
          }
          else
          {
              visitConsumers( profile, done, order );
          }
  
          order.add( profile );
      }
  
      /**
       * Traverse graph of components that provide services to
       * the specified profile.
       *
       * @param profile the Profile
       */
      private void visitProviders( final Profile profile,
                                   final ArrayList done,
                                   final ArrayList order )
      {
          final DependencyDescriptor[] descriptors =
              profile.getType().getDependencies();
  
          for( int i = 0; i < descriptors.length; i++ )
          {
              final Association assignment =
                  profile.getAssociation( descriptors[ i ].getRole() );
  
              // added != null clause to catch cases where an optional 
              // dependency exists and the dependecy has not been bound 
              // to a provider
  
              if( assignment != null ) 
              {
                  final Profile provider = assignment.getProvider();
                  visitcomponent( provider, true, done, order );
              }
              else
              {
                  if( descriptors[i].isRequired() )
                    throw new IllegalStateException( 
                      "unresolved dependency for role: " + descriptors[i].getRole() 
                      + " in profile: " + profile );
              }
          }
      }
  
      /**
       * Traverse all Consumers of profile. ie Anyone that uses
       * service provided by profile.
       *
       * @param profile the Profile
       */
      private void visitConsumers( final Profile profile,
                                   final ArrayList done,
                                   final ArrayList order )
      {
  
          final String name = profile.getName();
  
          final int size = m_components.size();
          for( int i = 0; i < size; i++ )
          {
              final Profile other =
                  (Profile)m_components.get( i );
              final Association[] providers = other.getAssociations();
  
              for( int j = 0; j < providers.length; j++ )
              {
                  if( providers[ j ].getProvider().equals( profile ) )
                  {
                      visitcomponent( other, false, done, order );
                  }
              }
          }
  
          final int childCount = m_children.size();
          for( int i = 0; i < childCount; i++ )
          {
              final DependencyGraph map = (DependencyGraph)m_children.get( i );
              map.visitConsumers( profile, done, order );
          }
      }
  }
  
  
  
  1.3       +12 -43    jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/ProfileRegistry.java
  
  Index: ProfileRegistry.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/ProfileRegistry.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ProfileRegistry.java	8 Jul 2002 01:14:01 -0000	1.2
  +++ ProfileRegistry.java	8 Jul 2002 09:57:36 -0000	1.3
  @@ -31,7 +31,7 @@
   import org.apache.excalibur.meta.builder.TypeBuilder;
   import org.apache.excalibur.meta.builder.ProfileBuilder;
   import org.apache.excalibur.configuration.ConfigurationUtil;
  -import org.apache.excalibur.merlin.kernel.Map;
  +import org.apache.excalibur.merlin.kernel.DependencyGraph;
   import org.apache.excalibur.merlin.kernel.Container;
   import org.apache.excalibur.merlin.kernel.Selector;
   
  @@ -42,7 +42,7 @@
    * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
    * @version $Revision$ $Date$
    */
  -final class ProfileRegistry extends AbstractLogEnabled implements Startable
  +final class ProfileRegistry extends AbstractLogEnabled 
   {
   
       //=======================================================================
  @@ -76,7 +76,7 @@
       */
       private ArrayList m_installed = new ArrayList();
   
  -    private Map m_map;
  +    private DependencyGraph m_map;
   
      //=======================================================================
       // constructor
  @@ -89,7 +89,8 @@
       * @param profiles the configuration fragment containing explicit component profiles
       */
       public ProfileRegistry( 
  -      Configuration[] directives, TypeRegistry registry, ClassLoader loader, Container parent, Map map )
  +      Configuration[] directives, TypeRegistry registry, ClassLoader loader, 
  +      Container parent, DependencyGraph map )
       {
           m_classloader = loader;
           m_types = registry;
  @@ -98,34 +99,6 @@
           m_map = map;
       }
   
  -    //======================================================================
  -    // Startable
  -    //======================================================================
  -
  -    public void start() throws Exception
  -    {
  -        Profile[] startup = m_map.getStartupGraph();
  -        getLogger().debug("startup");
  -        for( int i=0; i<startup.length; i++ )
  -        {
  -            Profile profile = startup[i];
  -            if( isLocalProfile( profile ) )
  -              getLogger().debug("start: " + profile.getName() );
  -        }
  -    }
  -
  -    public void stop()
  -    {
  -        Profile[] shutdown = m_map.getShutdownGraph();
  -        for( int i=0; i<shutdown.length; i++ )
  -        {
  -            Profile profile = shutdown[i];
  -            if( isLocalProfile( profile ) )
  -              getLogger().debug("stop: " + profile.getName() );
  -        }
  -    }
  -
  -
       //=======================================================================
       // PrifileRegistry
       //=======================================================================
  @@ -187,17 +160,13 @@
                   Profile[] facilities = getFacilities( dependency.getService() );
                   Profile provider = selectProfile( dependency, facilities, candidates );
                   if( provider == null )
  +                  throw new UnresolvedProviderException("no available provider", dependency );
  +                profile.addProvider( provider, role );
  +                if( isLocalProfile( provider ) ) 
                   {
  -                    throw new UnresolvedProviderException("no available provider", dependency );
  -                }
  -                else
  -                {
  -                    profile.addProvider( provider, role );
  -                    if( isLocalProfile( provider ) ) 
  -                    {
  -                        m_map.add( provider );
  -                        m_installed.add( provider );
  -                    }
  +                    getLogger().info("LOCAL: " + profile );
  +                    m_map.add( provider );
  +                    m_installed.add( provider );
                   }
               }
           }
  
  
  
  1.9       +84 -15    jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/Registry.java
  
  Index: Registry.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/Registry.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- Registry.java	8 Jul 2002 02:51:54 -0000	1.8
  +++ Registry.java	8 Jul 2002 09:57:36 -0000	1.9
  @@ -71,15 +71,19 @@
   import org.apache.excalibur.meta.verifier.AssemblyVerifier;
   import org.apache.excalibur.meta.verifier.MetaDataVerifier;
   import org.apache.excalibur.meta.verifier.VerifyException;
  +import org.apache.excalibur.meta.lifecycle.LifecycleHelper;
  +import org.apache.excalibur.meta.lifecycle.ResourceProvider;
  +import org.apache.excalibur.meta.lifecycle.LifecycleException;
   import org.apache.excalibur.configuration.ContextFactory;
   import org.apache.log.output.io.StreamTarget;
   import org.apache.log.Hierarchy;
   import org.apache.log.Priority;
   
  -import org.apache.excalibur.merlin.kernel.Map;
  +import org.apache.excalibur.merlin.kernel.DependencyGraph;
   import org.apache.excalibur.merlin.kernel.Container;
   import org.apache.excalibur.merlin.kernel.ContainerClassLoader;
   import org.apache.excalibur.merlin.kernel.Verifiable;
  +import org.apache.excalibur.merlin.kernel.DefaultProvider;
   
   /**
    * Provides support for the maintenance of a registry of 
  @@ -112,6 +116,11 @@
       */
       public static final String MAP_KEY = "map";
   
  +   /**
  +    * Context key used to locate the resource provider.
  +    */
  +    public static final String PROVIDER_KEY = "provider";
  +
       private static final Resources REZ =
           ResourceManager.getPackageResources( Registry.class );
   
  @@ -142,11 +151,6 @@
       private Configuration m_config;
   
      /**
  -    * Hashtable of all installed profiles keyed by profile name.
  -    */
  -    //private Hashtable m_profiles = new Hashtable();
  -
  -   /**
       * Internal class that maintains information about profile types.
       */
       private ProfileRegistry m_profiles; 
  @@ -154,7 +158,18 @@
      /**
       * The depenecy map supplied by the parent container.
       */
  -    private Map m_map;
  +    private DependencyGraph m_map;
  +
  +   /**
  +    * The resource provider to handle resource creation during profile activation.
  +    */
  +    private DefaultProvider m_provider;
  +
  +   /**
  +    * The lifecycle helper to use to process startup and shudown of services.
  +    */
  +    private LifecycleHelper m_helper = new LifecycleHelper();
  +
   
       //=======================================================================
       // Contextualizable
  @@ -167,14 +182,15 @@
       public void contextualize( Context context ) throws ContextException
       {
           m_classloader = (ContainerClassLoader) context.get( CLASSLOADER_KEY );
  -        m_map = (Map) context.get( MAP_KEY );
  +        m_map = (DependencyGraph) context.get( MAP_KEY );
  +        m_provider = (DefaultProvider) context.get( PROVIDER_KEY );
           try
           {
               m_parent = (Container) context.get( CONTAINER_KEY );
           }
  -        catch( ContextException e )
  +        catch( Throwable e )
           {
  -            // root container
  +            // this is the root container
           }
       }
   
  @@ -205,6 +221,7 @@
       public void initialize() throws Exception
       {
           getLogger().debug("registry initialization");
  +        m_helper.enableLogging( getLogger().getChildLogger("lifecycle") );
           m_types = new TypeRegistry( this, m_classloader );
           m_types.enableLogging( getLogger().getChildLogger("types") );
           String[] blocks = m_classloader.getComponentClassnames();
  @@ -288,15 +305,67 @@
   
       public void start() throws Exception
       {
  -        m_profiles.start();
  +        getLogger().debug("start");
  +        Profile[] startup = m_map.getStartupGraph();
  +        for( int i=0; i<startup.length; i++ )
  +        {
  +            Profile profile = startup[i];
  +            if( m_profiles.isLocalProfile( profile ) )
  +            {
  +                final String name = profile.getName();
  +                getLogger().debug(" > " + name );
  +                try
  +                {
  +                    m_helper.startup( name, profile, m_provider );
  +                }
  +                catch( LifecycleException le )
  +                {
  +                    final String warning = 
  +                      "Could not startup a service derived from profile: " + profile;
  +                    getLogger().warn( warning, le );
  +
  +                    // need to retract all profiles dependent on this profile
  +                }
  +                /*
  +                */
  +            }
  +        }
  +        getLogger().debug("started");
       }
   
       public void stop()
       {
  -        m_profiles.stop();
  +        getLogger().debug("stop");
  +        Profile[] shutdown = m_map.getShutdownGraph();
  +        for( int i=0; i<shutdown.length; i++ )
  +        {
  +            Profile profile = shutdown[i];
  +            if( m_profiles.isLocalProfile( profile ) )
  +            {
  +                final String name = profile.getName();
  +                getLogger().debug( " < " + name );
  +                Object object = m_provider.getSingletonInstance( profile );
  +                if( object == null )
  +                {
  +                    try
  +                    {
  +                        m_helper.shutdown( name, object );
  +                        m_provider.release( profile );
  +                    }
  +                    catch( LifecycleException le )
  +                    {
  +                        final String warning = 
  +                          "Could not shutdown a service derived from profile: " + profile;
  +                        getLogger().warn( warning, le );
  +                    }
  +                }
  +                /*
  +                */
  +            }
  +        }
  +        getLogger().debug("stopped");
       }
   
  -
       //=======================================================================
       // Verifiable
       //=======================================================================
  @@ -374,7 +443,7 @@
           }
       }
   
  -    private void listProfile( int n, Profile profile, Map map, List reported )
  +    private void listProfile( int n, Profile profile, DependencyGraph map, List reported )
       {
           if( !reported.contains( profile ) )
           {
  
  
  
  1.4       +1 -2      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/TypeRegistry.java
  
  Index: TypeRegistry.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/TypeRegistry.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TypeRegistry.java	8 Jul 2002 01:14:01 -0000	1.3
  +++ TypeRegistry.java	8 Jul 2002 09:57:36 -0000	1.4
  @@ -25,7 +25,6 @@
   import org.apache.excalibur.meta.verifier.ComponentVerifier;
   import org.apache.excalibur.meta.builder.TypeBuilder;
   import org.apache.excalibur.configuration.ConfigurationUtil;
  -import org.apache.excalibur.merlin.kernel.Map;
   
   /**
    * Internal table that holds available component type keyed relative
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/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.meta.lifecycle;
  
  import org.apache.avalon.framework.CascadingException;
  
  /**
   * 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/07/08 09:57:36 $
   */
  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/meta/lifecycle/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.meta.lifecycle;
  
  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.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.meta.data.Profile;
  
  /**
   * 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_INIT = 6;
      private static final int STAGE_START = 7;
      private static final int STAGE_STOP = 8;
      private static final int STAGE_DISPOSE = 9;
      private static final int STAGE_DESTROY = 10;
  
      /**
       * 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
       * @throws LifecycleException if an error occurs when the component passes
       *     through a specific lifecycle stage
       */
      public Object startup( final String name,
                             final Profile profile,
                             final ResourceProvider provider )
          throws LifecycleException
      {
          int stage = 0;
          try
          {
              //Creation stage
              stage = STAGE_CREATE;
              notice( name, stage );
              final Object object = provider.createObject( profile );
  
              //LogEnabled stage
              stage = STAGE_LOGGER;
              if( object instanceof LogEnabled )
              {
                  notice( name, stage );
                  final Logger logger = provider.createLogger( profile );
                  ContainerUtil.enableLogging( object, logger );
              }
  
              //Contextualize stage
              stage = STAGE_CONTEXT;
              if( object instanceof Contextualizable )
              {
                  notice( name, stage );
                  final Context context = provider.createContext( profile );
                  ContainerUtil.contextualize( object, context );
              }
  
              //Composition stage
              stage = STAGE_COMPOSE;
              if( object instanceof Serviceable )
              {
                  notice( name, stage );
                  final ServiceManager manager =
                      provider.createServiceManager( profile);
                  ContainerUtil.service( object, manager );
              }
              else if( object instanceof Composable )
              {
                  notice( name, stage );
                  final ComponentManager componentManager =
                      provider.createComponentManager( profile );
                  ContainerUtil.compose( object, componentManager );
              }
  
              //Configuring stage
              stage = STAGE_CONFIG;
              if( object instanceof Configurable )
              {
                  notice( name, stage );
                  final Configuration configuration =
                      provider.createConfiguration( profile );
                  ContainerUtil.configure( object, configuration );
              }
  
              //Parameterizing stage
              stage = STAGE_PARAMETER;
              if( object instanceof Parameterizable )
              {
                  notice( name, stage );
                  final Parameters parameters =
                      provider.createParameters( profile );
                  ContainerUtil.parameterize( object, parameters );
              }
  
              //Initialize stage
              stage = STAGE_INIT;
              if( object instanceof Initializable )
              {
                  notice( name, stage );
                  ContainerUtil.initialize( profile );
              }
  
              //Start stage
              stage = STAGE_START;
              if( object instanceof Startable )
              {
                  notice( name, stage );
                  ContainerUtil.start( profile );
              }
  
              return object;
          }
          catch( final Throwable t )
          {
              fail( name, 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 appropraitely.
       *
       * @param name the name of the component
       * @param object the component to shutdown
       */
      public void shutdown( final String name,
                            final Object object )
          throws LifecycleException
      {
  
          //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;
              }
          }
  
          //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.getMessage();
          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/meta/lifecycle/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.meta.lifecycle;
  
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.service.ServiceManager;
  
  import org.apache.excalibur.meta.data.Profile;
  
  /**
   * The interface via which resources required for a component
   * are aquired based on a supplied {@link Profile}.
   *
   * @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/07/08 09:57:36 $
   */
  public interface ResourceProvider
  {
      /**
       * Create an object specified by profile.
       *
       * @param profile the profile
       * @return the new object
       * @throws Exception if unable to create resource
       */
      Object createObject( Profile profile )
          throws Exception;
  
      /**
       * Create a new Logger for component.
       *
       * @param profile the profile
       * @return a new Logger for component
       * @throws Exception if unable to create resource
       */
      Logger createLogger( Profile profile )
          throws Exception;
  
      /**
       * Create a new Context for component.
       *
       * @param profile the profile
       * @return a new Context for component
       * @throws Exception if unable to create resource
       */
      Context createContext( Profile profile )
          throws Exception;
  
      /**
       * Create a new ComponentManager for component.
       *
       * @param profile the profile
       * @return a new ComponentManager for component
       * @throws Exception if unable to create resource
       */
      ComponentManager createComponentManager( Profile profile )
          throws Exception;
  
      /**
       * Create a new ServiceManager for component.
       *
       * @param profile the profile
       * @return a new ServiceManager for component
       * @throws Exception if unable to create resource
       */
      ServiceManager createServiceManager( Profile profile )
          throws Exception;
  
      /**
       * Create a new Configuration object for component.
       *
       * @param profile the profile
       * @return a new Configuration object for component
       * @throws Exception if unable to create resource
       */
      Configuration createConfiguration( Profile profile )
          throws Exception;
  
      /**
       * Create a new Parameters object for component.
       *
       * @param profile the profile
       * @return a new Parameters object for component
       * @throws Exception if unable to create resource
       */
      Parameters createParameters( Profile profile )
          throws Exception;
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/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#Initialization|7#Starting|8#Stopping|9#Disposing|10#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#Initialization|7#Starting|8#Stopping|9#Disposing|10#Destruction} stage. (Reason: {2}).
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/package.html
  
  Index: package.html
  ===================================================================
  
  <body>
  Helpers classes and interfaces supporting the declaration of a resource provider to a component during lifecycle processing.
  
  <h3>Package Structure (UML)</h3>
  <p><img src=doc-files/lifecycle.gif border=0></p>
  
  
  </body>
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/doc-files/LifecycleHelper.gif
  
  	<<Binary file>>
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/doc-files/ResourceProvider.gif
  
  	<<Binary file>>
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/doc-files/lifecycle.gif
  
  	<<Binary file>>
  
  

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