svn commit: r2142 - in development/main/metro: . activation/providers/metro/src/main/net/dpml/activation/metro composition/api/src/main/net/dpml/composition/model composition/builder/src/main/net/dpml/composition/builder composition/control/src/main/net/dpml/composition/control composition/impl/src/main/net/dpml/composition/model/impl composition/testing/acme composition/testing/acme/src/main/net/dpml/composition/testing composition/testing/unit composition/testing/unit/src composition/testing/unit/src/test composition/testing/unit/src/test/net composition/testing/unit/src/test/net/dpml composition/testing/unit/src/test/net/dpml/composition composition/testing/unit/src/test/net/dpml/composition/test context/impl/src/main/net/dpml/context/impl service/api/src/main/net/dpml/service

mcconnell at dpml.net mcconnell at dpml.net
Sat Mar 26 00:57:13 EST 2005


Author: mcconnell at dpml.net
Date: Sat Mar 26 00:57:13 2005
New Revision: 2142

Added:
   development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/ContextInvocationHandler.java
   development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DependencyInvocationHandler.java
   development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultValueModel.java
   development/main/metro/composition/testing/unit/
   development/main/metro/composition/testing/unit/build.xml
   development/main/metro/composition/testing/unit/src/
   development/main/metro/composition/testing/unit/src/test/
   development/main/metro/composition/testing/unit/src/test/net/
   development/main/metro/composition/testing/unit/src/test/net/dpml/
   development/main/metro/composition/testing/unit/src/test/net/dpml/composition/
   development/main/metro/composition/testing/unit/src/test/net/dpml/composition/test/
   development/main/metro/composition/testing/unit/src/test/net/dpml/composition/test/FreightTestCase.java
   development/main/metro/service/api/src/main/net/dpml/service/FulfillmentRuntimeException.java
Removed:
   development/main/metro/context/impl/src/main/net/dpml/context/impl/ContextInvocationHandler.java
Modified:
   development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DefaultComponentFactory.java
   development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DefaultServiceManager.java
   development/main/metro/composition/api/src/main/net/dpml/composition/model/ContainmentModel.java
   development/main/metro/composition/api/src/main/net/dpml/composition/model/ContextModel.java
   development/main/metro/composition/builder/src/main/net/dpml/composition/builder/TypeBuilderTask.java
   development/main/metro/composition/control/src/main/net/dpml/composition/control/CompositionController.java
   development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultContainmentModel.java
   development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultContextModel.java
   development/main/metro/composition/testing/acme/build.xml
   development/main/metro/composition/testing/acme/src/main/net/dpml/composition/testing/DefaultGizmo.java
   development/main/metro/composition/testing/acme/src/main/net/dpml/composition/testing/DefaultWidget.java
   development/main/metro/index.xml
Log:
Working implementation of a context and dependencies invocation handler capable of supporting the inner interface delivery model.

Added: development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/ContextInvocationHandler.java
==============================================================================
--- (empty file)
+++ development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/ContextInvocationHandler.java	Sat Mar 26 00:57:13 2005
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.activation.metro;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.lang.reflect.Method;
+import java.util.Hashtable;
+import java.util.Map;
+
+import net.dpml.meta.info.Type;
+import net.dpml.meta.info.EntryDescriptor;
+
+import net.dpml.composition.model.EntryModel;
+
+/**
+ * This makes a dynamic proxy for an object.  The object can be represented
+ * by one, some or all of it's interfaces.
+ *
+ * @author <a href="mailto:dev-dpml at lists.ibiblio.org">The Digital Product Meta Library</a>
+ * @version $Id: ApplianceInvocationHandler.java 2106 2005-03-21 18:46:10Z mcconnell at dpml.net $
+ */
+public final class ContextInvocationHandler
+  implements InvocationHandler
+{
+    //-------------------------------------------------------------------
+    // state
+    //-------------------------------------------------------------------
+
+   /**
+    * A map of context entry key name and context entry values.
+    */
+    private final Map m_map;
+
+   /**
+    * A map of the entry descriptors published by the component type
+    * and keyed by entry key.
+    */
+    private final Map m_entries = new Hashtable();
+
+   /**
+    * The component type.
+    */
+    private final Type m_type;
+
+    //-------------------------------------------------------------------
+    // constructor
+    //-------------------------------------------------------------------
+
+   /**
+    * Create a context invocation handler.
+    *
+    * @param type the component type
+    * @param map a map of context values keyed by entry key
+    */
+    public ContextInvocationHandler( Type type, Map map )
+        throws NullPointerException
+    {
+        assertNotNull( map, "map" );
+        assertNotNull( type, "type" );
+
+        m_map = map;
+        m_type = type;
+
+        EntryDescriptor[] entries = type.getContext().getEntries();
+        for( int i=0; i<entries.length; i++ )
+        {
+            EntryDescriptor p = entries[i];
+            String key = p.getKey();
+            boolean required = p.isRequired();
+            m_entries.put( key, p );
+            if( required && ( false == map.containsKey( key ) ) )
+            {
+                final String error = 
+                  "The component type ["
+                  + type.getInfo().getClassname() 
+                  + "] declares a required context entry under the key ["
+                  + key
+                  + "] however, no corresponding value has been supplied within the context map.";
+
+System.out.println( "## MAP: " + map );
+                throw new IllegalArgumentException( error );
+            }
+        }
+    }
+
+    //-------------------------------------------------------------------
+    // implementation
+    //-------------------------------------------------------------------
+
+   /**
+    * Invoke the specified method on underlying object.
+    * This is called by the proxy object.
+    *
+    * @param proxy the proxy object
+    * @param method the method invoked on proxy object
+    * @param args the arguments supplied to method
+    * @return the return value of method
+    * @throws Throwable if an error occurs
+    * @exception NullPointerException if any one of the proxy or method arguments
+    *            is null, or if the object instance has been destroyed earlier.
+    */
+    public Object invoke( final Object proxy, final Method method, final Object[] args )
+        throws Throwable, NullPointerException
+    {
+        if( proxy == null )
+          throw new NullPointerException( "proxy" );
+        if( method == null )
+          throw new NullPointerException( "method" );
+
+        Class source = method.getDeclaringClass();
+        if( Object.class == method.getDeclaringClass() )
+        {
+            return method.invoke( this, args );
+        }
+        
+        String name = method.getName();
+        String key = getKeyFromMethod( method );
+        EntryDescriptor entry = (EntryDescriptor) m_entries.get( key );
+
+        if( null == entry )
+        {
+            final String error =
+              "Illegal request for an undeclared context entry [" 
+              + key 
+              + "] withing the component type ["
+              + m_type.getInfo().getClassname()
+              + "].";
+            throw new IllegalArgumentException( error );               
+        }
+
+        //
+        // we have a valid key
+        //
+
+        EntryModel model = (EntryModel) m_map.get( key );
+        if( null == model )
+        {
+            return returnClientSuppliedDefaultArgument( entry, args );
+        }
+        else
+        {
+            Object value = model.getValue();
+            return value;
+        }
+    }
+
+    private String getKeyFromMethod( Method method )
+    {
+        String name = method.getName();
+        if( name.startsWith( "get" ) )
+        {
+            return formatKey( name.substring( 3 ) );
+        }
+        else
+        {
+            final String error = 
+              "Invalid method accessor ["
+              + name 
+              + "]";
+            throw new IllegalArgumentException( error );
+        }
+    }
+
+    private String formatKey( String key )
+    {
+        if( key.length() < 1 ) 
+        {
+            throw new IllegalArgumentException( "key" );
+        }
+        String first = key.substring( 0, 1 ).toLowerCase();
+        String remainder = key.substring( 1 );
+        return first + remainder;
+    }
+
+    private Object returnClientSuppliedDefaultArgument( EntryDescriptor entry, Object[] args )
+    {
+        if( args.length < 1 )
+        {
+            final String error = 
+              "Insuffient arguments to resolve a default value for the key ["
+              + entry.getKey() 
+              + "] within the component type ["
+              + m_type.getInfo().getName() 
+              + "].";
+            throw new IllegalArgumentException( error );
+        }
+        Object arg = args[0];
+        return arg;
+    }
+
+    //-------------------------------------------------------------------
+    // implementation
+    //-------------------------------------------------------------------
+
+    private void assertNotNull( Object object, String key )
+        throws NullPointerException
+    {
+        if( null == object )
+        {
+            throw new NullPointerException( key );
+        }
+    }
+}

Modified: development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DefaultComponentFactory.java
==============================================================================
--- development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DefaultComponentFactory.java	(original)
+++ development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DefaultComponentFactory.java	Sat Mar 26 00:57:13 2005
@@ -19,6 +19,9 @@
 package net.dpml.activation.metro;
 
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.Hashtable;
 import java.util.Map;
 
 import net.dpml.activation.ComponentFactory;
@@ -38,6 +41,7 @@
 import net.dpml.composition.model.ContextualizationHandler;
 import net.dpml.composition.model.DeploymentModel;
 import net.dpml.composition.model.ModelException;
+import net.dpml.composition.model.DependencyModel;
 
 import net.dpml.configuration.Configurable;
 import net.dpml.configuration.Configuration;
@@ -55,6 +59,8 @@
 import net.dpml.logging.LogEnabled;
 import net.dpml.logging.Logger;
 
+import net.dpml.meta.info.Type;
+
 import net.dpml.parameters.Parameterizable;
 import net.dpml.parameters.Parameters;
 
@@ -215,13 +221,14 @@
         final Logger logger = m_model.getLogger();
         final Configuration config = m_model.getConfiguration();
         final Parameters params = m_model.getParameters();
-        final ServiceManager manager = new DefaultServiceManager( m_model );
+        final Class managerInterfaceClass = getTargetServiceManagerInterface();
+        final Object manager = getTargetServiceManager( managerInterfaceClass );
         final Object context = getTargetContext();
         final Class contextClass = getContextCastingClass();
 
         final Object instance =
           instantiate(
-            clazz, logger, config, params, context, contextClass, manager );
+            clazz, logger, config, params, context, contextClass, managerInterfaceClass, manager );
 
         try
         {
@@ -240,7 +247,7 @@
             if( instance instanceof Serviceable )
             {
                 getLogger().debug( "applying service manager" );
-                ContainerUtil.service( instance, manager );
+                ContainerUtil.service( instance, (ServiceManager) manager );
             }
 
             if( instance instanceof Configurable )
@@ -316,12 +323,105 @@
         }
     }
 
+    private Class getTargetServiceManagerInterface()
+      throws LifecycleException
+    {
+        Class subject = m_model.getDeploymentClass();
+        Class[] classes = subject.getClasses();
+        Class inner = locateClass( "$Dependencies", classes );
+        if( null != inner )
+        {
+            return inner;
+        }
+        else
+        {
+            return ServiceManager.class;
+        }
+    }
+
+    private Object getTargetServiceManager( Class clazz )
+      throws LifecycleException
+    {
+        DependencyModel[] dependencies = m_model.getDependencyModels();
+        if( clazz == ServiceManager.class )
+        {
+            Logger logger = m_model.getLogger();
+            return new DefaultServiceManager( logger, dependencies );
+        }
+        else
+        {
+            Hashtable map = new Hashtable();
+            for( int i=0; i<dependencies.length; i++ )
+            {
+                DependencyModel dep = dependencies[i];
+                String key = dep.getDependency().getKey();
+                map.put( key, dep );
+            }
+            Type type = m_model.getType();
+            InvocationHandler handler = new DependencyInvocationHandler( type, map );
+            
+            ClassLoader classloader = m_model.getDeploymentClass().getClassLoader();
+            return Proxy.newProxyInstance( classloader, new Class[]{ clazz }, handler );
+        }
+    }
+
     private Object getTargetContext()
       throws LifecycleException
     {
         ContextModel model = m_model.getContextModel();
-        Class impl = getContextImplementationClass( model );
-        return createComponentContext( impl, model.getContextMap() );
+        String casting = model.getCastingClassname();
+        if( ( null != casting ) && casting.endsWith( "$Context" ) )
+        {
+            //
+            // return a proxy
+            //
+
+            Map map = model.getEntryModelMap();
+            Type type = m_model.getType();
+            InvocationHandler handler = new ContextInvocationHandler( type, map );
+            
+            Class inner = getInnerClass( "$Context" );
+            ClassLoader classloader = m_model.getDeploymentClass().getClassLoader();
+            return Proxy.newProxyInstance( classloader, new Class[]{ inner }, handler );
+        }
+        else
+        {
+            Class impl = getContextImplementationClass( model );
+            return createComponentContext( impl, model.getContextMap() );
+        }
+    }
+
+    private Class getInnerClass( String postfix )
+    {
+        Class subject = m_model.getDeploymentClass();
+        Class[] classes = subject.getClasses();
+        Class inner = locateClass( postfix, classes );
+        if( null == inner )
+        {
+           final String error = 
+             "Unable to locate the " + postfix + " inner class in component type ["
+             + subject.getName()
+             + "].";
+           throw new IllegalStateException( error );
+        }
+        else
+        {
+            return inner;
+        }
+    }
+
+    private Class locateClass( String postfix, Class[] classes )
+    {
+        for( int i=0; i<classes.length; i++ )
+        {
+            Class inner = classes[i];
+            String name = inner.getName();
+            if( name.endsWith( postfix ) )
+            {
+                return inner;
+            }
+        }
+        return null;
     }
 
     private Class getContextImplementationClass( ContextModel model ) throws LifecycleException
@@ -386,10 +486,9 @@
         }
     }
 
-
     private Object instantiate(
             Class clazz, Logger logger, Configuration config, Parameters params,
-            Object context, Class contextClass, ServiceManager manager )
+            Object context, Class contextClass, Class managerClass, Object manager )
         throws LifecycleException, NullArgumentException
     {
         Constructor constructor = getConstructor( clazz );
@@ -399,6 +498,7 @@
         for( int i=0; i<classes.length; i++ )
         {
             Class c = classes[i];
+
             if( Logger.class.isAssignableFrom( c ) )
             {
                 if( null == logger )
@@ -431,6 +531,10 @@
                 }
                 args[i] = params;
             }
+            else if( ( null != manager ) && managerClass.isAssignableFrom( c ) )
+            {
+                args[i] = manager;
+            }
             else if( ServiceManager.class.isAssignableFrom( c ) )
             {
                 if( null == manager )
@@ -499,6 +603,11 @@
       final Constructor constructor, final Object[] args )
       throws LifecycleException
     {
+        for( int i=0; i<args.length; i++ )
+        {
+            Object arg = args[i];
+        }
+
         try
         {
             if( args.length == 0 )

Modified: development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DefaultServiceManager.java
==============================================================================
--- development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DefaultServiceManager.java	(original)
+++ development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DefaultServiceManager.java	Sat Mar 26 00:57:13 2005
@@ -80,18 +80,11 @@
      * @param model component model of the component that is
      *   to be serviced.
      */
-    public DefaultServiceManager( ComponentModel model )
+    public DefaultServiceManager( Logger logger, DependencyModel[] dependencies )
         throws NullArgumentException
     {
-        if( model == null )
-        {
-            throw new NullArgumentException( "model" );
-        }
-
-        m_logger = model.getLogger();
-
+        m_logger = logger;
         m_map = new Hashtable();
-        DependencyModel[] dependencies = model.getDependencyModels();
         for( int i=0; i < dependencies.length; i++ )
         {
             final DependencyModel dependency = dependencies[i];
@@ -105,6 +98,7 @@
         }
     }
 
+
     //-------------------------------------------------------------------
     // ServiceManager
     //-------------------------------------------------------------------

Added: development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DependencyInvocationHandler.java
==============================================================================
--- (empty file)
+++ development/main/metro/activation/providers/metro/src/main/net/dpml/activation/metro/DependencyInvocationHandler.java	Sat Mar 26 00:57:13 2005
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.activation.metro;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Method;
+import java.util.Hashtable;
+import java.util.Map;
+
+import net.dpml.meta.info.Type;
+import net.dpml.meta.info.DependencyDescriptor;
+
+import net.dpml.composition.model.ComponentModel;
+import net.dpml.composition.model.DeploymentModel;
+import net.dpml.composition.model.DependencyModel;
+
+import net.dpml.composition.model.EntryModel;
+
+import net.dpml.service.FulfillmentRuntimeException;
+
+/**
+ * This makes a dynamic proxy for an object.  The object can be represented
+ * by one, some or all of it's interfaces.
+ *
+ * @author <a href="mailto:dev-dpml at lists.ibiblio.org">The Digital Product Meta Library</a>
+ * @version $Id: ApplianceInvocationHandler.java 2106 2005-03-21 18:46:10Z mcconnell at dpml.net $
+ */
+public final class DependencyInvocationHandler
+  implements InvocationHandler
+{
+    //-------------------------------------------------------------------
+    // state
+    //-------------------------------------------------------------------
+
+   /**
+    * A map of provider entry key name and dependency model entries.
+    */
+    private final Map m_map;
+
+   /**
+    * A map of the dependency descriptors published by the component type
+    * and keyed by entry key.
+    */
+    private final Map m_entries = new Hashtable();
+
+   /**
+    * The component type.
+    */
+    private final Type m_type;
+
+    //-------------------------------------------------------------------
+    // constructor
+    //-------------------------------------------------------------------
+
+   /**
+    * Create a dependency invocation handler.
+    *
+    * @param type the component type
+    * @param map a map of context values keyed by entry key
+    */
+    public DependencyInvocationHandler( Type type, Map map )
+        throws NullPointerException
+    {
+        assertNotNull( map, "map" );
+        assertNotNull( type, "type" );
+
+        m_map = map;
+        m_type = type;
+
+        DependencyDescriptor[] entries = type.getDependencies();
+        for( int i=0; i<entries.length; i++ )
+        {
+            DependencyDescriptor p = entries[i];
+            String key = p.getKey();
+            boolean required = p.isRequired();
+            m_entries.put( key, p );
+            if( required && ( false == map.containsKey( key ) ) )
+            {
+                final String error = 
+                  "The component type ["
+                  + type.getInfo().getClassname() 
+                  + "] declares a required service dependency entry under the key ["
+                  + key
+                  + "] however no corresponding provider is available.";
+                throw new IllegalArgumentException( error );
+            }
+        }
+    }
+
+    //-------------------------------------------------------------------
+    // implementation
+    //-------------------------------------------------------------------
+
+   /**
+    * Invoke the specified method on underlying object.
+    * This is called by the proxy object.
+    *
+    * @param proxy the proxy object
+    * @param method the method invoked on proxy object
+    * @param args the arguments supplied to method
+    * @return the return value of method
+    * @throws Throwable if an error occurs
+    * @exception NullPointerException if any one of the proxy or method arguments
+    *            is null, or if the object instance has been destroyed earlier.
+    */
+    public Object invoke( final Object proxy, final Method method, final Object[] args )
+        throws Throwable, NullPointerException
+    {
+        if( proxy == null )
+          throw new NullPointerException( "proxy" );
+        if( method == null )
+          throw new NullPointerException( "method" );
+
+        Class source = method.getDeclaringClass();
+        if( Object.class == method.getDeclaringClass() )
+        {
+            return method.invoke( this, args );
+        }
+        
+        String name = method.getName();
+        String key = getKeyFromMethod( method );
+        DependencyDescriptor entry = (DependencyDescriptor) m_entries.get( key );
+
+        if( null == entry )
+        {
+            final String error =
+              "Illegal request for an undeclared dependency [" 
+              + key 
+              + "] withing the component type ["
+              + m_type.getInfo().getClassname()
+              + "].";
+            throw new IllegalArgumentException( error );               
+        }
+
+        //
+        // we have a valid key
+        //
+
+        DependencyModel model = (DependencyModel) m_map.get( key );
+        final DeploymentModel provider = model.getProvider();
+        if( null == provider )
+        {
+            return returnClientSuppliedDefaultArgument( entry, args );
+        }
+        else
+        {
+            return getServiceInstance( key, provider );
+        }
+    }
+
+    private Object getServiceInstance( String key, DeploymentModel provider )
+    {
+        if( null == provider )
+        {
+            throw new NullPointerException( "provider" );
+        }
+
+        try
+        {
+            Object instance = provider.resolve();
+            if( Proxy.isProxyClass( instance.getClass() ) )
+            {
+                return instance;
+            }
+            else
+            {
+                return instance;
+            }
+        }
+        catch( Throwable e )
+        {
+            final String error =
+              "Unexpected runtime error while attempting to resolve the service for the key ["
+              + key 
+              + "] using the provider ["
+              + provider 
+              + "] within the component type ["
+              + m_type.getInfo().getClassname()
+              + "].";
+            throw new FulfillmentRuntimeException( key, error, e );
+        }
+    }
+
+    private String getKeyFromMethod( Method method )
+    {
+        String name = method.getName();
+        if( name.startsWith( "get" ) )
+        {
+            return formatKey( name.substring( 3 ) );
+        }
+        else
+        {
+            final String error = 
+              "Invalid method accessor ["
+              + name 
+              + "]";
+            throw new IllegalArgumentException( error );
+        }
+    }
+
+    private String formatKey( String key )
+    {
+        if( key.length() < 1 ) 
+        {
+            throw new IllegalArgumentException( "key" );
+        }
+        String first = key.substring( 0, 1 ).toLowerCase();
+        String remainder = key.substring( 1 );
+        return first + remainder;
+    }
+
+    private Object returnClientSuppliedDefaultArgument( DependencyDescriptor entry, Object[] args )
+    {
+        if( args.length < 1 )
+        {
+            final String error = 
+              "Insuffient arguments to resolve a default value for the key ["
+              + entry.getKey() 
+              + "] within the component type ["
+              + m_type.getInfo().getName() 
+              + "].";
+            throw new IllegalArgumentException( error );
+        }
+        Object arg = args[0];
+        return arg;
+    }
+
+    //-------------------------------------------------------------------
+    // implementation
+    //-------------------------------------------------------------------
+
+    private void assertNotNull( Object object, String key )
+        throws NullPointerException
+    {
+        if( null == object )
+        {
+            throw new NullPointerException( key );
+        }
+    }
+}

Modified: development/main/metro/composition/api/src/main/net/dpml/composition/model/ContainmentModel.java
==============================================================================
--- development/main/metro/composition/api/src/main/net/dpml/composition/model/ContainmentModel.java	(original)
+++ development/main/metro/composition/api/src/main/net/dpml/composition/model/ContainmentModel.java	Sat Mar 26 00:57:13 2005
@@ -19,6 +19,7 @@
 package net.dpml.composition.model;
 
 import java.net.URL;
+import java.net.URI;
 import java.util.List;
 
 import net.dpml.composition.data.DeploymentProfile;
@@ -129,6 +130,15 @@
       throws AssemblyException;
 
    /**
+    * Addition of a new subsidiary deployment model using a supplied part uri.
+    *
+    * @param uri a part uri
+    * @return the model based on the derived profile
+    * @exception ModelException if an error occurs during model establishment
+    */
+    DeploymentModel addModel( String name, URI uri ) throws ModelException;
+
+   /**
     * Addition of a new subsidiary containment model
     * using a supplied profile url.
     *

Modified: development/main/metro/composition/api/src/main/net/dpml/composition/model/ContextModel.java
==============================================================================
--- development/main/metro/composition/api/src/main/net/dpml/composition/model/ContextModel.java	(original)
+++ development/main/metro/composition/api/src/main/net/dpml/composition/model/ContextModel.java	Sat Mar 26 00:57:13 2005
@@ -81,4 +81,11 @@
     */
     Map getContextMap();
 
+   /**
+    * Return a map of EntryModel instances.
+    * 
+    * @return the entry model map.
+    */
+    Map getEntryModelMap();
+
 }

Modified: development/main/metro/composition/builder/src/main/net/dpml/composition/builder/TypeBuilderTask.java
==============================================================================
--- development/main/metro/composition/builder/src/main/net/dpml/composition/builder/TypeBuilderTask.java	(original)
+++ development/main/metro/composition/builder/src/main/net/dpml/composition/builder/TypeBuilderTask.java	Sat Mar 26 00:57:13 2005
@@ -622,8 +622,18 @@
 
     private ContextDescriptor createContextDescriptor( Class subject ) throws IntrospectionException
     {
-        EntryDescriptor[] entries = createEntryDescriptors( subject );
-        return new ContextDescriptor( null, entries );
+        Class[] classes = subject.getClasses();
+        Class param = locateClass( "$Context", classes );
+        if( null == param )
+        {
+            return new ContextDescriptor( null, new EntryDescriptor[0] );
+        }
+        else
+        {
+            EntryDescriptor[] entries = createEntryDescriptors( subject );
+            String classname = param.getName();
+            return new ContextDescriptor( classname, entries );
+        }
     }
 
     private EntryDescriptor[] createEntryDescriptors( Class subject ) 

Modified: development/main/metro/composition/control/src/main/net/dpml/composition/control/CompositionController.java
==============================================================================
--- development/main/metro/composition/control/src/main/net/dpml/composition/control/CompositionController.java	(original)
+++ development/main/metro/composition/control/src/main/net/dpml/composition/control/CompositionController.java	Sat Mar 26 00:57:13 2005
@@ -56,6 +56,11 @@
     // constructor
     //--------------------------------------------------------------------
 
+    public CompositionController()
+    {
+        this( new ConsoleMonitor( "metro", false ) );
+    }
+
     public CompositionController( Monitor monitor )
     {
         super();

Modified: development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultContainmentModel.java
==============================================================================
--- development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultContainmentModel.java	(original)
+++ development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultContainmentModel.java	Sat Mar 26 00:57:13 2005
@@ -63,6 +63,10 @@
 import net.dpml.composition.provider.ContainmentContext;
 import net.dpml.composition.provider.ModelFactory;
 
+import net.dpml.composition.control.CompositionController;
+
+import net.dpml.part.Part;
+
 import net.dpml.configuration.Configuration;
 import net.dpml.configuration.impl.DefaultConfigurationBuilder;
 
@@ -562,6 +566,47 @@
     }
 
    /**
+    * Addition of a new subsidiary deployment model using a supplied part uri.
+    *
+    * @param uri a part uri
+    * @return the model based on the derived profile
+    * @exception ModelException if an error occurs during model establishment
+    */
+    public DeploymentModel addModel( String name, URI uri ) throws ModelException
+    {
+        try
+        {
+            CompositionController controller = new CompositionController();
+            Part part = controller.loadPart( uri );
+            if( part instanceof DeploymentProfile )
+            {
+                DeploymentProfile profile = (DeploymentProfile) part;
+                return createDeploymentModel( name, profile );
+            }
+            else
+            {
+                final String error = 
+                  "Unknown part type ["
+                  + part.getClass().getName()
+                  + "]";
+                throw new ModelException( error );
+            }
+        }
+        catch( ModelException e )
+        {
+            throw e;
+        }
+        catch( Throwable e )
+        {
+            final String error = 
+              "Unexpected error while attempting to add a model using the ["
+              + uri
+              + "]";
+            throw new ModelException( error, e );
+        }
+    }
+
+   /**
     * Addition of a new subsidiary model within
     * the containment context.
     *
@@ -1112,10 +1157,6 @@
             }
             else
             {
-                //
-                // TODO: try and load the artifact as a serialized DeploymnetDirective
-                //
-
                 final String error =
                   "Don't know what to do with artifact: " + uri;
                 throw new ModelException( error );

Modified: development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultContextModel.java
==============================================================================
--- development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultContextModel.java	(original)
+++ development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultContextModel.java	Sat Mar 26 00:57:13 2005
@@ -22,6 +22,7 @@
 import java.util.Map;
 
 import net.dpml.composition.data.ConstructorDirective;
+import net.dpml.composition.data.ValueDirective;
 import net.dpml.composition.data.ContextDirective;
 import net.dpml.composition.data.EntryDirective;
 import net.dpml.composition.data.ImportDirective;
@@ -163,12 +164,6 @@
                 }
                 else
                 {
-                    //
-                    // there are only two context entry models - import
-                    // and constructor - identify the model to use then add
-                    // the resolved model to the map
-                    //
-
                     if( entryDirective instanceof ImportDirective )
                     {
                         //
@@ -194,6 +189,18 @@
                             m_map );
                         setEntryModel( alias, model );
                     }
+                    else if( entryDirective instanceof ValueDirective )
+                    {
+                        ValueDirective value =
+                          (ValueDirective) entryDirective;
+                        DefaultValueModel model =
+                          new DefaultValueModel(
+                            entry,
+                            value,
+                            context,
+                            m_map );
+                        setEntryModel( alias, model );
+                    }
                     else
                     {
                         String modelClass =
@@ -302,4 +309,15 @@
     {
         return new DefaultContextMap( m_map );
     }
+
+   /**
+    * Return the map of entry models.
+    *
+    * @return the entry model map
+    */
+    public Map getEntryModelMap()
+    {
+        return m_map;
+    }
+
 }

Added: development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultValueModel.java
==============================================================================
--- (empty file)
+++ development/main/metro/composition/impl/src/main/net/dpml/composition/model/impl/DefaultValueModel.java	Sat Mar 26 00:57:13 2005
@@ -0,0 +1,636 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.composition.model.impl;
+
+import java.lang.reflect.Constructor;
+
+import java.util.Map;
+
+import net.dpml.composition.data.ValueDirective;
+import net.dpml.composition.data.ValueDirective.Value;
+
+import net.dpml.composition.model.EntryModel;
+import net.dpml.composition.model.ModelException;
+
+import net.dpml.composition.provider.ComponentContext;
+
+import net.dpml.meta.info.EntryDescriptor;
+
+import net.dpml.i18n.ResourceManager;
+import net.dpml.i18n.Resources;
+
+import net.dpml.lang.NullArgumentException;
+
+
+/**
+ * Default implementation of a the context entry constructor model.
+ *
+ * @author <a href="mailto:dev-dpml at lists.ibiblio.org">The Digital Product Meta Library</a>
+ * @version $Id: DefaultConstructorModel.java 1518 2005-01-17 17:13:05Z niclas $
+ */
+public class DefaultValueModel extends DefaultEntryModel
+{
+    //==============================================================
+    // static
+    //==============================================================
+
+    private static final Resources REZ =
+      ResourceManager.getPackageResources( DefaultValueModel.class );
+
+    //==============================================================
+    // immutable state
+    //==============================================================
+
+    private final ValueDirective m_directive;
+
+    private final EntryDescriptor m_descriptor;
+
+    private final ComponentContext m_context;
+
+    private final Map m_map;
+
+    //==============================================================
+    // mutable state
+    //==============================================================
+
+    private Object m_value;
+
+    //==============================================================
+    // constructor
+    //==============================================================
+
+   /**
+    * Creation of a new context entry import model.
+    *
+    * @param descriptor the context entry descriptor
+    * @param directive the context entry directive
+    * @param context the containment context
+    * @param map a map of available context entries
+    * @exception NullArgumentException if either the directive argument or the
+    *            context argument is null.
+    */
+    public DefaultValueModel(
+            EntryDescriptor descriptor, ValueDirective directive,
+            ComponentContext context, Map map )
+        throws ModelException, NullArgumentException
+    {
+        super( descriptor );
+
+        if( directive == null )
+        {
+            throw new NullArgumentException( "directive" );
+        }
+        if( context == null )
+        {
+            throw new NullArgumentException( "context" );
+        }
+        m_descriptor = descriptor;
+        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 );
+        Value[] params = m_directive.getValues();
+
+        //
+        // TODO:
+        // wizz through and validate all of the value declarations
+        // and make sure that constructors exist that match the sub-parameter
+        // delcarations
+        //
+    }
+
+    private void validatePair( String descriptorClass, String directiveClass )
+        throws ModelException
+    {
+        System.out.println( "## DESCRIPTOR CLASS: " + descriptorClass );
+        System.out.println( "## DIRECTIVE CLASS: " + directiveClass );
+
+
+        if( "int".equals( descriptorClass ) )
+        {
+            if( ( null == directiveClass ) || "int".equals( directiveClass ) )
+            {
+                return;
+            }
+            else
+            {
+                final String error = 
+                  "Descriptor class ["
+                  + descriptorClass 
+                  + "] does not match the supplied directive class ["
+                  + directiveClass 
+                  + "].";
+                throw new ModelException( error );
+            }
+        }
+
+        if( null == directiveClass )
+        {
+            return;
+        }
+
+        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
+    //==============================================================
+
+   /**
+    * Return the context entry value.
+    *
+    * @return the context entry value
+    */
+    public Object getValue()
+        throws ModelException
+    {
+        if( m_value != null )
+        {
+            return m_value;
+        }
+
+        String target = m_descriptor.getKey();
+        Object object = null;
+        try
+        {
+            ClassLoader loader = m_context.getClassLoader();
+            String classname = getReturnTypeClassname();
+            String argument = m_directive.getLocalValue();
+            Value[] params = m_directive.getValues();
+            Class clazz = getValueClass( classname, loader );
+            object = getValue( loader, clazz, argument, params );
+        }
+        catch( Throwable e )
+        {
+            final String error =
+              "Cannot establish a constructed context entry for the key " + target
+              + " due to a runtime failure.";
+            throw new ModelException( error, e );
+        }
+
+        if( !m_descriptor.isVolatile() )
+        {
+            m_value = object;
+        }
+
+        return object;
+    }
+
+    private String getReturnTypeClassname()
+    {
+        String classname = m_directive.getClassname();
+        if( null == classname )
+        {
+            return m_descriptor.getClassname();
+        }
+        else
+        {
+            return classname;
+        }
+    }
+
+   /**
+    * Return the context entry value.
+    *
+    * @return the context entry value
+    */
+    public Object getValue( Value p )
+        throws ModelException
+    {
+        ClassLoader loader = m_context.getClassLoader();
+        String classname = p.getClassname();
+        String argument = p.getArgument();
+        Value[] params = p.getValueDirectives();
+        Class clazz = getValueClass( classname, loader );
+        return getValue( loader, clazz, argument, params );
+    }
+
+    /**
+     * Return the derived parameter value.
+     * @param loader the classloader to use
+     * @param clazz the constructor class
+     * @param argument a single string constructor argument
+     * @param parameters an alternative sequence of arguments
+     * @return the value
+     * @exception ModelException if the parameter value cannot be resolved
+     */
+    public Object getValue(
+            ClassLoader loader, Class clazz, String argument,
+            Value[] 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( parameters.length == 0 )
+        {
+            if( argument == null )
+            {
+                return getNullArgumentConstructorValue( clazz );
+            }
+            else
+            {
+                return getSingleArgumentConstructorValue( loader, clazz, argument );
+            }
+        }
+        else
+        {
+             return getMultiArgumentConstructorValue( loader, clazz, parameters );
+        }
+    }
+
+    private Object getMultiArgumentConstructorValue(
+      ClassLoader classLoader, Class clazz, Value[] parameters )
+      throws ModelException
+    {
+        //
+        // getting here means we are dealing with 0..n types parameter constructor where the
+        // parameters are defined by the nested parameter definitions
+        //
+
+        if ( parameters.length == 0 )
+        {
+            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 constructor for the class: '"
+                  + clazz.getName() + "'.";
+                throw new ModelException( error, e );
+            }
+        }
+        else
+        {
+            Class[] params = new Class[ parameters.length ];
+            for ( int i = 0; i < parameters.length; i++ )
+            {
+                String classname = parameters[i].getClassname();
+                try
+                {
+                    params[i] = classLoader.loadClass( classname );
+                }
+                catch ( Throwable e )
+                {
+                    final String error =
+                      "Unable to resolve sub-parameter class: "
+                        + classname
+                        + " for the parameter " + clazz.getName();
+                    throw new ModelException( error, e );
+                }
+            }
+
+            Object[] values = new Object[ parameters.length ];
+            for ( int i = 0; i < parameters.length; i++ )
+            {
+                Value p = parameters[i];
+                String classname = p.getClassname();
+                try
+                {
+                    values[i] = getValue( p );
+                }
+                catch ( Throwable e )
+                {
+                    final String error =
+                      "Unable to instantiate sub-parameter for value: "
+                        + classname
+                        + " inside the parameter " + clazz.getName();
+                    throw new ModelException( error, e );
+                }
+            }
+            Constructor constructor = null;
+            try
+            {
+                constructor = clazz.getConstructor( params );
+            }
+            catch ( NoSuchMethodException e )
+            {
+                final String error =
+                  "Supplied parameters for "
+                    + clazz.getName()
+                    + " do not match the available class constructors.";
+                throw new ModelException( error, e );
+            }
+
+            try
+            {
+                return constructor.newInstance( values );
+            }
+            catch ( InstantiationException e )
+            {
+                final String error =
+                  "Unable to instantiate an instance of a multi-parameter constructor for class: '"
+                  + clazz.getName() + "'.";
+                throw new ModelException( error, e );
+            }
+            catch ( IllegalAccessException e )
+            {
+                final String error =
+                  "Cannot access multi-parameter constructor for the class: '"
+                  + clazz.getName() + "'.";
+                throw new ModelException( error, e );
+            }
+            catch ( Throwable e )
+            {
+                final String error =
+                  "Unexpected error while attmpting to instantiate a multi-parameter constructor "
+                  + "for the class: '" + clazz.getName() + "'.";
+                throw new ModelException( error, e );
+            }
+        }
+    }
+
+    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
+    {
+        if ( argument.startsWith( "${" ) )
+        {
+            if ( argument.endsWith( "}" ) )
+            {
+                final String key = argument.substring( 2, argument.length() - 1 );
+                Object value = m_map.get( key );
+                if ( value != null )
+                {
+                    if( value instanceof EntryModel )
+                    {
+                        return ((EntryModel)value).getValue();
+                    }
+                    else
+                    {
+                        return value;
+                    }
+                }
+                else
+                {
+                    final String error =
+                      "Unresolvable context value: '" + key + "'.";
+                    throw new ModelException( error );
+                }
+            }
+            else
+            {
+                final String error =
+                  "Illegal format for context reference: '" + argument + "'.";
+                throw new ModelException( error );
+            }
+        }
+        else
+        {
+            //
+            // the argument is a simple type that takes a single String value
+            // as a constructor argument
+            //
+
+            if( clazz.isPrimitive() )
+            {
+                if( Integer.TYPE == clazz )
+                {
+                    return Integer.valueOf( argument );
+                }
+                else if( Boolean.TYPE == clazz )
+                {
+                    return Boolean.valueOf( argument );
+                }
+                else if( Byte.TYPE == clazz )
+                {
+                    return Byte.valueOf( argument );
+                }
+                else if( Short.TYPE == clazz )
+                {
+                    return Short.valueOf( argument );
+                }
+                else if( Long.TYPE == clazz )
+                {
+                    return Long.valueOf( argument );
+                }
+                else if( Float.TYPE == clazz )
+                {
+                    return Float.valueOf( argument );
+                }
+                else if( Double.TYPE == clazz )
+                {
+                    return Double.valueOf( argument );
+                }
+                else
+                {
+                    final String error =
+                      "The primitive return type ["
+                      + clazz.getName()
+                      + "] is not supported.";
+                    throw new ModelException( error );
+                }
+            }
+
+            try
+            {
+                final Class[] params = new Class[]{ String.class };
+                Constructor constructor = clazz.getConstructor( params );
+                final Object[] values = new Object[]{ argument };
+                return constructor.newInstance( values );
+            }
+            catch ( NoSuchMethodException e )
+            {
+                final String error =
+                  "Class: '" + clazz.getName()
+                  + "' does not implement a single string argument constructor.";
+                throw new ModelException( error );
+            }
+            catch ( InstantiationException e )
+            {
+                final String error =
+                  "Unable to instantiate instance of class: " + clazz.getName()
+                  + " with the single argument: '" + argument + "'";
+                throw new ModelException( error, e );
+            }
+            catch ( IllegalAccessException e )
+            {
+                final String error =
+                  "Cannot access single string parameter constructor for the class: '"
+                  + clazz.getName() + "'.";
+                throw new ModelException( error, e );
+            }
+            catch ( Throwable e )
+            {
+                final String error =
+                  "Unexpected exception while creating a single string parameter value for the class: '"
+                  + clazz.getName() + "'.";
+                throw new ModelException( error, e );
+            }
+        }
+    }
+
+    /**
+     * Return the classname of the parameter implementation to use.
+     * @param loader the classloader to use
+     * @return the parameter class
+     * @exception ModelException if the parameter class cannot be resolved
+     */
+    Class getValueClass( String classname, ClassLoader classLoader ) throws ModelException
+    {
+        try
+        {
+            return classLoader.loadClass( classname );
+        }
+        catch ( final ClassNotFoundException e )
+        {
+            if ( classname.equals( "int" ) )
+            {
+                return int.class;
+            }
+            else if ( classname.equals( "short" ) )
+            {
+                return short.class;
+            }
+            else if ( classname.equals( "long" ) )
+            {
+                return long.class;
+            }
+            else if ( classname.equals( "byte" ) )
+            {
+                return byte.class;
+            }
+            else if ( classname.equals( "double" ) )
+            {
+                return double.class;
+            }
+            else if ( classname.equals( "byte" ) )
+            {
+                return byte.class;
+            }
+            else if ( classname.equals( "float" ) )
+            {
+                return float.class;
+            }
+            else if ( classname.equals( "char" ) )
+            {
+                return char.class;
+            }
+            else if ( classname.equals( "char" ) )
+            {
+                return char.class;
+            }
+            else if ( classname.equals( "boolean" ) )
+            {
+                return boolean.class;
+            }
+            else
+            {
+                throw new ModelException(
+                  "Could not locate the parameter implementation for class: '"
+                     + classname + "'.", e );
+            }
+        }
+    }
+}

Modified: development/main/metro/composition/testing/acme/build.xml
==============================================================================
--- development/main/metro/composition/testing/acme/build.xml	(original)
+++ development/main/metro/composition/testing/acme/build.xml	Sat Mar 26 00:57:13 2005
@@ -15,15 +15,19 @@
 
     <!-- create a classic container model -->
     <container xmlns="plugin:dpml/composition/dpml-composition-builder" name="acme">
-      <component name="widget" class="net.dpml.composition.testing.DefaultWidget"/>
-      <component name="gizmo" class="net.dpml.composition.testing.DefaultGizmo">
+      <component name="widget" class="net.dpml.composition.testing.DefaultWidget">
         <context>
+          <entry key="foo" value="bar"/>
           <entry key="width" value="12"/>
           <entry key="height" value="100"/>
         </context>
+      </component>
+      <component name="gizmo" class="net.dpml.composition.testing.DefaultGizmo">
+        <!--
         <dependencies>
           <dependency key="widget" source="widget"/>
         </dependencies>
+        -->
         <parts>
           <value key="foo" value="bar"/>
           <value key="date" class="java.util.Date"/>

Modified: development/main/metro/composition/testing/acme/src/main/net/dpml/composition/testing/DefaultGizmo.java
==============================================================================
--- development/main/metro/composition/testing/acme/src/main/net/dpml/composition/testing/DefaultGizmo.java	(original)
+++ development/main/metro/composition/testing/acme/src/main/net/dpml/composition/testing/DefaultGizmo.java	Sat Mar 26 00:57:13 2005
@@ -28,13 +28,6 @@
 public class DefaultGizmo implements Gizmo
 {
     //------------------------------------------------------------------
-    // state
-    //------------------------------------------------------------------
-
-    private final Logger m_logger;
-    private final Widget m_widget;
-
-    //------------------------------------------------------------------
     // constructor
     //------------------------------------------------------------------
 
@@ -44,27 +37,20 @@
     * @param logger the logging channel assigned by the container
     * @param dependencies the requested dependencies
     */
-    public DefaultGizmo( Logger logger, Dependencies dependencies, Parts parts )
+    public DefaultGizmo( Logger logger, Dependencies dependencies )
     {
-        m_logger = logger;
-        m_widget = dependencies.getTheAcmeWidget();
-        m_logger.info( "up and running with: " + m_widget.toString() );
+        logger.info( "initializing" );
+        Widget widget = dependencies.getWidget();
+        logger.info( "widget established: " + widget );
     }
 
     //------------------------------------------------------------------
     // facards
     //------------------------------------------------------------------
 
-    public interface Context
-    {
-        int getWidth();
-
-        int getHeight( int defaultHeight );
-    }
-
     public interface Dependencies
     {
-        Widget getTheAcmeWidget();
+        Widget getWidget();
     }
 
     public interface Parts

Modified: development/main/metro/composition/testing/acme/src/main/net/dpml/composition/testing/DefaultWidget.java
==============================================================================
--- development/main/metro/composition/testing/acme/src/main/net/dpml/composition/testing/DefaultWidget.java	(original)
+++ development/main/metro/composition/testing/acme/src/main/net/dpml/composition/testing/DefaultWidget.java	Sat Mar 26 00:57:13 2005
@@ -34,12 +34,6 @@
     public static final boolean TYPE_THREADSAFE_CAPABLE = true;
 
     //------------------------------------------------------------------
-    // state
-    //------------------------------------------------------------------
-
-    private final Logger m_logger;
-
-    //------------------------------------------------------------------
     // constructor
     //------------------------------------------------------------------
 
@@ -48,9 +42,28 @@
     *
     * @param logger the logging channel asign by the container
     */
-    public DefaultWidget( Logger logger )
+    public DefaultWidget( Logger logger, Context context )
+    {
+        String foo = context.getFoo();
+        int width = context.getWidth();
+        int height = context.getHeight( 5024 );
+
+        logger.info( 
+          foo 
+          + " established with a width of " 
+          + width 
+          + " and a height of " 
+          + height );
+    }
+
+    //------------------------------------------------------------------
+    // facards
+    //------------------------------------------------------------------
+
+    public interface Context
     {
-        m_logger = logger;
-        m_logger.info( "up and running" );
+        String getFoo();
+        int getWidth();
+        int getHeight( int defaultHeight );
     }
 }

Added: development/main/metro/composition/testing/unit/build.xml
==============================================================================
--- (empty file)
+++ development/main/metro/composition/testing/unit/build.xml	Sat Mar 26 00:57:13 2005
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<project name="dpml-composition-testing-unit" default="install" basedir="."
+    xmlns:transit="antlib:net.dpml.transit" xmlns:x="plugin:dpml/magic/dpml-magic-core">
+
+  <transit:import uri="artifact:template:dpml/magic/standard"/>
+
+  <target name="init" depends="standard.init">
+    <x:property key="dpml-composition-testing-acme" feature="uri" type="part" name="acme.part"/>
+    <filter token="ACME-PART-URI" value="${acme.part}"/>
+  </target>
+
+</project>

Added: development/main/metro/composition/testing/unit/src/test/net/dpml/composition/test/FreightTestCase.java
==============================================================================
--- (empty file)
+++ development/main/metro/composition/testing/unit/src/test/net/dpml/composition/test/FreightTestCase.java	Sat Mar 26 00:57:13 2005
@@ -0,0 +1,67 @@
+/* 
+ * Copyright 2004 Apache Software Foundation
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.composition.test;
+
+import java.net.URI;
+
+import net.dpml.metro.unit.CompositionTestCase;
+
+import net.dpml.composition.model.DeploymentModel;
+import net.dpml.composition.model.ContainmentModel;
+
+import net.dpml.exception.ExceptionHelper;
+
+/**
+ * The hello component testcase validates that the 
+ * hello example is deployable.
+ */
+public class FreightTestCase extends CompositionTestCase
+{
+    //----------------------------------------------------------
+    // testcase
+    //----------------------------------------------------------
+
+    public void setUp() throws Exception
+    {
+        super.setupCompositionRoot();
+    }
+
+   /**
+    * Validate that the hello component is deployable and resolvable.
+    * @exception if a deployment error occurs
+    */
+    public void testFreight() throws Throwable
+    {
+        try
+        {
+            URI uri = new URI( "@ACME-PART-URI@" );
+            DeploymentModel test = getRoot().addModel( "test", uri );
+            test.commission();
+            Object object = test.resolve( false );
+            test.release( object );
+            getRoot().decommission();
+        }
+        catch( Throwable e )
+        {
+            final String header = "Derailed!";
+            String stack = ExceptionHelper.packException( header, e, true );
+            System.out.println( stack );
+            throw e;
+        }
+    }
+}

Modified: development/main/metro/index.xml
==============================================================================
--- development/main/metro/index.xml	(original)
+++ development/main/metro/index.xml	Sat Mar 26 00:57:13 2005
@@ -318,6 +318,7 @@
       </types>
     </info>
     <dependencies>
+      <include key="dpml-automation-part" tag="api"/>
       <include key="dpml-composition-spi"/>
       <include key="dpml-composition-impl" build="false"/>
       <include key="dpml-configuration-api"/>
@@ -412,6 +413,7 @@
       <include key="dpml-util-cli"/>
       <include key="dpml-activation-impl" build="false"/>
       <include key="dpml-test-playground" build="false"/>
+      <include key="dpml-composition-control"/>
     </dependencies>
   </project>
 
@@ -525,6 +527,22 @@
     </plugins>
   </project>
 
+  <project basedir="composition/testing/unit">
+    <info>
+      <group>dpml/test</group>
+      <name>dpml-composition-testing-unit</name>
+      <version>1.0.0</version>
+      <status>SNAPSHOT</status>
+      <types>
+        <type>jar</type>
+      </types>
+    </info>
+    <dependencies>
+      <include key="dpml-composition-testing-acme" build="false"/>
+      <include key="dpml-metro-unit"/>
+    </dependencies>
+  </project>
+
   <!-- Utitlities -->
 
   <project basedir="util/defaults">
@@ -849,7 +867,6 @@
       </types>
     </info>
     <dependencies>
-      <include key="dpml-activity-api" tag="api"/>
       <include key="dpml-composition-api" tag="api"/>
       <include key="avalon-framework-api" tag="api"/>
       <include key="dpml-activation-api" tag="api"/>
@@ -878,6 +895,7 @@
       <include key="dpml-transit-main" tag="api"/>
       <include key="dpml-activation-api" tag="api"/>
       <include key="dpml-composition-api" tag="api"/>
+      <include key="dpml-automation-part" tag="api"/>
       <include key="dpml-activation-metro-provider" build="false"/>
       <include key="dpml-activation-avalon-provider" build="false"/>
       <include key="dpml-system-impl" build="false"/>

Added: development/main/metro/service/api/src/main/net/dpml/service/FulfillmentRuntimeException.java
==============================================================================
--- (empty file)
+++ development/main/metro/service/api/src/main/net/dpml/service/FulfillmentRuntimeException.java	Sat Mar 26 00:57:13 2005
@@ -0,0 +1,51 @@
+/* 
+ * Copyright 2004 Stephen J. McConnell.
+ * 
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.service;
+
+/**
+ * Exception to indicate that there was a fatal service error.
+ *
+ * @author <a href="mailto:dev-dpml at lists.ibiblio.org">The Digital Product Meta Library</a>
+ * @version $Id: FatalServiceException.java 259 2004-10-30 07:24:40Z mcconnell $
+ */
+public class FulfillmentRuntimeException
+        extends RuntimeException 
+{
+     final String m_key;
+
+    /**
+     * Construct a new <code>FulfillmentRuntimeException</code> instance.
+     *
+     * @param key the lookup key
+     * @param message The detail message for this exception.
+     * @param cause expected service availability delay in milliseconds 
+     */
+    public FulfillmentRuntimeException( 
+      final String key, final String message, Throwable cause )
+    {
+        super( message, cause );
+        m_key = key;
+    }
+
+    public String getKey()
+    {
+        return m_key;
+    }
+}
+



More information about the notify-dpml mailing list