avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mcconn...@apache.org
Subject cvs commit: jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/verifier AssemblyVerifier.java ComponentVerifier.java MetaDataVerifier.java Resources.properties VerifyException.java package.html
Date Fri, 05 Jul 2002 10:39:01 GMT
mcconnell    2002/07/05 03:39:01

  Added:       assembly/src/java/org/apache/excalibur/meta/builder
                        ConfigurationBuilder.java DTDInfo.java
                        DTDResolver.java InfoCreator.java
                        Resources.properties SerializedInfoCreator.java
                        TypeBuilder.java XMLInfoCreator.java
                        componentinfo.dtd package.html
               assembly/src/java/org/apache/excalibur/meta/data
                        Assignment.java Assignment.java~
                        DefaultProfile.java Profile.java package.html
               assembly/src/java/org/apache/excalibur/meta/info
                        ComponentDescriptor.java ContextDescriptor.java
                        DefaultType.java DependencyDescriptor.java
                        Descriptor.java EntryDescriptor.java
                        LoggerDescriptor.java Resources.properties
                        ServiceDescriptor.java ServiceDesignator.java
                        Type.java package.html
               assembly/src/java/org/apache/excalibur/meta/verifier
                        AssemblyVerifier.java ComponentVerifier.java
                        MetaDataVerifier.java Resources.properties
                        VerifyException.java package.html
  Log:
  Cariant of containerkit supporting dynamic metadata construction, interface,
  and better naming conventions, support for profile level context, and
   (introperable at <conponent-info/> level with containerkit.
  
  Revision  Changes    Path
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/builder/ConfigurationBuilder.java
  
  Index: ConfigurationBuilder.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.builder;
  
  import java.io.IOException;
  import javax.xml.parsers.ParserConfigurationException;
  import javax.xml.parsers.SAXParser;
  import javax.xml.parsers.SAXParserFactory;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
  import org.xml.sax.InputSource;
  import org.xml.sax.SAXException;
  import org.xml.sax.XMLReader;
  
  /**
   * Utility class used to load Configuration trees from XML files.
   *
   * @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/05 10:38:59 $
   */
  class ConfigurationBuilder
  {
      private static final DTDInfo[] c_dtdInfo = new DTDInfo[]
      {
          new DTDInfo( "-//AVALON/Component Info DTD Version 1.0//EN",
                       "http://jakarta.apache.org/avalon/componentinfo_1_0.dtd",
                       "org/apache/excalibur/containerkit/infobuilder/componentinfo.dtd" ),
      };
  
      private static final DTDResolver c_resolver =
          new DTDResolver( c_dtdInfo, ConfigurationBuilder.class.getClassLoader() );
  
      /**
       * Private constructor to block instantiation.
       */
      private ConfigurationBuilder()
      {
      }
  
      /**
       * Utility method to create a new XML reader.
       */
      private static XMLReader createXMLReader()
          throws SAXException, ParserConfigurationException
      {
          final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
          saxParserFactory.setNamespaceAware( false );
          final SAXParser saxParser = saxParserFactory.newSAXParser();
          return saxParser.getXMLReader();
      }
  
      /**
       * Internally sets up the XMLReader
       */
      private static void setupXMLReader( final XMLReader reader,
                                          final SAXConfigurationHandler handler )
      {
          reader.setEntityResolver( c_resolver );
          reader.setContentHandler( handler );
          reader.setErrorHandler( handler );
      }
  
      /**
       * Build a configuration object using an URI
       * @param uri an input source system identifier
       * @exception SAXException is a parser exception is encountered
       * @exception ParserConfigurationException if a parser configuration failure occurs
       * @exception IOException if an IO exception occurs while attempting to read the
       *    resource identified by the system identifier
       */
      public static Configuration build( final String uri )
          throws SAXException, ParserConfigurationException, IOException
      {
          return build( new InputSource( uri ) );
      }
  
      /**
       * Build a configuration object using an XML InputSource object
       * @param input an input source
       * @exception SAXException is a parser exception is encountered
       * @exception ParserConfigurationException if a parser configuration failure occurs
       * @exception IOException if an IO exception occurs while attempting to read the
       *    resource associated with the input source
       */
      public static Configuration build( final InputSource input )
          throws SAXException, ParserConfigurationException, IOException
      {
          final XMLReader reader = createXMLReader();
          final SAXConfigurationHandler handler = new SAXConfigurationHandler();
          setupXMLReader( reader, handler );
          reader.parse( input );
          return handler.getConfiguration();
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/builder/DTDInfo.java
  
  Index: DTDInfo.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.builder;
  
  /**
   * Holds information about a given DTD.
   *
   * @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/05 10:38:59 $
   */
  class DTDInfo
  {
      /**
       * The public identifier. Null if unknown.
       */
      private final String m_publicId;
  
      /**
       * The system identifier.  Null if unknown.
       */
      private final String m_systemId;
  
      /**
       * The resource name, if a copy of the document is available.
       */
      private final String m_resource;
  
      public DTDInfo( final String publicId,
                      final String systemId,
                      final String resource )
      {
          m_publicId = publicId;
          m_systemId = systemId;
          m_resource = resource;
      }
  
      public String getPublicId()
      {
          return m_publicId;
      }
  
      public String getSystemId()
      {
          return m_systemId;
      }
  
      public String getResource()
      {
          return m_resource;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/builder/DTDResolver.java
  
  Index: DTDResolver.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.builder;
  
  import java.io.IOException;
  import java.io.InputStream;
  import org.xml.sax.EntityResolver;
  import org.xml.sax.InputSource;
  import org.xml.sax.SAXException;
  import org.apache.excalibur.meta.builder.DTDInfo;
  
  /**
   * A Class to help to resolve Entitys for items such as DTDs or
   * Schemas.
   *
   * @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/05 10:38:59 $
   */
  class DTDResolver
      implements EntityResolver
  {
      /**
       * The list of DTDs that can be resolved by this class.
       */
      private final DTDInfo[] m_dtdInfos;
  
      /**
       * The ClassLoader to use when loading resources for DTDs.
       */
      private final ClassLoader m_classLoader;
  
      /**
       * Construct a resolver using specified DTDInfos where resources are loaded
       * from specified ClassLoader.
       */
      public DTDResolver( final DTDInfo[] dtdInfos, final ClassLoader classLoader )
      {
          m_dtdInfos = dtdInfos;
          m_classLoader = classLoader;
      }
  
      /**
       * Resolve an entity in the XML file.
       * Called by parser to resolve DTDs.
       */
      public InputSource resolveEntity( final String publicId, final String systemId )
          throws IOException, SAXException
      {
          for( int i = 0; i < m_dtdInfos.length; i++ )
          {
              final DTDInfo info = m_dtdInfos[ i ];
  
              if( ( publicId != null && publicId.equals( info.getPublicId() ) ) ||
                  ( systemId != null && systemId.equals( info.getSystemId() ) ) )
              {
                  final ClassLoader classLoader = getClassLoader();
                  final InputStream inputStream =
                      classLoader.getResourceAsStream( info.getResource() );
                  return new InputSource( inputStream );
              }
          }
  
          return null;
      }
  
      /**
       * Return CLassLoader to load resource from.
       * If a ClassLoader is specified in the constructor use that,
       * else use ContextClassLoader unless that is null in which case
       * use the current classes ClassLoader.
       */
      private ClassLoader getClassLoader()
      {
          ClassLoader classLoader = m_classLoader;
          if( null == classLoader )
          {
              classLoader = Thread.currentThread().getContextClassLoader();
          }
          if( null == classLoader )
          {
              classLoader = getClass().getClassLoader();
          }
          return classLoader;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/builder/InfoCreator.java
  
  Index: InfoCreator.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.builder;
  
  import org.apache.excalibur.meta.info.Type;
  import java.io.InputStream;
  
  /**
   * Simple interface used to create {@link Type}
   * from stream. This abstraction was primarily created so
   * that the Type could be built from non-XML
   * sources and no XML classes need be in the classpath.
   *
   * @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/05 10:38:59 $
   */
  public interface InfoCreator
  {
      /**
       * Create a {@link Type} 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
       */
      Type createType( String key, InputStream inputStream )
          throws Exception;
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/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 XMLInfoCreator, usually due to not having XML classes on Classpath. Thus unable to lookup XML descriptor for component type "{0}".
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/builder/SerializedInfoCreator.java
  
  Index: SerializedInfoCreator.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.builder;
  
  import org.apache.excalibur.meta.info.Type;
  import java.io.InputStream;
  import java.io.ObjectInputStream;
  
  /**
   * Create {@link Type} from stream made up of
   * serialized object.
   *
   * @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/05 10:38:59 $
   */
  public class SerializedInfoCreator
      implements InfoCreator
  {
      public Type createType( final String key,
                                                final InputStream inputStream )
          throws Exception
      {
          final ObjectInputStream ois = new ObjectInputStream( inputStream );
          return (Type)ois.readObject();
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/builder/TypeBuilder.java
  
  Index: TypeBuilder.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.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.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.excalibur.meta.info.Type;
  
  /**
   * A TypeBuilder is responsible for building {@link Type}
   * objects from Configuration objects. The format for Configuration object
   * is specified in the <a href="package-summary.html#external">package summary</a>.
   *
   * @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/05 10:38:59 $
   */
  public final class TypeBuilder
      extends AbstractLogEnabled
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( TypeBuilder.class );
  
      private final InfoCreator m_xmlInfoCreator = createXMLInfoCreator();
      private final InfoCreator m_serialInfoCreator = new SerializedInfoCreator();
  
      /**
       * Setup logging for all subcomponents
       */
      public void enableLogging( final Logger logger )
      {
          super.enableLogging( logger );
          setupLogger( m_serialInfoCreator );
          if( null != m_xmlInfoCreator )
          {
              setupLogger( m_xmlInfoCreator );
          }
      }
  
      /**
       * Create a {@link Type} object for specified Class.
       *
       * @param clazz The class of Component
       * @return the created Type
       * @throws ConfigurationException if an error occurs
       */
      public Type build( final Class clazz )
          throws Exception
      {
          return build( clazz.getName(), clazz.getClassLoader() );
      }
  
      /**
       * Create a {@link Type} object for specified
       * classname, in specified ClassLoader.
       *
       * @param classname The classname of Component
       * @param classLoader the ClassLoader to load info from
       * @return the created Type
       * @throws ConfigurationException if an error occurs
       */
      public Type build( final String classname,
                                  final ClassLoader classLoader )
          throws Exception
      {
          final Type info = buildFromSerDescriptor( classname, classLoader );
          if( null != info )
          {
              return info;
          }
          else
          {
              return buildFromXMLDescriptor( classname, classLoader );
          }
      }
  
      /**
       * Build Type 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
       */
      private Type buildFromSerDescriptor( final String classname,
                                                    final ClassLoader classLoader )
          throws Exception
      {
          final String xinfo =
              classname.replace( '.', '/' ) + ".sinfo";
          final InputStream inputStream =
              classLoader.getResourceAsStream( xinfo );
          if( null == inputStream )
          {
              return null;
          }
  
          return m_serialInfoCreator.createType( classname, inputStream );
      }
  
      /**
       * Build Type 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
       */
      private Type buildFromXMLDescriptor( final String classname,
                                                    final ClassLoader classLoader )
          throws Exception
      {
          final String xinfo =
              classname.replace( '.', '/' ) + ".xinfo";
          final InputStream inputStream =
              classLoader.getResourceAsStream( xinfo );
          if( null == inputStream )
          {
              final String message =
                  REZ.getString( "builder.missing-info.error",
                                 classname );
              throw new Exception( message );
          }
  
          final InfoCreator xmlInfoCreator = getXMLInfoCreator( classname );
          return xmlInfoCreator.createType( classname, inputStream );
      }
  
      /**
       * Utility to get xml info builder, else throw
       * an exception if missing descriptor.
       *
       * @return the InfoCreator
       */
      private InfoCreator getXMLInfoCreator( final String classname )
          throws Exception
      {
          if( null != m_xmlInfoCreator )
          {
              return m_xmlInfoCreator;
          }
          else
          {
              final String message =
                  REZ.getString( "builder.missing-xml-creator.error",
                                 classname );
              throw new Exception( message );
          }
      }
  
      /**
       * Utility to get XMLInfoCreator if XML files are on
       * ClassPath.
       *
       * @return the XML {@link InfoCreator}
       */
      private static InfoCreator createXMLInfoCreator()
      {
          InfoCreator xmlInfoCreator = null;
          try
          {
              xmlInfoCreator = new XMLInfoCreator();
          }
          catch( final Exception e )
          {
              //Ignore it if ClassNot found due to no
              //XML Classes on classpath
          }
          return xmlInfoCreator;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/builder/XMLInfoCreator.java
  
  Index: XMLInfoCreator.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.builder;
  
  import java.io.InputStream;
  import java.util.ArrayList;
  import java.util.Properties;
  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.context.Context;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.excalibur.meta.info.ComponentDescriptor;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.meta.info.DefaultType;
  import org.apache.excalibur.meta.info.ContextDescriptor;
  import org.apache.excalibur.meta.info.DependencyDescriptor;
  import org.apache.excalibur.meta.info.EntryDescriptor;
  import org.apache.excalibur.meta.info.LoggerDescriptor;
  import org.apache.excalibur.meta.info.ServiceDescriptor;
  import org.apache.excalibur.meta.info.ServiceDesignator;
  import org.xml.sax.InputSource;
  
  /**
   * Handles internalization of an XML based description of a {@link Type}
   * 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:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/05 10:38:59 $
   */
  public final class XMLInfoCreator
      extends AbstractLogEnabled
      implements InfoCreator
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( XMLInfoCreator.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 Type createType( String implementationKey,
                                                InputStream inputStream )
          throws Exception
      {
          final InputSource input = new InputSource( inputStream );
          final String classname = implementationKey;
          final Configuration configuration = ConfigurationBuilder.build( input );
          return build( classname, configuration );
      }
  
      /**
       * Create a {@link Type} object for specified classname from
       * specified configuration data.
       *
       * @param classname The classname of Component
       * @param info the Type configuration
       * @return the created Type
       * @throws ConfigurationException if an error occurs
       */
      private Type build( final String classname,
                                   final Configuration info )
          throws Exception
      {
          if( getLogger().isDebugEnabled() )
          {
              final String message =
                  REZ.getString( "builder.creating-info.notice",
                                 classname );
              getLogger().debug( message );
          }
  
          final String topLevelName = info.getName();
          if( !topLevelName.equals( "component-info" ) )
          {
              final String message =
                  REZ.getString( "builder.bad-toplevel-element.error",
                                 classname,
                                 topLevelName );
              throw new ConfigurationException( message );
          }
  
          Configuration configuration = null;
  
          configuration = info.getChild( "loggers" );
          final LoggerDescriptor[] loggers = buildLoggers( configuration );
  
          configuration = info.getChild( "context" );
          final ContextDescriptor context = buildContext( configuration );
  
          configuration = info.getChild( "services" );
          final ServiceDescriptor[] services = buildServices( configuration );
  
          configuration = info.getChild( "dependencies" );
          final DependencyDescriptor[] dependencies = buildDependencies( classname, configuration );
  
          configuration = info.getChild( "component" );
          final ComponentDescriptor descriptor =
              buildComponentDescriptor( classname, configuration );
  
          if( getLogger().isDebugEnabled() )
          {
              final String message =
                  REZ.getString( "builder.created-info.notice",
                                 classname,
                                 new Integer( services.length ),
                                 new Integer( dependencies.length ),
                                 new Integer( context.getEntrys().length ),
                                 new Integer( loggers.length ) );
              getLogger().debug( message );
          }
  
          return new DefaultType( descriptor, loggers, context, services, dependencies );
      }
  
      /**
       * A utility method to build an array of {@link LoggerDescriptor} objects
       * from specified configuraiton.
       *
       * @param configuration the loggers configuration
       * @return the created LoggerDescriptor
       * @throws ConfigurationException if an error occurs
       */
      private LoggerDescriptor[] buildLoggers( final Configuration configuration )
          throws ConfigurationException
      {
          final Configuration[] elements = configuration.getChildren( "logger" );
          final ArrayList loggers = new ArrayList();
  
          for( int i = 0; i < elements.length; i++ )
          {
              final LoggerDescriptor logger = buildLogger( elements[ i ] );
              loggers.add( logger );
          }
  
          return (LoggerDescriptor[])loggers.toArray( new LoggerDescriptor[ loggers.size() ] );
      }
  
      /**
       * A utility method to build a {@link LoggerDescriptor}
       * object from specified configuraiton.
       *
       * @param logger the Logger configuration
       * @return the created LoggerDescriptor
       * @throws ConfigurationException if an error occurs
       */
      private LoggerDescriptor buildLogger( Configuration logger )
          throws ConfigurationException
      {
          final Properties attributes = buildAttributes( logger.getChild( "attributes" ) );
          final String name = logger.getAttribute( "name", "" );
          return new LoggerDescriptor( name, attributes );
      }
  
      /**
       * A utility method to build an array of {@link DependencyDescriptor}
       * objects from specified configuration and classname.
       *
       * @param classname The classname of Component (used for logging purposes)
       * @param configuration the dependencies configuration
       * @return the created DependencyDescriptor
       * @throws ConfigurationException if an error occurs
       */
      private DependencyDescriptor[] buildDependencies( final String classname,
                                                        final Configuration configuration )
          throws ConfigurationException
      {
          final Configuration[] elements = configuration.getChildren( "dependency" );
          final ArrayList dependencies = new ArrayList();
  
          for( int i = 0; i < elements.length; i++ )
          {
              final DependencyDescriptor dependency =
                  buildDependency( classname, elements[ i ] );
              dependencies.add( dependency );
          }
  
          return (DependencyDescriptor[])dependencies.toArray( new DependencyDescriptor[ 0 ] );
      }
  
      /**
       * A utility method to build a {@link DependencyDescriptor}
       * object from specified configuraiton.
       *
       * @param classname The classname of Component (used for logging purposes)
       * @param dependency the dependency configuration
       * @return the created DependencyDescriptor
       * @throws ConfigurationException if an error occurs
       */
      private DependencyDescriptor buildDependency( final String classname,
                                                    final Configuration dependency )
          throws ConfigurationException
      {
          final ServiceDesignator service =
              buildServiceDesignator( dependency.getChild( "service-ref" ) );
          final boolean optional =
              dependency.getAttributeAsBoolean( "optional", false );
  
          final Properties attributes =
              buildAttributes( dependency.getChild( "attributes" ) );
  
          String role = dependency.getChild( "role" ).getValue( null );
  
          //default to name of service if role unspecified
          if( null == role )
          {
              role = service.getClassname();
          }
          else
          {
              //If role is specified and it is the same as
              //service name then warn that it is redundent.
              if( role.equals( service.getClassname() ) )
              {
                  final String message =
                      REZ.getString( "builder.redundent-role.notice",
                                     classname,
                                     role );
                  getLogger().warn( message );
              }
          }
  
          return new DependencyDescriptor( role, service, optional, attributes );
      }
  
      /**
       * A utility method to build a {@link ContextDescriptor}
       * object from specified configuraiton.
       *
       * @param context the dependency configuration
       * @return the created ContextDescriptor
       * @throws ConfigurationException if an error occurs
       */
      private ContextDescriptor buildContext( final Configuration context )
          throws ConfigurationException
      {
          final EntryDescriptor[] entrys =
              buildEntrys( context.getChildren( "entry" ) );
  
          final Properties attributes =
              buildAttributes( context.getChild( "attributes" ) );
  
          final String type =
              context.getAttribute( "type",
                                    Context.class.getName() );
  
          return new ContextDescriptor( type, entrys, attributes );
      }
  
      /**
       * A utility method to build an array of {@link EntryDescriptor}
       * objects from specified configuraiton.
       *
       * @param entrySet the set of entrys to build
       * @return the created {@link EntryDescriptor}s
       * @throws ConfigurationException if an error occurs
       */
      private EntryDescriptor[] buildEntrys( final Configuration[] entrySet )
          throws ConfigurationException
      {
          final ArrayList entrys = new ArrayList();
  
          for( int i = 0; i < entrySet.length; i++ )
          {
              final EntryDescriptor service = buildEntry( entrySet[ i ] );
              entrys.add( service );
          }
  
          return (EntryDescriptor[])entrys.toArray( new EntryDescriptor[ entrys.size() ] );
      }
  
      /**
       * Create a {@link EntryDescriptor} from configuration.
       *
       * @param config the configuration
       * @return the created {@link EntryDescriptor}
       * @throws ConfigurationException if an error occurs
       */
      private EntryDescriptor buildEntry( final Configuration config )
          throws ConfigurationException
      {
          final String key = config.getAttribute( "key" );
          final String type = config.getAttribute( "type" );
          final boolean optional =
              config.getAttributeAsBoolean( "optional", false );
  
          return new EntryDescriptor( key, type, optional );
      }
  
      /**
       * A utility method to build an array of {@link ServiceDescriptor}
       * objects from specified configuraiton.
       *
       * @param servicesSet the services configuration
       * @return the created ServiceDescriptor
       * @throws ConfigurationException if an error occurs
       */
      private ServiceDescriptor[] buildServices( final Configuration servicesSet )
          throws ConfigurationException
      {
          final Configuration[] elements = servicesSet.getChildren( "service" );
          final ArrayList services = new ArrayList();
  
          for( int i = 0; i < elements.length; i++ )
          {
              final ServiceDescriptor service = buildService( elements[ i ] );
              services.add( service );
          }
  
          return (ServiceDescriptor[])services.toArray( new ServiceDescriptor[ 0 ] );
      }
  
      /**
       * A utility method to build a {@link ServiceDesignator}
       * object from specified configuraiton data.
       *
       * @param service the service Configuration
       * @return the created ServiceDesignator
       * @throws ConfigurationException if an error occurs
       */
      private ServiceDesignator buildServiceDesignator( final Configuration service )
          throws ConfigurationException
      {
          final String name = service.getAttribute( "type" );
          final String versionString = service.getAttribute( "version", "1.0" );
          final Version version = buildVersion( versionString );
          return new ServiceDesignator( name, version );
      }
  
      /**
       * A utility method to build a <code>ServiceDescriptor</code>
       * object from specified configuraiton data.
       *
       * @param service the service Configuration
       * @return the created ServiceDescriptor
       * @throws ConfigurationException if an error occurs
       */
      private ServiceDescriptor buildService( final Configuration service )
          throws ConfigurationException
      {
          final Configuration serviceRef = service.getChild( "service-ref" );
          final ServiceDesignator designator = buildServiceDesignator( serviceRef );
          final Properties attributes =
              buildAttributes( service.getChild( "attributes" ) );
          return new ServiceDescriptor( designator, attributes );
      }
  
      /**
       * Build up a list of attributes from specific config tree.
       *
       * @param config the attributes config
       * @return the Properties object representing attributes
       */
      private Properties buildAttributes( final Configuration config )
          throws ConfigurationException
      {
          final Properties attributes = new Properties();
          final Configuration[] children = config.getChildren( "attribute" );
          for( int i = 0; i < children.length; i++ )
          {
              Configuration child = children[ i ];
              final String key = child.getAttribute( "key" );
              final String value = child.getAttribute( "value" );
              attributes.setProperty( key, value );
          }
          return attributes;
      }
  
      /**
       * A utility method to build a {@link ComponentDescriptor}
       * object from specified configuraiton data and classname.
       *
       * @param classname The classname of Component (used to create descriptor)
       * @param component the Component Configuration
       * @return the created ComponentDescriptor
       * @throws ConfigurationException if an error occurs
       */
      private ComponentDescriptor buildComponentDescriptor( final String classname,
                                                            final Configuration component )
          throws ConfigurationException
      {
          final String name = component.getChild( "name" ).getValue( null );
          final Version version = buildVersion( component.getChild( "version" ).getValue( "1.0" ) );
          final Properties attributes =
              buildAttributes( component.getChild( "attributes" ) );
  
          return new ComponentDescriptor( name, classname, version, attributes );
      }
  
      /**
       * A utility method to parse a Version object from specified string.
       *
       * @param version the version string
       * @return the created Version object
       */
      private Version buildVersion( final String version )
      {
          return Version.getVersion( version );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/builder/componentinfo.dtd
  
  Index: componentinfo.dtd
  ===================================================================
  <!--
  
     This is the DTD defining the Avalon Type 1.0
     descriptor (XML) file format/syntax.
  
     Author: Peter Donald <peter@apache.org>
  
     A BlockInfo is an XML file used to describe Components and located side-by-side with
     the Component .class file. It describes the services the Component requires to operate,
     the services the Component is capable of offerring other Component, the context entrys
     that Component requires and other support meta data.
  
     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.
  
    -->
  
  <!--
  The component-info is the document root, it defines:
  
  component    the specifc details about this component
  loggers      the loggers used by this component
  context      the context required by this component
  services     the services offered by this component
  dependencies the services that this component require to operate
  -->
  <!ELEMENT component-info (component, loggers?, context?, services?, dependencies?)>
  <!--
    !ATTLIST component-info id ID #IMPLIED
            xmlns CDATA #FIXED "http://jakarta.apache.org/avalon/componentinfo_1_0.dtd"
   -->
  
  <!--
  The component element describes the component, it defines:
  
  name	        the human readable name of component type. Must be a string
               containing alphanumeric characters, '.', '_' and starting
               with a letter.
  version	     the version of the component in (in the format #.#.#, #.# or # where
               # is a integer
  -->
  <!ELEMENT component      (name?,version,attributes?)>
    <!ELEMENT name         (#PCDATA) >
    <!ELEMENT version      (#PCDATA) >
  
  <!--
  The logger element defines the loggers that are available to component.
  The element has one attribute specifying name of Logger. It contains:
  
  attributes	  Optional attributes about logger
  -->
  <!ELEMENT logger   (attributes?) >
    <!ATTLIST logger name CDATA #IMPLIED >
  
  <!--
  The context element defines what values and type of context
  is available to component.
  It contains:
  
  entrys    	  Key value pairs that component uses
  attributes	  Optional attributes about service
  -->
  <!ELEMENT context   (entry*,attributes?) >
    <!ATTLIST context type CDATA #IMPLIED >
  
  <!--
  The service element defines a service that the component
  can provide to other component.
  It contains:
  
  service-ref  the reference to service.
  attributes	  Optional attributes about service
  -->
  <!ELEMENT service   (service-ref,attributes?) >
  
  <!--
  The service element defines a reference to a service that the component
  can provide to other component, or this component depends upon.
  It defines:
  
  type         the name of the service. This must be equal to the class name of the
               interface that defines the service.
  version	     the version of the block in (in the format #.#.#, #.# or # where
               # is a integer
  -->
  <!ELEMENT service-ref   EMPTY >
    <!ATTLIST service-ref
         type CDATA #REQUIRED
         version CDATA #IMPLIED >
  
  <!--
  The service dependency describes a service that the component
  requires. It defines:
  
  role         the role of the service. This is the value that is used to lookup the
               service in the ComponentManager. If not provided it defaults to the
               value specified in the name attribute of service element
  service-ref  the service that is required
  -->
  <!ELEMENT dependency  (role?,service-ref,attributes?) >
    <!ATTLIST dependency optional CDATA #IMPLIED >
    <!ELEMENT role        (#PCDATA) >
  
  <!--
  The loggers element contains a list of loggers that component uses.
  -->
  <!ELEMENT loggers    (logger*)>
  
  <!--
  The services element contains a list of services that this component supports.
  It contains service elements.
  -->
  <!ELEMENT services    (service*)>
  
  <!--
  The dependencies element contains a list of services that this component requires.
  It contains dependency elements.
  -->
  <!ELEMENT dependencies    (dependency*)>
  
  <!--
  The attributes element contains a list of attributes for feature.
  -->
  <!ELEMENT attributes    (attribute*)>
  
  <!--
  The attribute element defines an attribute (an opaque key-value pair for a feature).
  It defines:
  
  key          the key for attribute.
  value  	     the value of attribute.
  -->
  <!ELEMENT attribute   EMPTY >
    <!ATTLIST attribute
         key CDATA #REQUIRED
         value CDATA #REQUIRED
    >
  
  <!--
  The entry element defines entry in context.
  It defines:
  
  key          the key for entry.
  value  	     the value of entry.
  optional     is entry optional
  -->
  <!ELEMENT entry   EMPTY >
    <!ATTLIST entry
         key CDATA #REQUIRED
         type CDATA #REQUIRED
         optional CDATA #IMPLIED
    >
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/builder/package.html
  
  Index: package.html
  ===================================================================
  <html><body>
  <p>Component information builder that handels internalization of an component type description supplied as a configuration instance.</P>
  
  <h3>Package Structure (UML)</h3>
  <!--<p><img src=doc-files/TypeBuilder.gif border=0></p>-->
  
  <a name="external"><h3>External Form (XML)</h3></a>
  <p>Configuration instances supplied to the builder shall correspond to the <a href="http://home.osm.net/componentinfo.dtd">component-info DTD</a>.  
  The structure of a component-info XML document is is described below:</p>
  
  <pre>
  
  <font color="gray"><i>&lt;!--
  Example of a component meta info external XML form. 
  The element contains the information required to construct an instance of
  org.apache.excalibur.containerkit.metainfo.ComponentInfo.  It includes 
  information about the component type, the service it provides, and the 
  services it is dependent on.
  --&gt;</i></font>
  
  &lt;component-info&gt;
  
  
    <font color="gray"><i>&lt;!--
    Defintion of a single component descriptor.
    --&gt;</i></font>
  
    &lt;component&gt;
  
      <font color="gray"><i>&lt;!-- the name of the component (character restriction appply) --&gt;</i></font>
  
      &lt;name&gt;<font color="darkred">my-component</font>&lt;/name&gt;
  
      <font color="gray"><i>&lt;!-- the implementation version --&gt;</i></font>
  
      &lt;version&gt;</strong><font color="darkred">1.2.1</font>&lt;/version&gt;
  
      <font color="gray"><i>&lt;!-- the set of attribibutes associated with the type
           (attribute names and values are examples only) --&gt;</i></font>
  
      &lt;attributes&gt;
  
         &lt;attribute key="<font color="darkred">avalon:display-name-i18n</font>" value="<font color="darkred">display-name</font>"/&gt;
         &lt;attribute key="<font color="darkred">avalon:lifestyle</font>" value="<font color="darkred">THREAD_SAFE</font>"/&gt;
  
      &lt;/attributes&gt;
  
    &lt;/component&gt;
  
    <font color="gray"><i>&lt;!-- 
    Declaration of the context constraints for the compoent type. 
    The "type" attribute is the name of an interface derived from the default
    contenxt interface org.apache.avalon.framework.context.Context 
    --&gt;</i></font>
  
    &lt;context type="<font color="darkred">MyContextInterface</font>"&gt;
  
      <font color="gray"><i>&lt;!-- 
      Declaration of an entry in a context object, the "key" is
      the key used by a component to locate the context entry,
      the "type" is the classname of value (typically an interface)
      or primative type.  The default value is java.lang.String.
      The "optional" attribute is a boolean value derived from the 
      TRUE or FALSE that indicates if the context value must be 
      provided or not (default is FALSE). 
      --&gt;</i></font>
  
      &lt;entry key="<font color="darkred">base</font>" type="<font color="darkred">java.io.File</font>"/&gt;
      &lt;entry key="<font color="darkred">mode</font>" optional="<font color="darkred">TRUE</font>"/&gt;
  
    &lt;/context&gt;
  
    <font color="gray"><i>&lt;!--
    Declaration of the set of services that this component is capable 
    of supplying.  Each service declarared under the services element
    may be referenced by other component info descriptions as a 
    dependecy.  A container is responsible for the assemably of 
    components based on the connection of supply components to 
    consumer components via a common service description. 
    --&gt;</i></font>
  
    &lt;services&gt;
  
        <font color="gray"><i>&lt;!-- 
        The service type is the classname of an interface and the
        version identifier qualifes the interface version.  The 
        default version value is 1.0.
        --&gt;</i></font>
  
        &lt;service&gt;
  
          &lt;service-ref type="<font color="darkred">SimpleService</font>" version="<font color="darkred">3.2</font>"&gt;
  
          &lt;attributes&gt;
  
             <font color="gray"><i>&lt;!--
             Service type attributes go here.
             Need some relevant examples. 
             --&gt;</i></font>
  
          &lt;/attributes&gt;
  
        &lt;/service&gt;
  
    &lt;/services&gt;
  
  
    <font color="gray"><i>&lt;!-- 
    Declaration of the set of dependecies that this component type has on 
    component suppliers.  Dependency declarations define the role name 
    that the component will use to access a service via a service
    or component manager.  The service element identifies a service 
    descriptor that is publised by a potential supplier component. 
    A dependecy may be declared as optional by setting the optional 
    attribute value to TRUE.  The default value for optional is FALSE.
    --&gt;</i></font>
  
    &lt;dependencies&gt;
  
      <font color="gray"><i>&lt;!-- 
      A dependecy declaration. In the following example the optional 
      attribute is redundant as it is equivalent to the default value
      but is included here for completness.
      --&gt;</i></font>
  
      &lt;dependency optional="<font color="darkred">FALSE</font>"&gt;
  
        <font color="gray"><i>&lt;!-- 
        The role name that the component will use as the argument to 
        lookup. The default value is the value of the service type 
        attribute listed below.
        --&gt;</i></font>
  
        &lt;role&gt;<font color="darkred">my-transformer</font>&lt;/role&gt;
  
        <font color="gray"><i>&lt;!-- 
        service reference containing the classname of the service interface
        and the version value where version defaults to 1.0 
        --&gt;</i></font>
  
        &lt;service-ref type="<font color="darkred">org.apache.cocoon.api.Transformer</font>" version="<font color="darkred">1.1</font>"/&gt;
  
        <font color="gray"><i>&lt;!-- the set of attributes associated with the dependency --&gt;</i></font>
  
        &lt;attributes&gt;
  
             <font color="gray"><i>&lt;!-- 
             Service type constraints go here.
             Need some relevant examples. 
             --&gt;</i></font>
  
        &lt;/attributes&gt;
  
      &lt;/dependency&gt;
  
    &lt;/dependencies&gt;
  
  &lt;/component-info&gt;
  
  </pre>
  
  </body></html>
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/data/Assignment.java
  
  Index: Assignment.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.data;
  
  
  
  /**
   * The Assignment 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 Assignment which
   * has a matching role. The name value in Assignment 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/05 10:39:00 $
   */
  public final class Assignment
  {
      /**
       * 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 Assignment( 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/meta/data/Assignment.java~
  
  Index: Assignment.java~
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.data;
  
  /**
   * The Assignment 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 Assignment which
   * has a matching role. The name value in Assignment 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/05 10:39:00 $
   */
  public interface Assignment
  {
      /**
       * 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 the <code>Profile</code> instance that will used to
       * fulfill the dependency.
       *
       * @return the component that will provide the dependency.
       */
      public Profile getProvider();
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/data/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.meta.data;
  
  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.meta.data.Profile;
  import org.apache.excalibur.meta.data.Assignment;
  
  /**
   * Each component declared in the application is represented by
   * a ComponentProfile. 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/05 10:39:00 $
   */
  public class DefaultProfile 
    implements Profile
  {
      /**
       * 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_componentInfo;
  
      /**
       * 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;
  
      /**
       * Create a Profile instance.
       *
       * @param name the abstract name of component meta data instance
       * @param dependencies the meta data for any dependencies
       * @param componentInfo the component componentInfo desribing the component type
       */
      public DefaultProfile( final String name,
                                final Parameters parameters,
                                final Configuration configuration,
                                final Context context,
                                final Type componentInfo )
      {
          if( null == name )
          {
              throw new NullPointerException( "name" );
          }
          if( null == componentInfo )
          {
              throw new NullPointerException( "componentInfo" );
          }
  
          m_name = name;
          m_parameters = parameters;
          m_configuration = configuration;
          m_componentInfo = componentInfo;
          m_context = context;
      }
  
      /**
       * 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 getInfo()
      {
          return m_componentInfo;
      }
  
      /**
       * Return the assigned service providers.
       *
       * @return the set of service provider assignments.
       */
      public Assignment[] getAssignments()
      {
          return (Assignment[])m_dependencies.values().toArray( new Assignment[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 dependency metadata for component type with specified role.
       *
       * @return the dependency metadata for component with specified role.
       */
      public Assignment getAssignment( final String role )
      {
          return (Assignment) m_dependencies.get( role );
      }
  
     /**
      * 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 Assignment( role, provider ) );
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/data/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.meta.data;
  
  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 ComponentProfile. 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/05 10:39:00 $
   */
  public interface Profile
  {
  
      /**
       * Return the name of component metadata instance.
       *
       * @return the name of the component.
       */
      public String getName();
  
      /**
       * Return the info for component.
       *
       * @return the info for component type.
       */
      public Type getInfo();
  
      /**
       * Return the assigned service providers.
       *
       * @return the dependency metadata for component.
       */
      public Assignment[] getAssignments();
  
      /**
       * Return the Parameters for component (if any).
       *
       * @return the Parameters for Component (if any).
       */
      public Parameters getParameters();
  
      /**
       * Return the Configuration for component(if any).
       *
       * @return the Configuration for component
       */
      public Configuration getConfiguration();
  
      /**
       * Return the Context for component (if any).
       *
       * @return the Context for component
       */
      public Context getContext();
  
      /**
       * Return the Assignment for specified role.
       *
       * @return the Assignment for specified role.
       */
      public Assignment getAssignment( final String role );
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/data/package.html
  
  Index: package.html
  ===================================================================
  
  <body>
  <p>
  Profile is the assembly of object instances that collectively defines a potential instantiation state for the type including information about the references to provider components capable of servicing declared dependecies, together with logging, configuration, parameterization, and contextualization state.
  </p>
  </body>
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/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.meta.info;
  
  import java.util.Properties;
  import org.apache.avalon.framework.Version;
  
  /**
   * This class is used to provide explicit information to assembler
   * and administrator about the Component. It includes information
   * such as;
   *
   * <ul>
   *   <li>a symbolic name</li>
   *   <li>classname</li>
   *   <li>version</li>
   * </ul>
   *
   * <p>The ComponentDescriptor also includes an arbitrary set
   * of attributes about component. Usually these are container
   * specific attributes that can store arbitrary information.
   * The attributes should be stored with keys based on package
   * name of container. 
   *
   * @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/05 10:39:00 $
   */
  public final class ComponentDescriptor extends Descriptor 
  {
      /**
       * The short name of the Component Type. Useful for displaying
       * human readable strings describing the type in
       * assembly tools or generators.
       */
      private final String m_name;
  
      /**
       * The implementation key for component (usually classname).
       */
      private final String m_implementationKey;
  
      /**
       * The version of component that descriptor describes.
       */
      private final Version m_version;
  
      public ComponentDescriptor( final String name,
                                  final String key,
                                  final Version version,
                                  final Properties attributes )
      {
          super( attributes );
  
          if( key.indexOf("/") > -1 )
          {
              throw new IllegalArgumentException( "implementationKey: " + key );
          }
  
          m_name = name;
          m_implementationKey = key;
          m_version = version;
      }
  
      /**
       * Return the symbolic name of component.
       *
       * @return the symbolic name of component.
       */
      public String getName()
      {
          return m_name;
      }
  
      /**
       * Return the implementation key for component (usually classname).
       *
       * @return the implementation key for component (usually classname).
       */
      public String getImplementationKey()
      {
          return m_implementationKey;
      }
  
      /**
       * Return the version of component.
       *
       * @return the version of component.
       */
      public Version getVersion()
      {
          return m_version;
      }
  }
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/ContextDescriptor.java
  
  Index: ContextDescriptor.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.info;
  
  import java.util.Properties;
  
  import org.apache.excalibur.meta.info.EntryDescriptor;
  
  /**
   * A descriptor describing the Context that the Component
   * is passed to describe information about Runtime environment
   * of Component. It contains information such as;
   * <ul>
   *   <li>classname: the classname of the Context type if it
   *       differs from base Context class (ie BlockContext).</li>
   *   <li>entrys: a list of entrys contained in context</li>
   * </ul>
   *
   * <p>Also associated with each Context is a set of arbitrary
   * attributes that can be used to store extra information
   * about Context requirements.</p>
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/05 10:39:00 $
   */
  public class ContextDescriptor extends Descriptor 
  {
      private final String m_type;
      private final EntryDescriptor[] m_entrys;
  
      /**
       * Create a descriptor sans attributes.
       */
      public ContextDescriptor( final String type,
                                final EntryDescriptor[] entrys )
      {
          this( type, entrys, null );
      }
  
      /**
       * Create a descriptor.
       * @exception NullPointerException if type or entrys argument is null
       * @exception IllegalArgumentException if the classname format is invalid
       */
      public ContextDescriptor( final String type,
                                final EntryDescriptor[] entrys,
                                final Properties attributes )
      {
          super( attributes );
  
          if( null == type )
          {
              throw new NullPointerException( "type" );
          }
  
          if( null == entrys )
          {
              throw new NullPointerException( "entrys" );
          }
  
          if( type.indexOf("/") > -1 )
          {
              throw new IllegalArgumentException( "classname: " + type );
          }
  
          m_type = type;
          m_entrys = entrys;
      }
  
      /**
       * Return the type of Context class.
       *
       * @return the type of Context class.
       */
      public String getType()
      {
          return m_type;
      }
  
      /**
       * Return the entrys contained in the context.
       *
       * @return the entrys contained in the context.
       */
      public EntryDescriptor[] getEntrys()
      {
          return m_entrys;
      }
  
      /**
       * Return the entry with specified key.
       *
       * @return the entry with specified key.
       */
      public EntryDescriptor getEntry( final String key )
      {
          for( int i = 0; i < m_entrys.length; i++ )
          {
              final EntryDescriptor entry = m_entrys[ i ];
              if( entry.getKey().equals( key ) )
              {
                  return entry;
              }
          }
          return null;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/DefaultType.java
  
  Index: DefaultType.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.info;
  
  import java.io.Serializable;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.meta.info.ComponentDescriptor;
  import org.apache.excalibur.meta.info.ContextDescriptor;
  import org.apache.excalibur.meta.info.DependencyDescriptor;
  import org.apache.excalibur.meta.info.LoggerDescriptor;
  import org.apache.excalibur.meta.info.ServiceDescriptor;
  import org.apache.excalibur.meta.info.ServiceDesignator;
  
  /**
   * This class contains the meta information about a particular
   * component type. It describes;
   *
   * <ul>
   *   <li>Human presentable meta data such as name, version, description etc
   *   useful when assembling the system.</li>
   *   <li>the context object capabilities that this component requires</li>
   *   <li>the services that this component type is capable of providing</li>
   *   <li>the services that this component type requires to operate (and the
   *   names via which services are accessed)</li>
   * </ul>
   *
   * @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/05 10:39:00 $
   */
  public class DefaultType implements Type, Serializable
  {
      private final ComponentDescriptor m_descriptor;
      private final ContextDescriptor m_context;
      private final ServiceDescriptor[] m_services;
      private final DependencyDescriptor[] m_dependencies;
      private final LoggerDescriptor[] m_loggers;
  
      /**
       * Basic constructor that takes as parameters all parts.
       */
      public DefaultType( final ComponentDescriptor descriptor,
                            final LoggerDescriptor[] loggers,
                            final ContextDescriptor context,
                            final ServiceDescriptor[] services,
                            final DependencyDescriptor[] dependencies )
      {
          if( null == descriptor )
          {
              throw new NullPointerException( "descriptor" );
          }
          if( null == loggers )
          {
              throw new NullPointerException( "loggers" );
          }
          if( null == context )
          {
              throw new NullPointerException( "context" );
          }
          if( null == services )
          {
              throw new NullPointerException( "services" );
          }
          if( null == dependencies )
          {
              throw new NullPointerException( "dependencies" );
          }
          m_descriptor = descriptor;
          m_loggers = loggers;
          m_context = context;
          m_services = services;
          m_dependencies = dependencies;
      }
  
      /**
       * Return the Component descriptor.
       *
       * @return the Component descriptor.
       */
      public ComponentDescriptor getDescription()
      {
          return m_descriptor;
      }
  
      /**
       * Return the set of Logger that this Component will use.
       *
       * @return the set of Logger that this Component will use.
       */
      public LoggerDescriptor[] getLoggers()
      {
          return m_loggers;
      }
  
      /**
       * Return the ContextDescriptor for Component, may be null.
       * If null then this component does not implement Contextualizable.
       *
       * @return the ContextDescriptor for Component, may be null.
       */
      public ContextDescriptor getContextDescriptor()
      {
          return m_context;
      }
  
      /**
       * Return the set of Services that this Component is capable of providing.
       *
       * @return the set of Services that this Component is capable of providing.
       */
      public ServiceDescriptor[] getServices()
      {
          return m_services;
      }
  
      /**
       * Return the set of Dependencies that this Component requires to operate.
       *
       * @return the set of Dependencies that this Component requires to operate.
       */
      public DependencyDescriptor[] getDependencies()
      {
          return m_dependencies;
      }
  
      /**
       * Retrieve a dependency with a particular role.
       *
       * @param role the role
       * @return the dependency or null if it does not exist
       */
      public DependencyDescriptor getDependency( final String role )
      {
          for( int i = 0; i < m_dependencies.length; i++ )
          {
              if( m_dependencies[ i ].getRole().equals( role ) )
              {
                  return m_dependencies[ i ];
              }
          }
  
          return null;
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/DependencyDescriptor.java
  
  Index: DependencyDescriptor.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.info;
  
  import java.util.Properties;
  
  /**
   * A descriptor that describes dependency information for
   * a particular Component. This class contains information
   * about;
   * <ul>
   *   <li>role: the name component uses to look up dependency</li>
   *   <li>service: the class/interface that the dependency must provide</li>
   * </ul>
   *
   * <p>Also associated with each dependency is a set of arbitrary
   * attributes that can be used to store extra information
   * about dependency. See {@link ComponentDescriptor} for example
   * of how to declare the container specific attributes.</p>
   *
   * <p>Possible uses for the attributes are to declare container
   * specific constraints of component. For example a dependency on
   * a Corba ORB may also require that the Corba ORB contain the
   * TimeServer and PersistenceStateService at initialization. Or it
   * may require that the componenet be multi-thread safe or that
   * it is persistent etc. These are all container specific
   * demands.</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/05 10:39:00 $
   */
  public final class DependencyDescriptor extends Descriptor
  {
      /**
       * The name the component uses to lookup dependency.
       */
      private final String m_role;
  
      /**
       * The service class/interface that the dependency must provide.
       */
      private final ServiceDesignator m_service;
  
      /**
       * True if dependency is optional, false otherwise.
       */
      private final boolean m_optional;
  
      /**
       * Constructor a dependency sans Attributes.
       */
      public DependencyDescriptor( final String role,
                                   final ServiceDesignator service )
      {
          this( role, service, false, null );
      }
  
      /**
       * Constructor that has all parts sans parent.
       */
      public DependencyDescriptor( final String role,
                                   final ServiceDesignator service,
                                   final boolean optional,
                                   final Properties attributes )
      {
          super( attributes );
  
          if( null == role )
          {
              throw new NullPointerException( "role" );
          }
  
          if( null == service )
          {
              throw new NullPointerException( "service" );
          }
  
          m_role = role;
          m_service = service;
          m_optional = optional;
      }
  
      /**
       * Return the name the component uses to lookup dependency.
       *
       * @return the name the component uses to lookup dependency.
       */
      public String getRole()
      {
          return m_role;
      }
  
      /**
       * Return the service class/interface descriptor that describes the
       * dependency must fulfilled by a provider.
       *
       * @return a reference to service descriptor that describes the fulfillment
       *  obligations that must be met by a service provider.
       */
      public ServiceDesignator getService()
      {
          return m_service;
      }
  
      /**
       * Return true if dependency is optional, false otherwise.
       *
       * @return true if dependency is optional, false otherwise.
       */
      public boolean isOptional()
      {
          return m_optional;
      }
  
      /**
       * Return true if dependency is required, false otherwise.
       *
       * @return true if dependency is required, false otherwise.
       */
      public boolean isRequired()
      {
          return !isOptional();
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/Descriptor.java
  
  Index: Descriptor.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.info;
  
  import java.util.Properties;
  import java.io.Serializable;
  
  
  /**
   * This is the Abstract class for all feature feature descriptors.
   *
   * @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/05 10:39:00 $
   */
  public abstract class Descriptor
      implements Serializable
  {
      private static final String[] EMPTY_SET = new String[0];
  
      /**
       * The arbitrary set of attributes associated with Component.
       */
      private final Properties m_attributes;
  
      protected Descriptor( final Properties attributes )
      {
          m_attributes = attributes;
      }
  
      /**
       * Return the attribute for specified key.
       *
       * @return the attribute for specified key.
       */
      public String getAttribute( final String key )
      {
          if( null == m_attributes )
          {
              return null;
          }
          else
          {
              return m_attributes.getProperty( key );
          }
      }
  
      /**
       * Return the attribute for specified key.
       *
       * @return the attribute for specified key.
       */
      public String getAttribute( final String key,
                                  final String defaultValue )
      {
          if( null == m_attributes )
          {
              return defaultValue;
          }
          else
          {
              return m_attributes.getProperty( key, defaultValue );
          }
      }
  
      /**
      * Returns the set of attribute names available under this descriptor.
      *
      * @return an array of the properties names held by the descriptor.
      */
      public String[] getAttributeNames()
      {
          if( null == m_attributes )
          {
              return EMPTY_SET;
          }
          else
          {
              return (String[]) m_attributes.keySet().toArray( EMPTY_SET );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/EntryDescriptor.java
  
  Index: EntryDescriptor.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.info;
  
  import java.io.Serializable;
  
  /**
   * A descriptor that describes a value that must be placed
   * in components Context. It contains information about;
   * <ul>
   *   <li>key: the key that component uses to look up entry</li>
   *   <li>type: the class/interface of the entry</li>
   *   <li>isOptional: true if entry is optional rather than required</li>
   * </ul>
   *
   * @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/05 10:39:00 $
   */
  public final class EntryDescriptor
      implements Serializable
  {
      /**
       * The name the component uses to lookup entry.
       */
      private final String m_key;
  
      /**
       * The class/interface of the Entry.
       */
      private final String m_type;
  
      /**
       * True if entry is optional, false otherwise.
       */
      private final boolean m_optional;
  
      /**
       * Construct an Entry.
       */
      public EntryDescriptor( final String key,
                              final String type )
      {
          this( key, type, false );
      }
  
      /**
       * Construct an Entry.
       */
      public EntryDescriptor( final String key,
                              final String type,
                              final boolean optional )
      {
          if( null == key )
          {
              throw new NullPointerException( "key" );
          }
  
          if( null == type )
          {
              throw new NullPointerException( "type" );
          }
  
          m_key = key;
          m_type = type;
          m_optional = optional;
      }
  
      /**
       * Return the key that Component uses to lookup entry.
       *
       * @return the key that Component uses to lookup entry.
       */
      public String getKey()
      {
          return m_key;
      }
  
      /**
       * Return the key type of value that is stored in Context.
       *
       * @return the key type of value that is stored in Context.
       */
      public String getType()
      {
          return m_type;
      }
  
      /**
       * Return true if entry is optional, false otherwise.
       *
       * @return true if entry is optional, false otherwise.
       */
      public boolean isOptional()
      {
          return m_optional;
      }
  
      /**
       * Return true if entry is required, false otherwise.
       *
       * @return true if entry is required, false otherwise.
       */
      public boolean isRequired()
      {
          return !isOptional();
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/LoggerDescriptor.java
  
  Index: LoggerDescriptor.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.info;
  
  import java.util.Properties;
  
  /**
   * A descriptor describing the Loggers that the Component
   * will use. The name of each Logger is relative to the
   * Logger passed to the component (namespace separator is '.').
   * "" names root logger.
   *
   * <p>Also associated with each Logger is a set of arbitrary
   * attributes that can be used to store extra information
   * about Logger requirements.</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/05 10:39:00 $
   */
  public class LoggerDescriptor
      extends Descriptor
  {
      private final String m_name;
  
      /**
       * Create a descriptor for Logger.
       *
       * @exception NullPointerException if name argument is null
       */
      public LoggerDescriptor( final String name,
                               final Properties attributes )
      {
          super( attributes );
          if( null == name )
          {
              throw new NullPointerException( "name" );
          }
  
          m_name = name;
      }
  
      /**
       * Return the name of logger.
       *
       * @return the name of Logger.
       */
      public String getName()
      {
          return m_name;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  #From ComponentDescriptor and ContextDescriptor classes
  component.invalid-classname.error=Invalid classname {1}.
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/ServiceDescriptor.java
  
  Index: ServiceDescriptor.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.info;
  
  import java.util.Properties;
  import org.apache.avalon.framework.Version;
  
  
  /**
   * This descriptor defines the type of service offerend or required
   * by a component. The type corresponds to the class name of the
   * class/interface implemented by component. Associated with each
   * classname is a version object so that different versions of same
   * interface can be represented.
   *
   * <p>Also associated with each service is a set of arbitrary
   * attributes that can be used to store extra information
   * about service. See {@link ComponentDescriptor} for example
   * of how to declare the container specific attributes.</p>
   *
   * <p>Possible uses for the attributes are to declare a service
   * as "stateless", "pass-by-value", "remotable" or even to attach
   * attributes such as security or transaction constraints. These
   * attributes are container specific and should not be relied
   * upon to work in all containers.</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/05 10:39:00 $
   */
  public final class ServiceDescriptor
      extends Descriptor
  {
      /**
       * The service reference that descriptor is describing.
       */
      private final ServiceDesignator m_designator;
  
      /**
       * Construct a service descriptor for specified ServiceDesignator.
       *
       * @param designator the ServiceDesignator
       */
      public ServiceDescriptor( final ServiceDesignator designator )
      {
          this( designator, null );
      }
  
      /**
       * Construct a service with specified name, version and attributes.
       *
       * @param designator the ServiceDesignator
       * @param attributes the attributes of service
       */
      public ServiceDescriptor( final ServiceDesignator designator,
                                final Properties attributes )
      {
          super( attributes );
  
          if( null == designator )
          {
              throw new NullPointerException( "designator" );
          }
  
          m_designator = designator;
      }
  
      /**
       * Retrieve the service that service descriptor refers to.
       *
       * @return the service that service descriptor refers to.
       */
      public ServiceDesignator getServiceDesignator()
      {
          return m_designator;
      }
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/ServiceDesignator.java
  
  Index: ServiceDesignator.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.info;
  
  import java.io.Serializable;
  import org.apache.avalon.framework.Version;
  
  /**
   * This service reference defines the type of service required
   * by a component. The type corresponds to the class name of the
   * class/interface implemented by component. Associated with each
   * classname is a version object so that different versions of same
   * interface can be represented.
   *
   * @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/05 10:39:00 $
   */
  public final class ServiceDesignator
      implements Serializable
  {
      /**
       * The name of service class.
       */
      private final String m_classname;
  
      /**
       * The version of service class.
       */
      private final Version m_version;
  
      /**
       * Construct a service with specified name, version and attributes.
       *
       * @param classname the name of the service
       * @param version the version of service
       */
      public ServiceDesignator( final String classname,
                                final Version version )
      {
          if( null == classname )
          {
              throw new NullPointerException( "classname" );
          }
  
          if( null == version )
          {
              throw new NullPointerException( "version" );
          }
  
          m_classname = classname;
          m_version = version;
      }
  
      /**
       * Return classname of Service (which coresponds to the interface
       * name eg org.apache.block.WebServer)
       *
       * @return the classname of the Service
       */
      public String getClassname()
      {
          return m_classname;
      }
  
      /**
       * Return the version of interface
       *
       * @return the version of interface
       */
      public Version getVersion()
      {
          return m_version;
      }
  
      /**
       * Determine if specified service will match this service.
       * To match a service has to have same name and must comply with version.
       *
       * @param other the other ServiceInfo
       * @return true if matches, false otherwise
       */
      public boolean matches( final ServiceDesignator other )
      {
          return
              other.getClassname().equals( getClassname() ) &&
              other.getVersion().complies( getVersion() );
      }
  
      /**
       * Convert to a string of format name/version
       *
       * @return string describing service
       */
      public String toString()
      {
          return getClassname() + "/" + getVersion();
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/Type.java
  
  Index: Type.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.info;
  
  /**
   * This class contains the meta information about a particular
   * component type. It describes;
   *
   * <ul>
   *   <li>Human presentable meta data such as name, version, description etc
   *   useful when assembling the system.</li>
   *   <li>the context object capabilities that this component requires</li>
   *   <li>the services that this component type is capable of providing</li>
   *   <li>the services that this component type requires to operate (and the
   *   names via which services are accessed)</li>
   * </ul>
   *
   * @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/05 10:39:00 $
   */
  public interface Type
  {
  
      /**
       * Return the Component descriptor.
       *
       * @return the Component descriptor.
       */
      public ComponentDescriptor getDescription();
  
      /**
       * Return the set of Logger that this Component will use.
       *
       * @return the set of Logger that this Component will use.
       */
      public LoggerDescriptor[] getLoggers();
  
      /**
       * Return the ContextDescriptor for Component, may be null.
       * If null then this component does not implement Contextualizable.
       *
       * @return the ContextDescriptor for Component, may be null.
       */
      public ContextDescriptor getContextDescriptor();
  
      /**
       * Return the set of Services that this Component is capable of providing.
       *
       * @return the set of Services that this Component is capable of providing.
       */
      public ServiceDescriptor[] getServices();
  
      /**
       * Return the set of Dependencies that this Component requires to operate.
       *
       * @return the set of Dependencies that this Component requires to operate.
       */
      public DependencyDescriptor[] getDependencies();
  
      /**
       * Retrieve a dependency with a particular role.
       *
       * @param role the role
       * @return the dependency or null if it does not exist
       */
      public DependencyDescriptor getDependency( final String role );
  
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/info/package.html
  
  Index: package.html
  ===================================================================
  
  <body>
  <p>
  Type is an assembly of descriptors of the constraints a component
  type declares towards a container and includes declaration of service 
  dependencies, Logger establishment criteria, Configuration, Parameters 
  and Context establishment criteria, in addition to human-readable 
  information about the component type.
  </p>
  </body>
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/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.meta.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.data.Profile;
  import org.apache.excalibur.meta.data.Assignment;
  import org.apache.excalibur.meta.info.Type;
  import org.apache.excalibur.meta.info.DependencyDescriptor;
  import org.apache.excalibur.meta.info.ServiceDescriptor;
  import org.apache.excalibur.meta.info.ServiceDesignator;
  
  /**
   * This Class verifies that Sars are valid. It performs a number
   * of checks to make sure that the Sar represents a valid
   * application and excluding runtime errors will start up validly.
   * Some of the checks it performs 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/05 10:39:00 $
   */
  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().info( message );
          verifyValidNames( components );
  
          message = REZ.getString( "assembly.unique-names.notice" );
          getLogger().info( message );
          checkNamesUnique( components );
  
          message = REZ.getString( "assembly.dependencies-mapping.notice" );
          getLogger().info( message );
          verifyValidDependencies( components );
  
          message = REZ.getString( "assembly.dependency-references.notice" );
          getLogger().info( message );
          verifyDependencyReferences( components );
  
          message = REZ.getString( "assembly.nocircular-dependencies.notice" );
          getLogger().info( 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 Assignment[] deps = component.getAssignments();
  
          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.getInfo();
          final Assignment[] roles = component.getAssignments();
  
          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.getInfo().getServices();
              if( !hasMatchingService( service, services ) )
              {
                  final String message =
                      REZ.getString( "assembly.dependency-missing-service.error",
                                     providerName,
                                     service,
                                     component.getName() );
                  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 Assignment 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 Assignment[] dependencySet = component.getAssignments();
  
          for( int i = 0; i < dependencySet.length; i++ )
          {
              final String roleName = dependencySet[ i ].getRole();
              final DependencyDescriptor descriptor = component.getInfo().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.getInfo().getDependencies();
          for( int i = 0; i < dependencies.length; i++ )
          {
              final DependencyDescriptor dependency = dependencies[ i ];
              final Assignment role = component.getAssignment( 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 ].getServiceDesignator();
              if( service.matches( other ) )
              {
                  return true;
              }
          }
  
          return false;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/verifier/ComponentVerifier.java
  
  Index: ComponentVerifier.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.verifier;
  
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Modifier;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.framework.activity.Suspendable;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.component.Recomposable;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Reconfigurable;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.context.Recontextualizable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.logger.LogEnabled;
  import org.apache.avalon.framework.parameters.Parameterizable;
  import org.apache.avalon.framework.parameters.Reparameterizable;
  import org.apache.avalon.framework.service.Serviceable;
  
  /**
   * Utility class to help verify that component respects the
   * rules of an Avalon component.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/05 10:39:00 $
   */
  public class ComponentVerifier
      extends AbstractLogEnabled
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( ComponentVerifier.class );
  
      private static final Class[] EMPTY_TYPES = new Class[ 0 ];
  
      /**
       * The interfaces representing lifecycle stages.
       */
      private static final Class[] FRAMEWORK_CLASSES = new Class[]
      {
          LogEnabled.class,
          Contextualizable.class,
          Recontextualizable.class,
          Composable.class,
          Recomposable.class,
          Serviceable.class,
          Configurable.class,
          Reconfigurable.class,
          Parameterizable.class,
          Reparameterizable.class,
          Initializable.class,
          Startable.class,
          Suspendable.class,
          Disposable.class
      };
  
      /**
       * Verify that the supplied implementation class
       * and service classes are valid for a component.
       *
       * @param name the name of component
       * @param implementation the implementation class of component
       * @param services the classes representing services
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyComponent( final String name,
                                   final Class implementation,
                                   final Class[] services )
          throws VerifyException
      {
          verifyClass( name, implementation );
          verifyLifecycles( name, implementation );
          verifyServices( name, services );
          verifyImplementsServices( name, implementation, services );
      }
  
      /**
       * Verify that the supplied implementation implements the specified
       * services.
       *
       * @param name the name of component
       * @param implementation the class representign component
       * @param services the services that the implementation must provide
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyImplementsServices( final String name,
                                            final Class implementation,
                                            final Class[] services )
          throws VerifyException
      {
          for( int i = 0; i < services.length; i++ )
          {
              if( !services[ i ].isAssignableFrom( implementation ) )
              {
                  final String message =
                      REZ.getString( "verifier.noimpl-service.error",
                                     name,
                                     implementation.getName(),
                                     services[ i ].getName() );
                  throw new VerifyException( message );
              }
          }
      }
  
      /**
       * Verify that the supplied class is a valid class for
       * a Component.
       *
       * @param name the name of component
       * @param clazz the class representing component
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyClass( final String name,
                               final Class clazz )
          throws VerifyException
      {
          verifyNoArgConstructor( name, clazz );
          verifyNonAbstract( name, clazz );
          verifyNonArray( name, clazz );
          verifyNonInterface( name, clazz );
          verifyNonPrimitive( name, clazz );
          verifyPublic( name, clazz );
      }
  
      /**
       * Verify that the supplied classes are valid classes for
       * a service.
       *
       * @param name the name of component
       * @param classes the classes representign services
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyServices( final String name,
                                  final Class[] classes )
          throws VerifyException
      {
          for( int i = 0; i < classes.length; i++ )
          {
              verifyService( name, classes[ i ] );
          }
      }
  
      /**
       * Verify that the supplied class is a valid class for
       * a service.
       *
       * @param name the name of component
       * @param clazz the class representign service
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyService( final String name,
                                 final Class clazz )
          throws VerifyException
      {
          verifyServiceIsaInterface( name, clazz );
          verifyServiceIsPublic( name, clazz );
          verifyServiceNotALifecycle( name, clazz );
      }
  
      /**
       * Verify that the implementation class does not
       * implement incompatible lifecycle interfaces.
       *
       * @param name the name of component
       * @param implementation the implementation class
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyLifecycles( final String name,
                                    final Class implementation )
          throws VerifyException
      {
          final boolean composable =
              Composable.class.isAssignableFrom( implementation ) ||
              Recomposable.class.isAssignableFrom( implementation );
          final boolean serviceable = Serviceable.class.isAssignableFrom( implementation );
          if( serviceable && composable )
          {
              final String message =
                  REZ.getString( "verifier.incompat-serviceable.error",
                                 name,
                                 implementation.getName() );
              getLogger().error( message );
              throw new VerifyException( message );
          }
  
          final boolean configurable =
              Configurable.class.isAssignableFrom( implementation ) ||
              Reconfigurable.class.isAssignableFrom( implementation );
          final boolean parameterizable =
              Parameterizable.class.isAssignableFrom( implementation ) ||
              Reparameterizable.class.isAssignableFrom( implementation );
          if( parameterizable && configurable )
          {
              final String message =
                  REZ.getString( "verifier.incompat-config.error",
                                 name,
                                 implementation.getName() );
              getLogger().error( message );
              throw new VerifyException( message );
          }
      }
  
      /**
       * Verify that the service implemented by
       * specified component is an interface.
       *
       * @param name the name of component
       * @param clazz the class representign service
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyServiceIsaInterface( final String name,
                                             final Class clazz )
          throws VerifyException
      {
          if( !clazz.isInterface() )
          {
              final String message =
                  REZ.getString( "verifier.non-interface-service.error",
                                 name,
                                 clazz.getName() );
              getLogger().error( message );
              throw new VerifyException( message );
          }
      }
  
      /**
       * Verify that the service implemented by
       * specified component is public.
       *
       * @param name the name of component
       * @param clazz the class representign service
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyServiceIsPublic( final String name,
                                         final Class clazz )
          throws VerifyException
      {
          final boolean isPublic =
              Modifier.isPublic( clazz.getModifiers() );
          if( !isPublic )
          {
              final String message =
                  REZ.getString( "verifier.non-public-service.error",
                                 name,
                                 clazz.getName() );
              getLogger().error( message );
              throw new VerifyException( message );
          }
      }
  
      /**
       * Verify that the service implemented by
       * specified component does not extend any lifecycle interfaces.
       *
       * @param name the name of component
       * @param clazz the class representign service
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyServiceNotALifecycle( final String name,
                                              final Class clazz )
          throws VerifyException
      {
          for( int i = 0; i < FRAMEWORK_CLASSES.length; i++ )
          {
              final Class lifecycle = FRAMEWORK_CLASSES[ i ];
              if( lifecycle.isAssignableFrom( clazz ) )
              {
                  final String message =
                      REZ.getString( "verifier.service-isa-lifecycle.error",
                                     name,
                                     clazz.getName(),
                                     lifecycle.getName() );
                  getLogger().error( message );
                  throw new VerifyException( message );
              }
          }
      }
  
      /**
       * Verify that the component has a no-arg aka default
       * constructor.
       *
       * @param name the name of component
       * @param clazz the class representign component
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyNoArgConstructor( final String name,
                                          final Class clazz )
          throws VerifyException
      {
          try
          {
              final Constructor ctor = clazz.getConstructor( EMPTY_TYPES );
              if( !Modifier.isPublic( ctor.getModifiers() ) )
              {
                  final String message =
                      REZ.getString( "verifier.non-public-ctor.error",
                                     name,
                                     clazz.getName() );
                  getLogger().error( message );
                  throw new VerifyException( message );
              }
          }
          catch( final NoSuchMethodException nsme )
          {
              final String message =
                  REZ.getString( "verifier.missing-noargs-ctor.error",
                                 name,
                                 clazz.getName() );
              getLogger().error( message );
              throw new VerifyException( message );
          }
      }
  
      /**
       * Verify that the component is not represented by
       * abstract class.
       *
       * @param name the name of component
       * @param clazz the class representign component
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyNonAbstract( final String name,
                                     final Class clazz )
          throws VerifyException
      {
          final boolean isAbstract =
              Modifier.isAbstract( clazz.getModifiers() );
          if( isAbstract )
          {
              final String message =
                  REZ.getString( "verifier.abstract-class.error",
                                 name,
                                 clazz.getName() );
              getLogger().error( message );
              throw new VerifyException( message );
          }
      }
  
      /**
       * Verify that the component is not represented by
       * abstract class.
       *
       * @param name the name of component
       * @param clazz the class representign component
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyPublic( final String name,
                                final Class clazz )
          throws VerifyException
      {
          final boolean isPublic =
              Modifier.isPublic( clazz.getModifiers() );
          if( !isPublic )
          {
              final String message =
                  REZ.getString( "verifier.nonpublic-class.error",
                                 name,
                                 clazz.getName() );
              getLogger().error( message );
              throw new VerifyException( message );
          }
      }
  
      /**
       * Verify that the component is not represented by
       * primitive class.
       *
       * @param name the name of component
       * @param clazz the class representign component
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyNonPrimitive( final String name,
                                      final Class clazz )
          throws VerifyException
      {
          if( clazz.isPrimitive() )
          {
              final String message =
                  REZ.getString( "verifier.primitive-class.error",
                                 name,
                                 clazz.getName() );
              getLogger().error( message );
              throw new VerifyException( message );
          }
      }
  
      /**
       * Verify that the component is not represented by
       * interface class.
       *
       * @param name the name of component
       * @param clazz the class representign component
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyNonInterface( final String name,
                                      final Class clazz )
          throws VerifyException
      {
          if( clazz.isInterface() )
          {
              final String message =
                  REZ.getString( "verifier.interface-class.error",
                                 name,
                                 clazz.getName() );
              getLogger().error( message );
              throw new VerifyException( message );
          }
      }
  
      /**
       * Verify that the component is not represented by
       * an array class.
       *
       * @param name the name of component
       * @param clazz the class representign component
       * @throws VerifyException if error thrown on failure and
       *         component fails check
       */
      public void verifyNonArray( final String name,
                                  final Class clazz )
          throws VerifyException
      {
          if( clazz.isArray() )
          {
              final String message =
                  REZ.getString( "verifier.array-class.error",
                                 name,
                                 clazz.getName() );
              getLogger().error( message );
              throw new VerifyException( message );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/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.meta.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.meta.data.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;
  
  /**
   * 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/05 10:39:00 $
   */
  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.getInfo().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.getInfo();
          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.getAssignments().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 ].getServiceDesignator();
              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.getInfo().getDescription().getImplementationKey();
      }
  }
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/verifier/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  #From Verifier class
  verifier.non-public-ctor.error=The implementation class {1} for component named "{0}" does not have a public no-arg constructor.
  verifier.missing-noargs-ctor.error=The implementation class {1} for component named "{0}" does not have a no-arg constructor.
  verifier.abstract-class.error=The implementation class {1} for component named "{0}" is abstract.
  verifier.nonpublic-class.error=The implementation class {1} for component named "{0}" is not public.
  verifier.primitive-class.error=The implementation class {1} for component named "{0}" is primitive.
  verifier.interface-class.error=The implementation class {1} for component named "{0}" is an interface.
  verifier.array-class.error=The implementation class {1} for component named "{0}" is an array class.
  verifier.non-interface-service.error=The service class {1} for component named "{0}" is not an interface.
  verifier.non-public-service.error=The service class {1} for component named "{0}" is not public.
  verifier.incompat-serviceable.error=The implementation class {1} for component named "{0}" is both Serviceable and Composable (incompatible lifecycle interfaces).
  verifier.incompat-config.error=The implementation class {1} for component named "{0}" is both Configurable and Parameterizable (incompatible lifecycle interfaces).
  verifier.noimpl-service.error=The implementation class {1} for component named "{0}" does not implement the service interface {2} which it declares it supports.
  
  #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=Dependency "{0}" of Block "{2}" does not offer the required service "{1}".
  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/meta/verifier/VerifyException.java
  
  Index: VerifyException.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.excalibur.meta.verifier;
  
  import org.apache.avalon.framework.CascadingException;
  
  /**
   * Exception to indicate error verifying a Block or application.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/07/05 10:39:00 $
   */
  public final class VerifyException
      extends CascadingException
  {
      /**
       * Construct a new <code>VerifyException</code> instance.
       *
       * @param message The detail message for this exception.
       */
      public VerifyException( final String message )
      {
          this( message, null );
      }
  
      /**
       * Construct a new <code>VerifyException</code> instance.
       *
       * @param message The detail message for this exception.
       * @param throwable the root cause of the exception
       */
      public VerifyException( final String message, final Throwable throwable )
      {
          super( message, throwable );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/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.containerkit.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.containerkit.verifier.AssemblyVerifier} performs
  validation of the structural integrity of a set component assembly based on
  assembly meta-data.
  </body>
  
  
  

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


Mime
View raw message