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/04/04 14:17:19 UTC
cvs commit: avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context casting.xml entries.xml index.xml navigation.xml standard.xml
mcconnell 2003/04/04 04:17:19
Modified: merlin/merlin-smp/xdocs/starting/hello navigation.xml
merlin/merlin-smp/xdocs/starting/hello/context casting.xml
entries.xml index.xml navigation.xml standard.xml
Log:
Supplimentary tutorial content.
Revision Changes Path
1.4 +1 -1 avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/navigation.xml
Index: navigation.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/navigation.xml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- navigation.xml 3 Apr 2003 22:14:07 -0000 1.3
+++ navigation.xml 4 Apr 2003 12:17:19 -0000 1.4
@@ -20,7 +20,7 @@
<item name="Configurations" href="/starting/hello/config.html"/>
<item name="Contextualization" href="/starting/hello/context/index.html"/>
<item name="Dependencies" href="/starting/hello/dependencies.html"/>
- <item name="Publishing Services" href="/starting/hello/services.html"/>
+ <item name="Services" href="/starting/hello/services.html"/>
</item>
<item name="Advanced Features" href="/starting/advanced/index.html"/>
</item>
1.2 +238 -5 avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context/casting.xml
Index: casting.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context/casting.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- casting.xml 3 Apr 2003 22:12:58 -0000 1.1
+++ casting.xml 4 Apr 2003 12:17:19 -0000 1.2
@@ -9,16 +9,249 @@
</header>
<body>
<section name="Using Merlin">
- <subsection name="Casting Context">
+ <subsection name="Casting Context to a custom Interface">
<p>
- This tutorial presents information about the declaration
- and implementation of a custom contextualization stage
- handler.
+ This tutorial describes how Merlin provides support
+ for the safe casting of a supplied context instance to
+ a domain specific context interface.
</p>
<p>
Resource supporting this tutorial are contained in the
- turorial/xxx package.
+ turorial/005 package.
</p>
+ </subsection>
+ <subsection name="Requirments">
+ <p>
+ While the context interface provides the mechanisms to
+ access any object type, it is sometimes convinient to
+ declare a domain specific interface and context
+ implementation. This enables client code to take advantage
+ of convinience accessors, resulting in code less cluttered
+ with casting and context entry key references.
+ </p>
+ <p>
+ For example, the followign code fragment demonstrates a type
+ safe casting of a supplied context value by the component to
+ domain specific context interface.
+ </p>
+<source>
+ /**
+ * Contextualization of the component using a context
+ * class that implements a domain specific context interface.
+ */
+ public void contextualize( Context context )
+ throws ContextException
+ {
+ DemoContext c = (DemoContext) context;
+ getLogger().info( "name: " + c.getName() );
+ getLogger().info( "partition: " + c.getPartition() );
+ getLogger().info( "home: " + c.getHomeDirectory() );
+ getLogger().info( "temp: " + c.getWorkingDirectory() );
+ }
+</source>
+ </subsection>
+ <subsection name="Sample Code">
+ <p>
+ The following code is an example of an extended context
+ interface.
+ </p>
+ <source>
+package tutorial;
+
+import java.io.File;
+
+import org.apache.avalon.framework.context.Context;
+
+/**
+ * An example of an convinience interface that extends the
+ * standard Avalon Context interface.
+ */
+public interface DemoContext extends Context
+{
+
+ /**
+ * Return the component name.
+ * @return the component name
+ */
+ String getName();
+
+ /**
+ * Return the name of the partition assigned to the component.
+ * @return the partition name
+ */
+ String getPartition();
+
+ /**
+ * Return the home directory.
+ * @return the directory
+ */
+ File getHomeDirectory();
+
+ /**
+ * Return the temporary working directory.
+ * @return the directory
+ */
+ File getWorkingDirectory();
+}
+</source>
+ <p>
+ The following source is the implementation of the domain
+ specific context interface. The implementation class must include
+ a constructor that takes a single map parameter. The supplied map
+ contains the default conterxt entries together with any supplimentary
+ context entries requested by the component type. The implementation
+ provides convinence access to these context entries.
+ </p>
+ <source>
+package tutorial;
+
+import java.util.Map;
+import java.io.File;
+
+import org.apache.avalon.framework.context.DefaultContext;
+import org.apache.avalon.framework.context.ContextException;
+
+
+/**
+ * A demonstration class that that we will instantiate via
+ * context directives within the component declaration.
+ */
+public class DemoContextProvider extends DefaultContext implements DemoContext
+{
+
+ /**
+ * A custom context type implementation must provide
+ * the following constructor.
+ * @param entries a map of context entries
+ */
+ public DemoContextProvider( Map entries )
+ {
+ super( entries );
+ }
+
+ /**
+ * Return the component name.
+ * @return the component name
+ */
+ public String getName()
+ {
+ try
+ {
+ return (String) super.get( "urn:avalon:name" );
+ }
+ catch( ContextException ce )
+ {
+ // should not happen
+ throw new RuntimeException( ce.toString() );
+ }
+ }
+
+ /**
+ * Return the name of the partition assigned to the component.
+ * @return the partition name
+ */
+ public String getPartition()
+ {
+ try
+ {
+ return (String) super.get( "urn:avalon:partition" );
+ }
+ catch( ContextException ce )
+ {
+ // should not happen
+ throw new RuntimeException( ce.toString() );
+ }
+ }
+
+ /**
+ * Return the home directory.
+ * @return the home directory
+ */
+ public File getHomeDirectory()
+ {
+ try
+ {
+ return (File) super.get( "urn:avalon:home" );
+ }
+ catch( ContextException ce )
+ {
+ // should not happen
+ throw new RuntimeException( ce.toString() );
+ }
+ }
+
+
+ /**
+ * Return the temporary working directory.
+ * @return the temp directory
+ */
+ public File getWorkingDirectory()
+ {
+ try
+ {
+ return (File) super.get( "urn:avalon:work" );
+ }
+ catch( ContextException ce )
+ {
+ // should not happen
+ throw new RuntimeException( ce.toString() );
+ }
+ }
+}
+</source>
+ </subsection>
+ <subsection name="Declaring the context interface">
+ <p>
+ To be supplied with a domain specific context to which
+ the component can safely cast, we need to declare this
+ dependency within the component xinfo descriptor.
+ </p>
+<source><![CDATA[
+<type>
+ <info>
+ <name>hello</name>
+ <version>1.0</version>
+ </info>
+ <context type="tutorial.DemoContext"/>
+</type>
+]]></source>
+ <p>
+ Secondly, we need to provide corresoponding meta-data to Merlin
+ describing the implementation class that it can use to construct
+ the context instance. The following changes to the block.xml
+ description include the "class" attribute on the coontext directive.
+ The class attribute tells Merlin to use the named class as the
+ context implementation.
+ </p>
+<source><![CDATA[
+<block name="tutorial">
+ <container>
+ <component name="hello" class="tutorial.HelloComponent" activation="startup">
+ <context class="tutorial.DemoContextProvider"/>
+ </component>
+ </container>
+</block>
+]]></source>
+ </subsection>
+ <subsection name="Executing the example">
+ <p>
+ Build and run the tutorial.
+ </p>
+ <source>
+$ ant jar
+$ merlin build\classes
+ </source>
+ <p>
+ In the logging output we see the standard context values
+ accessed via the domain specific context interface.
+ </p>
+<source>
+[INFO ] (tutorial.hello): name: hello
+[INFO ] (tutorial.hello): partition: /tutorial/hello
+[INFO ] (tutorial.hello): home: F:\tutorial\005\working\home\tutorial\hello
+[INFO ] (tutorial.hello): temp: F:\tutorial\005\working\temp\tutorial\hello
+</source>
+
</subsection>
</section>
</body>
1.2 +109 -77 avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context/entries.xml
Index: entries.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context/entries.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- entries.xml 3 Apr 2003 22:12:58 -0000 1.1
+++ entries.xml 4 Apr 2003 12:17:19 -0000 1.2
@@ -9,53 +9,76 @@
</header>
<body>
<section name="Using Merlin">
- <subsection name="Managing Configurations">
+ <subsection name="Custom Context Management">
<p>
- This tutorial presents information about the management
- of the runtime context supplied to your component.
+ Merlin provides support for the creation and assignment of
+ custom context entries to a component through a combination
+ of requirments specification at the level of a type, and
+ context creation directives.
</p>
<p>
Resource supporting this tutorial are contained in the
- turorial/003 package.
+ turorial/004 package.
</p>
</subsection>
- <subsection name="Adding context support to the component">
+ <subsection name="Creating a non-Component Object">
<p>
- In order to receive a runtime context we need to update the
- HelloComponent source so that it implements the Avalon
- Contextualization stage interface. Merlin will build and
- supply a context object containing the following four
- context entries:
- </p>
- <p><i>Merlin Standard Context Entries</i></p>
- <table>
- <tr>
- <th>Key</th><th>Class</th><th>Description</th>
- </tr>
- <tr>
- <td>urn:avalon:home</td><td>java.io.File</td><td>The working directory.</td>
- </tr>
- <tr>
- <td>urn:avalon:work</td><td>java.io.File</td><td>The temporary directory.</td>
- </tr>
- <tr>
- <td>urn:avalon:name</td><td>java.io.File</td><td>The component name.</td>
- </tr>
- <tr>
- <td>urn:avalon:partition</td><td>java.io.File</td>
- <td>The assigned partition name.</td>
- </tr>
- </table>
- <p>
- In addition to the standard context entries, Merlin provides
- support for the declaration by a component type of the supplimentary
- context entry requirements (key and casting class). This criteria
- is declared under the xinfo resource co-located with the component
- class. An example of a simple custom context entry constrain is
- included in the example xinfo descriptor presented below:
+ To demonstrate Merlin's support for the supply on non
+ component objects to a component, we need to create a
+ example object. Non-component object approaches may be
+ required when you are integrating legacy applications
+ into a component platform and you are obliged to deal
+ with an existing code base.
</p>
- <p><i>Sample component xinfo with context entry.</i></p>
+ <p>
+ Out non-componet example NumberCruncher takes two values
+ in a constructor and returns the result of the multiplication
+ of the two number via an accessor. While not very useful, the
+ purpose of NumberCruncher is to demonstrate how you can use
+ Merlin to construct the instance and associate it as a context
+ entry for the component.
+ </p>
+ <p>
+ <i>NumberCruncher.java</i>
+ </p>
+ <source>
+package tutorial;
+
+/**
+ * A demonstration class that that we will instantiate via
+ * context directives within the component declaration.
+ */
+public class NumberCruncher
+{
+ private final int m_primary;
+ private final float m_secondary;
+
+ public NumberCruncher( Integer primary, Double secondary )
+ {
+ m_primary = primary.intValue();
+ m_secondary = secondary.floatValue();
+ }
+
+ /**
+ * Multiply the supplied constructor arguments together and
+ * return the value.
+ */
+ public float crunch()
+ {
+ return ( m_secondary * m_primary );
+ }
+}
+ </source>
+ </subsection>
+
+ <subsection name="Updating HelloComponent.xinfo">
+ <p>
+ HelloComponent.xinfo is updated to include the declaration of
+ the components requirement for the supply of a context entry
+ named 'cruncher' corresponding to the type NumberCruncher.
+ </p>
+ <p><i>HelloComponent.xinfo</i></p>
<source><![CDATA[
<?xml version="1.0"?>
<!DOCTYPE type
@@ -67,59 +90,73 @@
<version>1.0</version>
</info>
<context>
- <entry key="location"/>
+ <entry key="cruncher" type="tutorial.NumberCruncher"/>
</context>
</type>
]]></source>
<p>
- In the above example we have declared that the component requires
- a context entry under the key "location" returning a String (the default
- context entry class) value.
+ The following source demonstrates the implementation
+ of the contextualization stage, access and casting of
+ a context entry to the NumberCruncher class, and the
+ the invocation of on operation on that class.
</p>
<source>
package tutorial;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.activity.Initializable;
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
public class HelloComponent extends AbstractLogEnabled
- implements Configurable, Initializable
+ implements Contextualizable
{
- private String m_source = "undefined";
/**
- * Configuration of the component by the container. The
- * implementation get a child element named 'source' and
- * assigns the value of the element to a local variable.
- *
- * @param config the component configuration
- * @exception ConfigurationException if a configuration error occurs
+ * Contextualization of the component by the container.
+ * The context supplied by the container shall contain
+ * a NumberCruncher instance as declared in the xinfo resource.
*/
- public void configure( Configuration config ) throws ConfigurationException
+ public void contextualize( Context context )
+ throws ContextException
{
- getLogger().info( "configuration stage" );
- m_source = config.getChild( "source" ).getValue( "unknown" );
- }
-
- /**
- * Initialization of the component by the container.
- * @exception Exception if an initialization error occurs
- */
- public void initialize() throws Exception
- {
- getLogger().info( "initialization stage" );
- final String message =
- "source: " + m_source;
- getLogger().info( message );
+ NumberCruncher cruncher =
+ (NumberCruncher) context.get( "cruncher" );
+ float value = cruncher.crunch();
+ getLogger().info( "result: " + value );
}
}
</source>
+
+ </subsection>
+
+ <subsection name="Context Directives">
<p>
- Build and run the tutorial without declaring any configuration.
+ As Merlin knows nothing about the NumberCruncher class
+ we need to provide additional information under the component
+ deployment descriptor. In the case of NumberCruncher, the
+ class constructor takes two constructor arguments, an Integer
+ and a Double.
+ </p>
+ <p><i>block.xml</i></p>
+<source><![CDATA[
+<block name="tutorial">
+ <container>
+ <component name="hello" class="tutorial.HelloComponent" activation="startup">
+ <context>
+ <entry key="cruncher" class="tutorial.NumberCruncher">
+ <parameter class="java.lang.Integer">7</parameter>
+ <parameter class="java.lang.Double">1.5</parameter>
+ </entry>
+ </context>
+ </component>
+ </container>
+</block>
+]]></source>
+
+ <p>
+ Build and run the tutorial.
</p>
<source>
$ ant jar
@@ -127,18 +164,13 @@
</source>
<p>
In the logging output we see that Merlin has created and
- supplied an empty configuration to the component.
+ supplied the NumberCruncher instance to the component.
</p>
<source>
-$ ant jar
-$ merlin build\classes
-[INFO ] (tutorial.hello): configuration stage
-[INFO ] (tutorial.hello): initialization stage
-[INFO ] (tutorial.hello): source: unknown
+[INFO ] (tutorial.hello): result: 10.5
</source>
</subsection>
-
</section>
</body>
1.2 +2 -8 avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context/index.xml
Index: index.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context/index.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- index.xml 3 Apr 2003 22:12:58 -0000 1.1
+++ index.xml 4 Apr 2003 12:17:19 -0000 1.2
@@ -25,7 +25,8 @@
<td>
Declaration of the custom context entry requirements
and the mechanisms used to construct and supply
- corresponding context entry values.
+ corresponding context entry values using parameterized
+ constructors.
</td>
</tr>
<tr>
@@ -34,13 +35,6 @@
Examples of how you use domain specific context
specializations and safely cast the supplied context
instance.
- </td>
- </tr>
- <tr>
- <td><a href="stage.html">Custom Contextualization</a></td>
- <td>
- Building and deploying a completly custom contextaulization
- stage.
</td>
</tr>
</table>
1.2 +3 -4 avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context/navigation.xml
Index: navigation.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context/navigation.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- navigation.xml 3 Apr 2003 22:12:58 -0000 1.1
+++ navigation.xml 4 Apr 2003 12:17:19 -0000 1.2
@@ -21,11 +21,10 @@
<item name="Contextualization" href="/starting/hello/context/index.html">
<item name="Standard Entries" href="/starting/hello/context/standard.html"/>
<item name="Custom Entries" href="/starting/hello/context/entries.html"/>
- <item name="Context Casting" href="/starting/hello/context/types.html"/>
- <item name="Custom Contextualization" href="/starting/hello/context/stage.html"/>
+ <item name="Context Casting" href="/starting/hello/context/casting.html"/>
</item>
- <item name="Managing Dependencies" href="/starting/hello/dependencies.html"/>
- <item name="Publishing Services" href="/starting/hello/services.html"/>
+ <item name="Dependencies" href="/starting/hello/dependencies.html"/>
+ <item name="Services" href="/starting/hello/services.html"/>
</item>
<item name="Advanced Features" href="/starting/advanced/index.html"/>
</item>
1.2 +60 -39 avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context/standard.xml
Index: standard.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/merlin-smp/xdocs/starting/hello/context/standard.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- standard.xml 3 Apr 2003 22:12:58 -0000 1.1
+++ standard.xml 4 Apr 2003 12:17:19 -0000 1.2
@@ -20,7 +20,7 @@
</p>
</subsection>
- <subsection name="Adding context support to the component">
+ <subsection name="Merlin Standard Context Entries">
<p>
In order to receive a runtime context we need to update the
HelloComponent source so that it implements the Avalon
@@ -34,83 +34,104 @@
<th>Key</th><th>Class</th><th>Description</th>
</tr>
<tr>
- <td>urn:avalon:home</td><td>java.io.File</td><td>The working directory.</td>
+ <td>urn:avalon:home</td><td>java.io.File</td>
+ <td>The working directory.</td>
</tr>
<tr>
- <td>urn:avalon:work</td><td>java.io.File</td><td>The temporary directory.</td>
+ <td>urn:avalon:work</td><td>java.io.File</td>
+ <td>The temporary directory that will be destory at the
+ end of the session.</td>
</tr>
<tr>
- <td>urn:avalon:name</td><td>java.io.File</td><td>The component name.</td>
+ <td>urn:avalon:name</td><td>java.io.File</td>
+ <td>The name assigned to the component.</td>
</tr>
<tr>
<td>urn:avalon:partition</td><td>java.lang.String</td>
<td>The assigned partition name.</td>
</tr>
</table>
+ </subsection>
+
+ <subsection name="Adding context support to the component">
+ <p>
+ In order to receive a runtime context we need to update the
+ HelloComponent source so that it implements the Avalon
+ Contextualization stage interface. Merlin will build and
+ supply a context object containing the standard four
+ context entries.
+ </p>
+ <p><i>HelloComponent.java</i></p>
<source>
package tutorial;
+import java.io.File;
+
import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.activity.Initializable;
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
public class HelloComponent extends AbstractLogEnabled
- implements Configurable, Initializable
+ implements Contextualizable
{
- private String m_source = "undefined";
- /**
- * Configuration of the component by the container. The
- * implementation get a child element named 'source' and
- * assigns the value of the element to a local variable.
- *
- * @param config the component configuration
- * @exception ConfigurationException if a configuration error occurs
- */
- public void configure( Configuration config ) throws ConfigurationException
- {
- getLogger().info( "configuration stage" );
- m_source = config.getChild( "source" ).getValue( "unknown" );
- }
+ private File m_home = null;
+ private File m_temp = null;
+ private String m_name = "unknown";
+ private String m_partition = "unknown";
/**
- * Initialization of the component by the container.
- * @exception Exception if an initialization error occurs
+ * Contextualization of the component by the container.
+ * The context supplied by the container holds the
+ * Merlin standard context entries for the home and
+ * working directories, component name and partition.
*/
- public void initialize() throws Exception
+ public void contextualize( Context context )
+ throws ContextException
{
- getLogger().info( "initialization stage" );
- final String message =
- "source: " + m_source;
- getLogger().info( message );
+ m_home = (File) context.get( "urn:avalon:home" );
+ m_temp = (File) context.get( "urn:avalon:work" );
+ m_name = (String) context.get( "urn:avalon:name" );
+ m_partition = (String) context.get( "urn:avalon:partition" );
+
+ //
+ // log the standard values
+ //
+
+ StringBuffer buffer = new StringBuffer( "standard context entries" );
+ buffer.append( "\n name: " + m_name );
+ buffer.append( "\n home: " + m_home );
+ buffer.append( "\n temp: " + m_temp );
+ buffer.append( "\n partition: " + m_partition );
+
+ getLogger().info( buffer.toString() );
+
}
}
</source>
<p>
- Build and run the tutorial without declaring any configuration.
+ Build and run the tutorial.
</p>
<source>
$ ant jar
$ merlin build\classes
</source>
<p>
- In the logging output we see that Merlin has created and
- supplied an empty configuration to the component.
+ In the logging output we see the values provided by
+ Merlin to the component.
</p>
<source>
-$ ant jar
-$ merlin build\classes
-[INFO ] (tutorial.hello): configuration stage
-[INFO ] (tutorial.hello): initialization stage
-[INFO ] (tutorial.hello): source: unknown
+[INFO ] (tutorial.hello): standard context entries
+ name: hello
+ home: F:\tutorial\working\home\hello
+ temp: F:\tutorial\workin\temp\hello
+ partition: /tutorial/hello
</source>
</subsection>
</section>
</body>
-
</document>
---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe@avalon.apache.org
For additional commands, e-mail: cvs-help@avalon.apache.org