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