mcconnell    2002/11/30 06:47:51

  Modified:    assembly/src/java/org/apache/avalon/assembly/engine
                        DefaultEngine.java Engine.java
               assembly/src/test/org/apache/avalon/assembly/engine
                        EngineTestCase.java
  Added:       assembly/src/java/org/apache/avalon/assembly/lifecycle
                        ContextHandler.java
  Log:
  Engine, Default engine and test case update to make the interfaces easier to
  deal with and more intative.
  
  Revision  Changes    Path
  1.2       +39 -8     
avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/DefaultEngine.java
  
  Index: DefaultEngine.java
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/DefaultEngine.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultEngine.java        29 Nov 2002 13:18:01 -0000      1.1
  +++ DefaultEngine.java        30 Nov 2002 14:47:51 -0000      1.2
  @@ -97,6 +97,7 @@
       private ApplianceManager m_appliances;
   
       private ClassLoader m_classloader;
  +    private Map m_map;
   
       //==============================================================
       // Contextualizable
  @@ -145,6 +146,15 @@
           {
               // ignore
           }
  +
  +        try
  +        {
  +            m_map = (Map) context.get( "assembly:system-map" );
  +        }
  +        catch( ContextException ce )
  +        {
  +            // ignore
  +        }
       }
   
       //==============================================================
  @@ -184,7 +194,7 @@
       * @param path the path to the appliance implementation class
       * @return the appliance
       */
  -    public void register( String path ) throws Exception
  +    public void register( String path ) throws EngineRuntimeException
       {
           try
           {
  @@ -197,7 +207,7 @@
           {
               final String error = 
                 "Failed to register one or more profiles.";
  -            throw new EngineException( error, e );
  +            throw new EngineRuntimeException( error, e );
           }
       }
   
  @@ -338,16 +348,22 @@
       private ApplianceManager createApplianceManager( ClassLoader classloader 
) throws Exception
       {
           DefaultApplianceManager manager = new DefaultApplianceManager();
  +
           manager.enableLogging( getLogger() );
  +
           DefaultContext context = new DefaultContext( getSystemContext() );
           context.put( "assembly:classloader", classloader );
  +        context.put( "assembly:pool-manager", getPoolManager() );
           context.makeReadOnly();
           manager.contextualize( context );
  +
           DefaultServiceManager services = new DefaultServiceManager();
           services.put( "assembly:engine", this );
           services.makeReadOnly();
           manager.service( services );
  +
           manager.initialize();
  +
           return manager;
       }
   
  @@ -355,15 +371,30 @@
       {
           if( m_context == null )
           {
  -            DefaultContext context = new DefaultContext();
  -            final File home = new File( System.getProperty( "user.dir" ) );
  -            context.put( "avalon:home", home );
  -            context.put( "assembly:pool-manager", getPoolManager() );
  +            DefaultContext context;
  +            if( m_map != null )
  +            {
  +                context = new DefaultContext( m_map );
  +            }
  +            else
  +            {
  +                context = new DefaultContext();
  +            }
  +
  +            try
  +            {
  +                context.get( "avalon:home" );
  +            }
  +            catch( ContextException ce )
  +            {
  +                final File home = new File( System.getProperty( "user.dir" ) 
);
  +                context.put( "avalon:home", home );
  +            }
  +    
               m_context = context;
           }
           return m_context;
       }
  -
   
       private PoolManager getPoolManager()
       {
  
  
  
  1.2       +3 -2      
avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/Engine.java
  
  Index: Engine.java
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/Engine.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Engine.java       29 Nov 2002 13:18:01 -0000      1.1
  +++ Engine.java       30 Nov 2002 14:47:51 -0000      1.2
  @@ -71,8 +71,9 @@
       * Register a type and associated profiles with the container.
       * @param path the path to the appliance implementation class
       * @return the appliance
  +    * @exception EngineRuntimeException if a registration error occurs
       */
  -    void register( String path ) throws Exception;
  +    void register( String path ) throws EngineRuntimeException;
   
      /**
       * Create a new appliance.
  
  
  
  1.1                  
avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/lifecycle/ContextHandler.java
  
  Index: ContextHandler.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
  
  */
  
  package org.apache.avalon.assembly.lifecycle;
  
  import java.util.Map;
  import java.lang.reflect.Constructor;
  import java.util.HashMap;
  
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.DefaultContext;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.assembly.appliance.Appliance;
  import org.apache.avalon.meta.model.Entry;
  import org.apache.avalon.meta.model.Import;
  import org.apache.avalon.meta.model.Profile;
  import org.apache.avalon.meta.model.ContextDirective;
  import org.apache.avalon.meta.info.ContextDescriptor;
  import org.apache.avalon.meta.info.EntryDescriptor;
  import org.apache.avalon.meta.info.ExtensionDescriptor;
  
  /**
   * The context service provides support for the contextualization of a 
   * supplied component instance relative to the criteria establihsed under a 
   * supplied appliance.
   *
   * @author <a href="mailto:avalon-dev@jakarta.apache.org";>Avalon Development 
Team</a>
   * @version $Revision: 1.1 $ $Date: 2002/11/30 14:47:51 $
   */
  public class ContextHandler extends AbstractLogEnabled implements 
Contextualizable
  {
      //==============================================================
      // state
      //==============================================================
  
      private Context m_context;
  
      private ClassLoader m_classloader;
  
      //==============================================================
      // Contextualizable
      //==============================================================
  
     /**
      * <p>Application of a runtime context to this appliance.
      * The supplied context contains standard and container specific context
      * entries and may be used by the context service in establish the 
      * context to apply to components.</p>
      * @param context the containerment context
      */
      public void contextualize( Context context ) throws ContextException
      {
          m_context = context;
          m_classloader = (ClassLoader) context.get( "assembly:classloader" );
      }
  
      //==============================================================
      // utilities
      //==============================================================
  
      /**
       * Internal utility to construct a context instance using a descriptor, 
directive and source
       * context instances.
       *
       * @param descriptors the descriptor containing the context dependency 
declarations
       * @param directive an optional context directive containing import and 
context value
       *    creation parameters
       * @param context a supplimentary context object to used during value 
resolution
       * @return a context object containing only those context entries 
desribed under the
       *   supplied descriptor
       * @exception Exception if a required context value cannot be resolved or 
an error
       *   occurs during context value creation
       */
      protected Context buildContext(
                             ContextDescriptor descriptors,
                             ContextDirective directive,
                             Context context )
        throws Exception
      {
          Map map = new HashMap();
          Context result;
  
          if( directive != null )
          {
              final String classname = directive.getClassname();
              Class clazz;
              try
              {
                  clazz = m_classloader.loadClass( classname );
              }
              catch( ClassNotFoundException cnfe )
              {
                  throw new ContextException(
                      "Could not find context class " + classname, cnfe );
              }
  
              try
              {
                  Constructor constructor = clazz.getConstructor(
                      new Class[]{Map.class, Context.class} );
                  result = (Context)constructor.newInstance( new Object[]{map, 
null} );
              }
              catch( Throwable e )
              {
                  throw new ContextException(
                      "Unexpected exception while creating context form "
                      + classname, e );
              }
          }
          else
          {
              result = new DefaultContext( map );
          }
  
          EntryDescriptor[] entries = descriptors.getEntrys();
          for( int i = 0; i < entries.length; i++ )
          {
              EntryDescriptor entry = entries[ i ];
              String key = entry.getKey();
  
              //
              // if the entry is already in the supplied context then use it
              //
  
              Object object = getContextValue( context, key );
  
              //
              // If the context value is unresolved, try to handle resolution
              // using an import directive supplied under the directive
              //
  
              if( object == null )
              {
  
                  //
                  // check if the profile declares an import directive
                  // for the context
                  //
  
                  if( directive != null )
                  {
                      Import imp = directive.getImport( key );
                      if( imp != null )
                      {
                          String name = imp.getImportName();
                          object = getContextValue( context, name );
                          if( object == null )
                          {
                              final String error =
                                  "Import directive for key: " + key + " via 
name: " + name
                                  + " cannot be resolved.";
                              getLogger().warn( error );
                          }
                      }
  
                      //
                      // if the context value is unresolved, try to construct a 
context
                      // value using an entry constructor directive
                      //
  
                      if( object == null )
                      {
                          //
                          // check if the directive declares a context value 
constructor
                          //
  
                          Entry ent = directive.getEntry( key );
                          if( ent != null )
                          {
                              object = ent.getValue( m_classloader, map );
                          }
                      }
                  }
              }
  
              //
              // finally, if the object is still null, and its not optional, 
then
              // throw an exception, otherwise, add the object to the context
              //
  
              if( object != null )
              {
                  try
                  {
                      boolean ok = objectImplementsType( object, 
entry.getType() );
                      if( ok )
                      {
                          map.put( key, object );
                      }
                      else
                      {
                          final String error =
                              "Object resolved for the key '" + key + "' of 
class '"
                              + object.getClass().getName() + "' does not 
implement the type '"
                              + entry.getType();
                          throw new ContextException( error );
                      }
                  }
                  catch( ClassNotFoundException cnfe )
                  {
                      final String error =
                          "Context criteria for the key '" + key + "' specifies 
an unknown type '"
                          + entry.getType() + "'.";
                      throw new ContextException( error );
                  }
              }
              else
              {
                  if( entry.isRequired() )
                  {
                      final String error =
                        "Unable to resolve a context value for the entry: '" 
                        + key + "' type: "
                        + entry.getType();
                      throw new ContextException( error );
                  }
              }
          }
  
          if( result instanceof DefaultContext )
          {
              ( (DefaultContext)result ).makeReadOnly();
          }
  
          return result;
      }
  
      /**
       * Create a new Context for an extension.
       *
       * @param extension the extension descriptor
       * @param context a supplimentary context used during import resolution
       * @return a new Context for service
       * @throws Exception if unable to create context
       */
      protected Context createContext( ExtensionDescriptor extension, Context 
context )
          throws Exception
      {
          ContextDescriptor descriptor = extension.getContext();
          return buildContext( descriptor, null, context );
      }
  
      /**
       * Internal utility to get a context value or null if the context key
       * is unknown.
       * @param context the context object
       * @param key the context key to lookup
       * @return the context value derived from the key or null if the key is 
unknown
       */
      protected Object getContextValue( Context context, String key )
      {
          if( context == null )
          {
              return null;
          }
  
          try
          {
              return context.get( key );
          }
          catch( ContextException e )
          {
              return null;
          }
      }
  
      /**
       * Check whether the specified value is compatible with specified type.
       *
       * @param value the value
       * @param type the desired type
       * @return true if value is compatible with type, false otherwise
       */
      protected boolean objectImplementsType( final Object value, final String 
type )
          throws ClassNotFoundException
      {
          if( type == null )
          {
              throw new NullPointerException( "type" );
          }
  
          if( value == null )
          {
              throw new NullPointerException( "value" );
          }
  
          final Class clazz = value.getClass();
          final Class typeClass = m_classloader.loadClass( type );
          return typeClass.isAssignableFrom( clazz );
      }
  }
  
  
  
  1.2       +36 -18    
avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/engine/EngineTestCase.java
  
  Index: EngineTestCase.java
  ===================================================================
  RCS file: 
/home/cvs/avalon-sandbox/assembly/src/test/org/apache/avalon/assembly/engine/EngineTestCase.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- EngineTestCase.java       29 Nov 2002 13:24:45 -0000      1.1
  +++ EngineTestCase.java       30 Nov 2002 14:47:51 -0000      1.2
  @@ -51,25 +51,40 @@
       }
   
      /**
  -    * Test a component with custom context type and profile based import and 
entry creation directives.
  +    * Test a component with custom context type and profile based import and 
  +    * entry creation directives and no service dependencies.
       */
       public void testBasicComponent()
       {
  -        final String classname = 
"org.apache.avalon.playground.BasicComponent";
  +        //
  +        // register the component types with the engine - this will result 
in the 
  +        // automatic loading of the type defintion and the any packaged 
profiles
  +        //
   
  -        ReferenceDescriptor reference = 
  -          new ReferenceDescriptor(
  -            "org.apache.avalon.playground.BasicService",
  -            Version.getVersion( "1.1" ) );
  +        try
  +        {
  +            final String classname = 
"org.apache.avalon.playground.BasicComponent";
  +            m_engine.register( classname );
  +            assertTrue( true );
  +        }
  +        catch( Throwable e )
  +        {
  +            ExceptionHelper.printException( "Registration failure.", e, 
this, true );
  +            assertTrue( false );
  +        }
  +
  +        //
  +        // get a full assembled and verified appliance from the engine using
  +        // a service classname and version
  +        //
   
  +        Appliance appliance = null;
  +        final String servicename = 
"org.apache.avalon.playground.BasicService";
           DependencyDescriptor dependency = 
  -          new DependencyDescriptor( "test", reference );
  +          new DependencyDescriptor( "test", servicename, Version.getVersion( 
"1.1" ) );
             
  -        Appliance appliance = null;
           try
           {
  -            m_engine.register( classname );
  -            assertTrue( true );
               appliance = m_engine.resolve( dependency );
               assertTrue( appliance != null );
           }
  @@ -79,6 +94,11 @@
               assertTrue( false );
           }
   
  +        //
  +        // request an instance of a service provided by the appliance
  +        // that the engine returned to us
  +        //
  +
           try
           {
               Object object = appliance.access( dependency );
  @@ -92,7 +112,7 @@
       }
   
      /**
  -    * Test a component with custom context type and profile based import and 
entry creation directives.
  +    * Test a component with service and extension depedencies.
       */
       public void testSimpleComponent()
       {
  @@ -101,13 +121,10 @@
           final String exploiter = 
"org.apache.avalon.playground.ExploitationManager";
           final String demo = "org.apache.avalon.playground.DemoManager";
   
  -        ReferenceDescriptor reference = 
  -          new ReferenceDescriptor(
  -            "org.apache.avalon.playground.SimpleService",
  -            Version.getVersion( "1.1" ) );
  +        final String service = "org.apache.avalon.playground.SimpleService";
   
           DependencyDescriptor dependency = 
  -          new DependencyDescriptor( "test", reference );
  +          new DependencyDescriptor( "test", service, Version.getVersion( 
"1.1" ) );
             
           Appliance appliance = null;
           try
  @@ -117,12 +134,13 @@
               m_engine.register( demo );
               m_engine.register( simple );
               assertTrue( true );
  +
               appliance = m_engine.resolve( dependency );
               assertTrue( appliance != null );
           }
           catch( Throwable e )
           {
  -            System.out.println("failed to resolve : " + reference );
  +            System.out.println("failed to resolve : " + dependency );
               ExceptionHelper.printException( "Resolution failure.", e, 
appliance, true );
               assertTrue( false );
           }
  @@ -134,7 +152,7 @@
           }
           catch( Throwable e )
           {
  -            System.out.println("appliance access failure : " + reference );
  +            System.out.println("appliance access failure : " + dependency );
               ExceptionHelper.printException( "Access failure.", e, appliance, 
true );
               assertTrue( false );
           }
  
  
  

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

Reply via email to