You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by mc...@apache.org on 2003/06/04 07:22:37 UTC

cvs commit: avalon-sandbox/merlin/merlin-smp/xdocs/starting/advanced context.xml

mcconnell    2003/06/03 22:22:37

  Modified:    merlin/merlin-smp/xdocs/starting/advanced context.xml
  Log:
  Addition of the custom contextualization management tutorial.
  
  Revision  Changes    Path
  1.2       +261 -1    avalon-sandbox/merlin/merlin-smp/xdocs/starting/advanced/context.xml
  
  Index: context.xml
  ===================================================================
  RCS file: /home/cvs/avalon-sandbox/merlin/merlin-smp/xdocs/starting/advanced/context.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- context.xml	2 Apr 2003 15:52:16 -0000	1.1
  +++ context.xml	4 Jun 2003 05:22:37 -0000	1.2
  @@ -1,16 +1,276 @@
   <?xml version="1.0"?>
   
   <document>
  +
     <header>
       <title>Using Merlin</title>
       <authors>
         <person name="Stephen McConnell" email="mcconnell@apache.org"/>
       </authors>
     </header>
  +
     <body>
       <section name="Advanced Features">
         <subsection name="Creating a custom Contextualizer">
  -        <p>In preparation.</p>
  +        <p>
  +         Merlin provides support for the pluggable introduction
  +         of contextualization stage handlers that are completely
  +         indepedent of the Avalon component model.
  +        </p>
  +        <p>
  +         Establishing a custom contextualizer involves:
  +        </p>
  +        <ul>
  +          <li>defining the contextualization interface</li>
  +          <li>implementation of a contextualization handler</li>
  +          <li>implementing the contextualization stage in a component</li>
  +        </ul>
  +        <p>
  +         Resources supporting this tutorial are included in the 
  +         src/tutorial/contextualization package.
  +        </p>
  +      </subsection>
  +      <subsection name="Contextualization stage defintion">
  +        <p>
  +         You can declare any interface to serve as the contextualization
  +         lifecycle stage.  The following example follows the Avalon 
  +         pattern but passes a domain specific context as the contextualization
  +         argument (i.e. eliminating the need to cast to a domain specific
  +         interface).
  +        </p>
  +        <source><![CDATA[
  +public interface Contextualizable
  +{
  +    /**
  +     * Contextualization of the component.
  +     * @param context the containement context
  +     * @exception ContextException if a contextualization error occurs
  +     */
  +    void contextualize( StandardContext context ) 
  +      throws ContextException;
  +}
  +]]></source>
  +      </subsection>
  +
  +      <subsection name="Contextualization handler implementation">
  +        <p>
  +         A custom contextualization stage is managed by a contextualization
  +         handler component that you define.  The only constraint on a handler is 
  +         it implements the org.apache.avalon.assembly.lifecycle.Contextualization
  +         interface.
  +        </p>
  +        <source><![CDATA[
  +package tutorial;
  +
  +import java.util.Map;
  +import org.apache.avalon.assembly.lifecycle.Contextualization;
  +import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.meta.model.ContextDirective;
  +
  +public class ContextualizationHandler implements Contextualization
  +{
  +    /**
  +     * Handle the contextualization stage of a component lifecycle.
  +     * @param loader the classloader
  +     * @param directive the context directitive
  +     * @param object the object to contextualize
  +     * @param map the map of context entries
  +     * @exception ContextException if a contextualization error occurs
  +     */
  +    public void contextualize(
  +      ClassLoader loader, ContextDirective directive, Object object, Map map )
  +      throws ContextException
  +    {
  +        //
  +        // based on the supplied context directives, the container supplied 
  +        // map of base context entries and a classloader, build and apply
  +        // a context object to the supplied target object
  +        //
  +
  +        if( object instanceof Contextualizable )
  +        {
  +            Object context = 
  +              createContextArgument( loader, directive, StandardContext.class, map );
  +            if( context instanceof StandardContext )
  +            {
  +                ( (Contextualizable)object ).contextualize( (StandardContext) context );
  +            }
  +            else
  +            {
  +                final String error =
  +                  "Supplied context does not implement the StandardContext interface.";
  +                throw new ContextException( error );
  +            }
  +        }
  +        else
  +        {
  +            final String error =
  +              "Target object does not implement the "
  +              + Contextualizable.class.getName() + " interface.";
  +            throw new ContextException( error );
  +        }
  +    }
  +
  +   /**
  +    * Returns a instance of a class established using the supplied map as a
  +    * constructor argument.
  +    *
  +    * @param descriptor the context descriptor
  +    * @param clazz the default class if no class defined in the descriptor
  +    * @param map the context entry map
  +    * @return the context argument value
  +    */
  +    private Object createContextArgument( 
  +       ClassLoader loader, ContextDirective directive, Class clazz, Map map )
  +       throws ContextException
  +    {
  +        if( directive == null )
  +        {
  +            throw new NullPointerException( "directive" );
  +        }
  +        if( clazz == null )
  +        {
  +            throw new NullPointerException( "clazz" );
  +        }
  +        if( map == null )
  +        {
  +            throw new NullPointerException( "map" );
  +        }
  +
  +        String classname = directive.getClassname();
  +        Class base;
  +        if( classname != null )
  +        {
  +            try
  +            {
  +                base = loader.loadClass( classname );
  +            }
  +            catch( ClassNotFoundException cnfe )
  +            {
  +                throw new ContextException(
  +                  "Could not find context class: " + classname, cnfe );
  +            }
  +        }
  +        else
  +        {
  +            base = clazz;
  +        }
  +
  +        try
  +        {
  +            Constructor constructor = base.getConstructor(
  +               new Class[]{ Map.class } );
  +            return constructor.newInstance( new Object[]{ map } );
  +        }
  +        catch( NoSuchMethodException e )
  +        {
  +            final String error =
  +              "Custom context class: [" + classname
  +              + "] does not implement a constructor pattern <init>{ Map }.";
  +            throw new ContextException( error, e );
  +        }
  +        catch( Throwable e )
  +        {
  +            throw new ContextException(
  +                "Unexpected exception while creating context from "
  +                + base.getName(), e );
  +        }
  +    }
  +}
  +]]></source>
  +
  +      </subsection>
  +
  +      <subsection name="Declaration of the handler">
  +        <p>
  +          In order for the handler component to be recognized by 
  +          Merlin we need to declare a type defintion.  The defintion
  +          includes the declaration of the components support for 
  +          the custom contextualization interface under an extension
  +          declaration.
  +        </p>
  +<source><![CDATA[
  +<type>
  +  <info>
  +    <name>context</name>
  +  </info>
  +  <extensions>
  +    <extension type="tutorial.Contextualizable" />
  +  </extensions>
  +</type>
  +]]></source>
  +      </subsection>
  +
  +      <subsection name="Create the component">
  +        <p>
  +          With the stage interface defined and the handler implementation
  +          in place, we can go ahead and create a component that implements
  +          the new contextualization interface.
  +        </p>
  +<source><![CDATA[
  +public class StandardComponent 
  +    implements Contextualizable
  +{
  +    /**
  +     * Supply of the the component context to the component type.
  +     * @param context the context value
  +     */
  +    public void contextualize( StandardContext context )
  +    {
  +        //
  +        // do some domain specific stuff using the supplied 
  +        // context 
  +        //
  +    }
  +}
  +]]></source>
  +        <p>
  +          Meta-info in the component context descriptor is required to declare to 
  +          Merlin that the component uses a custom context interface.  In the 
  +          following type descriptor the attribute key
  +          "urn:assembly:lifecycle.context.strategy" contains the classname of the
  +          interface used by the component for contextualization.
  +        </p>
  +<source><![CDATA[
  +<type>
  +
  +  <info>
  +    <name>standard</name>
  +  </info>
  +
  +  <context>
  +    <attributes>
  +      <attribute key="urn:assembly:lifecycle.context.strategy"
  +          value="tutorial.Contextualizable"/>
  +    </attributes>
  +  </context>
  +
  +]]></source>
  +      </subsection>
  +
  +      <subsection name="Execution">
  +        <p>
  +          Execute the folowing commands to build and run the tutorial.
  +        </p>
  +<source><![CDATA[
  +$ ant jar
  +$ merlin tutorial.jar
  +]]></source>
  +        <p>
  +          Logging output from the tutorial execution is shown below:
  +        </p>
  +<source><![CDATA[
  +[INFO   ] (sys): initialization: localhost
  +[INFO   ] (sys): commencing block assembly phase
  +[INFO   ] (standard): context
  +  contextualization using a custom hander
  +  home: F:\dev\tutorial\contextualization\working\home\standard
  +  work: F:\dev\tutorial\contextualization\working\temp\standard
  +  name: standard
  +  partition: /standard
  +
  +[INFO   ] (sys): Block hierarchy established.
  +]]></source>
         </subsection>
       </section>
     </body>
  
  
  

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