mcconnell    2003/07/14 15:03:44

  Modified:    merlin/composition/src/java/org/apache/avalon/composition/model/impl
                        DefaultConstructorModel.java
                        DefaultTypeRepository.java Resources.properties
                        Scanner.java
               merlin/composition/src/test/conf context.xml
               merlin/composition/src/test/org/apache/avalon/composition/model/test
                        ContextTestCase.java
               merlin/composition/src/test/org/apache/avalon/composition/model/testa
                        TestA.xinfo
  Log:
  Add declared extension class checking, more i18n and some more ddetailed exception 
handling to the scanner.
  
  Revision  Changes    Path
  1.3       +113 -10   
avalon-sandbox/merlin/composition/src/java/org/apache/avalon/composition/model/impl/DefaultConstructorModel.java
  
  Index: DefaultConstructorModel.java
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin/composition/src/java/org/apache/avalon/composition/model/impl/DefaultConstructorModel.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DefaultConstructorModel.java      14 Jul 2003 04:46:24 -0000      1.2
  +++ DefaultConstructorModel.java      14 Jul 2003 22:03:43 -0000      1.3
  @@ -111,7 +111,7 @@
       */
       public DefaultConstructorModel( 
         EntryDescriptor descriptor, ConstructorDirective directive, 
  -      DeploymentContext context, Map map )
  +      DeploymentContext context, Map map ) throws ModelException
       {
           super( descriptor );
   
  @@ -127,8 +127,78 @@
           m_directive = directive;
           m_context = context;
           m_map = map;
  +
  +        validate();
  +    }
  +
  +    private void validate() throws ModelException
  +    {
  +        final String descriptorClassName = m_descriptor.getClassname();
  +        final String directiveClassName = m_directive.getClassname();
  +        validatePair( descriptorClassName, directiveClassName );
  +        Parameter[] params = m_directive.getParameters();
  +
  +        //
  +        // TODO:
  +        // wizz through and validate all of the parameter declarations
  +        // and make sure that constructors exist that match the sub-parameter
  +        // delcarations
  +        //
       }
   
  +    private void validatePair( String descriptorClass, String directiveClass )
  +      throws ModelException
  +    {
  +        final String key = m_descriptor.getKey();
  +        ClassLoader loader = m_context.getClassLoader();
  +
  +        Class target = null;
  +        try
  +        {
  +            target = loader.loadClass( descriptorClass );
  +        }
  +        catch( ClassNotFoundException e )
  +        {
  +            final String error = 
  +              REZ.getString( "constructor.descriptor.unknown.error", key, 
descriptorClass );
  +            throw new ModelException( error ); 
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              REZ.getString( "constructor.descriptor.load.error", key, 
descriptorClass );
  +            throw new ModelException( error, e ); 
  +        }
  +
  +        Class source = null;
  +        try
  +        {
  +            source = loader.loadClass( directiveClass );
  +        }
  +        catch( ClassNotFoundException e )
  +        {
  +            final String error = 
  +              REZ.getString( "constructor.directive.unknown.error", key, 
directiveClass );
  +            throw new ModelException( error ); 
  +        }
  +        catch( Throwable e )
  +        {
  +            final String error = 
  +              REZ.getString( "constructor.directive.load.error", key, 
directiveClass );
  +            throw new ModelException( error, e ); 
  +        }
  +
  +        if( !target.isAssignableFrom( source ) )
  +        {
  +            final String error = 
  +              REZ.getString( 
  +                "constructor.invalid-model.error", 
  +                key, descriptorClass, directiveClass );
  +            throw new ModelException( error ); 
  +        }
  +    }
  +
  +
       //==============================================================
       // EntryModel
       //==============================================================
  @@ -150,7 +220,6 @@
           try
           {
               ClassLoader loader = m_context.getClassLoader();
  -
               String classname = m_directive.getClassname();
               String argument = m_directive.getArgument();
               Parameter[] params = m_directive.getParameters();
  @@ -171,7 +240,6 @@
           }
           
           return object;
  -
       }
   
      /**
  @@ -181,7 +249,6 @@
       */
       public Object getValue( Parameter p ) throws ModelException
       {
  -       
           ClassLoader loader = m_context.getClassLoader();
           String classname = p.getClassname();
           String argument = p.getArgument();
  @@ -201,20 +268,26 @@
          ClassLoader loader, Class clazz, String argument, 
          Parameter[] parameters ) throws ModelException
       {
  -
           //
           // if the parameter contains a text argument then check if its a reference
           // to a map entry (in the form"${<key>}" ), otherwise its a simple 
constructor
           // case with a single string paremeter
           //
   
  -        if( argument != null )
  +        if( parameters.length == 0 )
           {
  -            return getSingleArgumentConstructorValue( loader, clazz, argument );
  +            if( argument == null )
  +            {
  +                return getNullArgumentConstructorValue( clazz );
  +            }
  +            else
  +            {
  +                return getSingleArgumentConstructorValue( loader, clazz, argument );
  +            }
           }
           else
           {
  -            return getMultiArgumentConstructorValue( loader, clazz, parameters );
  +             return getMultiArgumentConstructorValue( loader, clazz, parameters );
           }
       }
   
  @@ -327,6 +400,35 @@
           }
       }
   
  +    private Object getNullArgumentConstructorValue( Class clazz )
  +      throws ModelException
  +    {
  +        try
  +        {
  +            return clazz.newInstance();
  +        }
  +        catch ( InstantiationException e )
  +        {
  +            final String error = 
  +              "Unable to instantiate instance of class: " + clazz.getName();
  +            throw new ModelException( error, e );
  +        }
  +        catch ( IllegalAccessException e )
  +        {
  +            final String error =
  +              "Cannot access null parameter constructor for the class: '"
  +              + clazz.getName() + "'.";
  +            throw new ModelException( error, e );
  +        }
  +        catch ( Throwable e )
  +        {
  +            final String error =
  +              "Unexpected exception while creating the class: '"
  +                + clazz.getName() + "'.";
  +            throw new ModelException( error, e );
  +        }
  +    }
  +
       private Object getSingleArgumentConstructorValue( 
         ClassLoader classLoader, Class clazz, String argument )
         throws ModelException
  @@ -350,7 +452,8 @@
                       }
                       else
                       {
  -                        final String error = "Unresolvable primative context value: 
'" + key + "'.";
  +                        final String error = 
  +                          "Unresolvable primative context value: '" + key + "'.";
                           throw new ModelException( error );
                       }
                   }
  
  
  
  1.7       +2 -1      
avalon-sandbox/merlin/composition/src/java/org/apache/avalon/composition/model/impl/DefaultTypeRepository.java
  
  Index: DefaultTypeRepository.java
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin/composition/src/java/org/apache/avalon/composition/model/impl/DefaultTypeRepository.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- DefaultTypeRepository.java        12 Jul 2003 21:10:45 -0000      1.6
  +++ DefaultTypeRepository.java        14 Jul 2003 22:03:43 -0000      1.7
  @@ -72,6 +72,7 @@
   import org.apache.avalon.meta.info.DependencyDescriptor;
   import org.apache.avalon.meta.info.ReferenceDescriptor;
   import org.apache.avalon.meta.info.ServiceDescriptor;
  +import org.apache.avalon.meta.info.ExtensionDescriptor;
   import org.apache.avalon.meta.info.StageDescriptor;
   import org.apache.avalon.meta.info.Type;
   import org.apache.avalon.meta.info.builder.TypeBuilder;
  
  
  
  1.10      +34 -13    
avalon-sandbox/merlin/composition/src/java/org/apache/avalon/composition/model/impl/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin/composition/src/java/org/apache/avalon/composition/model/impl/Resources.properties,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- Resources.properties      14 Jul 2003 04:46:24 -0000      1.9
  +++ Resources.properties      14 Jul 2003 22:03:43 -0000      1.10
  @@ -1,25 +1,31 @@
   
   #
   # DefaultContainmentModelFactory
  +# ==============================
   factory.containment.create.error=Unable to construct a new containment model: {0}.
   
  +
   # DefaultClassLoaderModel
  +# =======================
   classloader.unsatisfied-extensions.error=Classpath contains {0} unsatisfied 
extension dependencies.
   classloader.missing.extension.error=Unable to locate a required extension.\n  
Extension Name: {0}\n  Specification Vendor: {1}\n  Specification Version: {2}\n  
Implementation Vendor: {3}\n  Implementation Vendor-Id: {4}\n  Implementation Version: 
{5}\n  Implementation URL: {6}
   classloader.bad-classpath-entry.error=Cannot load manifest from classpath 
reference: {0}.
   classloader.child.creation.error=Internal error while attempt to construct a child 
classloader model for containment profile: {0}.
   
  +
   # DefaultContainmentModel
  +# =======================
   containment.classloader.create.error=Unable to create a classloader for the 
containment context: {0}.
  -containment.composition.create.error=Unable to create composition model: {1} in {0}.
  -containment.container.create.error=Unable to create containment model: {1} in {0}.
  -containment.deployment.create.error=Unable to create deployment model: {1} in {0}.
  +containment.container.create.error=Unable to create nested containment model: {1} 
in the containment model {0}.
  +containment.deployment.create.error=Unable to create a nested deployment model: {1} 
in the containment model {0}.
   containment.unknown-profile-class.error=Unknown profile class: {1} in {0}.
   containment.context.home.not-a-directory.error=Supplied home dir is not a 
directory: {0}
   containment.context.temp.not-a-directory.error=Supplied temp dir is not a 
directory: {0}
   containment.add=added: {0}
   
  +
   # DefaultDeploymentModel
  +# ======================
   deployment.parameters.irrational=Illegal attempt to set a parameter value for a 
component type '{0}' that is not parameterizable in the model: {1}.
   deployment.configuration.irrational=Illegal attempt to set a configuration value 
for a component type '{0}' that is not configurable in the model: {1}.
   deployment.context.home.not-a-directory.error=Supplied home dir is not a directory: 
{0}
  @@ -31,19 +37,27 @@
   deployment.context.internal.error=The context key [{0}] was recognized but could 
not be fulfilled as no context entry model has be assigned to handle the request.
   deployment.registration.override.error=Illegal attempt to override an existing 
model entry [{0}].
   
  +
   # DefaultModel
  +# ============
   created=created: {0}
   
  +
   # DefaultSystemContext
  +# ====================
   system.context.base.not-a-directory.error="Base directory argument is not a 
directory: {0}.
   
  +
   # DefaultTypeRepository
  +# =====================
   type.repository.null-create.error=Internal error while creating NullComponent type 
defintion. {0}
   type.repository.bootstrap.error=bootstrap: {0}
   type.repository.count=type install count: {0}
   type.repository.addition=add: {0}, ({1}).
   
  +
   #Scanner
  +# ======
   scanner.scanning=scanning: {0}
   scanner.dir-scan.error=Unexpected error while attempting to scan directory: {0}
   scanner.nested-jar-unsupported.error=Embeded jar file loading not supported: {0}
  @@ -54,38 +68,45 @@
   scanner.type.verification.failure=Ignoring type due to verification error: {0}
   scanner.service.addition=type: {0}
   scanner.service.verification.failure=Ignoring service due to verification error: {0}
  -scanner.service.missing-class.error=Could not locate implementation class for 
service: {0}
  -scanner.type.missing-class.error=Could not locate implementation class for type: {0}
  +scanner.service.missing-class.error=Cannot load service because the implementation 
class for service [{0}] does not exist within the classloader.
  +scanner.service.bad-class.error=Cannot load service [{0}] because the class 
references the class [{1}] which does not exist in the classloader.
   scanner.url-not-a-directory.error=URL does not refer to a directory: {0}
   scanner.not-file-protocol.error=URL protocol does not match the required 'file' 
protocol: {0}
  +scanner.type.missing-class.error=Cannot load component type because the type class 
{0} does not exist in the classloader.
  +scanner.type.bad-class.error=Component type [{0}] contains a reference to the class 
[{1}] which does not exist in the classloader.
  +scanner.extension.bad-class.error=Cannot load component type [{0}] because the type 
declares an extension class [{1}] which cannot be loaded to a missing class [{2}].
  +scanner.extension.missing.error=Cannot load component type [{0}] contains because 
the extension class it declares [{1}] does not exist in the classloader.
   
   # DefaultImportModel
  +# ==================
   import.type-conflict.error=The object returned from the internal deployment context 
matching the import directive key: {0} does not implement the context entry class: {1} 
requested by the component under its local key: {2}.;
  -
   import.missing-entry.error=Cannot import context entry {0} requested for the 
component context entry key {1} because the requested import key is unknown within the 
scope of the supplied containment context.
  -
   import.load.error=Cannot load context entry for the component key: {0} because a 
corresponding import directive could not load the class {1} declared as a constraint 
by the component type entry declaration.
  -
   import.null-object.error=Resolution of the include directive for the containment 
key {0} undeer the component context entry {1) return a null object reference. 
   
   #DefaultContextModel
  +# ==================
   context.strategy.custom=custom strategy: {0}
   context.strategy.avalon=avalon strategy
   context.non-standard-avalon-key.error=The component has requested a Avalon context 
entry that is not know within the family of standard Avalon context keys.  The 
offending key is: {0}.
  -
   context.missing-directive.error=The component has requested a non-avalon context 
entry. The container cannot resolve this request because no entry directive can be 
found the matches the key: {0}.
  -
   context.unsupported-directive.error=The component has requested a context entry 
under the key [{0}]. The container cannot resolve this request because the entry 
directive type [{1}] is not supported at this time.
  -
   context.non-compliance-constructor.error="Custom context class [{0}] does not 
implement a constructor pattern <init>( org.apache.avalon.framework.Context ).
  -
   context.custom-unexpected.error=Unexpected error occured while attempting to 
construct a custom context using the class [{0}].
  -
   context.strategy.custom.missing.error=Custom stategy class [{0}] is not present in 
the classpath. 
   context.strategy.custom.unexpected.error=Unable to load the custom stategy class 
[{0}] due to an unexpected error. 
   context.strategy.avalon.missing.error=Classic Avalon context stategy class [{0}] is 
not present in the classpath. 
   context.strategy.avalon.unexpected.error=Unable to load the classic Avalon stategy 
class [{0}] due to an unexpected error. 
   
   # DefaultContext
  +# ==============
   context.entry.model.error=Cannot fulfill request due to an model-related error 
while attempting to resolve a context entry for the key: {0}.
  +
  +# DefaultConstructorModel
  +# =======================
  +constructor.descriptor.unknown.error=The constructor entry descriptor declared 
under the key [{0}] references a class [{1}] that does not exist within the associated 
classloader. 
  +constructor.descriptor.load.error=The constructor entry descriptor declared under 
the key [{0}] references a class [{1}] that that could not be loaded due to an runtime 
error.
  +constructor.directive.unknown.error=The constructor entry directive declared under 
the key [{0}] references a class [{1}] that does not exist within the associated 
classloader. 
  +constructor.directive.load.error=The constructor entry directive declared under the 
key [{0}] references a class [{1}] that that could not be loaded due to an runtime 
error. 
  +constructor.invalid-model.error=The component type declares a dependency under the 
context entry [{0}] on a runtime entry of the type [{1}], however, the corresponding 
directive declares a constructor that establishes an instance of the class [{2}] which 
does not implement or extend the class declared by the directive.
   
  
  
  
  1.8       +93 -42    
avalon-sandbox/merlin/composition/src/java/org/apache/avalon/composition/model/impl/Scanner.java
  
  Index: Scanner.java
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin/composition/src/java/org/apache/avalon/composition/model/impl/Scanner.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- Scanner.java      12 Jul 2003 21:10:45 -0000      1.7
  +++ Scanner.java      14 Jul 2003 22:03:43 -0000      1.8
  @@ -79,6 +79,7 @@
   import org.apache.avalon.meta.data.builder.ProfilePackageBuilder;
   import org.apache.avalon.meta.info.Service;
   import org.apache.avalon.meta.info.ServiceDescriptor;
  +import org.apache.avalon.meta.info.ExtensionDescriptor;
   import org.apache.avalon.meta.info.Type;
   import org.apache.avalon.meta.info.builder.TypeBuilder;
   import org.apache.avalon.meta.info.builder.ServiceBuilder;
  @@ -371,33 +372,12 @@
       private void addType( List types, String name ) throws Exception
       {
           String classname = parseResourceName( name );
  -        Class clazz = null;
  -        try
  -        {
  -            clazz = m_classloader.loadClass( classname );
  -        }
  -        catch( NoClassDefFoundError ncdf )
  -        {
  -            String ref = parseResourceName( ncdf.getMessage() );
  -            final String error = 
  -              "Component type: " + classname 
  -              + " references the class: " + ref
  -              + " which does not exist in the classloader.";
  -            throw new ModelException( error );
  -        }
  -        catch( ClassNotFoundException cnfe )
  -        {
  -            final String error = 
  -              "Component type: " + classname 
  -              + " does not exist in the classloader.";
  -            throw new ModelException( error, cnfe );
  -        }
  -
  +        Class clazz = getComponentClass( classname );
           Type type = TYPE_BUILDER.buildType( clazz );
   
           try
           {
  -            verifyType( type );
  +            verifyType( type, clazz );
               if( getLogger().isDebugEnabled() )
               {
                   final String message =
  @@ -448,17 +428,65 @@
       /**
        * Verify the intergrity of the supplied type.
        * @param type the type to verify
  +     * @param clazz the implementation class
        * @exception Exception if an verification failure occurs
        */
  -    private void verifyType( Type type ) throws Exception
  +    private void verifyType( Type type, Class clazz ) throws Exception
       {
  -        String name = type.getInfo().getName();
  -        Class clazz = getComponentClass( type );
  -        Class[] classes = getServiceClasses( type );
  -        ComponentVerifier verifier = new ComponentVerifier();
  +        final String name = type.getInfo().getName();
  +        final Class[] classes = getServiceClasses( type );
  +        final Class[] extensions = getExtensionClasses( type );
  +        final ComponentVerifier verifier = new ComponentVerifier();
           verifier.verifyComponent( name, clazz, classes );
       }
   
  +   /**
  +    * Return the set of lifecycle extension classes provided 
  +    * by the given type.  This method is used as part of the 
  +    * process of verifying the integrity of a type.
  +    *
  +    * @param type the component type
  +    * @return an array of classes represnting the lifecycle
  +    *   extension interfaces provided by the type
  +    */
  +    private Class[] getExtensionClasses( Type type ) 
  +      throws ModelException
  +    {
  +        ArrayList list = new ArrayList();
  +        ExtensionDescriptor[] extensions = type.getExtensions();
  +        for( int i = 0; i < extensions.length; i++ )
  +        {
  +            ExtensionDescriptor extension = extensions[i];
  +            list.add( getExtensionClass( type, extension ) );
  +        }
  +        return (Class[]) list.toArray( new Class[0] );
  +    }
  +
  +    private Class getExtensionClass( Type type, ExtensionDescriptor extension ) 
  +      throws ModelException
  +    {
  +        final String classname = extension.getReference().getClassname();
  +        final String typeClass = type.getInfo().getClassname();
  +        try
  +        {
  +            return m_classloader.loadClass( classname );
  +        }
  +        catch( NoClassDefFoundError ncdf )
  +        {
  +            String ref = parseResourceName( ncdf.getMessage() );
  +            final String error = 
  +              REZ.getString( "scanner.extension.bad-class.error", typeClass, 
classname, ref );
  +            throw new ModelException( error );
  +        }
  +        catch( ClassNotFoundException cnfe )
  +        {
  +            final String error = 
  +              REZ.getString( "scanner.extension.missing-class.error", typeClass, 
classname );
  +            throw new ModelException( error );
  +        }
  +    }
  +
  +
       /**
        * Verify the intergrity of the supplied type.
        * @param type the type to verify
  @@ -471,11 +499,18 @@
           {
               m_classloader.loadClass( classname );
           }
  -        catch( Throwable e )
  +        catch( NoClassDefFoundError ncdf )
           {
  -            final String error =
  +            String ref = parseResourceName( ncdf.getMessage() );
  +            final String error = 
  +              REZ.getString( "scanner.service.bad-class.error", classname, ref );
  +            throw new ModelException( error );
  +        }
  +        catch( ClassNotFoundException cnfe )
  +        {
  +            final String error = 
                 REZ.getString( "scanner.service.missing-class.error", classname );
  -            throw new ModelException( error, e );
  +            throw new ModelException( error );
           }
       }
   
  @@ -488,7 +523,8 @@
        * @param type the component type
        * @return an array of classes represnting the type's service interfaces
        */
  -    private Class[] getServiceClasses( Type type ) throws ModelException
  +    private Class[] getServiceClasses( Type type ) 
  +      throws ModelException
       {
           ArrayList list = new ArrayList();
           ServiceDescriptor[] services = type.getServices();
  @@ -509,26 +545,42 @@
        * Returns the component type implementation class.
        * @param type the component type descriptor
        * @return the class implementing the component type
  -     * @exception TypeException if a classloader error occurs
  +     * @exception ModelException if a classloader error occurs
        */
  -    private Class getComponentClass( Type type ) throws ModelException
  +    private Class getComponentClass( Type type ) 
  +      throws ModelException
       {
           if( null == type )
           {
               throw new NullPointerException( "type" );
           }
  +        return getComponentClass( type.getInfo().getClassname() );
  +    }
   
  -        final String classname = type.getInfo().getClassname();
  -
  +    /**
  +     * Returns the component type implementation class.
  +     * @param classname the component type implementation classname
  +     * @exception ModelException if a classloader error occurs
  +     */
  +    private Class getComponentClass( String classname ) 
  +      throws ModelException
  +    {
           try
           {
               return m_classloader.loadClass( classname );
           }
  -        catch( Throwable e )
  +        catch( NoClassDefFoundError ncdf )
           {
  -            final String error =
  +            String ref = parseResourceName( ncdf.getMessage() );
  +            final String error = 
  +              REZ.getString( "scanner.type.bad-class.error", classname, ref );
  +            throw new ModelException( error );
  +        }
  +        catch( ClassNotFoundException cnfe )
  +        {
  +            final String error = 
                 REZ.getString( "scanner.type.missing-class.error", classname );
  -            throw new ModelException( error, e );
  +            throw new ModelException( error );
           }
       }
   
  @@ -536,7 +588,7 @@
        * Returns the service type implementation class.
        * @param service the service type descriptor
        * @return the class implementing the service type
  -     * @exception TypeRuntimeException if a classloader error occurs
  +     * @exception ModelException if a classloader error occurs
        */
       private Class getServiceClass( ServiceDescriptor service ) throws ModelException
       {
  @@ -552,7 +604,6 @@
               throw new ModelException( error, e );
           }
       }
  -
   
       private boolean isDirectory( URL url )
       {
  
  
  
  1.2       +16 -1     avalon-sandbox/merlin/composition/src/test/conf/context.xml
  
  Index: context.xml
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/merlin/composition/src/test/conf/context.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- context.xml       14 Jul 2003 04:49:36 -0000      1.1
  +++ context.xml       14 Jul 2003 22:03:43 -0000      1.2
  @@ -14,6 +14,21 @@
        </classpath>
      </classloader>
   
  -   <component name="test-a" 
class="org.apache.avalon.composition.model.testa.TestA"/>
  +   <component name="test-a" class="org.apache.avalon.composition.model.testa.TestA">
  +     <context class="org.apache.avalon.composition.model.testa.DefaultFacade">
  +       <entry key="home">
  +         <constructor class="java.io.File">
  +           <param class="java.io.File">${urn:avalon:home.dir}</param>
  +           <param>xxx</param>
  +         </constructor>
  +       </entry>
  +       <entry key="time">
  +         <constructor class="java.util.Date"/>
  +       </entry>
  +       <entry key="path">
  +         <import key="urn:avalon:partition.name"/>
  +       </entry>
  +     </context>
  +   </component>
   
   </container>
  
  
  
  1.2       +59 -1     
avalon-sandbox/merlin/composition/src/test/org/apache/avalon/composition/model/test/ContextTestCase.java
  
  Index: ContextTestCase.java
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin/composition/src/test/org/apache/avalon/composition/model/test/ContextTestCase.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ContextTestCase.java      14 Jul 2003 04:49:36 -0000      1.1
  +++ ContextTestCase.java      14 Jul 2003 22:03:43 -0000      1.2
  @@ -5,6 +5,7 @@
   import java.io.File;
   import java.io.IOException;
   import java.net.URL;
  +import java.util.Date;
   
   import org.apache.avalon.composition.model.Model;
   import org.apache.avalon.composition.model.DeploymentModel;
  @@ -15,10 +16,13 @@
   import org.apache.avalon.framework.context.ContextException;
   import org.apache.avalon.meta.info.DependencyDescriptor;
   import org.apache.avalon.meta.info.ServiceDescriptor;
  +import org.apache.avalon.composition.model.testa.Facade;
   
   public class ContextTestCase extends AbstractTestCase
   {
  -
  +   private static final String FACADE_CLASSNAME =
  +     "org.apache.avalon.composition.model.testa.DefaultFacade";
  +      
      //-------------------------------------------------------
      // constructor
      //-------------------------------------------------------
  @@ -103,5 +107,59 @@
           {
               assertTrue( "name", false );
           }
  +
  +        //
  +        // validate volatile entries
  +        //
  +
  +        Date date = null;
  +        try
  +        {
  +            date = (Date) context.get( "time" );
  +            try
  +            {
  +                Thread.currentThread().sleep( 1200 );
  +            }
  +            catch( Throwable e )
  +            {
  +                // continue
  +            }
  +        }
  +        catch( ContextException e )
  +        {
  +            assertTrue( "date", false );
  +        }
  +
  +        try
  +        {
  +            Date now = (Date) context.get( "time" );
  +            assertTrue( "volatile", now.after( date ) );
  +        }
  +        catch( ContextException e )
  +        {
  +            assertTrue( "now", false );
  +        }
  +
  +        //
  +        // validate an imported context entry
  +        //
  +
  +        try
  +        {
  +            String path = (String) context.get( "path" );
  +        }
  +        catch( ContextException e )
  +        {
  +            assertTrue( "path", false );
  +        }
  +
  +        //
  +        // validate context safe-casting
  +        // (e.g. ((MyContext)m_context).myMethod() type of thing)
  +        //
  +
  +        final String className =  context.getClass().getName();
  +        boolean classNameMatches = className.equals( FACADE_CLASSNAME );
  +        assertTrue( "custom context", classNameMatches );
       }
   }
  
  
  
  1.3       +4 -1      
avalon-sandbox/merlin/composition/src/test/org/apache/avalon/composition/model/testa/TestA.xinfo
  
  Index: TestA.xinfo
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/merlin/composition/src/test/org/apache/avalon/composition/model/testa/TestA.xinfo,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- TestA.xinfo       14 Jul 2003 04:49:36 -0000      1.2
  +++ TestA.xinfo       14 Jul 2003 22:03:44 -0000      1.3
  @@ -4,12 +4,15 @@
       <name>component-a</name>
       <lifestyle>singleton</lifestyle>
     </info>
  -  <context>
  +  <context type="org.apache.avalon.composition.model.testa.Facade">
       <entry key="urn:avalon:partition.name"/>
       <entry key="urn:avalon:classloader"/>
       <entry key="urn:avalon:home.dir"/>
       <entry key="urn:avalon:temp.dir"/>
       <entry key="urn:avalon:name" alias="name"/>
  +    <entry key="home" type="java.io.File"/>
  +    <entry key="time" type="java.util.Date" volatile="true"/>
  +    <entry key="path"/>
     </context>
     <services>
       <service type="org.apache.avalon.composition.model.testa.A"/>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to