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/12 14:04:56 UTC

cvs commit: jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/verifier AssemblyVerifier.java MetaDataVerifier.java Resources.properties package.html

mcconnell    2002/07/12 05:04:56

  Modified:    assembly/src/java/org/apache/excalibur/merlin Container.java
                        Main.java
               assembly/src/java/org/apache/excalibur/merlin/container
                        DefaultContainer.java DefaultContainer.xinfo
                        ProfileRegistry.java ProfileTable.java
                        Resources.properties package.html
               assembly/src/java/org/apache/excalibur/merlin/kernel
                        ContainerClassLoader.java DefaultKernel.java
                        DefaultKernel.xinfo DefaultLoggerManager.java
                        DefaultProvider.java DependencyGraph.java
                        TypeRegistry.java package.html
  Added:       assembly/src/java/org/apache/excalibur/merlin/model
                        AbstractContainer.java Association.java
                        CategoryDescriptor.java ClasspathDescriptor.java
                        ComponentDescriptor.java ContainerDescriptor.java
                        DefaultProfile.java DirsetDescriptor.java
                        ExtensionsDescriptor.java FileTargetProvider.java
                        FilesetDescriptor.java IncludeDescriptor.java
                        KernelDescriptor.java LoggingDescriptor.java
                        Profile.java TargetDescriptor.java
                        TargetProvider.java package.html
               assembly/src/java/org/apache/excalibur/merlin/model/builder
                        ContainerCreator.java KernelCreator.java
                        ProfileBuilder.java ProfileCreator.java
                        Resources.properties TypeManager.java
                        XMLContainerCreator.java XMLKernelCreator.java
                        XMLProfileCreator.java package.html
               assembly/src/java/org/apache/excalibur/merlin/model/verifier
                        AssemblyVerifier.java MetaDataVerifier.java
                        Resources.properties package.html
  Log:
  rationalization
  
  Revision  Changes    Path
  1.2       +10 -2     jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/Container.java
  
  Index: Container.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/Container.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Container.java	12 Jul 2002 10:16:19 -0000	1.1
  +++ Container.java	12 Jul 2002 12:04:54 -0000	1.2
  @@ -8,7 +8,7 @@
   
   package org.apache.excalibur.merlin;
   
  -import org.apache.excalibur.merlin.meta.data.Profile;
  +import org.apache.excalibur.merlin.model.Profile;
   import org.apache.excalibur.meta.info.ServiceDesignator;
   
   /**
  @@ -27,6 +27,14 @@
       * @return the set of potential supplier profile
       */
       Profile[] getProviders( ServiceDesignator service );
  +
  +   /**
  +    * Test if the container is managing a supplied profile.
  +    * @param profile the profile
  +    * @return TRUE if the profile is managed by the container.
  +    */
  +    public boolean contains( Profile profile );
  +
   
   
   }
  
  
  
  1.2       +7 -7      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/Main.java
  
  Index: Main.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/Main.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Main.java	12 Jul 2002 10:16:19 -0000	1.1
  +++ Main.java	12 Jul 2002 12:04:54 -0000	1.2
  @@ -61,12 +61,12 @@
   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.merlin.meta.data.builder.XMLKernelCreator;
  -import org.apache.excalibur.merlin.meta.data.KernelDescriptor;
  -import org.apache.excalibur.merlin.meta.data.ClasspathDescriptor;
  -import org.apache.excalibur.merlin.meta.data.ExtensionsDescriptor;
  -import org.apache.excalibur.merlin.meta.data.LoggingDescriptor;
  -import org.apache.excalibur.merlin.meta.data.ContainerDescriptor;
  +import org.apache.excalibur.merlin.model.builder.XMLKernelCreator;
  +import org.apache.excalibur.merlin.model.KernelDescriptor;
  +import org.apache.excalibur.merlin.model.ClasspathDescriptor;
  +import org.apache.excalibur.merlin.model.ExtensionsDescriptor;
  +import org.apache.excalibur.merlin.model.LoggingDescriptor;
  +import org.apache.excalibur.merlin.model.ContainerDescriptor;
   import org.apache.excalibur.merlin.kernel.DefaultKernel;
   import org.apache.excalibur.merlin.kernel.DefaultLoggerManager;
   import org.apache.excalibur.merlin.kernel.ContainerClassLoader;
  
  
  
  1.2       +277 -40   jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/DefaultContainer.java
  
  Index: DefaultContainer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/DefaultContainer.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultContainer.java	12 Jul 2002 10:17:20 -0000	1.1
  +++ DefaultContainer.java	12 Jul 2002 12:04:54 -0000	1.2
  @@ -18,6 +18,7 @@
   import java.util.LinkedList;
   import java.util.Hashtable;
   import java.util.Properties;
  +import java.util.ArrayList;
   import java.util.Vector;
   import java.util.Iterator;
   import java.util.jar.Attributes;
  @@ -57,15 +58,18 @@
   import org.apache.avalon.excalibur.extension.OptionalPackage;
   import org.apache.avalon.excalibur.extension.DefaultPackageRepository;
   import org.apache.avalon.excalibur.logger.LoggerManager;
  +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.verifier.VerifyException;
   import org.apache.excalibur.merlin.meta.data.Profile;
  +import org.apache.excalibur.merlin.meta.data.ComponentDescriptor;
   import org.apache.excalibur.merlin.meta.data.ContainerDescriptor;
   import org.apache.excalibur.merlin.meta.data.CategoryDescriptor;
  -import org.apache.excalibur.merlin.container.Registry;
  +import org.apache.excalibur.merlin.meta.data.verifier.AssemblyVerifier;
  +import org.apache.excalibur.merlin.meta.data.verifier.MetaDataVerifier;
   import org.apache.excalibur.merlin.kernel.ContainerClassLoader;
   import org.apache.excalibur.merlin.kernel.DependencyGraph;
   import org.apache.excalibur.merlin.kernel.DefaultProvider;
  @@ -73,6 +77,7 @@
   import org.apache.excalibur.merlin.Container;
   import org.apache.excalibur.merlin.Verifiable;
   import org.apache.excalibur.merlin.Manageable;
  +import org.apache.excalibur.merlin.ResourceProvider;
   import org.apache.log.Hierarchy;
   import org.apache.log.Priority;
   import org.apache.log.output.io.StreamTarget;
  @@ -88,20 +93,56 @@
    * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
    * @version $Revision$ $Date$
    */
  -public class DefaultContainer extends Registry implements Container
  +public class DefaultContainer extends AbstractLogEnabled implements Container, Contextualizable, Initializable, Disposable, Startable
   {
  -
       //=======================================================================
  -    // state
  +    // static
       //=======================================================================
   
      /**
  -    * Configuration.
  +    * Context key used to locate the application classloader.
  +    */
  +    public static final String CLASSLOADER_KEY = "classloader";
  +
  +   /**
  +    * Context key used to locate the application classloader.
  +    */
  +    public static final String CONTAINER_KEY = "container";
  +
  +   /**
  +    * Context key used to locate the application classloader.
       */
  -    //private Configuration m_config;
  +    public static final String MAP_KEY = "map";
   
      /**
  -    * The registry of embedded containers.
  +    * Context key used to locate the logger manager.
  +    */
  +    public static final String LOG_MANAGER_KEY = "logging";
  +
  +   /**
  +    * Context key used to locate the logger manager.
  +    */
  +    public static final String CATEGORY_PATH_KEY = "path";
  +
  +   /**
  +    * Context key used to locate the resource provider.
  +    */
  +    public static final String PROVIDER_KEY = "provider";
  +
  +   /**
  +    * Context key used to locate the logger manager.
  +    */
  +    public static final String CONTAINER_DESCRIPTOR_KEY = "descriptor";
  +
  +    private static final Resources REZ =
  +        ResourceManager.getPackageResources( DefaultContainer.class );
  +
  +    //=======================================================================
  +    // state
  +    //=======================================================================
  +
  +   /**
  +    * The list of embedded containers.
       */
       private List m_containers = new LinkedList();
   
  @@ -116,7 +157,7 @@
   
       private DependencyGraph m_map;
   
  -    private DefaultProvider m_provider;
  +    private ResourceProvider m_provider;
   
       private DefaultLoggerManager m_logging;
   
  @@ -124,6 +165,17 @@
   
       private ContainerDescriptor m_descriptor;
   
  +   /**
  +    * The lifecycle helper to use to process startup and shudown of services.
  +    */
  +    private LifecycleHelper m_helper = new LifecycleHelper();
  +
  +   /**
  +    * Internal class that maintains information about profile types managed 
  +    * by this container.
  +    */
  +    private ProfileRegistry m_profiles; 
  +
       //=======================================================================
       // Contextualizable
       //=======================================================================
  @@ -137,45 +189,19 @@
           m_classloader = (ContainerClassLoader) context.get( CLASSLOADER_KEY );
           m_logging = (DefaultLoggerManager) context.get( LOG_MANAGER_KEY );
           m_descriptor = (ContainerDescriptor) context.get( CONTAINER_DESCRIPTOR_KEY );
  -
  +        m_map = (DependencyGraph) context.get( MAP_KEY );
  +        m_provider = (ResourceProvider) context.get( PROVIDER_KEY );
           try
           {
               m_parent = (Container) context.get( CONTAINER_KEY );
  -            super.contextualize( context );
           }
           catch( ContextException e )
           {
               // root container
  -
  -            m_map = new DependencyGraph();
  -            m_provider = new DefaultProvider( m_classloader, m_logging );
  -            m_provider.enableLogging( getLogger() );
  -
  -            DefaultContext dc = new DefaultContext( context );
  -            dc.put( MAP_KEY, m_map );
  -            dc.put( PROVIDER_KEY, m_provider );
  -
  -            super.contextualize( dc );
           }
       }
   
       //=======================================================================
  -    // Configurable
  -    //=======================================================================
  -
  -   /**
  -    * Invoked by the container to establish the registry configuration.
  -    * @param config a component configuration
  -    */
  -/*
  -    public void configure( Configuration config)
  -    {
  -        getLogger().debug("container configuration");
  -        super.configure( config );
  -        m_config = config;
  -    }
  -*/
  -    //=======================================================================
       // Initializable
       //=======================================================================
   
  @@ -191,8 +217,48 @@
       public void initialize() throws Exception
       {
           getLogger().debug("initilization");
  -        super.initialize();
  -        
  +        m_helper.enableLogging( getLogger().getChildLogger("lifecycle") );
  +
  +        // 
  +        // initiate profile creation
  +        //
  +
  +        m_profiles = new ProfileRegistry( 
  +          m_descriptor, m_classloader, m_classloader, m_parent, m_map );
  +        m_profiles.enableLogging( getLogger().getChildLogger( "profiles") );
  +
  +        // 
  +        // explicit component profile registration
  +        //
  +
  +        getLogger().debug("explicit profile registration");
  +        ComponentDescriptor[] children = m_descriptor.getComponentDescriptors();
  +        for( int i=0; i<children.length; i++ )
  +        {
  +            m_profiles.register( children[i] );
  +        }
  +
  +        // 
  +        // packaged and implict profile registration
  +        //
  +
  +        getLogger().debug("packaged and implicit profile registration");
  +        Type[] types = m_classloader.getTypes();
  +        for( int i=0; i<types.length; i++ )
  +        {
  +            m_profiles.register( types[i] );
  +        }
  +
  +        try
  +        {
  +            getLogger().debug("profile assembly");
  +            m_profiles.assembleProfiles();
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = "Assembly failure.";
  +            throw new AssemblyException( error, e );
  +        }
   
           getLogger().debug("subsidiary container creation");
           ContainerDescriptor[] containers = m_descriptor.getContainers();
  @@ -215,7 +281,7 @@
       */
       public void verify() throws VerifyException
       {
  -        super.verify();
  +        verifyContainer();
           Iterator iterator = m_containers.iterator();
           while( iterator.hasNext() )
           {
  @@ -224,6 +290,75 @@
       }
   
       //======================================================================
  +    // Startable
  +    //======================================================================
  +
  +    public void start() throws Exception
  +    {
  +        getLogger().debug("start");
  +        Profile[] startup = m_map.getStartupGraph();
  +        for( int i=0; i<startup.length; i++ )
  +        {
  +            Profile profile = startup[i];
  +            if( this.contains( profile ) )
  +            {
  +                final String name = profile.getName();
  +                try
  +                {
  +                    if( getLogger().isDebugEnabled() )
  +                      getLogger().debug("starting: " + name );
  +                    m_helper.startup( name, profile, m_provider );
  +                    if( getLogger().isInfoEnabled() )
  +                      getLogger().info("started: " + name );
  +                }
  +                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()
  +    {
  +        getLogger().debug("stop");
  +        Profile[] shutdown = m_map.getShutdownGraph();
  +        for( int i=0; i<shutdown.length; i++ )
  +        {
  +            Profile profile = shutdown[i];
  +            if( this.contains( profile ) )
  +            {
  +                final String name = profile.getName();
  +                if( getLogger().isDebugEnabled() )
  +                  getLogger().debug("stopping: " + name );
  +                Object object = m_provider.getSingletonInstance( profile );
  +                if( object != null )
  +                {
  +                    try
  +                    {
  +                        m_helper.shutdown( name, object );
  +                        m_provider.release( profile );
  +                        if( getLogger().isInfoEnabled() )
  +                          getLogger().info("stopped: " + name );
  +                    }
  +                    catch( LifecycleException le )
  +                    {
  +                        final String warning = 
  +                          "Could not shutdown a service derived from profile: " + profile;
  +                        getLogger().warn( warning, le );
  +                    }
  +                }
  +            }
  +        }
  +        getLogger().debug("stopped");
  +    }
  +
  +    //======================================================================
       // Manageable
       //======================================================================
   
  @@ -265,8 +400,110 @@
       }
   
       //=======================================================================
  +    // Container
  +    //=======================================================================
  +
  +    public boolean contains( Profile profile )
  +    {
  +        return m_profiles.isLocalProfile( profile );
  +    }
  +
  +    public Profile[] getProviders( ServiceDesignator designator )
  +    {
  +        Profile[] local = m_profiles.getProviders( designator );
  +        if( m_parent != null )
  +        {
  +            Profile[] facilities = m_parent.getProviders( designator );
  +            ArrayList list = new ArrayList();
  +            for( int i=0; i<local.length; i++ )
  +            {
  +                list.add( local[i] );
  +            }
  +            for( int i=0; i<facilities.length; i++ )
  +            {
  +                list.add( facilities[i] );
  +            }
  +            return (Profile[]) list.toArray( new Profile[0] );
  +        }
  +        return local;
  +    }
  +
  +    //=======================================================================
  +    // Disposable
  +    //=======================================================================
  +
  +   /**
  +    * Disposal of this component.
  +    */
  +    public void dispose()
  +    {
  +        getLogger().debug("dispose");
  +    }
  +
  +    //=======================================================================
       // private
       //=======================================================================
  +
  +   /**
  +    * Internal verification of the container.
  +    *
  +    * @exception ValidationException if a validation failure occurs
  +    */
  +    private void verifyContainer() throws VerifyException
  +    {
  +        getLogger().debug("verify");
  +        
  +        Profile[] profiles = m_map.getStartupGraph();
  +        MetaDataVerifier mdv = new MetaDataVerifier();
  +        for( int i=0; i<profiles.length; i++ )
  +        {
  +            try
  +            {
  +                mdv.verifyType( profiles[i], m_classloader );
  +            }
  +            catch( Throwable e )
  +            {
  +                getLogger().error("verification failure", e );
  +            }
  +        }
  +
  +        AssemblyVerifier verifier = new AssemblyVerifier();
  +        verifier.enableLogging( getLogger().getChildLogger("verifier") );
  +        getLogger().debug("commencing assembly verification");
  +        verifier.verifyAssembly( profiles );
  +        listProfiles( profiles );
  +    }
  +
  +    private void listProfiles( Profile[] profiles )
  +    {
  +        getLogger().debug("listing profiles");
  +        List reported = new LinkedList();
  +        for( int i=0; i<profiles.length; i++ )
  +        {
  +            listProfile( i+1, profiles[i], m_map, reported );
  +        }
  +    }
  +
  +    private void listProfile( int n, Profile profile, DependencyGraph map, List reported )
  +    {
  +        if( !reported.contains( profile ) )
  +        {
  +            reported.add( profile );
  +            getLogger().debug( "" + n + ": " + profile.toString() );
  +            Profile[] suppliers = map.getProviderGraph( profile );
  +            for( int j=0; j<suppliers.length; j++ )
  +            {
  +                Profile supplier = suppliers[j];
  +                getLogger().debug("   supplier: " + supplier );
  +            }
  +            Profile[] consumers = map.getConsumerGraph( profile );
  +            for( int j=0; j<consumers.length; j++ )
  +            {
  +                Profile consumer = consumers[j];
  +                getLogger().debug("   consumer: " + consumer.getName() );
  +            }
  +        }
  +    }
   
       private DefaultContainer createContainer( ContainerDescriptor descriptor ) throws Exception
       {
  
  
  
  1.2       +5 -0      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/DefaultContainer.xinfo
  
  Index: DefaultContainer.xinfo
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/DefaultContainer.xinfo,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultContainer.xinfo	12 Jul 2002 10:17:20 -0000	1.1
  +++ DefaultContainer.xinfo	12 Jul 2002 12:04:54 -0000	1.2
  @@ -19,6 +19,11 @@
   
     <context>
       <entry key="classloader" type="org.apache.excalibur.merlin.kernel.ContainerClassLoader" optional="false"/>
  +    <entry key="logging" type="org.apache.excalibur.merlin.kernel.DefaultLoggerManager" optional="false"/>
  +    <entry key="provider" type="org.apache.excalibur.merlin.kernel.DefaultProvider" optional="false"/>
  +    <entry key="descriptor" type="org.apache.excalibur.merlin.model.ContainerDescriptor" optional="false"/>
  +    <entry key="map" type="org.apache.excalibur.merlin.kernel.DependencyGraph" optional="false"/>
  +    <entry key="container" type="org.apache.excalibur.merlin.Container" optional="true"/>
     </context>
   
     <services>
  
  
  
  1.2       +7 -7      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/ProfileRegistry.java
  
  Index: ProfileRegistry.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/ProfileRegistry.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ProfileRegistry.java	12 Jul 2002 10:17:20 -0000	1.1
  +++ ProfileRegistry.java	12 Jul 2002 12:04:54 -0000	1.2
  @@ -29,12 +29,12 @@
   import org.apache.excalibur.meta.info.builder.TypeBuilder;
   import org.apache.excalibur.meta.verifier.ComponentVerifier;
   import org.apache.excalibur.configuration.ConfigurationUtil;
  -import org.apache.excalibur.merlin.meta.data.builder.TypeManager;
  -import org.apache.excalibur.merlin.meta.data.Profile;
  -import org.apache.excalibur.merlin.meta.data.ContainerDescriptor;
  -import org.apache.excalibur.merlin.meta.data.ComponentDescriptor;
  -import org.apache.excalibur.merlin.meta.data.builder.ProfileBuilder;
  -import org.apache.excalibur.merlin.meta.data.Selector;
  +import org.apache.excalibur.merlin.model.builder.TypeManager;
  +import org.apache.excalibur.merlin.model.Profile;
  +import org.apache.excalibur.merlin.model.ContainerDescriptor;
  +import org.apache.excalibur.merlin.model.ComponentDescriptor;
  +import org.apache.excalibur.merlin.model.builder.ProfileBuilder;
  +import org.apache.excalibur.merlin.Selector;
   import org.apache.excalibur.merlin.kernel.DependencyGraph;
   import org.apache.excalibur.merlin.Container;
   
  
  
  
  1.2       +2 -2      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/ProfileTable.java
  
  Index: ProfileTable.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/ProfileTable.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ProfileTable.java	12 Jul 2002 10:17:20 -0000	1.1
  +++ ProfileTable.java	12 Jul 2002 12:04:54 -0000	1.2
  @@ -13,7 +13,7 @@
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.excalibur.meta.info.ServiceDesignator;
   import org.apache.excalibur.meta.info.Type;
  -import org.apache.excalibur.merlin.meta.data.Profile;
  +import org.apache.excalibur.merlin.model.Profile;
   
   /**
    * Internal table that holds references to the available component types 
  
  
  
  1.2       +3 -0      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/Resources.properties,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Resources.properties	12 Jul 2002 10:17:20 -0000	1.1
  +++ Resources.properties	12 Jul 2002 12:04:54 -0000	1.2
  @@ -18,3 +18,6 @@
   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}
  +
  +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.2       +1 -1      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/package.html
  
  Index: package.html
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/package.html,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- package.html	12 Jul 2002 10:17:20 -0000	1.1
  +++ package.html	12 Jul 2002 12:04:54 -0000	1.2
  @@ -18,7 +18,7 @@
   </ul>
   
   <h3>Object Model</h3>
  -<p>The primary service is a type {@link org.apache.excalibur.merlin.container.Registry}.  The registry acts as a component {@link org.apache.excalibur.meta.info.Type} repository and {@link org.apache.excalibur.merlin.meta.data.Profile} manager.  Each component type represents a concrete component implementation class.  For each component type, the container associates at least one instantiation {@link org.apache.excalibur.merlin.meta.data.Profile}.  A profile is either a default profile generated by the registry based on meta-information derived from the type, or, an explicit profile declared by the component assembler via the registry configuration.  Multiple profiles for a particular component type can coexist in the same registry.
  +<p>The primary service is a type {@link org.apache.excalibur.merlin.container.Registry}.  The registry acts as a component {@link org.apache.excalibur.meta.info.Type} repository and {@link org.apache.excalibur.merlin.model.Profile} manager.  Each component type represents a concrete component implementation class.  For each component type, the container associates at least one instantiation {@link org.apache.excalibur.merlin.model.Profile}.  A profile is either a default profile generated by the registry based on meta-information derived from the type, or, an explicit profile declared by the component assembler via the registry configuration.  Multiple profiles for a particular component type can coexist in the same registry.
   
   
   <h3>Package Structure (UML)</h3>
  
  
  
  1.4       +240 -47   jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/ContainerClassLoader.java
  
  Index: ContainerClassLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/ContainerClassLoader.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ContainerClassLoader.java	4 Jul 2002 09:01:34 -0000	1.3
  +++ ContainerClassLoader.java	12 Jul 2002 12:04:54 -0000	1.4
  @@ -29,14 +29,27 @@
   import org.apache.avalon.framework.logger.LogEnabled;
   import org.apache.avalon.framework.CascadingRuntimeException;
   import org.apache.avalon.framework.configuration.Configuration;
  +import org.apache.avalon.framework.activity.Initializable;
  +import org.apache.avalon.framework.context.Context;
  +import org.apache.avalon.framework.context.Contextualizable;
  +import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.framework.activity.Initializable;
   import org.apache.avalon.excalibur.i18n.ResourceManager;
   import org.apache.avalon.excalibur.i18n.Resources;
   import org.apache.avalon.excalibur.extension.Extension;
   import org.apache.avalon.excalibur.extension.PackageManager;
   import org.apache.avalon.excalibur.extension.PackageRepository;
   import org.apache.avalon.excalibur.extension.OptionalPackage;
  +import org.apache.avalon.excalibur.extension.DefaultPackageRepository;
   
  -import org.apache.excalibur.merlin.registry.*;
  +import org.apache.excalibur.meta.info.Type;
  +import org.apache.excalibur.meta.info.ServiceDesignator;
  +import org.apache.excalibur.merlin.model.ClasspathDescriptor;
  +import org.apache.excalibur.merlin.model.FilesetDescriptor;
  +import org.apache.excalibur.merlin.model.IncludeDescriptor;
  +import org.apache.excalibur.merlin.model.ExtensionsDescriptor;
  +import org.apache.excalibur.merlin.model.DirsetDescriptor;
  +import org.apache.excalibur.merlin.model.builder.TypeManager;
   
   /**
    * Classloader for an assembly of components.
  @@ -45,7 +58,8 @@
    * @version $Revision$ $Date$
    */ 
   
  -public class ContainerClassLoader extends URLClassLoader implements LogEnabled
  +public class ContainerClassLoader extends URLClassLoader 
  +  implements LogEnabled, Contextualizable, Initializable, TypeManager
   {
   
       //===================================================================
  @@ -55,6 +69,9 @@
       private static final Resources REZ =
           ResourceManager.getPackageResources( ContainerClassLoader.class );
   
  +    public static final String EXTENSIONS_DESCRIPTOR_KEY = "extensions";
  +    public static final String CLASSPATH_DESCRIPTOR_KEY = "classpath";
  +
       //===================================================================
       // state
       //===================================================================
  @@ -70,60 +87,121 @@
   
       private Logger m_logger;
   
  +    private ExtensionsDescriptor m_extensions;
  +
  +    private ClasspathDescriptor m_classpath;
  +
  +    private TypeRegistry m_types;
  +
       //===================================================================
       // constructor
       //===================================================================
   
  -    ContainerClassLoader( ClassLoader parent, Configuration classpath, Logger logger )
  +    public ContainerClassLoader( )
       {
  -        this( null, parent, classpath, logger );
  +        super( new URL[ 0 ], Thread.currentThread().getContextClassLoader() );
       }
   
  -    ContainerClassLoader( 
  -      PackageRepository repository, ClassLoader parent, Configuration classpath, Logger logger )
  +    public ContainerClassLoader( ClassLoader parent )
       {
           super( new URL[ 0 ], parent );
  +    }
  +
  +    //===================================================================
  +    // LogEnabled
  +    //===================================================================
  +
  +    public void enableLogging( Logger logger )
  +    {
           m_logger = logger;
  -        if( repository != null )
  -          m_manager = new PackageManager( repository );
  -        addClasspath( classpath );
       }
   
  -    public void addClasspath( Configuration classpath )
  +    public Logger getLogger()
  +    {
  +        return m_logger;
  +    }
  +
  +    //=======================================================================
  +    // Contextualizable
  +    //=======================================================================
  +
  +   /**
  +    * Invoked by the bootstrap process to supply to kernel defintion.
  +    * @param context the context object containing the inital parameters
  +    * @exception ContextException if the supplied does not contain a DESCRIPTOR_KEY value 
  +    */
  +    public void contextualize( Context context ) throws ContextException
       {
  +        getLogger().debug( "contextualize" );
           try
           {
  -            URL[] urls = Fileset.expandClasspath( classpath );
  -            for( int i = 0; i < urls.length; i++ )
  -            {
  -                addURL( urls[ i ] );
  -            }
  -            String[] path = Fileset.urlsToStrings( urls );
  -            final File[] extensions = getOptionalPackagesFor( path );
  -            for( int i = 0; i < extensions.length; i++ )
  -            {
  -                addURL( extensions[ i ].toURL() );
  -            }
  +            m_extensions = (ExtensionsDescriptor) context.get( EXTENSIONS_DESCRIPTOR_KEY );
           }
  -        catch( Throwable e )
  +        catch( ContextException e )
  +        {
  +            // ignore - optional context element
  +        }
  +
  +        try
           {
  -            final String error = "Unexpected exception while creating classloader";
  -            throw new RegistryRuntimeException( error, e );
  +            m_classpath = (ClasspathDescriptor) context.get( CLASSPATH_DESCRIPTOR_KEY );
  +        }
  +        catch( ContextException e )
  +        {
  +            // ignore - optional context element
           }
       }
   
  -    //===================================================================
  -    // LogEnabled
  -    //===================================================================
  +    //=======================================================================
  +    // Initializable
  +    //=======================================================================
   
  -    public void enableLogging( Logger logger )
  +    public void initialize() throws Exception
       {
  -        m_logger = logger;
  +        getLogger().debug("initilize");
  +
  +        m_types = new TypeRegistry( this );
  +        m_types.enableLogging( getLogger().getChildLogger( "types" ) );
  +
  +        if( m_extensions != null )
  +          initializeExtensions();
  +        if( m_classpath != null )
  +          initializeClasspath();
       }
   
  -    public Logger getLogger()
  +    private void initializeExtensions() throws Exception
       {
  -        return m_logger;
  +        getLogger().debug( "initializing extensions" );
  +        ArrayList list = new ArrayList();
  +        File dir = new File( System.getProperty("user.dir") );
  +        DirsetDescriptor[] dirs = m_extensions.getDirsetDescriptors();
  +        for( int i=0; i<dirs.length; i++ )
  +        {
  +            DirsetDescriptor descriptor = dirs[i];
  +            File base = new File( dir, descriptor.getBaseDirectory() );
  +            IncludeDescriptor[] includes = descriptor.getIncludeDescriptors();
  +            for( int j=0; j<includes.length; j++ )
  +            {
  +                File include = new File( base, includes[j].getFile() );
  +                if( include.isDirectory() )
  +                {
  +                    list.add( include );
  +                }
  +                else
  +                {
  +                   throw new IllegalArgumentException(
  +                    "Include dir does not refer to a directory: " + include );
  +                }
  +            }
  +        }
  +        File[] files = (File[]) list.toArray( new File[0] );
  +        PackageRepository repository = new DefaultPackageRepository( files );
  +        m_manager = new PackageManager( repository );
  +    }
  +
  +    private void initializeClasspath() throws Exception
  +    {
  +        addClasspath( m_classpath );
       }
   
       //===================================================================
  @@ -131,28 +209,143 @@
       //===================================================================
   
      /**
  -    * 
  +    * Add a URL to the classpath.
  +    * @param url the URL to add to the classpath
       */
       protected void addURL( URL url )
       {
  -        try
  +        super.addURL( url );
  +        String[] entries = getBlocksEntries( url );
  +        for( int j=0; j<entries.length; j++ )
           {
  -            super.addURL( url );
  -            getLogger().debug("scanning: " + url );    
  -            String[] entries = getBlocksEntries( url );
  -            for( int i=0; i<entries.length; i++ )
  +            getLogger().debug("located: " + entries[j] );
  +            String classname = entries[j].replace('/','.');
  +            try
               {
  -                getLogger().debug("component: " + entries[i] );
  -                m_blocks.add( entries[i] );
  +                m_types.register( classname );
  +            }
  +            catch( Throwable e )
  +            {
  +                final String warning = "Ignoring component: " + classname ;
  +                getLogger().warn( warning, e );
               }
           }
  -        catch( Throwable e )
  +    }
  +
  +    //===================================================================
  +    // TypeManager
  +    //===================================================================
  +
  +    //#######################################//
  +    // Need to change this to protected      //
  +    //#######################################//
  +
  +   /**
  +    * Add classes to the manager declared within a classpath structure.
  +    * @param classpath the classpath descriptor
  +    * @exception Exception if an exception occurs during class loading
  +    */
  +    public void addClasspath( ClasspathDescriptor classpath ) throws Exception
  +    {
  +
  +        getLogger().debug( "adding classpath" );
  +        ArrayList list = new ArrayList();
  +        File dir = new File( System.getProperty("user.dir") );
  +        FilesetDescriptor[] dirs = classpath.getFilesetDescriptors();
  +        for( int i=0; i<dirs.length; i++ )
  +        {
  +            FilesetDescriptor descriptor = dirs[i];
  +            File base = new File( dir, descriptor.getBaseDirectory() );
  +            IncludeDescriptor[] includes = descriptor.getIncludeDescriptors();
  +            for( int j=0; j<includes.length; j++ )
  +            {
  +                File include = new File( base, includes[j].getFile() );
  +                list.add( include.toURL() );
  +            }
  +        }
  +        URL[] urls = (URL[]) list.toArray( new URL[0] );
  +        for( int i = 0; i < urls.length; i++ )
  +        {
  +            getLogger().info("adding: " + urls[i] );    
  +            addURL( urls[i] );
  +        }
  +        String[] path = urlsToStrings( urls );
  +        final File[] extensions = getOptionalPackagesFor( path );
  +        for( int i = 0; i < extensions.length; i++ )
  +        {
  +            URL url = extensions[ i ].toURL();
  +            getLogger().info("extension: " + extensions[ i ].toURL() ); 
  +            addURL( url );
  +        }
  +        getLogger().debug( "classpath addition complete" );
  +
  +    }
  +
  +    private String[] urlsToStrings( URL[] urls )
  +    {
  +        Vector vector = new Vector();
  +        for( int i=0; i<urls.length; i++ )
           {
  -            throw new CascadingRuntimeException(
  -              "Unexpected error while attempting to add classloader URL: " + url, e );
  +            vector.add( urls[i].toString() );
           }
  +        return (String[]) vector.toArray( new String[ vector.size() ] );
       }
   
  +   /**
  +    * Resolve a {@link Type} from a classname.
  +    *
  +    * @param classname the component type
  +    * @return the component type
  +    */
  +    public Type lookup( String classname ) throws Exception
  +    {
  +        return m_types.lookup( classname );
  +    }
  +
  +   /**
  +    * Register a potential supplier component type.  The implementation will
  +    * create a component type instance for the entry if not already known and 
  +    * return the existing or new instance to the invoking client.
  +    *
  +    * @param classname the component class name
  +    * @return the component type
  +    */
  +    public Type register( String classname ) throws Exception
  +    {
  +        System.out.println("classname: " + classname );
  +        System.out.println("types: " + m_types);
  +
  +        return m_types.register( classname );
  +    }
  +
  +   /**
  +    * Returns the set of component types know to the registry.
  +    * @return the set of component types registered with the registry
  +    */
  +    public Type[] getTypes()
  +    {
  +        return m_types.getTypes( );
  +    }
  +
  +   /**
  +    * Returns the set of component types know to the registry that are capable of 
  +    * supporting the supplied service.
  +    * @return the set of candidate component types
  +    */
  +    public Type[] getTypes( ServiceDesignator service )
  +    {
  +        return m_types.getTypes( service );
  +    }
  +
  +   /**
  +    * Returns a registered component type.
  +    * @return the component type from the registry or null if the type is unknown
  +    */
  +    public Type getType( String classname )
  +    {
  +        return m_types.getType( classname );
  +    }
  +  
       //===================================================================
       // ClassLoader extensions
       //===================================================================
  @@ -184,10 +377,10 @@
        * Returns an array of <code>String</code>s corresponding to the set of classnames
        * where each classname is a declared block within the supplied jar file.
        * @param file a jar file
  -     * @exception RegistryRuntimeException if a general exception occurs
  +     * @exception KernelRuntimeException if a general exception occurs
        */
       private String[] getBlocksEntries( URL base )
  -        throws RegistryRuntimeException
  +        throws KernelRuntimeException
       {
           Vector vector = new Vector();
           try
  @@ -217,12 +410,12 @@
           catch( IOException e )
           {
               final String error = "IO exception while attempt to read block manifest.";
  -            throw new RegistryRuntimeException( error, e );
  +            throw new KernelRuntimeException( error, e );
           }
           catch( Throwable e )
           {
               final String error = "Unexpected exception while inspecting manifest on file: ";
  -            throw new RegistryRuntimeException( error + base, e );
  +            throw new KernelRuntimeException( error + base, e );
           }
           finally
           {
  
  
  
  1.10      +98 -44    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.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- DefaultKernel.java	9 Jul 2002 10:59:35 -0000	1.9
  +++ DefaultKernel.java	12 Jul 2002 12:04:54 -0000	1.10
  @@ -63,7 +63,14 @@
   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.merlin.model.KernelDescriptor;
  +import org.apache.excalibur.merlin.model.DirsetDescriptor;
  +import org.apache.excalibur.merlin.model.Profile;
  +import org.apache.excalibur.merlin.model.ContainerDescriptor;
  +import org.apache.excalibur.merlin.model.CategoryDescriptor;
  +import org.apache.excalibur.merlin.model.builder.TypeManager;
  +import org.apache.excalibur.merlin.container.DefaultContainer;
  +import org.apache.excalibur.merlin.Kernel;
   
   /**
    * Default kernel implementation.
  @@ -72,32 +79,46 @@
    * @version $Revision$ $Date$
    */
   public class DefaultKernel extends AbstractLogEnabled 
  -  implements Kernel, Configurable, Initializable
  +  implements Kernel, Contextualizable, Initializable
   {
  +    //=======================================================================
  +    // static
  +    //=======================================================================
  +
  +    public static final String ROOT_CONTAINER_DESCRIPTOR_KEY = "descriptor";
  +    public static final String CLASSLOADER_KEY = "classloader";
  +    public static final String LOG_MANAGER_KEY = "logmanager";
   
       //=======================================================================
       // state
       //=======================================================================
   
  -    private Configuration m_config;
  -
  -    private DefaultContainer m_container = new DefaultContainer();
  +    private DefaultContainer m_container;
   
       private boolean m_verified = false;
   
  -    private LoggerManager m_manager;
  +    private DefaultLoggerManager m_logging;
  +
  +    private ContainerDescriptor m_descriptor;
  +
  +    private boolean m_initialized = false;
  +
  +    private ClassLoader m_classloader;
   
       //=======================================================================
  -    // Configurable
  +    // Contextualizable
       //=======================================================================
   
      /**
  -    * Invoked by the container to establish the registry configuration.
  -    * @param config a component configuration
  +    * Invoked by the bootstrap process to supply to kernel defintion.
  +    * @param context the context object containing the inital parameters
  +    * @exception ContextException if the supplied does not contain a DESCRIPTOR_KEY value 
       */
  -    public void configure( Configuration config)
  +    public void contextualize( Context context ) throws ContextException
       {
  -        m_config = config;
  +        m_descriptor = (ContainerDescriptor) context.get( ROOT_CONTAINER_DESCRIPTOR_KEY );
  +        m_classloader = (ClassLoader) context.get( CLASSLOADER_KEY );
  +        m_logging = (DefaultLoggerManager) context.get( LOG_MANAGER_KEY );
       }
   
       //=======================================================================
  @@ -106,28 +127,70 @@
   
       public void initialize() throws Exception
       {
  -        m_manager = createLoggingManager();
  -        Logger logger = m_manager.getLoggerForCategory("kernel") ;
  -        enableLogging( logger );
  -
  -        final ContainerClassLoader loader = new ContainerClassLoader(
  -          new DefaultPackageRepository( 
  -            Fileset.expandExtensions( 
  -              m_config.getChild( "extensions" ) 
  -            ) 
  -          ),
  -          Thread.currentThread().getContextClassLoader(), 
  -          m_config.getChild("container").getChild("classpath"),
  -          getLogger().getChildLogger( "loader" )
  -        );
  +        getLogger().debug( "initialize" );
   
  +        //
  +        // root container criteria
  +        //
  +
  +        CategoryDescriptor loggers = m_descriptor.getCategoryDescriptor();
  +        m_logging.addCategories( loggers );
  +        
  +        //
  +        // classloader setup
  +        //
  +
  +        getLogger().debug( "root container classloader creation" );
  +        final ContainerClassLoader loader = new ContainerClassLoader( m_classloader );
           try
           {
  -            DefaultContext context = new DefaultContext();
  -            context.put( DefaultContainer.CLASSLOADER_KEY, loader );
  -            m_container.enableLogging( getLogger().getChildLogger("container") );
  +            loader.enableLogging( getLogger().getChildLogger( "loader" ) );
  +            DefaultContext loaderContext = new DefaultContext();
  +            loaderContext.put( 
  +              ContainerClassLoader.CLASSPATH_DESCRIPTOR_KEY, 
  +              m_descriptor.getClasspathDescriptor() );
  +            loaderContext.makeReadOnly();
  +            loader.contextualize( loaderContext );
  +            loader.initialize();
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = "Error during root container classloader creation.";
  +            if( getLogger() != null )
  +              getLogger().error( error, e );
  +            throw new KernelException( error, e );
  +        }
  +
  +        //
  +        // provider setup
  +        //
  +
  +        DefaultProvider provider = new DefaultProvider( loader, m_logging );
  +        provider.enableLogging( getLogger().getChildLogger( "provider" ) );
  +
  +        //
  +        // container context creation
  +        //
  +
  +        getLogger().debug( "root container context creation" );
  +        DefaultContext context = new DefaultContext();
  +        context.put( DefaultContainer.CLASSLOADER_KEY, loader );
  +        context.put( DefaultContainer.LOG_MANAGER_KEY, m_logging );
  +        context.put( DefaultContainer.CONTAINER_DESCRIPTOR_KEY, m_descriptor );
  +        context.put( DefaultContainer.MAP_KEY, new DependencyGraph() );
  +        context.put( DefaultContainer.PROVIDER_KEY, provider );
  +        context.makeReadOnly();
  +
  +        //
  +        // container instantiation
  +        //
  +
  +        getLogger().debug( "root container instantiation" );
  +        try
  +        {
  +            m_container = new DefaultContainer();
  +            m_container.enableLogging( m_logging.getLoggerForCategory( m_descriptor.getName() ) );
               m_container.contextualize( context );
  -            m_container.configure( m_config.getChild("container" ) );
               m_container.initialize( );
               m_container.verify();
           }
  @@ -138,6 +201,9 @@
                 getLogger().error( error, e );
               throw new KernelException( error, e );
           }
  +
  +        m_initialized = true;
  +
       }
   
       //=======================================================================
  @@ -146,6 +212,7 @@
   
       public void startup() throws Exception
       {
  +        if( !m_initialized ) return;
           //listProfiles();
           if( getLogger().isInfoEnabled() )
             getLogger().info("startup");
  @@ -164,22 +231,9 @@
   
       public void shutdown()
       {
  +        if( !m_initialized ) return;
           if( getLogger().isInfoEnabled() )
             getLogger().info("shutdown");
           m_container.shutdown();
  -    }
  -
  -    //=======================================================================
  -    // internals
  -    //=======================================================================
  -
  -    private LoggerManager createLoggingManager() throws Exception
  -    {
  -        final File home = new File( System.getProperty( "user.dir" ) );
  -        final Configuration config = m_config.getChild( "logging" );
  -        final DefaultLoggerManager manager = new DefaultLoggerManager( 
  -           home, config );
  -        manager.initialize( );
  -        return manager;
       }
   }
  
  
  
  1.4       +7 -1      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.xinfo
  
  Index: DefaultKernel.xinfo
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.xinfo,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DefaultKernel.xinfo	4 Jul 2002 09:01:35 -0000	1.3
  +++ DefaultKernel.xinfo	12 Jul 2002 12:04:54 -0000	1.4
  @@ -17,9 +17,15 @@
       <version>1.0</version>
     </component>
   
  +  <context>
  +    <entry key="classloader" type="org.apache.excalibur.merlin.kernel.ContainerClassLoader" optional="false"/>
  +    <entry key="logging" type="org.apache.excalibur.merlin.kernel.DefaultLoggerManager" optional="false"/>
  +    <entry key="descriptor" type="org.apache.excalibur.merlin.model.KernelDescriptor" optional="false"/>
  +  </context>
  +
     <services>
       <service>
  -      <service-ref type="org.apache.excalibur.merlin.kernel.Kernel" version="1.0"/>
  +      <service-ref type="org.apache.excalibur.merlin.Kernel" version="1.0"/>
       </service>
     </services>
   
  
  
  
  1.2       +149 -141  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultLoggerManager.java
  
  Index: DefaultLoggerManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultLoggerManager.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultLoggerManager.java	9 Jul 2002 10:59:35 -0000	1.1
  +++ DefaultLoggerManager.java	12 Jul 2002 12:04:54 -0000	1.2
  @@ -13,7 +13,6 @@
   import org.apache.avalon.excalibur.i18n.ResourceManager;
   import org.apache.avalon.excalibur.i18n.Resources;
   import org.apache.avalon.excalibur.logger.LoggerManager;
  -import org.apache.avalon.framework.activity.Initializable;
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
  @@ -29,6 +28,11 @@
   import org.apache.log.Priority;
   import org.apache.log.output.io.FileTarget;
   import org.apache.log.output.io.StreamTarget;
  +import org.apache.excalibur.merlin.model.CategoryDescriptor;
  +import org.apache.excalibur.merlin.model.TargetDescriptor;
  +import org.apache.excalibur.merlin.model.LoggingDescriptor;
  +import org.apache.excalibur.merlin.model.TargetProvider;
  +import org.apache.excalibur.merlin.model.FileTargetProvider;
   
   /**
    * A <code>LoggerManager</code> that supports a verifiable logging hierarchy creation directive.
  @@ -37,9 +41,12 @@
    * @author <a href="mailto:colus@isoft.co.kr">Eung-ju Park</a>
    * @author <a href="mailto:peter@apache.org">Peter Donald</a>
    */
  -class DefaultLoggerManager
  -    implements LoggerManager, Initializable
  +public class DefaultLoggerManager
  +    implements LoggerManager
   {
  +
  +    public static final String DEFAULT_PRIORITY = "INFO";
  +
       public static final String HOME_KEY = "app.home";
   
       private static final Resources REZ =
  @@ -56,7 +63,7 @@
      /**
       * log hierarchy.
       */
  -    private Hierarchy m_logHierarchy = new Hierarchy();
  +    private Hierarchy m_logHierarchy;
   
      /**
       * default logger
  @@ -71,12 +78,13 @@
      /**
       * the default priority if undefined
       */
  -    private String m_defaultPriority = "INFO";
  +    private String m_priority = "INFO";
   
  -   /**
  -    * the supplied configuration
  -    */
  -    private Configuration m_config;
  +    private final HashMap m_targets = new HashMap();
  +
  +    private DefaultLoggerManager m_parent;
  +
  +    private String m_category;
   
       //===============================================================
       // constructor
  @@ -84,132 +92,120 @@
   
      /**
       * Creation of a new LoggerManager.
  -    * @param base the base directory against which file targets are 
  -    *   logicaly created
  -    * @param config the logging configuration
  +    * @param descriptor the logging system description
  +    * @exception Exception is an error occurs
       */
  -    public DefaultLoggerManager( File base, Configuration config )
  +    public DefaultLoggerManager( final LoggingDescriptor descriptor ) throws Exception
       {
  -        m_baseDirectory = base;
  -        m_config = config;
  -    }
   
  -    //===============================================================
  -    // Initializable
  -    //===============================================================
  +        //
  +        // setup the hierarchy, default logging target, and default priority
  +        //
   
  -   /**
  -    * Initialization of the logging manager.
  -    * @exception Exception if an error furing the initialization process occurs
  -    */
  -    public void initialize( ) throws Exception
  -    {
  -        m_defaultPriority = m_config.getAttribute("priority", "INFO" );
  -        Priority priority = Priority.getPriorityForName( 
  -            m_defaultPriority
  -        );
           m_stream = new StreamTarget( System.out, new AvalonFormatter( DEFAULT_FORMAT ) );
  +        m_baseDirectory = new File( System.getProperty("user.dir") );
  +        m_logHierarchy = new Hierarchy();
           getHierarchy().setDefaultLogTarget( m_stream );
  -        getHierarchy().setDefaultPriority( priority );
  +        m_targets.put( descriptor.getTarget(), m_stream );
  +        getHierarchy().setDefaultPriority( 
  +          Priority.getPriorityForName( descriptor.getPriority() ) );
   
  -        final Configuration[] targets = m_config.getChildren( "target" );
  -        final HashMap targetSet = configureTargets( targets );
  -        final Configuration[] categories = m_config.getChildren( "category" );
  -        configureCategories( categories, targetSet );
  -    }
  +        TargetDescriptor[] targets = descriptor.getTargetDescriptors();
  +        for( int i=0; i<targets.length; i++ )
  +        {
  +            addTarget( targets[i] );
  +        }
   
  -    //===============================================================
  -    // LoggerManager
  -    //===============================================================
  +        addCategories( descriptor.getCategoryDescriptor() );
  +    }
   
  -    /**
  -     * Return the Logger for the specified category.
  -     */
  -    public org.apache.avalon.framework.logger.Logger getLoggerForCategory( final String category )
  +    public void addCategories( CategoryDescriptor descriptor )
       {
  -        return new LogKitLogger( getHierarchy().getLoggerFor( category ) );
  +        addSingleCategory( descriptor );
  +        CategoryDescriptor[] categories = descriptor.getCategories();
  +        for( int i=0; i<categories.length; i++ )
  +        {
  +            addCategories( categories[i] );
  +        }
       }
   
  -    /**
  -     * Return the default Logger.  This is the same
  -     * as getting the Logger for the "" category.
  -     */
  -    public org.apache.avalon.framework.logger.Logger getDefaultLogger( )
  +    private Logger addSingleCategory( CategoryDescriptor descriptor )
       {
  -        if( m_logger == null )
  -          m_logger = getLoggerForCategory("");
  -        return m_logger;
  -    }
  +        final String name = descriptor.getPath();
  +        final String priority = descriptor.getPriority();
  +        final String target = descriptor.getTarget();
  +        final String path = descriptor.getPath();
   
  -    //===============================================================
  -    // internals
  -    //===============================================================
  +        final Priority priorityValue = Priority.getPriorityForName( priority );
  +        if( !priorityValue.getName().equals( priority ) )
  +        {
  +            final String message = REZ.getString( "unknown-priority", priority, name );
  +            throw new IllegalArgumentException( message );
  +        }
   
  -    private Hierarchy getHierarchy()
  +        String category = name;
  +        if( category == null )
  +          category = "";
  +
  +        final Logger logger = getHierarchy().getLoggerFor( category );
  +
  +        logger.setPriority( priorityValue );
  +        final LogTarget logTarget = (LogTarget) m_targets.get( descriptor.getTarget() );
  +        if( logTarget != null )
  +          logger.setLogTargets( new LogTarget[]{logTarget} );
  +
  +        if( getDefaultLogger().isDebugEnabled() )
  +        {
  +            final String message =
  +                REZ.getString( "category-create", category, target, priorityValue.getName() );
  +            getDefaultLogger().debug( message );
  +        }
  +        return logger;
  +    }
  +
  +    private void addTarget( TargetDescriptor target ) throws Exception
       {
  -        return m_logHierarchy;
  +         File base = new File( System.getProperty("user.dir") );
  +         final String name = target.getName();
  +         TargetProvider provider = target.getProvider();
  +         if( provider instanceof FileTargetProvider )
  +         {
  +             FileTargetProvider fileProvider = (FileTargetProvider) provider;
  +             String filename = fileProvider.getLocation();
  +             final AvalonFormatter formatter = new AvalonFormatter( DEFAULT_FORMAT );
  +             try
  +             {
  +                 File file = new File( base, filename );
  +                 FileTarget logTarget = new FileTarget( file.getAbsoluteFile(), false, formatter );
  +                 m_targets.put( name, logTarget );
  +             }
  +             catch( final IOException ioe )
  +             {
  +                 final String message =
  +                     REZ.getString( "target.nocreate", name, filename, ioe.getMessage() );
  +                 throw new KernelException( message, ioe );
  +             }
  +         }
  +         else
  +         {
  +            final String error = 
  +              "Unrecognized logging provider: " + provider.getClass().getName();
  +              throw new IllegalArgumentException( error );
  +         }
       }
   
       /**
  -     * Configure a set of logtargets based on config data.
  +     * Configure Logging categories.
        *
  -     * @param targets the target configuration data
  -     * @return a Map of target-name to target
  +     * @param categories configuration data for categories
  +     * @param targets a hashmap containing the already existing taregt
        * @throws ConfigurationException if an error occurs
        */
  -    private HashMap configureTargets( final Configuration[] targets )
  -        throws ConfigurationException
  +    public org.apache.avalon.framework.logger.Logger getLoggerForCategory( 
  +      final String name, String target, String priority )
  +        throws Exception
       {
  -
  -        final HashMap targetSet = new HashMap();
  -
  -        //  
  -        // Create the default target.
  -        //
  -
  -        targetSet.put( "default", m_stream );
  -
  -        for( int i = 0; i < targets.length; i++ )
  -        {
  -            final Configuration target = targets[ i ];
  -            final String name = target.getAttribute( "name" );
  -            final Configuration fileDef = target.getChild( "file", false );
  -            if( fileDef != null )
  -            {
  -                String location = fileDef.getAttribute( "location" ).trim();
  -                final String format = fileDef.getAttribute( "format", DEFAULT_FORMAT );
  -                if( '/' == location.charAt( 0 ) )
  -                    location = location.substring( 1 );
  -
  -                final AvalonFormatter formatter = new AvalonFormatter( format );
  -
  -                //Specify output location for logging
  -                final File file = new File( m_baseDirectory, location );
  -
  -                //Setup logtarget
  -                FileTarget logTarget = null;
  -                try
  -                {
  -                    logTarget = new FileTarget( file.getAbsoluteFile(), false, formatter );
  -                }
  -                catch( final IOException ioe )
  -                {
  -                    final String message =
  -                        REZ.getString( "target.nocreate", name, file, ioe.getMessage() );
  -                    throw new ConfigurationException( message, ioe );
  -                }
  -
  -                targetSet.put( name, logTarget );
  -            }
  -            else
  -            {
  -                final String error = 
  -                  "Unrecognized elements declaration in the logging target named: " + name;
  -                throw new IllegalArgumentException( error );
  -            }
  -        }
  -
  -        return targetSet;
  +        return new LogKitLogger( addSingleCategory( new CategoryDescriptor( name, target, priority ) ) );
       }
   
       /**
  @@ -219,38 +215,50 @@
        * @param targets a hashmap containing the already existing taregt
        * @throws ConfigurationException if an error occurs
        */
  -    private void configureCategories( final Configuration[] categories, final HashMap targets )
  -        throws ConfigurationException
  +    public org.apache.avalon.framework.logger.Logger getLoggerForCategory( 
  +      final CategoryDescriptor category )
  +        throws Exception
       {
  -        for( int i = 0; i < categories.length; i++ )
  +        return new LogKitLogger( addSingleCategory( category ) );
  +    }
  +
  +    //===============================================================
  +    // LoggerManager
  +    //===============================================================
  +
  +    /**
  +     * Return the Logger for the specified category.
  +     */
  +    public org.apache.avalon.framework.logger.Logger getLoggerForCategory( final String category )
  +    {
  +        if( category == null )
  +        {
  +            return new LogKitLogger( getHierarchy().getLoggerFor( "" ) );
  +        }
  +        else
           {
  -            final Configuration category = categories[ i ];
  -            final String name = category.getAttribute( "name", "" );
  -            final String target = category.getAttribute( "target" , "default" );
  -            final String priorityName = category.getAttribute( "priority", m_defaultPriority );
  -
  -            final Logger logger = getHierarchy().getLoggerFor( name );
  -
  -            final LogTarget logTarget = (LogTarget)targets.get( target );
  -
  -            final Priority priority = Priority.getPriorityForName( priorityName );
  -            if( !priority.getName().equals( priorityName ) )
  -            {
  -                final String message = REZ.getString( "unknown-priority", priorityName, name );
  -                throw new ConfigurationException( message );
  -            }
  -
  -            logger.setPriority( priority );
  -            if( logTarget != null )
  -              logger.setLogTargets( new LogTarget[]{logTarget} );
  -
  -            if( getDefaultLogger().isDebugEnabled() )
  -            {
  -                final String message =
  -                    REZ.getString( "category-create", name, target, priorityName );
  -                getDefaultLogger().debug( message );
  -            }
  +            return new LogKitLogger( getHierarchy().getLoggerFor( category ) );
           }
  +    }
  +
  +    /**
  +     * Return the default Logger.  This is the same
  +     * as getting the Logger for the "" category.
  +     */
  +    public org.apache.avalon.framework.logger.Logger getDefaultLogger( )
  +    {
  +        if( m_logger == null )
  +          m_logger = getLoggerForCategory("kernel.logging");
  +        return m_logger;
  +    }
  +
  +    private Hierarchy getHierarchy()
  +    {
  +        if( m_parent != null )
  +        {
  +            return m_parent.getHierarchy();
  +        }
  +        return m_logHierarchy;
       }
   
   }
  
  
  
  1.2       +26 -16    jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultProvider.java
  
  Index: DefaultProvider.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultProvider.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultProvider.java	8 Jul 2002 09:57:36 -0000	1.1
  +++ DefaultProvider.java	12 Jul 2002 12:04:54 -0000	1.2
  @@ -63,16 +63,16 @@
   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.verifier.VerifyException;
   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.excalibur.merlin.model.Profile;
  +import org.apache.excalibur.merlin.model.Association;
  +import org.apache.excalibur.merlin.model.CategoryDescriptor;
  +import org.apache.excalibur.merlin.ResourceProvider;
   import org.apache.log.Hierarchy;
   import org.apache.log.Priority;
   import org.apache.log.output.io.StreamTarget;
  @@ -99,9 +99,9 @@
       //=======================================================================
   
      /**
  -    * The container that this provider is assigned to.
  +    * The classloader to use when servicing object creation requests.
       */
  -    private final ClassLoader m_classloader;
  +    private ClassLoader m_classloader;
   
      /**
       * The parent provider.
  @@ -113,19 +113,25 @@
       */
       private final Hashtable m_singletons = new Hashtable();
   
  +   /**
  +    * The log manager.
  +    */
  +    private DefaultLoggerManager m_logging;
  +
       //=======================================================================
       // constructor
       //=======================================================================
   
  -    DefaultProvider( ClassLoader loader )
  +    public DefaultProvider( ClassLoader loader, DefaultLoggerManager manager )
       {
  -        this( null, loader );
  +        this( null, loader, manager );
       }
   
  -    DefaultProvider( DefaultProvider parent, ClassLoader loader )
  +    public DefaultProvider( DefaultProvider parent, ClassLoader loader, DefaultLoggerManager manager )
       {
           m_parent = parent;
           m_classloader = loader;
  +        m_logging = manager;
       }
   
       //=======================================================================
  @@ -157,7 +163,7 @@
                   final String error = 
                     "Unexpected exception while attempting to load class '" 
                     + classname + "' for the profile: " + profile;
  -                throw new ContainerException( error, e );
  +                throw new KernelException( error, e );
               }
   
               try
  @@ -168,8 +174,9 @@
               catch( Throwable e )
               {
                   final String error = 
  -                  "Unexpected exception while attempting to instantiate an instance from profile: " + profile;
  -                throw new ContainerException( error, e );
  +                  "Unexpected exception while attempting to instantiate an instance from profile: " 
  +                    + profile;
  +                throw new KernelException( error, e );
               }
           }
           return object;
  @@ -185,7 +192,10 @@
       public Logger createLogger( Profile profile )
           throws Exception
       {
  -        return getLogger().getChildLogger( profile.getName() );
  +        final String name = profile.getName();
  +        CategoryDescriptor loggers = profile.getCategoryDescriptor();
  +        m_logging.addCategories( loggers );
  +        return m_logging.getLoggerForCategory( loggers );
       }
   
       /**
  @@ -363,7 +373,7 @@
           final String error = 
             "Unable to locate an instantiated service instance implementing the interface: "
             + service + ", from the provider: " + provider;
  -        throw new ContainerException( error );
  +        throw new KernelException( error );
       }
   
       private Object lookupInstance( Profile provider )
  
  
  
  1.2       +3 -8      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DependencyGraph.java
  
  Index: DependencyGraph.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DependencyGraph.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DependencyGraph.java	8 Jul 2002 09:57:36 -0000	1.1
  +++ DependencyGraph.java	12 Jul 2002 12:04:54 -0000	1.2
  @@ -8,8 +8,8 @@
   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.merlin.model.Profile;
  +import org.apache.excalibur.merlin.model.Association;
   import org.apache.excalibur.meta.info.DependencyDescriptor;
   
   /**
  @@ -30,11 +30,6 @@
        * 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.,
  
  
  
  1.2       +3 -4      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/TypeRegistry.java
  
  Index: TypeRegistry.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/TypeRegistry.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TypeRegistry.java	12 Jul 2002 10:22:05 -0000	1.1
  +++ TypeRegistry.java	12 Jul 2002 12:04:54 -0000	1.2
  @@ -22,8 +22,7 @@
   import org.apache.excalibur.meta.info.DependencyDescriptor;
   import org.apache.excalibur.meta.info.Type;
   import org.apache.excalibur.meta.info.builder.TypeBuilder;
  -import org.apache.excalibur.merlin.meta.data.Profile;
  -import org.apache.excalibur.merlin.meta.data.Selector;
  +import org.apache.excalibur.merlin.model.Profile;
   import org.apache.excalibur.meta.verifier.ComponentVerifier;
   import org.apache.excalibur.configuration.ConfigurationUtil;
   
  @@ -34,7 +33,7 @@
    * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
    * @version $Revision$ $Date$
    */
  -public final class TypeRegistry extends AbstractLogEnabled 
  +final class TypeRegistry extends AbstractLogEnabled 
   {
   
       //=======================================================================
  
  
  
  1.7       +2 -2      jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/package.html
  
  Index: package.html
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/package.html,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- package.html	7 Jul 2002 23:18:34 -0000	1.6
  +++ package.html	12 Jul 2002 12:04:54 -0000	1.7
  @@ -1,7 +1,7 @@
   
   <body>
   <p>
  -The kernel package defines a top level {@link org.apache.excalibur.merlin.kernel.Kernel} that serves as a host to a root {@link org.apache.excalibur.merlin.kernel.Container} that provides support for container hierachy creation. The default kernel implementation handles the setup of the logging infrastructure, extension manager, and the root container.
  +The kernel package defines a top level {@link org.apache.excalibur.merlin.Kernel} that serves as a host to a root {@link org.apache.excalibur.merlin.Container} that provides support for container hierachy creation. The default kernel implementation handles the setup of the logging infrastructure, extension manager, and the root container.
   
   </p>
   <h3>Funtional Summary</h3>
  @@ -22,7 +22,7 @@
   </ul>
   
   <h3>Object Model (UML)</h3>
  -<p>An {@link org.apache.excalibur.merlin.kernel.Container} is primarily a component type manager. Actual type management is handled by an supertype {@link org.apache.excalibur.merlin.registry.Registry}.  In addition to component type support, the container provides a framework from the creation of container hierachies.  Services established in a parent container are available as potential candidate suppliers to component providers in sibling containers.</p>
  +<p>An {@link org.apache.excalibur.merlin.Container} is primarily a component type manager. Actual type management is handled by an supertype {@link org.apache.excalibur.merlin.container.Registry}.  In addition to component type support, the container provides a framework from the creation of container hierachies.  Services established in a parent container are available as potential candidate suppliers to component providers in sibling containers.</p>
   <p><img src=doc-files/UML.gif border=0></p>
   </body>
   
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/AbstractContainer.java
  
  Index: AbstractContainer.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.model;
  
  /**
   * Interface implemeted by objects capable of acting as a container.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public interface AbstractContainer
  {
  
      /**
       * Return the container name.
       *
       * @return the name of the container
       */
      String getName();
  
      /**
       * Return the logging descriptor.
       *
       * @return the {@link CategoryDescriptor} for the component loggers.
       */
      CategoryDescriptor getCategoryDescriptor();
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/Association.java
  
  Index: Association.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.model;
  
  
  
  /**
   * The Association is the mapping of a component as a dependency
   * of another component. Each component declares dependencies (via Type)
   * and for each dependency there must be a coressponding Association which
   * has a matching role. The name value in Association object must refer
   * to another Component that implements a service as specified in DependencyInfo.
   *
   * <p>Note that it is invalid to have circular dependencies.</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/12 12:04:55 $
   */
  public final class Association
  {
      /**
       * The name that the client component will use to access a dependency.
       */
      private final String m_role;
  
      /**
       * the name of the component metadata instance that represents a component
       * type that is capable of fullfilling the dependency.
       */
      private final Profile m_provider;
  
      /**
       * Create Profile with specified name and role.
       *
       * @param role the name client uses to access component
       * @param providerName the name of <code>ComponentProfile</code> instance
       *   that is associated as a service provider
       */
      public Association( final String role,
                                 final Profile provider )
      {
          m_role = role;
          m_provider = provider;
      }
  
      /**
       * Return the name that will be used by a component instance to access a
       * dependent service.
       *
       * @return the name that the client component will use to access dependency.
       * @see org.apache.avalon.framework.service.ServiceManager#lookup( String )
       */
      public String getRole()
      {
          return m_role;
      }
  
      /**
       * Return the name of a <code>ComponentProfile</code> instance that will used to
       * fulfill the dependency.
       *
       * @return the name of the Component that will provide the dependency.
       */
      public Profile getProvider()
      {
          return m_provider;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/CategoryDescriptor.java
  
  Index: CategoryDescriptor.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.model;
  
  import java.util.Hashtable;
  
  /**
   * A logging category descriptor hierachy.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class CategoryDescriptor 
  {
  
       public static final String DEBUG = "DEBUG";
       public static final String INFO = "INFO";
       public static final String WARN = "WARN";
       public static final String ERROR = "ERROR";
  
       public static final String DEFAULT_LOGGING_TARGET = "default";
       public static final String DEFAULT_LOGGING_PRIORITY = INFO;
  
      /**
       * The logging category name.
       */
      private String m_name;
  
      /**
       * The default logging priority.
       */
      private final String m_priority;
  
      /**
       * The default logging target.
       */
      private final String m_target;
  
      /**
       * The loggers descriptor parent.
       */
      protected CategoryDescriptor m_parent;
  
      /**
       * Subsidiary categories.
       */
      private final Hashtable m_categories = new Hashtable();
  
  
      /**
       */
      public CategoryDescriptor( CategoryDescriptor parent, final String name )
      {
          this( parent, name, null, null, new CategoryDescriptor[0] );
      }
  
      /**
       */
      public CategoryDescriptor( final String name, final String priority, final String target )
      {
          this( null, name, priority, target, new CategoryDescriptor[0] );
      }
  
      /**
       */
      public CategoryDescriptor( 
        final String name, final String priority, final String target,
          final CategoryDescriptor[] categories  )
      {
          this( null, name, priority, target, categories  );
      }
  
      /**
       */
      public CategoryDescriptor( 
        CategoryDescriptor parent, final String name, final String priority, final String target,
          final CategoryDescriptor[] categories  )
      {
          m_name = name;
          m_target = target;
          m_priority = priority;
          m_parent = parent;
          for( int i=0; i<categories.length; i++ )
          {
              CategoryDescriptor category = categories[i];
              m_categories.put( category.getName(), category );
              category.setParent( this );
          }
  
      }
  
      /**
       * Return the category name.
       *
       * @return the category name
       */
      public String getName()
      {
          return m_name;
      }
  
      /**
       * Return the default logging priority for the group of categories.
       *
       * @return the default logging priority
       */
      public String getPriority( )
      {
          if( m_priority == null )
          {
              if( m_parent != null )
              {
                  return m_parent.getPriority();
              }
              else
              {
                  return DEFAULT_LOGGING_PRIORITY;
              }
          }
          return m_priority;
      }
  
      /**
       * Return the default log target for the group of categories.
       *
       * @return the default target name
       */
      public String getTarget( )
      {
          if( m_target == null )
          {
              if( m_parent != null )
              {
                  return m_parent.getTarget();
              }
              else
              {
                  return DEFAULT_LOGGING_TARGET;
              }
          }
          return m_target;
      }
  
      public void setParent( CategoryDescriptor parent )
      {
          m_parent = parent;
      }
  
      /**
       * Return the category path.
       *
       * @return the category path
       */
      public String getPath()
      {
          if( m_parent != null )
          {
              String path = m_parent.getPath();
              if( path.equals("") )
              {
                  return getName();
              }
              else
              {
                  return path + "." + getName();
              }
          }
          else
          {
              return getName();
          }
      }
  
      /**
       * Return the set of logging categories.
       *
       * @return the set of service provider assignments.
       */
      public CategoryDescriptor[] getCategories()
      {
          return (CategoryDescriptor[]) m_categories.values().toArray( new CategoryDescriptor[0] );
      }
  
      /**
       * Return a named category.
       * @param name the category name
       * @return the named category of null if unknown
       */
      public CategoryDescriptor getCategory( String name )
      {
          CategoryDescriptor category = (CategoryDescriptor) m_categories.get( name );
          if( category == null )
          {
              category = new CategoryDescriptor( this, name );
              m_categories.put( name, category );
          }
          return category;
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/ClasspathDescriptor.java
  
  Index: ClasspathDescriptor.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.model;
  
  /**
   * A classpath descriptor.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class ClasspathDescriptor 
  {
      /**
       * The base directory
       */
      private final FilesetDescriptor[] m_filesets;
  
  
      /**
       * Create a ClasspathDescriptor instance.
       *
       * @param filesets the set of filesets to include in the classpath
       */
      public ClasspathDescriptor( final FilesetDescriptor[] filesets )
      {
          m_filesets = filesets;
      }
  
      /**
       * Return the filesets held within the classpath descriptor.
       *
       * @return the filesets
       */
      public FilesetDescriptor[] getFilesetDescriptors()
      {
          return m_filesets;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/ComponentDescriptor.java
  
  Index: ComponentDescriptor.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.model;
  
  import java.io.Serializable;
  import java.util.Hashtable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.context.Context;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.Association;
  import org.apache.excalibur.configuration.ConfigurationUtil;
  
  /**
   * A component profile description.
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class ComponentDescriptor extends DefaultProfile 
  {
  
      /**
       * Create a Profile instance.
       *
       * @param name the abstract name of component meta data instance
       * @param dependencies the meta data for any dependencies
       * @param type the component type
       */
      public ComponentDescriptor( final String name,
                             final Parameters parameters,
                             final Configuration configuration,
                             final Context context,
                             final CategoryDescriptor loggers,
                             final Type type,
                             final int mode )
      {
          super( name, parameters, configuration, context, loggers, type, mode );
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/ContainerDescriptor.java
  
  Index: ContainerDescriptor.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.model;
  
  import java.util.ArrayList;
  
  /**
   * A container profile.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class ContainerDescriptor implements AbstractContainer
  {
      /**
       * The parent.
       */
      private AbstractContainer m_parent;
  
      /**
       * The container name.
       */
      private final String m_name;
  
      /**
       * The loggers defintion.
       */
      private final CategoryDescriptor m_loggers;
  
      /**
       * The container classpath descriptor.
       */
      private final ClasspathDescriptor m_classpath;
  
      /**
       * The component described within the scope of the container.
       */
      //private final ArrayList m_components = new ArrayList();
      private final ComponentDescriptor[] m_components;
  
      /**
       * The component described within the scope of the container.
       */
      private final ContainerDescriptor[] m_containers;
  
      /**
       * Create a ContainerDescriptor instance.
       *
       */
      public ContainerDescriptor( final String name,
                             final CategoryDescriptor loggers,
                             final ClasspathDescriptor classpath,
                             final ComponentDescriptor[] components,
                             final ContainerDescriptor[] containers )
      {
          if( name == null ) 
            throw new NullPointerException("name");
          if( loggers == null ) 
            throw new NullPointerException("loggers");
          if( classpath == null ) 
            throw new NullPointerException("classpath");
  
          m_name = name;
          m_loggers = loggers;
          m_classpath = classpath;
          m_components = components;
          m_containers = containers;
  
          for( int i=0; i<containers.length; i++ )
          {
              containers[i].getCategoryDescriptor().setParent( loggers );
          }
          for( int i=0; i<components.length; i++ )
          {
              components[i].getCategoryDescriptor().setParent( loggers );
          }
      }
  
      /**
       * Return the container name.
       *
       * @return the name of the container
       */
      public String getName()
      {
          return m_name;
      }
  
      /**
       * Return the logging descriptor.
       *
       * @return the {@link CategoryDescriptor} for the component loggers.
       */
      public CategoryDescriptor getCategoryDescriptor()
      {
          return m_loggers;
      }
  
      /**
       * Return the classpath descriptor.
       *
       * @return the {@link ClasspathDescriptor} for the container.
       */
      public ClasspathDescriptor getClasspathDescriptor()
      {
          return m_classpath;
      }
  
      /**
       * Add a container to this container.
       *
       * @parent the container to add
       */
      //public void addComponent( ComponentDescriptor component )
      //{
      //    m_components.add( component );
      //    component.getCategoryDescriptor().setParent( getCategoryDescriptor() );
      //}
  
      /**
       * Return the set of component descriptors contained within this container.
       *
       * @return the target descriptors
       */
      public ComponentDescriptor[] getComponentDescriptors()
      {
          //return (ComponentDescriptor[]) m_components.toArray( new ComponentDescriptor[0] );
          return m_components;
      }
  
      /**
       * Return the set of subsidiary containers contained within this container.
       *
       * @return the target descriptors
       */
      public ContainerDescriptor[] getContainers()
      {
          return m_containers;
      }
  
  
      /**
       * Set the parent container.
       *
       * @param the container containing this container.
       * @exception IllegalStateException if the parent is already set
       */
      public void setParent( AbstractContainer parent ) throws IllegalStateException
      {
         if( m_parent != null )
           throw new IllegalStateException("parent");
  
         m_parent = parent;
  
         ContainerDescriptor[] containers = getContainers();
         for( int i=0; i<containers.length; i++ )
         {
            containers[i].setParent( this );
         }
      }
  
      /**
       * Return the parent container.
       *
       * @return the container containing this container.
       */
      public AbstractContainer getParent()
      {
          return m_parent;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/DefaultProfile.java
  
  Index: DefaultProfile.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.model;
  
  import java.io.Serializable;
  import java.util.Hashtable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.context.Context;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.Association;
  import org.apache.excalibur.configuration.ConfigurationUtil;
  
  /**
   * Abstract defintion of a compoent 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/12 12:04:55 $
   */
  public class DefaultProfile 
    implements Profile, Serializable
  {
      /**
       * The name of the component metadata instance. This is an
       * abstract name used during assembly.
       */
      private final String m_name;
  
      /**
       * The dependencies keyed by role name.
       */
      private final Hashtable m_dependencies = new Hashtable();
  
      /**
       * The info object for component type.
       */
      private final Type m_type;
  
      /**
       * The parameters for component (if any).
       */
      private final Parameters m_parameters;
  
      /**
       * The configuration for component (if any).
       */
      private final Configuration m_configuration;
  
      /**
       * The configuration for component (if any).
       */
      private final Context m_context;
  
      /**
       * The logging descriptor.
       */
      private final CategoryDescriptor m_loggers;
  
      /**
       * The creation mode.
       */
      private final int m_mode;
  
  
      /**
       * Create a Profile instance.
       *
       * @param name the abstract name of component meta data instance
       * @param dependencies the meta data for any dependencies
       * @param type the component type
       */
      public DefaultProfile( final String name,
                             final Parameters parameters,
                             final Configuration configuration,
                             final Context context,
                             final CategoryDescriptor loggers,
                             final Type type,
                             final int mode )
      {
          if( null == name )
          {
              m_name = "" + System.identityHashCode( this );
          }
          else
          {
              m_name = name;
          }
  
          if( null == type )
          {
              throw new NullPointerException( "type" );
          }
  
          m_parameters = parameters;
          m_configuration = configuration;
          m_type = type;
          m_context = context;
          m_loggers = loggers;
          m_mode = mode;
      }
  
      /**
       * Return the name of component metadata instance.
       *
       * @return the name of the component.
       */
      public String getName()
      {
          return m_name;
      }
  
      /**
       * Return the info for component.
       *
       * @return the info for component type.
       */
      public Type getType()
      {
          return m_type;
      }
  
      /**
       * Return the assigned service providers.
       *
       * @return the set of service provider assignments.
       */
      public Association[] getAssociations()
      {
          return (Association[])m_dependencies.values().toArray( new Association[0] );
      }
  
      /**
       * Return the Context for component (if any).
       *
       * @return the Context  for component (if any).
       */
      public Context getContext()
      {
          return m_context;
      }
  
      /**
       * Return the Parameters for Component (if any).
       *
       * @return the Parameters for Component (if any).
       */
      public Parameters getParameters()
      {
          return m_parameters;
      }
  
      /**
       * Return the Configuration for Component (if any).
       *
       * @return the Configuration for Component (if any).
       */
      public Configuration getConfiguration()
      {
          return m_configuration;
      }
  
      /**
       * Return the logging descriptor.
       *
       * @return the {@link CategoryDescriptor} for the component loggers.
       */
      public CategoryDescriptor getCategoryDescriptor()
      {
          return m_loggers;
      }
  
      /**
       * Return the dependency metadata for component type with specified role.
       *
       * @return the dependency metadata for component with specified role.
       */
      public Association getAssociation( final String role )
      {
          return (Association) m_dependencies.get( role );
      }
  
      /**
       * Returns the creation mode for this profile.
       * @return a value of EXPLICIT, PACKAGED or IMPLICIT
       */
      public int getMode()
      {
          return m_mode;
      }
  
     /**
      * Add a provider for a service dependecy role.
      * @param provider the compenont provider profile
      * @param role the dependent role
      */
      public void addProvider( Profile provider, String role )
      {
          m_dependencies.put( role, new Association( role, provider ) );
      }
  
      public String toString()
      {
          return "Profile name: " + getName() 
            + ", type: " + getType().getInfo().getName() 
            + ", mode: " + modeToString( getMode() );
      }
  
      private String modeToString( int mode )
      {
          if( mode == IMPLICIT )
          {
              return "IMPLICIT";
          }
          else if( mode == PACKAGED )
          {
              return "PACKAGED";
          }
          else if( mode == EXPLICIT )
          {
              return "EXPLICIT";
          }
          else
          {
              return "?";
          }
      }
  
     /**
      * Provide a textual report on the profile.
      * @return the formatted profile report
      */
      public String list()
      {
          StringBuffer buffer = new StringBuffer();
          buffer.append( "PROFILE REPORT\n" );
          buffer.append( "\n  name: " + getName() );
          buffer.append( "\n  base: " + getType().getInfo().getName() );
          buffer.append( "\n  key: " + getType().getInfo().getImplementationKey() );
          buffer.append( "\n  context: " + getContext( ) );
          buffer.append( "\n  configuration:" );
          if( getConfiguration() != null )
          {
              buffer.append( ConfigurationUtil.list( getConfiguration() ) );
          }
          else
          {
              buffer.append( " null" );
          }
          buffer.append( "\n  parameters: " + getParameters() );
          buffer.append( "\n  dependecies" );
  
          Association[] dependencies = getAssociations();
          if( dependencies.length == 0 )
          {
              buffer.append( " (none)\n\n" );
              return buffer.toString();
          }
  
          for( int i=0; i<dependencies.length; i++ )
          {
              buffer.append( "\n  dependency " + i );
              buffer.append( "\n    role: " + dependencies[i].getRole() );
              buffer.append( "\n    provider: " + dependencies[i].getProvider() );
          }
  
          buffer.append( "\n\n" );
          return buffer.toString();
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/DirsetDescriptor.java
  
  Index: DirsetDescriptor.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.model;
  
  
  /**
   * A description of a directory set.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class DirsetDescriptor 
  {
      /**
       * The base directory
       */
      private final String m_base;
  
      /**
       * The set of include directives.
       */
      private final IncludeDescriptor[] m_includes;
  
      /**
       * Create a FilesetDescriptor instance.
       *
       * @param filesets the set of filesets to include in the classpath
       */
      public DirsetDescriptor( final String base, final IncludeDescriptor[] includes )
      {
          m_base = base;
          m_includes = includes;
      }
  
      /**
       * Return the base directory.
       *
       * @return the directory
       */
      public String getBaseDirectory()
      {
          return m_base;
      }
  
  
      /**
       * Return the filesets held within the classpath descriptor.
       *
       * @return the filesets
       */
      public IncludeDescriptor[] getIncludeDescriptors()
      {
          return m_includes;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/ExtensionsDescriptor.java
  
  Index: ExtensionsDescriptor.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.model;
  
  /**
   * An extensions descriptor.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class ExtensionsDescriptor 
  {
      /**
       * The base directory
       */
      private final DirsetDescriptor[] m_dirs;
  
  
      /**
       * Create a ExtensionsDescriptor instance.
       *
       * @param filesets the set of filesets to include in the classpath
       */
      public ExtensionsDescriptor( final DirsetDescriptor[] dirs )
      {
          m_dirs = dirs;
      }
  
      /**
       * Return the dirset held within the extensions descriptor.
       *
       * @return the directory set
       */
      public DirsetDescriptor[] getDirsetDescriptors()
      {
          return m_dirs;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/FileTargetProvider.java
  
  Index: FileTargetProvider.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.model;
  
  /**
   * File target provider type.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class FileTargetProvider extends TargetProvider
  {
      private final String m_location;
  
      public FileTargetProvider( final String location )
      {
          m_location = location;
      }
  
      public String getLocation()
      {
          return m_location;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/FilesetDescriptor.java
  
  Index: FilesetDescriptor.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.model;
  
  /**
   * A fileset descriptor.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class FilesetDescriptor 
  {
      /**
       * The base directory
       */
      private final String m_base;
  
      /**
       * The set of include directives.
       */
      private final IncludeDescriptor[] m_includes;
  
      /**
       * Create a FilesetDescriptor instance.
       *
       * @param filesets the set of filesets to include in the classpath
       */
      public FilesetDescriptor( final String base, final IncludeDescriptor[] includes )
      {
          m_base = base;
          m_includes = includes;
      }
  
      /**
       * Return the base directory.
       *
       * @return the directory
       */
      public String getBaseDirectory()
      {
          return m_base;
      }
  
      /**
       * Return the filesets held within the classpath descriptor.
       *
       * @return the filesets
       */
      public IncludeDescriptor[] getIncludeDescriptors()
      {
          return m_includes;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/IncludeDescriptor.java
  
  Index: IncludeDescriptor.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.model;
  
  
  /**
   * An file include directive.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class IncludeDescriptor 
  {
      /**
       * The base directory
       */
      private final String m_file;
  
      /**
       * Create a FilesetDescriptor instance.
       *
       * @param filesets the set of filesets to include in the classpath
       */
      public IncludeDescriptor( final String file )
      {
          m_file = file;
      }
  
      /**
       * Return the included filename.
       *
       * @return the file
       */
      public String getFile()
      {
          return m_file;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/KernelDescriptor.java
  
  Index: KernelDescriptor.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.model;
  
  /**
   * Kernel creation profile.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class KernelDescriptor implements AbstractContainer
  {
      /**
       * The kernel name
       */
      private final String m_name;
  
      /**
       * The logging defintion.
       */
      private final LoggingDescriptor m_logging;
  
      /**
       * The extensions defintion.
       */
      private final ExtensionsDescriptor m_extensions;
  
      /**
       * The root container.
       */
      private ClasspathDescriptor m_classpath;
  
      /**
       * The root container.
       */
      private ContainerDescriptor m_container;
  
      /**
       * Create a KernelDescriptor instance.
       *
       */
      public KernelDescriptor( final String name,
                             final LoggingDescriptor logging,
                             final ExtensionsDescriptor extensions,
                             final ContainerDescriptor container )
      {
  
          if( name == null ) 
            throw new NullPointerException("name");
          if( logging == null ) 
            throw new NullPointerException("logging");
          if( extensions == null ) 
            throw new NullPointerException("extensions");
  
          m_name = name;
          m_logging = logging;
          m_extensions = extensions;
          m_container = container;
      }
  
      /**
       * Return the container name.
       *
       * @return the name of the container
       */
      public String getName()
      {
          return m_name;
      }
  
      /**
       * Return the logging descriptor.
       *
       * @return the {@link LoggingDescriptor} for the component loggers.
       */
      public LoggingDescriptor getLoggingDescriptor()
      {
          return m_logging;
      }
  
      /**
       * Return the root logging descriptor. 
       *
       * @return the {@link CategoryDescriptor} for the component loggers.
       */
      public CategoryDescriptor getCategoryDescriptor()
      {
          return getLoggingDescriptor().getCategoryDescriptor();
      }
  
      /**
       * Return the classpath descriptor.
       *
       * @return the {@link ClasspathDescriptor} for the container.
       */
      public ExtensionsDescriptor getExtensionsDescriptor()
      {
          return m_extensions;
      }
  
      /**
       * Return the classpath descriptor.
       *
       * @return the {@link ClasspathDescriptor} for the container.
       */
      public ClasspathDescriptor getClasspathDescriptor()
      {
          return m_classpath;
      }
  
      /**
       * Sets the root container for the kernel.
       *
       * @param root the root {@link ContainerDescriptor} of the container hierachy.
       */
      //public void setContainerDescriptor( ContainerDescriptor container )
      //{
      //    if( container == null ) 
      //      throw new NullPointerException("container");
      //    m_container = container;
      //    container.setParent( this );
      //}
      
      /**
       * Return the root container.
       *
       * @return the root {@link ContainerDescriptor}.
       */
      public ContainerDescriptor getContainerDescriptor()
      {
          return m_container;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/LoggingDescriptor.java
  
  Index: LoggingDescriptor.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.model;
  
  /**
   * Description of a top level logging environment.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public final class LoggingDescriptor 
  {
      /**
       * The root category hierachy.
       */
      private CategoryDescriptor m_category;
  
      /**
       * The defaulr priority.
       */
      private String m_priority;
  
      /**
       * The default target.
       */
      private String m_target;
  
      /**
       * The dependencies keyed by role name.
       */
      private final TargetDescriptor[] m_targets;
  
      /**
       * Create a LoggingDescriptor instance.
       */
      public LoggingDescriptor( final String priority,
                             final String target,
                             final TargetDescriptor[] targets,
                             final CategoryDescriptor category )
      {
          m_targets = targets;
          m_priority = priority;
          m_target = target;
          m_category = category;
      }
  
      /**
       * Return the default logging priority for the group of categories.
       *
       * @return the default logging priority
       */
      public String getPriority( )
      {
          return m_priority;
      }
  
      /**
       * Return the default log target for the group of categories.
       *
       * @return the default target name
       */
      public String getTarget( )
      {
         return m_target;
      }
  
      /**
       * Return the set of logging target descriptors.
       *
       * @return the target descriptors
       */
      public TargetDescriptor[] getTargetDescriptors()
      {
          return m_targets;
      }
  
      /**
       * Return the root catagory descriptor.
       *
       * @return the target descriptors
       */
      public CategoryDescriptor getCategoryDescriptor()
      {
          return m_category;
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/Profile.java
  
  Index: Profile.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.model;
  
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.context.Context;
  import org.apache.excalibur.meta.info.Type;
  
  /**
   * Each component declared in the application is represented by
   * a Profile. Note that this does not necessarily imply
   * that there is only one instance of actual component. The
   * ComponentProfile could represent a pool of components, a single
   * component or a component prototype that is reused to create
   * new components as needed.
   *
   * @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/12 12:04:55 $
   */
  public interface Profile
  {
  
       static final int IMPLICIT = 0;
       static final int PACKAGED = 1;
       static final int EXPLICIT = 2;
  
      /**
       * Return the name of component metadata instance.
       *
       * @return the name of the component.
       */
      String getName();
  
      /**
       * Return the info for component.
       *
       * @return the info for component type.
       */
      Type getType();
  
      /**
       * Return the Parameters for component (if any).
       *
       * @return the Parameters for Component (if any).
       */
      Parameters getParameters();
  
      /**
       * Return the Configuration for component(if any).
       *
       * @return the Configuration for component
       */
      Configuration getConfiguration();
  
      /**
       * Return the Context for component (if any).
       *
       * @return the Context for component
       */
      Context getContext();
  
      /**
       * Return the logging descriptor.
       *
       * @return the {@link CategoryDescriptor} for the component loggers.
       */
      public CategoryDescriptor getCategoryDescriptor();
  
      /**
       * Return the assigned service providers.
       *
       * @return the dependency metadata for component.
       */
      Association[] getAssociations();
  
      /**
       * Return the Association for specified role.
       *
       * @return the Association for specified role.
       */
      Association getAssociation( final String role );
  
      /**
       * Returns the creation mode for this profile.
       * @return a value of EXPLICIT, PACKAGED or IMPLICIT
       */
       int getMode();
  
     /**
      * Add a provider for a service dependency role.
      * @param provider the compenont provider profile
      * @param role the dependent role
      */
      void addProvider( Profile provider, String role );
  
     /**
      * Provide a textual report on the profile.
      * @return the formatted profile report
      */
      String list();
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/TargetDescriptor.java
  
  Index: TargetDescriptor.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.model;
  
  /**
   * A logging target descriptor.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public final class TargetDescriptor 
  {
      /**
       * The target name.
       */
      private final String m_name;
  
      /**
       * The target provider descriptor.
       */
      private final TargetProvider m_provider;
  
      /**
       * Create a LoggingDescriptor instance.
       *
       * @param name the abstract name of component meta data instance
       * @param dependencies the meta data for any dependencies
       * @param type the component type
       */
      public TargetDescriptor( final String name,
                             final TargetProvider provider )
      {
          m_name = name;
          m_provider = provider;
      }
  
      /**
       * Return the target name.
       *
       * @return the target name.
       */
      public String getName()
      {
          return m_name;
      }
  
      /**
       * Return the target provider descriptor
       *
       * @return the provider descriptor
       */
      public TargetProvider getProvider()
      {
          return m_provider;
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/TargetProvider.java
  
  Index: TargetProvider.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.model;
  
  /**
   * Abstract logging target provider type.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public abstract class TargetProvider 
  {
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/package.html
  
  Index: package.html
  ===================================================================
  
  <body>
  <p>
  The <code>model</code> package contains the formal meta data model for the Merlin kernel, container and profile abstractions.  These classes define the criteria for creation of new containers, component and factory profiles, classloaders, extensions, and the kernel itself.
  </p>
  </body>
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/ContainerCreator.java
  
  Index: ContainerCreator.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.model.builder;
  
  import org.apache.excalibur.merlin.model.ContainerDescriptor;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.excalibur.merlin.model.builder.TypeManager;
  
  /**
   * Simple interface used to create {@link ContainerDescriptor}
   * from a Configuration sorce.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public interface ContainerCreator
  {
      /**
       * Create a {@link Profile} from configuration
       *
       * @param config the confiugration source
       * @return the newly created {@link ContainerDescriptor}
       * @throws Exception
       */
      ContainerDescriptor createContainerDescriptor( Configuration config, TypeManager manager )
          throws Exception;
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/KernelCreator.java
  
  Index: KernelCreator.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.model.builder;
  
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.excalibur.merlin.model.KernelDescriptor;
  import org.apache.excalibur.merlin.model.builder.TypeManager;
  
  /**
   * Simple interface used to create {@link ContainerDescriptor}
   * from a Configuration sorce.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public interface KernelCreator
  {
      /**
       * Create a {@link KernelDescriptor} from configuration
       *
       * @param config the confiugration source
       * @return the newly created {@link ContainerDescriptor}
       * @throws Exception
       */
      KernelDescriptor createKernelDescriptor( Configuration config, TypeManager manager )
          throws Exception;
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/ProfileBuilder.java
  
  Index: ProfileBuilder.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.model.builder;
  
  import java.io.InputStream;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.configuration.DefaultConfiguration;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.meta.info.builder.TypeBuilder;
  import org.apache.excalibur.merlin.model.Profile;
  
  /**
   * A ProfileBuilder is responsible for building {@link Profile}
   * objects from Configuration objects. 
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public final class ProfileBuilder
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( TypeBuilder.class );
  
      private final ProfileCreator m_xmlProfileCreator = createXMLProfileCreator();
  
      /**
       * Build Profile from the XML descriptor format.
       *
       * @param classname The classname of Component
       * @param classLoader the ClassLoader to load info from
       * @return the created Type
       * @throws Exception if an error occurs
       */
      public Profile[] build( Type type, final ClassLoader classLoader )
          throws Exception
      {
          final String xprofile =
              type.getInfo().getImplementationKey().replace( '.', '/' ) + ".xprofile";
          final InputStream inputStream =
              classLoader.getResourceAsStream( xprofile );
          final ProfileCreator creator = getXMLProfileCreator( xprofile );
          if( null == inputStream )
          {
              return creator.createProfiles( type, new DefaultConfiguration("profiles", null ) );
          }
          else
          {
              return creator.createProfiles( type, inputStream );
          }
      }
  
      public Profile build( Type type, Configuration profile )
          throws Exception
      {
          final ProfileCreator creator = getXMLProfileCreator( "implicit" );
          return creator.createProfile( type, profile );
      }
  
      /**
       * Utility to get xml info builder, else throw
       * an exception if missing descriptor.
       *
       * @return the TypeCreator
       */
      private ProfileCreator getXMLProfileCreator( final String classname )
          throws Exception
      {
          if( null != m_xmlProfileCreator )
          {
              return m_xmlProfileCreator;
          }
          else
          {
              final String message =
                  REZ.getString( "builder.missing-xml-creator.error",
                                 classname );
              throw new Exception( message );
          }
      }
  
      /**
       * Utility to get XMLProfileCreator if XML files are on
       * ClassPath.
       *
       * @return the XML {@link TypeCreator}
       */
      private static ProfileCreator createXMLProfileCreator()
      {
          ProfileCreator xmlProfileCreator = null;
          try
          {
              xmlProfileCreator = new XMLProfileCreator();
          }
          catch( final Exception e )
          {
              //Ignore it if ClassNot found due to no
              //XML Classes on classpath
          }
          return xmlProfileCreator;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/ProfileCreator.java
  
  Index: ProfileCreator.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.model.builder;
  
  import java.io.InputStream;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.merlin.model.Profile;
  
  /**
   * Simple interface used to create {@link Profile}
   * from stream or Configuration sorce.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public interface ProfileCreator
  {
      /**
       * Create a {@link Profile} from stream
       *
       * @param key the name of component type that we are looking up
       * @param inputStream the stream that the resource is loaded from
       * @return the newly created {@link Type}
       * @throws Exception
       */
      Profile[] createProfiles( Type type, InputStream inputStream )
          throws Exception;
  
      /**
       * Create a {@link Profile} from a configuration
       *
       * @param key the name of component type that we are looking up
       * @param inputStream the stream that the resource is loaded from
       * @return the newly created {@link Type}
       * @throws Exception
       */
      Profile[] createProfiles( Type type, Configuration config )
          throws Exception;
  
      Profile createProfile( Type type, Configuration config )
          throws Exception;
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  builder.redundent-role.notice=Warning: Type for class {0} redundently specifies role name "{1}" in dependency when it is identical to the name of service. It is recomended that the <role/> section be elided.
  builder.creating-info.notice=Creating a Type for class "{0}".
  builder.created-info.notice=Constructed Type object for class {0}. ComponentInfo contains {1} services, {2} dependencies, {3} context entrys and {4} loggers.
  builder.bad-toplevel-element.error=Error the component implemented by "{0}" has an invalid element at top level of component info descriptor. Expected: "component-info". Actual: "{1}"
  builder.missing-info.error=Unable to locate resource from which to load info for component implemented by class "{0}".
  builder.missing-xml-creator.error=Unable to create XMLTypeCreator, usually due to not having XML classes on Classpath. Thus unable to lookup XML descriptor for component type "{0}".
  
  builder.creating-profile.notice=Creating Profiles for class "{0}".
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/TypeManager.java
  
  Index: TypeManager.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.model.builder;
  
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.meta.info.ServiceDesignator;
  import org.apache.excalibur.merlin.model.ClasspathDescriptor;
  
  /**
   * Interface implemented by resources capable a resolving a Type form a classname.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public interface TypeManager
  {
  
     /**
      * Add classes to the manager declared within a classpath structure.
      * @param classpath the classpath descriptor
      * @exception Exception if an exception occurs during class loading
      */
      void addClasspath( ClasspathDescriptor classpath ) throws Exception;
  
     /**
      * Resolve a {@link Type} from a classname.
      *
      * @param classname the component type
      * @return the component type
      */
      Type lookup( String classname ) throws Exception;
  
     /**
      * Register a potential supplier component type.  The implementation will
      * create a component type instance for the entry if not already known and 
      * return the existing or new instance to the invoking client.
      *
      * @param classname the component class name
      * @return the component type
      */
      Type register( String classname ) throws Exception;
  
     /**
      * Returns the set of component types know to the registry.
      * @return the set of component types registered with the registry
      */
      Type[] getTypes();
  
     /**
      * Returns the set of component types know to the registry that are capable of 
      * supporting the supplied service.
      * @return the set of candidate component types
      */
      Type[] getTypes( ServiceDesignator service );
  
     /**
      * Returns a registered component type.
      * @return the component type from the registry or null if the type is unknown
      */
      Type getType( String classname );
  
  
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/XMLContainerCreator.java
  
  Index: XMLContainerCreator.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.model.builder;
  
  import java.io.InputStream;
  import java.util.ArrayList;
  import java.util.Properties;
  import java.util.Vector;
  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.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.configuration.ContextFactory;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.DefaultProfile;
  import org.apache.excalibur.merlin.model.CategoryDescriptor;
  import org.apache.excalibur.merlin.model.IncludeDescriptor ;
  import org.apache.excalibur.merlin.model.FilesetDescriptor;
  import org.apache.excalibur.merlin.model.ClasspathDescriptor;
  import org.apache.excalibur.merlin.model.ContainerDescriptor;
  import org.apache.excalibur.merlin.model.ComponentDescriptor;
  import org.apache.excalibur.merlin.model.builder.TypeManager;
  
  /**
   * Handles internalization of an XML based description of a {@link Profile}
   * from a Configuration object. The format for Configuration object
   * is specified in the <a href="package-summary.html#external">package summary</a>.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class XMLContainerCreator extends XMLProfileCreator
      implements ContainerCreator
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( XMLContainerCreator.class );
  
  
      public ContainerDescriptor[] createContainerDescriptors( Configuration[] configs, TypeManager manager )
        throws Exception
      {
          ArrayList list = new ArrayList();
          for( int i=0; i<configs.length; i++ )
          {
              Configuration config = configs[i];
              list.add( createContainerDescriptor( config, manager ) );
          }
          return (ContainerDescriptor[]) list.toArray( new ContainerDescriptor[0] );
      }
  
      /**
       * Create a {@link ContainerDescriptor} from configuration
       *
       * @param config the confiugration source
       * @return the newly created {@link ContainerDescriptor}
       * @throws Exception
       */
      public ContainerDescriptor createContainerDescriptor( Configuration config, TypeManager manager )
          throws Exception
      {
          final String name = config.getAttribute("name");
          CategoryDescriptor loggers = createCategoryDescriptor( config.getChild("loggers"), name );
          ClasspathDescriptor classpath = createClasspathDescriptor( config.getChild("classpath") );
  
          manager.addClasspath( classpath );
          ComponentDescriptor[] components = createComponentDescriptors( 
            manager, config.getChildren("component") );
  
          ContainerDescriptor[] containers = createContainerDescriptors( 
            config.getChildren("container"), manager );
  
          return new ContainerDescriptor( name, loggers, classpath, components, containers );
      }
  
      public ComponentDescriptor[] createComponentDescriptors( TypeManager manager, Configuration[] configs )
        throws Exception
      {
          ArrayList list = new ArrayList();
          for( int i=0; i<configs.length; i++ )
          {
              Configuration config = configs[i];
              Type type = manager.lookup( config.getAttribute("class") );
              list.add( super.createProfile( type, config ) );
          }
          return (ComponentDescriptor[]) list.toArray( new ComponentDescriptor[0] );
      }
  
      public ClasspathDescriptor createClasspathDescriptor( Configuration config )
        throws ConfigurationException
      {
          ArrayList list = new ArrayList();
          Configuration[] configs = config.getChildren("fileset");
          for( int i=0; i<configs.length; i++ )
          {
              Configuration c = configs[i];
              list.add( createFilesetDescriptor( c ) );
          }
          FilesetDescriptor[] filesets = (FilesetDescriptor[]) list.toArray( new FilesetDescriptor[0] );
          return new ClasspathDescriptor( filesets );
      }
  
      public FilesetDescriptor createFilesetDescriptor( Configuration config ) 
        throws ConfigurationException
      {
          String base = config.getAttribute("dir");
          ArrayList list = new ArrayList();
          Configuration[] includeConfigs = config.getChildren("include");
          for( int i=0; i<includeConfigs.length; i++ )
          {
              Configuration includeConfig = includeConfigs[i];
              list.add( createIncludeDescriptor( includeConfig ) );
          }
          IncludeDescriptor[] includes = (IncludeDescriptor[]) list.toArray( new IncludeDescriptor[0] );
          return new FilesetDescriptor( base, includes );
      }
  
      public IncludeDescriptor createIncludeDescriptor( Configuration config ) 
        throws ConfigurationException
      {
          String filename = config.getAttribute("name");
          return new IncludeDescriptor( filename );
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/XMLKernelCreator.java
  
  Index: XMLKernelCreator.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.model.builder;
  
  import java.io.InputStream;
  import java.util.ArrayList;
  import java.util.Properties;
  import java.util.Vector;
  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.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.DefaultProfile;
  import org.apache.excalibur.merlin.model.CategoryDescriptor;
  import org.apache.excalibur.merlin.model.IncludeDescriptor ;
  import org.apache.excalibur.merlin.model.FilesetDescriptor;
  import org.apache.excalibur.merlin.model.ClasspathDescriptor;
  import org.apache.excalibur.merlin.model.ContainerDescriptor;
  import org.apache.excalibur.merlin.model.ComponentDescriptor;
  import org.apache.excalibur.merlin.model.DirsetDescriptor;
  import org.apache.excalibur.merlin.model.ExtensionsDescriptor;
  import org.apache.excalibur.merlin.model.KernelDescriptor;
  import org.apache.excalibur.merlin.model.TargetDescriptor;
  import org.apache.excalibur.merlin.model.FileTargetProvider;
  import org.apache.excalibur.merlin.model.TargetProvider;
  import org.apache.excalibur.merlin.model.LoggingDescriptor;
  import org.apache.excalibur.merlin.model.builder.TypeManager;
  
  /**
   * Handles internalization of an XML based description of a {@link Profile}
   * from a Configuration object. The format for Configuration object
   * is specified in the <a href="package-summary.html#external">package summary</a>.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public final class XMLKernelCreator extends XMLContainerCreator
      implements KernelCreator
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( XMLKernelCreator.class );
  
      /**
       * Create a {@link KernelDescriptor} from configuration
       *
       * @param config the confiugration source
       * @return the newly created {@link ContainerDescriptor}
       * @throws Exception
       */
      public KernelDescriptor createKernelDescriptor( Configuration config, TypeManager manager )
          throws Exception
      {
          final String name = config.getName();
          LoggingDescriptor logging = createLoggingDescriptor( config.getChild("logging"), name );
          ExtensionsDescriptor extensions = createExtensionsDescriptor( config.getChild("extensions") );
          ClasspathDescriptor classpath = createClasspathDescriptor( config.getChild("classpath") );
          ContainerDescriptor container = createContainerDescriptor( config.getChild("container"), manager );
          return new KernelDescriptor( name, logging, extensions, container );
      }
  
      public LoggingDescriptor createLoggingDescriptor( Configuration config, String name )
        throws ConfigurationException
      {
          final String target = config.getAttribute( 
             "target", CategoryDescriptor.DEFAULT_LOGGING_TARGET );
          final String priority = config.getAttribute( "priority", null );
  
          ArrayList list = new ArrayList();
          Configuration[] configs = config.getChildren("target");
          for( int i=0; i<configs.length; i++ )
          {
              Configuration c = configs[i];
              list.add( createTargetDescriptor( c ) );
          }
          TargetDescriptor[] targets = (TargetDescriptor[]) list.toArray( new TargetDescriptor[0] );
          CategoryDescriptor loggers = super.createCategoryDescriptor( config.getChild("loggers"), name );
          return new LoggingDescriptor( priority, target, targets, loggers );
      }
  
      public TargetDescriptor createTargetDescriptor( Configuration config )
        throws ConfigurationException
      {
          final String name = config.getAttribute("name");
          if( config.getChildren().length == 0 )
            throw new ConfigurationException(
              "missing target provider elememt in '" + config.getName() + "'.");
          final Configuration c = config.getChildren()[0];
          TargetProvider provider = null;
          if( c.getName().equals("file") )
          {
              provider = createFileTargetProvider( c );
          }
          else
          {
              throw new ConfigurationException(
                "Unrecognized provider: " + c.getName() + " in " + config.getName() );
          }
          return new TargetDescriptor( name, provider );
      }
  
      public FileTargetProvider createFileTargetProvider( Configuration config )
        throws ConfigurationException
      {
          String file = config.getAttribute("location");
          return new FileTargetProvider( file );
      }
  
      public ExtensionsDescriptor createExtensionsDescriptor( Configuration config )
        throws ConfigurationException
      {
          ArrayList list = new ArrayList();
          Configuration[] configs = config.getChildren("dirset");
          for( int i=0; i<configs.length; i++ )
          {
              Configuration c = configs[i];
              list.add( createDirsetDescriptor( c ) );
          }
          DirsetDescriptor[] dirs = (DirsetDescriptor[]) list.toArray( new DirsetDescriptor[0] );
          return new ExtensionsDescriptor( dirs );
      }
  
      public DirsetDescriptor createDirsetDescriptor( Configuration config ) 
        throws ConfigurationException
      {
          String base = config.getAttribute("dir");
          ArrayList list = new ArrayList();
          Configuration[] includeConfigs = config.getChildren("include");
          for( int i=0; i<includeConfigs.length; i++ )
          {
              Configuration includeConfig = includeConfigs[i];
              list.add( createIncludeDescriptor( includeConfig ) );
          }
          IncludeDescriptor[] includes = (IncludeDescriptor[]) list.toArray( new IncludeDescriptor[0] );
          return new DirsetDescriptor( base, includes );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/XMLProfileCreator.java
  
  Index: XMLProfileCreator.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.model.builder;
  
  import java.io.InputStream;
  import java.util.ArrayList;
  import java.util.Properties;
  import java.util.Vector;
  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.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.meta.info.builder.XMLTypeCreator;
  import org.apache.excalibur.meta.ConfigurationBuilder;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.DefaultProfile;
  import org.apache.excalibur.merlin.model.CategoryDescriptor;
  import org.apache.excalibur.merlin.model.ComponentDescriptor;
  import org.apache.excalibur.configuration.ContextFactory;
  import org.xml.sax.InputSource;
  
  /**
   * Handles internalization of an XML based description of a {@link Profile}
   * from a Configuration object. The format for Configuration object
   * is specified in the <a href="package-summary.html#external">package summary</a>.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
   */
  public class XMLProfileCreator
      implements ProfileCreator
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( XMLTypeCreator.class );
  
      /**
       * Create a {@link Type} object for specified
       * classname, loaded from specified {@link InputStream}.
       *
       * @param implementationKey The classname of Component
       * @param inputStream the InputStream to load Type from
       * @return the created Type
       * @throws ConfigurationException if an error occurs
       */
      public Profile[] createProfiles( Type type, InputStream inputStream )
          throws Exception
      {
          final InputSource input = new InputSource( inputStream );
          final Configuration configuration = ConfigurationBuilder.build( input );
          return createProfiles( type, configuration );
      }
  
      /**
       * Create a {@link Profile} object for specified classname from
       * specified configuration data associated with a single type.
       *
       * @param classname The classname of Component
       * @param info the Type configuration
       * @return the created Type
       * @throws ConfigurationException if an error occurs
       */
      public Profile[] createProfiles( Type type, final Configuration info )
          throws Exception
      {
          Vector vector = new Vector();
          Configuration[] profiles = info.getChildren("component");
          if( profiles.length == 0 )
          {
              //
              // build a default profile
              //
  
              CategoryDescriptor loggers = new CategoryDescriptor( 
                type.getInfo().getName(), null, null );
  
              return new Profile[]{ 
                 new ComponentDescriptor( null, null, null, null, loggers, type, Profile.IMPLICIT  ) };
          }
          for( int i=0; i<profiles.length; i++ )
          {
             vector.add( buildProfile( type, profiles[i], Profile.PACKAGED ) );
          }
          return (Profile[]) vector.toArray( new Profile[0] );
      }
  
      public Profile createProfile( Type type, Configuration config )
          throws Exception
      {
          return buildProfile( type, config, Profile.EXPLICIT );
      }
  
      private Profile buildProfile( Type type, Configuration profile, int mode ) throws Exception
      {
          String name = null;
          if( mode == Profile.EXPLICIT )
          {
              name = profile.getAttribute("name");
          }
          Parameters params = Parameters.fromConfiguration( profile.getChild("parameters") );
          Configuration config = profile.getChild("configuration");
          Configuration loggersConfig = profile.getChild("loggers");
          CategoryDescriptor loggers = createCategoryDescriptor( loggersConfig, name );
          Context context = ContextFactory.createContextFromConfiguration( 
            null, profile.getChild("context") );
          return new ComponentDescriptor( name, params, config, context, loggers, type, mode  );
      }
  
      public CategoryDescriptor createCategoryDescriptor( Configuration config, String fallback ) 
        throws ConfigurationException
      {
          final String name = config.getAttribute( "name", fallback );
          final String priority = config.getAttribute( "priority", null );
          final String target = config.getAttribute( "target", null );
          CategoryDescriptor[] categories = createCategoryDescriptors( config );
          return new CategoryDescriptor( name, priority, target, categories );
      }
  
      private CategoryDescriptor[] createCategoryDescriptors( Configuration config )
        throws ConfigurationException
      {
          ArrayList list = new ArrayList();
          Configuration[] categories = config.getChildren( "category" );
          for( int i=0; i<categories.length; i++ )
          {
              CategoryDescriptor category = createCategoryDescriptor( categories[i], null );
              list.add( category );
          }
          return (CategoryDescriptor[]) list.toArray( new CategoryDescriptor[0] );
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/package.html
  
  Index: package.html
  ===================================================================
  <html><body>
  <p>Merlin model information builders that handle internalization of a model supplied as a configuration instance.</P>
  </body></html>
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/verifier/AssemblyVerifier.java
  
  Index: AssemblyVerifier.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.model.verifier;
  
  import java.util.ArrayList;
  import java.util.Stack;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.meta.verifier.VerifyException;
  import org.apache.excalibur.meta.info.DependencyDescriptor;
  import org.apache.excalibur.meta.info.ServiceDescriptor;
  import org.apache.excalibur.meta.info.ServiceDesignator;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.merlin.model.Association;
  
  /**
   * This Class verifies that a set of profiles are valid. It performs a number
   * of checks to make sure that the profile set represents a valid
   * application and excluding runtime errors will start up normally.
   * Some of the checks performed include;
   *
   * <ul>
   *   <li>Verify names of Components contain only
   *       letters, digits or the '_' character.</li>
   *   <li>Verify that the names of the Components are unique to the
   *       Assembly.</li>
   *   <li>Verify that the specified dependeny mapping correspond to
   *       dependencies specified in Type files.</li>
   *   <li>Verify that the inter-Component dependendencies are valid.
   *       This essentially means that if Component A requires Service S
   *       from Component B then Component B must provide Service S.</li>
   *   <li>Verify that there are no circular dependendencies between
   *       components.</li>
   *   <li>Verify that the Class objects for Component implement the
   *       service interfaces.</li>
   *   <li>Verify that the Class is a valid Avalon Component as per the
   *       rules in {@link ComponentVerifier} object.</li>
   * </ul>
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:56 $
   */
  public class AssemblyVerifier
      extends AbstractLogEnabled
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( AssemblyVerifier.class );
  
      /**
       * Validate and Verify the specified assembly (ie organization
       * of components). See the Class Javadocs for the rules and
       * regulations of assembly.
       *
       * @param components the Components that make up assembly
       * @throws VerifyException if an error occurs
       */
      public void verifyAssembly( final Profile[] components )
          throws VerifyException
      {
          String message = null;
  
          message = REZ.getString( "assembly.valid-names.notice" );
          getLogger().debug( message );
          verifyValidNames( components );
  
          message = REZ.getString( "assembly.unique-names.notice" );
          getLogger().debug( message );
          checkNamesUnique( components );
  
          message = REZ.getString( "assembly.dependencies-mapping.notice" );
          getLogger().debug( message );
          verifyValidDependencies( components );
  
          message = REZ.getString( "assembly.dependency-references.notice" );
          getLogger().debug( message );
          verifyDependencyReferences( components );
  
          message = REZ.getString( "assembly.nocircular-dependencies.notice" );
          getLogger().debug( message );
          verifyNoCircularDependencies( components );
      }
  
      /**
       * Verfiy that all Components have the needed dependencies specified correctly.
       *
       * @param components the Profile objects for the components
       * @throws VerifyException if an error occurs
       */
      public void verifyValidDependencies( final Profile[] components )
          throws VerifyException
      {
          for( int i = 0; i < components.length; i++ )
          {
              verifyDependenciesMap( components[ i ] );
          }
      }
  
      /**
       * Verfiy that there are no circular references between Components.
       *
       * @param components the Profile objects for the components
       * @throws VerifyException if an circular dependency error occurs
       */
      protected void verifyNoCircularDependencies( final Profile[] components )
          throws VerifyException
      {
          for( int i = 0; i < components.length; i++ )
          {
              final Profile component = components[ i ];
  
              final Stack stack = new Stack();
              stack.push( component );
              verifyNoCircularDependencies( component, components, stack );
              stack.pop();
          }
      }
  
      /**
       * Verfiy that there are no circular references between Components.
       *
       * @param component ???
       * @param components the Profile objects for the components
       * @param stack the ???
       * @throws VerifyException if an error occurs
       */
      protected void verifyNoCircularDependencies( final Profile component,
                                                   final Profile[] components,
                                                   final Stack stack )
          throws VerifyException
      {
          final Profile[] dependencies = getDependencies( component, components );
          for( int i = 0; i < dependencies.length; i++ )
          {
              final Profile dependency = dependencies[ i ];
              if( stack.contains( dependency ) )
              {
                  final String trace = getDependencyTrace( dependency, stack );
                  final String message =
                      REZ.getString( "assembly.circular-dependency.error",
                                     component.getName(),
                                     trace );
                  throw new VerifyException( message );
              }
  
              stack.push( dependency );
              verifyNoCircularDependencies( dependency, components, stack );
              stack.pop();
          }
      }
  
      /**
       * Get a string defining path from top of stack till
       * it reaches specified component.
       *
       * @param component the component
       * @param stack the Stack
       * @return the path of dependency
       */
      protected String getDependencyTrace( final Profile component,
                                           final Stack stack )
      {
          final StringBuffer sb = new StringBuffer();
          sb.append( "[ " );
  
          final String name = component.getName();
          final int size = stack.size();
          final int top = size - 1;
          for( int i = top; i >= 0; i-- )
          {
              final Profile other = (Profile)stack.get( i );
              if( top != i )
              {
                  sb.append( ", " );
              }
              sb.append( other.getName() );
  
              if( other.getName().equals( name ) )
              {
                  break;
              }
          }
  
          sb.append( ", " );
          sb.append( name );
  
          sb.append( " ]" );
          return sb.toString();
      }
  
      /**
       * Get array of dependencies for specified Component from specified
       * Component array.
       *
       * @param component the component to get dependencies of
       * @param components the total set of components in application
       * @return the dependencies of component
       */
      protected Profile[] getDependencies( final Profile component,
                                                     final Profile[] components )
      {
          final ArrayList dependencies = new ArrayList();
          final Association[] deps = component.getAssociations();
  
          for( int i = 0; i < deps.length; i++ )
          {
              final String name = deps[ i ].getProvider().getName();
              final Profile other = getProfile( name, components );
              dependencies.add( other );
          }
  
          return (Profile[])dependencies.toArray( new Profile[ 0 ] );
      }
  
      /**
       * Verfiy that the inter-Component dependencies are valid.
       *
       * @param components the Profile objects for the components
       * @throws VerifyException if an error occurs
       */
      protected void verifyDependencyReferences( final Profile[] components )
          throws VerifyException
      {
          for( int i = 0; i < components.length; i++ )
          {
              verifyDependencyReferences( components[ i ], components );
          }
      }
  
      /**
       * Verfiy that the inter-Component dependencies are valid for specified Component.
       *
       * @param component the Profile object for the component
       * @param others the Profile objects for the other components
       * @throws VerifyException if an error occurs
       */
      protected void verifyDependencyReferences( final Profile component,
                                                 final Profile[] others )
          throws VerifyException
      {
          final Type info = component.getType();
          final Association[] roles = component.getAssociations();
  
          for( int i = 0; i < roles.length; i++ )
          {
              final String providerName = roles[ i ].getProvider().getName();
              final String roleName = roles[ i ].getRole();
              final ServiceDesignator service =
                  info.getDependency( roleName ).getService();
  
              //Get the other component that is providing service
              final Profile provider = getProfile( providerName, others );
              if( null == provider )
              {
                  final String message =
                      REZ.getString( "assembly.missing-dependency.error",
                                     roleName,
                                     providerName,
                                     component.getName() );
                  throw new VerifyException( message );
              }
  
              //make sure that the component offers service
              //that user expects it to be providing
              final ServiceDescriptor[] services = provider.getType().getServices();
              if( !hasMatchingService( service, services ) )
              {
                  final String message =
                      REZ.getString( "assembly.dependency-missing-service.error",
                                     component.getName(),
                                     providerName,
                                     roleName,
                                     service );
                  throw new VerifyException( message );
              }
          }
      }
  
      /**
       * Get component with specified name from specified Component array.
       *
       * @param name the name of component to get
       * @param components the array of components to search
       * @return the Component if found, else null
       */
      protected Profile getProfile( final String name,
                                                        final Profile[] components )
      {
          for( int i = 0; i < components.length; i++ )
          {
              if( components[ i ].getName().equals( name ) )
              {
                  return components[ i ];
              }
          }
  
          return null;
      }
  
      /**
       * Verify that the names of the specified Components are valid.
       *
       * @param components the Components metadata
       * @throws VerifyException if an error occurs
       */
      protected void verifyValidNames( final Profile[] components )
          throws VerifyException
      {
          for( int i = 0; i < components.length; i++ )
          {
              final String name = components[ i ].getName();
              if( !isValidName( name ) )
              {
                  final String message =
                      REZ.getString( "assembly.bad-name.error", name );
                  throw new VerifyException( message );
              }
          }
      }
  
      /**
       * Return true if specified name is valid.
       * Valid names consist of letters, digits or the '_' character.
       *
       * @param name the name to check
       * @return true if valid, false otherwise
       */
      protected boolean isValidName( final String name )
      {
          final int size = name.length();
          for( int i = 0; i < size; i++ )
          {
              final char ch = name.charAt( i );
  
              if( !Character.isLetterOrDigit( ch ) && '-' != ch )
              {
                  return false;
              }
          }
  
          return true;
      }
  
      /**
       * Verify that the names of the specified components and listeners are unique.
       * It is not valid for the same name to be used in multiple components.
       *
       * @param components the Components
       * @throws VerifyException if an error occurs
       */
      protected void checkNamesUnique( final Profile[] components )
          throws VerifyException
      {
          for( int i = 0; i < components.length; i++ )
          {
              final String name = components[ i ].getName();
              verifyUniqueName( components, name, i );
          }
      }
  
      /**
       * Verfify that specified name is unique among the specified components.
       *
       * @param components the array of components to check
       * @param name the name of component
       * @param index the index of component in array (so we can skip it)
       * @throws VerifyException if names are not unique
       */
      private void verifyUniqueName( final Profile[] components,
                                     final String name,
                                     final int index )
          throws VerifyException
      {
          for( int i = 0; i < components.length; i++ )
          {
              final String other = components[ i ].getName();
              if( index != i && other.equals( name ) )
              {
                  final String message =
                      REZ.getString( "assembly.duplicate-name.error", name );
                  throw new VerifyException( message );
              }
          }
      }
  
      /**
       * Retrieve a list of Association objects for Profile
       * and verify that there is a 1 to 1 map with dependencies specified
       * in Type.
       *
       * @param component the Profile describing the component
       * @throws VerifyException if an error occurs
       */
      protected void verifyDependenciesMap( final Profile component )
          throws VerifyException
      {
          //Make sure all role entries specified in config file are valid
          final Association[] dependencySet = component.getAssociations();
  
          for( int i = 0; i < dependencySet.length; i++ )
          {
              final String roleName = dependencySet[ i ].getRole();
              final DependencyDescriptor descriptor = component.getType().getDependency( roleName );
  
              //If there is no dependency descriptor in Type then
              //user has specified an uneeded dependency.
              if( null == descriptor )
              {
                  final String message =
                      REZ.getString( "assembly.unknown-dependency.error",
                                     roleName,
                                     roleName,
                                     component.getName() );
                  throw new VerifyException( message );
              }
          }
  
          //Make sure all dependencies in Type file are satisfied
          final DependencyDescriptor[] dependencies = component.getType().getDependencies();
          for( int i = 0; i < dependencies.length; i++ )
          {
              final DependencyDescriptor dependency = dependencies[ i ];
              final Association role = component.getAssociation( dependency.getRole() );
  
              //If there is no Role then the user has failed
              //to specify a needed dependency.
              if( null == role && !dependency.isOptional() )
              {
                  final String message =
                      REZ.getString( "assembly.unspecified-dependency.error",
                                     dependency.getRole(),
                                     component.getName() );
                  throw new VerifyException( message );
              }
          }
      }
  
      /**
       * Return true if specified service reference matches any of the
       * candidate services.
       *
       * @param service the service descriptor reference
       * @param candidates an array of candidate services
       * @return true if candidate services contains a service that matches
       *         specified service, false otherwise
       */
      protected boolean hasMatchingService( final ServiceDesignator service,
                                            final ServiceDescriptor[] candidates )
      {
          for( int i = 0; i < candidates.length; i++ )
          {
              final ServiceDesignator other = candidates[ i ].getService();
              if( service.matches( other ) )
              {
                  return true;
              }
          }
  
          return false;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/verifier/MetaDataVerifier.java
  
  Index: MetaDataVerifier.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.model.verifier;
  
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.service.Serviceable;
  import org.apache.excalibur.merlin.model.Profile;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.meta.info.ContextDescriptor;
  import org.apache.excalibur.meta.info.ServiceDescriptor;
  import org.apache.excalibur.meta.info.ServiceDesignator;
  import org.apache.excalibur.meta.verifier.VerifyException;
  import org.apache.excalibur.meta.verifier.ComponentVerifier;
  
  /**
   * This Class verifies that an implementation is valid wrt the
   * Profile. It performs a number of checks to make sure
   * that the implementation class is consistent with MetaData.
   * Some of the checks it performs include;
   *
   * <ul>
   *   <li>Verify that the Class objects for Component implement the
   *       service interfaces.</li>
   *   <li>Verify that the Class is a valid Avalon Component as per the
   *       rules in {@link ComponentVerifier} object.</li>
   *   <li>Verify that the Class is Composable/Serviceable if and only if
   *       dependencies are declared.</li>
   *   <li>Verify that the Class is Contextualizable if and context
   *       entrys are declared.</li>
   * </ul>
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:56 $
   */
  public class MetaDataVerifier
      extends AbstractLogEnabled
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( MetaDataVerifier.class );
  
      /**
       * The verifier for components in assembly.
       */
      private final ComponentVerifier m_verifier;
  
      /**
       * Create an MetaDataVerifier using base Componert ComponentVerifier.
       */
      public MetaDataVerifier()
      {
          this( new ComponentVerifier() );
      }
  
      /**
       * Create an AssemblyVerifier using specified Component ComponentVerifier.
       */
      public MetaDataVerifier( final ComponentVerifier verifier )
      {
          if( null == verifier )
          {
              throw new NullPointerException( "verifier" );
          }
  
          m_verifier = verifier;
      }
  
      public void enableLogging( final Logger logger )
      {
          super.enableLogging( logger );
          setupLogger( m_verifier );
      }
      /**
       * Verfiy that specified components designate classes that implement the
       * advertised interfaces. And confrorm to expectations of MetaData.
       *
       * @param component the Profile object for the components
       * @param classLoader the ClassLoader to load component from
       * @throws VerifyException if an error occurs
       */
      public void verifyType( final Profile component,
                                 final ClassLoader classLoader )
          throws VerifyException
      {
          final Class clazz = getClass( classLoader, component );
          verifyType( component, clazz );
      }
  
      /**
       * Verfiy that specified components designate classes that implement the
       * advertised interfaces. And confrorm to expectations of MetaData.
       *
       * @param component the Profile object for the components
       * @throws VerifyException if an error occurs
       */
      public void verifyType( final Profile component,
                                 final Class clazz )
          throws VerifyException
      {
          final String name = component.getName();
          final Class[] interfaces =
              getServiceClasses( name,
                                 component.getType().getServices(),
                                 clazz.getClassLoader() );
  
          m_verifier.verifyComponent( name, clazz, interfaces );
  
          verifyDependencyPresence( component, clazz );
          verifyContextPresence( component, clazz );
      }
  
      /**
       * Verify that the if  the component is not Contextualizable that it
       * does not declare Context Entrys.
       *
       * @param component the component metadata
       * @param clazz the class implementing component
       * @throws VerifyException if fails verification check
       */
      protected void verifyContextPresence( final Profile component,
                                            final Class clazz )
          throws VerifyException
      {
          final Type info = component.getType();
          final ContextDescriptor context = info.getContextDescriptor();
          final int count = context.getEntrys().length;
  
          if( !Contextualizable.class.isAssignableFrom( clazz ) )
          {
              if( 0 != count )
              {
                  final String message =
                      REZ.getString( "metadata.declare-uneeded-entrys.error",
                                     component.getName(),
                                     getClassname( component ) );
                  throw new VerifyException( message );
              }
          }
      }
  
      /**
       * Verify the component assembly logic.
       * The implications verifies that the component:
       * <p>Is not Composable/Serviceable and does not declare dependencys</p>
       * <p>or</p>
       * <p>Is Composable/Serviceable and does declare dependencys</p>
       *
       * @param component the component metadata
       * @param clazz the class implementing component
       * @throws VerifyException if fails verification check
       */
      protected void verifyDependencyPresence( final Profile component,
                                               final Class clazz )
          throws VerifyException
      {
          final int count = component.getAssociations().length;
          final boolean aquiresServices =
              Composable.class.isAssignableFrom( clazz ) ||
              Serviceable.class.isAssignableFrom( clazz );
          if( !aquiresServices )
          {
              if( 0 != count )
              {
                  final String message =
                      REZ.getString( "metadata.declare-uneeded-deps.error",
                                     component.getName(),
                                     getClassname( component ) );
                  throw new VerifyException( message );
              }
          }
      }
  
      /**
       * Retrieve an array of Classes for all the services that a Component
       * offers. This method also makes sure all services offered are
       * interfaces.
       *
       * @param name the name of component
       * @param services the services the component offers
       * @param classLoader the classLoader
       * @return an array of Classes for all the services
       * @throws VerifyException if an error occurs
       */
      protected Class[] getServiceClasses( final String name,
                                           final ServiceDescriptor[] services,
                                           final ClassLoader classLoader )
          throws VerifyException
      {
          final Class[] classes = new Class[ services.length ];
          for( int i = 0; i < services.length; i++ )
          {
              final ServiceDesignator service = services[ i ].getService();
              final String classname = service.getClassname();
              try
              {
                  classes[ i ] = classLoader.loadClass( classname );
              }
              catch( final Throwable t )
              {
                  final String message =
                      REZ.getString( "metadata.bad-service-class.error",
                                     name,
                                     classname,
                                     t.toString() );
                  throw new VerifyException( message, t );
              }
          }
  
          return classes;
      }
  
      /**
       * Load class object for specified Profile.
       *
       * @param classLoader the ClassLoader to use
       * @param component the meta data associate with component
       * @return the Class object
       * @throws VerifyException if unable to aquire class object
       */
      private Class getClass( final ClassLoader classLoader,
                              final Profile component )
          throws VerifyException
      {
          Class clazz = null;
          try
          {
              clazz = classLoader.loadClass( getClassname( component ) );
          }
          catch( final Exception e )
          {
              final String message =
                  REZ.getString( "assembly.bad-class.error",
                                 component.getName(),
                                 getClassname( component ),
                                 e.toString() );
              throw new VerifyException( message );
          }
          return clazz;
      }
  
      /**
       * Utility method to aquire classname for component.
       *
       * @param component the component
       * @return the classname for component
       */
      private String getClassname( final Profile component )
      {
          return component.getType().getInfo().getImplementationKey();
      }
  }
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/verifier/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  
  #Assembly Verifier
  assembly.valid-names.notice=Verifying that the names specified for Component are valid.
  assembly.unique-names.notice=Verifying that the names specified for the Components are unique.
  assembly.dependencies-mapping.notice=Verifying that the dependency mapping is valid according to ComponentInfos.
  assembly.dependency-references.notice=Verifying that the dependency mapping for every Component is valid with respect to other components.
  assembly.nocircular-dependencies.notice=Verifying that there are no circular dependencies between Components.
  assembly.component-type.notice=Verifying that the specified Components have valid types.
  assembly.circular-dependency.error=Component named "{0}" has a circular dependency via path: {1}.
  assembly.missing-dependency.error=Component "{1}" that satisfies the dependency with role "{0}" of Component "{2}" does not exist.
  assembly.dependency-missing-service.error=Profile {0}" is associated to profile "{1}" under the role "{2}" however, the provider does not supply the required service "{3}".
  
  assembly.bad-class.error=Unable to load class "{1}" for Component named "{0}". (Reason: {2}).
  assembly.bad-name.error=The Component name "{0}" is invalid. Valid names contain only letters, digits and the '-' character.
  assembly.duplicate-name.error=The name "{0}" is used by multiple Components in assembly.
  assembly.unknown-dependency.error=Unknown dependency named "{0}" with role "{1}" declared for Component {2}.
  assembly.unspecified-dependency.error=Dependency for role "{0}" not specified for the Component named "{1}".
  
  #MetaData Verifier
  metadata.bad-service-class.error=Unable to load service class "{1}" for Component named "{0}". (Reason: {2}).
  metadata.nodeclare-deps.error=Component named "{0}" of type "{1}" is Composable or Serviceable but does not declare any dependencies.
  metadata.declare-uneeded-deps.error=Component named "{0}" of type "{1}" is not Composable or Serviceable but declares dependencies.
  metadata.declare-uneeded-entrys.error=Component named "{0}" of type "{1}" is not Contextualizable but declares Context Entrys.
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/verifier/package.html
  
  Index: package.html
  ===================================================================
  
  <body>
  A set of classes supporting verification of components and component
  assemblies using class and component meta-data information.
  
  <h3>Overview</h3>
  <p>This package includes a set of classes supporting the verification of the
  integrity of a component class and the verification of the integrity of a
  relationships and inter-dependecies based on supplied meta-data. The
  {@link org.apache.excalibur.merlin.model.verifier.ComponentVerifier} provides
  support for the validation of a component class.  It includes validation
  functions that check for structural and best-practice integrity related to
  the class, lifecycle patterns and service. The
  {@link org.apache.excalibur.merlin.model.verifier.AssemblyVerifier} performs
  validation of the structural integrity of a set component assembly based on
  assembly meta-data.
  </body>
  
  
  

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