mcconnell 2002/12/09 04:16:26
Modified: merlin build.xml kernel.xml
merlin/src/etc demo.mf project.mf
merlin/src/java/org/apache/avalon/merlin/block Block.java
DefaultBlock.java
merlin/src/java/org/apache/avalon/merlin/kernel
DefaultKernel.java
Added: merlin/src/test/config block.xml
merlin/src/test/org/apache/avalon/merlin/kernel
KernelTestCase.java
merlin/src/test/org/apache/avalon/playground
BasicComponent.java BasicComponent.xconfig
BasicComponent.xinfo BasicComponent.xprofile
BasicContext.java BasicContextInterface.java
BasicService.java BasicService.xservice
Removed: merlin/src/java/org/apache/avalon/merlin/block
BlockFactory.java DefaultBlockFactory.java
DefaultBlockFactory.xinfo
Log:
Incorporating block abstraction and supporting test-cases.
Revision Changes Path
1.4 +23 -2 avalon-sandbox/merlin/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/build.xml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- build.xml 7 Dec 2002 09:47:26 -0000 1.3
+++ build.xml 9 Dec 2002 12:16:25 -0000 1.4
@@ -44,6 +44,12 @@
<pathelement location="${build.testclasses}"/>
</path>
+ <path id="runtime.class.path">
+ <pathelement location="${build.dir}/lib/${jar.name}"/>
+ <pathelement location="${build.dir}/lib/${demo.jar}"/>
+ <pathelement location="${build.testclasses}"/>
+ </path>
+
<target name="main" depends="jar,jar-playground" description="Build the project"/>
<target name="rebuild" depends="clean,main" description="Rebuild the project"/>
<target name="all" depends="rebuild,docs" description="Rebuild the project"/>
@@ -367,6 +373,14 @@
</fileset>
</copy>
+ <copy todir="${build.playground}" flatten="true">
+ <fileset dir="${src.dir}/test/config" includes="block.xml"/>
+ </copy>
+
+ <copy todir="${build.dir}/tests">
+ <fileset dir="${basedir}" includes="kernel.xml"/>
+ </copy>
+
</target>
@@ -380,6 +394,9 @@
<zipfileset dir="${build.conf}" prefix="META-INF/">
<include name="LICENSE.txt"/>
</zipfileset>
+ <zipfileset dir="${build.playground}" prefix="BLOCK-INFO/">
+ <include name="block.xml"/>
+ </zipfileset>
</jar>
</target>
@@ -392,8 +409,12 @@
<junit fork="true"
haltonfailure="${junit.failonerror}"
printsummary="yes"
- dir="${build.tests}">
- <classpath refid="test.class.path"/>
+ dir="${basedir}">
+ <classpath>
+ <path refid="runtime.class.path"/>
+ <pathelement location="${build.test}"/>
+ </classpath>
+ <jvmarg value="-Djava.ext.dirs=common;lib"/>
<formatter type="xml"/> <!-- xml reports for junitreport -->
<formatter type="plain" usefile="false"/> <!-- text reports for humans
-->
1.2 +8 -185 avalon-sandbox/merlin/kernel.xml
Index: kernel.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/kernel.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- kernel.xml 3 Dec 2002 07:09:47 -0000 1.1
+++ kernel.xml 9 Dec 2002 12:16:25 -0000 1.2
@@ -1,52 +1,6 @@
-<!--
-Merlin demonstration kernal configuration.
-
-This configuration assembles a set of component instance within a container
-hierachy and is used as one of several validation points. The example includes
-demonstration of some of the main Merlin features:
-
- a) automatic component assembly
- b) multiple candidate resolution
- c) lifestyle support
- d) lifecycle extension
- e) custom containers
- f) dynamic component addition
- g) context management
- h) configuration management
- i) use of explicit, packaged and implicit profiles
- j) nested containers
-
--->
-
<kernel>
- <!--
- Declaration of the domain name that this kernel is operating within.
- -->
-
- <system>
- <host>localhost</host>
- </system>
-
- <!--
- Optional logging catagory creation directive. The logging element declares
- the application wide default logging priority.
- A target element enables defintion of a logging file to which log entries will
- be directed. The target name attribute is the name referenced by category
elements
- defined within the loggers element.
-
- The target defaults of "default" which corresponds to a internal default logging
- target that issue messages to System.out (unless overriden by a target named
default).
- If the target is declared inside a catagory element, it must refer to a named
target
- element. The priority attribute may contain one of the values <code>DEBUG</code>
- <code>INFO</code>, <code>WARN</code>, or <code>ERROR</code> and declares the
system
- wide default logging priority.
-
- The target must contain a single file element with the attribute
<code>location</code>
- the corresponds to the name of the logging file to which log entries shall be
written.
- -->
-
<logging priority="INFO" target="default">
<category name="/sys/logger" priority="WARN"/>
<target name="kernel">
@@ -60,153 +14,22 @@
<engine>
- <!--
- Declaration of installed extension directories and kernel level classpath.
- In this demo we are referencing the Merlin classes in the embedded demo so
- we need to include Merlin and its' extension depedencies in directory
- referenced within the library element.
- -->
-
<library dir=".">
- <include name="extensions"/>
+ <include name="build/lib"/>
</library>
- <!--
- Defintion of the lifestyle manager.
- The lifestyles class attribute must reference a class implementing the
- interface org.apache.excalibur.merlin.resource.LifestyleManager.
- -->
-
- <lifestyles
class="org.apache.excalibur.merlin.resource.DefaultLifestyleManager"/>
-
- <!--
- Declaration of the root container.
- -->
-
- </engine>
-
- <container name="root">
-
- <!--
- A container has a number of internal logging catagories that you can modify to
- see what's going on. In practice you will probably only declare categories
under
- components, however - the container level logging categories are presented
here
- for completness.
- -->
-
- <categories priority="INFO">
- <category priority="WARN" name="loader" />
- <category priority="WARN" name="loader.services" />
- <category priority="WARN" name="loader.deployment" />
- <category priority="WARN" name="loader.lifecycle" />
- <category priority="WARN" name="loader.resource" />
- <category priority="WARN" name="loader.types" />
- </categories>
-
- <!--
- Declaration of the classpath for this container.
- -->
-
<classpath>
<fileset dir="build/lib">
- <include name="demo.jar"/>
+ <include name="avalon-merlin-demo-2.0.jar"/>
</fileset>
</classpath>
- <!--
- Declaration of the services hosted by this container. Service container here
- will be managed relative to other provider components at the same level and
- may be serviced by components declared in parent container.
- -->
-
- <component name="complex"
class="org.apache.excalibur.playground.ComplexComponent" activation="startup">
-
- <categories priority="DEBUG">
- <category name="init" priority="DEBUG" />
- </categories>
-
- <!--
- Include the following context value in the context supplied a component
using this
- profile. Context entries are normally only required in the case where the
component
- type declares a required context type and entry values. Generally speaking,
a component
- will normally qualify it's instantiation criteria through a configuration
declaration.
- Any context values defined at this level will override context values
supplied by the
- container.
- -->
-
- <context>
- <entry key="location" value="Paris"/>
- </context>
-
- <!--
- Apply the following configuration when instantiating the component. This
configuration
- will be applied as the primary configuration in a cascading configuration
chain. A
- type may declare a default configuration under a "classname".xconfig file
that will be
- used to dereference any configuration requests not resolvable by the
configuration
- supplied here.
- -->
-
- <configuration>
- <message value="Hello"/>
- </configuration>
-
- <!--
- The parameterization criteria from this instance of the component type.
- -->
-
- <parameters/>
-
- </component>
-
- <!--
- A containers declaration will cause the creation of a new registry holding the
- child container instances.
- -->
-
- <container name="custom"
class="org.apache.excalibur.playground.CustomContainer">
-
- <container name="demo">
-
- <categories priority="INFO">
- <category priority="WARN" name="loader" />
- </categories>
-
- <!--
- Including the next entry demonstrates the resolution of a dependency via a
profile
- resolved from a parent container. SimpleComponent needs BasicService with
is available
- from either TerminalComponent or BasicComponent implicitly created in the
parent
- container path (due to a depenency declared by ComplexComponent). In
addition, this
- profile demonstrates the use of a cascading configuration. The
configuration passed
- to the instantiated component is based primarily on this configuration
declared here
- with defaults derived from SimpleComponent.xconfig.
- -->
- <component name="simple"
- class="org.apache.excalibur.playground.SimpleComponent"
- enabled="true"
- activation="true">
-
- <configuration>
- <message>This is a custom message.</message>
- </configuration>
-
- </component>
-
- </container>
-
- </container>
-
- <component name="basic-sample"
class="org.apache.excalibur.playground.BasicComponent" activation="startup">
-
- <categories priority="DEBUG">
- <category priority="WARN" name="loader" />
- </categories>
-
- <context class="org.apache.excalibur.playground.BasicContext">
- <entry key="location">My Place</entry>
- <import name="avalon:home" key="home"/>
- </context>
- </component>
+ </engine>
- </container>
+ <blocks>
+ <fileset dir="build/lib">
+ <include name="avalon-merlin-demo-2.0.jar"/>
+ </fileset>
+ </blocks>
</kernel>
1.2 +5 -15 avalon-sandbox/merlin/src/etc/demo.mf
Index: demo.mf
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/src/etc/demo.mf,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- demo.mf 3 Dec 2002 07:08:02 -0000 1.1
+++ demo.mf 9 Dec 2002 12:16:25 -0000 1.2
@@ -1,18 +1,8 @@
Manifest-Version: 1.0
Created-By: Apache Avalon
-Extension-List: framework meta lifecycle i18n
-framework-Extension-Name: avalon-framework
-framework-Specification-Version: 1.0
-framework-Implementation-Version: 4.1.2
-meta-Extension-Name: avalon-meta
-meta-Specification-Version: 1.0
-lifecycle-Extension-Name: avalon-lifecycle
-lifecycle-Specification-Version: 1.0
-assembly-Extension-Name: avalon-assembly
-assembly-Specification-Version: 1.0
-configuration-Extension-Name: excalibur-configuration
-configuration-Specification-Version: 1.0
-i18n-Extension-Name: excalibur-i18n
-i18n-Specification-Version: 1.0
-
+Extension-List: merlin
+merlin-Extension-Name: avalon-merlin
+merlin-Specification-Version: 2.0
+Name: Avalon-Block
+Block-Name: demo
1.3 +0 -1 avalon-sandbox/merlin/src/etc/project.mf
Index: project.mf
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/src/etc/project.mf,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- project.mf 7 Dec 2002 14:02:36 -0000 1.2
+++ project.mf 9 Dec 2002 12:16:25 -0000 1.3
@@ -25,4 +25,3 @@
Name: Avalon-Block
Block-Name: Merlin
-Kernel-Service: true
\ No newline at end of file
1.2 +2 -6
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/block/Block.java
Index: Block.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/block/Block.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Block.java 3 Dec 2002 07:08:02 -0000 1.1
+++ Block.java 9 Dec 2002 12:16:25 -0000 1.2
@@ -50,17 +50,13 @@
package org.apache.avalon.merlin.block;
-import java.net.URL;
-
-import org.apache.avalon.assembly.appliance.Appliance;
-
/**
* A block is a deployment model supporting composite components.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development
Team</a>
* @version $Revision$ $Date$
*/
-public interface Block extends Appliance
+public interface Block
{
static final String AVALON_BLOCK_KEY = "Avalon-Block";
}
1.3 +61 -29
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/block/DefaultBlock.java
Index: DefaultBlock.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/block/DefaultBlock.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- DefaultBlock.java 7 Dec 2002 09:47:26 -0000 1.2
+++ DefaultBlock.java 9 Dec 2002 12:16:25 -0000 1.3
@@ -7,46 +7,78 @@
import java.net.URL;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
+import java.util.jar.JarFile;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.assembly.appliance.DefaultAppliance;
+import org.apache.avalon.assembly.engine.EngineClassLoader;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.context.ContextException;
-public class DefaultBlock extends DefaultAppliance implements Block
+public class DefaultBlock extends AbstractLogEnabled implements Block,
Contextualizable, Initializable
{
- public static final Attributes.Name BLOCK_NAME = new Attributes.Name(
"Block-Name" );
+ //==============================================================
+ // static
+ //==============================================================
- private JarFile m_base;
+ public static final Attributes.Name BLOCK_NAME = new Attributes.Name(
"Block-Name" );
- public String getName()
+ public static String getName( Manifest manifest )
{
- try
+ Attributes attributes = manifest.getAttributes( Block.AVALON_BLOCK_KEY );
+ if( attributes == null )
{
- Manifest manifest = m_base.getManifest();
- if( manifest == null )
- {
- throw new NullPointerException( "manifest" );
- }
-
- Attributes attributes = manifest.getAttributes( Block.AVALON_BLOCK_KEY
);
- if( attributes == null )
- {
- throw new NullPointerException( "attributes" );
- }
-
- if( attributes.containsKey( BLOCK_NAME ) )
- {
- return (String) attributes.get( BLOCK_NAME );
- }
- else
- {
- return "default";
- }
+ return null;
}
- catch( IOException ioe )
+ if( attributes.containsKey( BLOCK_NAME ) )
{
- final String error =
- "Unexpected IO Exception while reading manifest on jarfile: " +
m_base.getName();
- throw new RuntimeException( error );
+ return (String) attributes.get( BLOCK_NAME );
}
+ return null;
+ }
+
+ //==============================================================
+ // state
+ //==============================================================
+
+ private EngineClassLoader m_engine;
+
+ private Manifest m_manifest;
+
+ //==============================================================
+ // Contextualizable
+ //==============================================================
+
+ /**
+ * <p>Application of a runtime context to the lifestyle service.
+ * The context value will be passed directly to lifestyle handlers
+ * established by this service.
+ * @param context the runtime context
+ */
+ public void contextualize( Context context ) throws ContextException
+ {
+ m_engine = (EngineClassLoader) context.get( "urn:assembly:classloader" );
+ m_manifest = (Manifest) context.get( "urn:merlin:block.manifest" );
+ }
+
+ //==============================================================
+ // Initializable
+ //==============================================================
+
+ public void initialize() throws Exception
+ {
+ getLogger().info( "initialization" );
+ }
+
+ //==============================================================
+ // Block
+ //==============================================================
+
+ public String getName()
+ {
+ return getName( m_manifest );
}
}
1.4 +82 -13
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/DefaultKernel.java
Index: DefaultKernel.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/DefaultKernel.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- DefaultKernel.java 9 Dec 2002 03:05:55 -0000 1.3
+++ DefaultKernel.java 9 Dec 2002 12:16:25 -0000 1.4
@@ -54,10 +54,11 @@
import java.io.IOException;
import java.io.FileInputStream;
import java.io.InputStream;
-import java.net.URLClassLoader;
+import java.net.URL;
import java.util.jar.JarFile;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
+import java.net.JarURLConnection;
import org.apache.avalon.framework.CascadingException;
import org.apache.avalon.framework.logger.Logger;
@@ -82,7 +83,11 @@
import org.apache.avalon.assembly.logging.DefaultLoggingManager;
import org.apache.avalon.assembly.engine.EngineClassLoader;
import org.apache.avalon.assembly.engine.Engine;
+import org.apache.avalon.assembly.engine.model.LibraryDescriptor;
+import org.apache.avalon.assembly.engine.model.ClasspathDescriptor;
import org.apache.avalon.assembly.util.ExceptionHelper;
+import org.apache.avalon.merlin.block.Block;
+import org.apache.avalon.merlin.block.DefaultBlock;
/**
* Default kernel implementation. The implementation provides support for
@@ -243,7 +248,7 @@
if( getLogger().isDebugEnabled() )
{
- getLogger().debug( "initialization" );
+ getLogger().debug( "initialization: " + m_home );
}
//
@@ -259,7 +264,8 @@
catch( Throwable e )
{
final String error =
- "Bootstrap engine establishment error.";
+ "Bootstrap engine establishment error. Extension path: "
+ + System.getProperty("java.ext.dirs");
String log = ExceptionHelper.packException( error, e );
if( getLogger().isErrorEnabled() )
{
@@ -274,10 +280,57 @@
if( getLogger().isDebugEnabled() )
{
- getLogger().debug( "container assembly" );
+ getLogger().debug( "commencing container assembly" );
+ }
+
+ ClasspathDescriptor blocks =
+ m_creator.createClasspathDescriptor( m_config.getChild( "blocks" ) );
+ URL[] urls = ClasspathDescriptor.expand( m_home, blocks );
+
+ for( int i=0; i<urls.length; i++ )
+ {
+ URL url = urls[i];
+ try
+ {
+ installBlock( url );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Error during block deployment for url: " + url;
+ }
}
}
+ private Block installBlock( URL url ) throws Exception
+ {
+ Manifest manifest = getManifest( url );
+ if( !isBlock( manifest ) )
+ {
+ final String warning =
+ "Manifest does not declare a block on resource: " + url;
+ throw new IllegalArgumentException( warning );
+ }
+
+ String name = DefaultBlock.getName( manifest );
+ if( name == null )
+ {
+ final String error = "Missing name in block: " + url;
+ throw new IllegalArgumentException( error );
+ }
+
+ getLogger().debug( "installing block: " + name );
+ DefaultBlock block = new DefaultBlock();
+ block.enableLogging( getLogger().getChildLogger( name ) );
+ DefaultContext context = new DefaultContext();
+ context.put( "urn:assembly:classloader", m_engine );
+ context.put( "urn:merlin:block.manifest", manifest );
+ context.makeReadOnly();
+ block.contextualize( context );
+ block.initialize();
+ return block;
+ }
+
//==============================================================
// Startable
//==============================================================
@@ -398,6 +451,13 @@
getLogger().debug( "bootstrap engine" );
}
+ LibraryDescriptor extensions =
+ m_creator.createLibraryDescriptor(
+ config.getChild( "library" ) );
+
+ ClasspathDescriptor classpath =
+ m_creator.createClasspathDescriptor( config.getChild( "classpath" ) );
+
try
{
EngineClassLoader engine = new EngineClassLoader();
@@ -406,6 +466,8 @@
DefaultContext context = new DefaultContext();
context.put( "urn:avalon:home", m_home );
context.put( "urn:assembly:engine.bootstrap", "true" );
+ context.put( "urn:assembly:engine.extensions", extensions );
+ context.put( "urn:assembly:engine.classpath", classpath );
context.makeReadOnly();
engine.contextualize( context );
DefaultServiceManager manager = new DefaultServiceManager();
@@ -427,24 +489,31 @@
return m_local;
}
- private boolean isBlock( JarFile jar )
+ private boolean isBlock( Manifest manifest )
+ {
+ if( manifest == null )
+ {
+ return false;
+ }
+ return ( manifest.getAttributes( Block.AVALON_BLOCK_KEY ) != null );
+ }
+
+ private Manifest getManifest( URL url )
{
try
{
- Manifest manifest = jar.getManifest();
- if( manifest == null )
- {
- return false;
- }
- return ( manifest.getAttributes( Block.AVALON_BLOCK_KEY ) != null );
+ JarURLConnection connection = (JarURLConnection) url.openConnection();
+ JarFile jar = connection.getJarFile();
+ return jar.getManifest();
}
catch( IOException ioe )
{
final String error =
- "Unexpected IO Exception while reading manifest on jarfile: " +
jar.getName();
+ "Unexpected IO Exception while reading manifest on url: " + url;
throw new RuntimeException( error );
}
}
+
/**
* Return a string representation of the kernel.
1.1 avalon-sandbox/merlin/src/test/config/block.xml
Index: block.xml
===================================================================
<!--
Merlin default kernel configuration.
-->
<block>
<!--
Defintion of the default logging priorities.
-->
<categories priority="WARN">
<category priority="DEBUG" name="/sys" />
</categories>
<!--
Configuration of the component management engine that will be supplied
to the block during deployment.
-->
<engine>
<!--
Declaration of supplimentary extension directories.
-->
<!--
<library dir=".">
<include name="build/lib"/>
</library>
-->
<!--
Declaration of the location of additional supporting jar files
not accessible as extensions.
-->
<classpath>
<fileset dir="build/lib">
<include name="avalon-merlin-demo-2.0.jar"/>
</fileset>
</classpath>
</engine>
<!--
Declaration the block implemetation.
-->
<container>
<import/>
<component name="basic" class="org.apache.excalibur.playground.BasicComponent"
activation="startup">
<categories priority="DEBUG"/>
<context class="org.apache.excalibur.playground.BasicContext">
<entry key="location">My Place</entry>
<import name="avalon:home" key="home" />
</context>
</component>
<export>
<reference type="org.apache.excalibur.playground.BasicService"/>
</export>
</container>
<!--
Declaration of any subsidiary blocks.
-->
<blocks>
<!--
<fileset dir="build/lib">
<include name="xxx.jar"/>
</fileset>
-->
</blocks>
</block>
1.1
avalon-sandbox/merlin/src/test/org/apache/avalon/merlin/kernel/KernelTestCase.java
Index: KernelTestCase.java
===================================================================
package org.apache.avalon.merlin.kernel;
import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.StringTokenizer;
import java.util.Enumeration;
import java.util.List;
import java.util.Iterator;
import java.util.jar.JarFile;
import java.util.ArrayList;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.net.URLClassLoader;
import java.net.URL;
import java.util.zip.ZipEntry;
import java.net.MalformedURLException;
import java.net.JarURLConnection;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.merlin.block.Block;
import org.apache.avalon.merlin.block.DefaultBlock;
import org.apache.avalon.merlin.kernel.DefaultKernel;
import org.apache.avalon.merlin.kernel.KernelException;
import org.apache.avalon.assembly.util.ExceptionHelper;
import junit.framework.TestCase;
public class KernelTestCase extends TestCase
{
private DefaultKernel m_kernel;
public KernelTestCase( )
{
this( "kernel" );
}
public KernelTestCase( String name )
{
super( name );
}
public void testDefaultKernel() throws Exception
{
String[] args = new String[]{ "kernel.xml" };
m_kernel = new DefaultKernel();
try
{
Runtime.getRuntime().addShutdownHook(
new Thread()
{
public void run()
{
try
{
m_kernel.stop();
}
catch( Throwable e )
{
// ignore it
}
finally
{
m_kernel.dispose();
}
}
}
);
}
catch( IllegalStateException ise )
{
if( m_kernel != null )
{
try
{
m_kernel.stop();
}
catch( Throwable e )
{
// ignore it
}
finally
{
m_kernel.dispose();
}
}
return;
}
File base = getWorkingDirectory();
DefaultContext context = new DefaultContext();
context.put( "urn:urn:avalon:home", base );
context.makeReadOnly();
File file = getConfigurationFile( base, args );
if( !file.exists() )
{
final String error =
"Missing kernel configuration: " + file;
throw new RuntimeException( error );
}
Configuration config;
try
{
config = getConfiguration( file );
}
catch( Throwable e )
{
final String error = "Problem loading kernel configuration form file: "
+ file;
throw new RuntimeException( error );
}
try
{
m_kernel.configure( config );
m_kernel.contextualize( context );
m_kernel.initialize();
m_kernel.start();
}
catch( KernelException e )
{
// its already been logged
}
catch( Throwable e )
{
final String error = "Controller deployment failure.";
ExceptionHelper.printException( error, e, null, true );
m_kernel.dispose();
}
}
/**
* Get the target configuration file.
* @param args the command line arguments
*/
public File getConfigurationFile( File base, String[] args )
{
String filename;
if( args.length > 0 )
{
filename = args[ 0 ];
}
else
{
filename = "kernel.xml";
}
return new File( base, filename );
}
/**
* Get the target configuration file.
* @param args the command line arguments
*/
public File getWorkingDirectory( )
{
return new File( System.getProperty( "user.dir" ) );
}
private Configuration getConfiguration( final File file ) throws
ConfigurationException
{
try
{
DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
InputStream is = new FileInputStream( file );
if( is == null )
{
throw new ConfigurationException(
"Could not load the configuration resource \"" + file + "\"" );
}
return builder.build( is );
}
catch( Throwable e )
{
final String error = "Unable to create configuration from file: " + file;
throw new ConfigurationException( error, e );
}
}
}
1.1
avalon-sandbox/merlin/src/test/org/apache/avalon/playground/BasicComponent.java
Index: BasicComponent.java
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, 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", "Avalon", 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 (INCLUDING, 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.playground;
import java.io.File;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
/**
* This is a minimal demonstration component that implements the
* <code>BasicService</code> interface and has no dependencies.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development Team</a>
*/
public class BasicComponent extends AbstractLogEnabled
implements Contextualizable, Configurable, Initializable, Startable, Disposable,
BasicService
{
private String m_location;
private String m_message;
private File m_home;
//=======================================================================
// Contextualizable
//=======================================================================
/**
* Supply of the the component context to the component type.
* @param context the context value
*/
public void contextualize( Context context )
{
BasicContextInterface c = (BasicContextInterface)context;
m_location = c.getLocation();
m_home = c.getWorkingDirectory();
}
//=======================================================================
// Configurable
//=======================================================================
/**
* Supply of the the component configuration to the type.
* @param config the configuration value
*/
public void configure( Configuration config )
{
getLogger().debug( "configure" );
m_message = config.getChild( "message" ).getValue( null );
}
//=======================================================================
// Initializable
//=======================================================================
/**
* Initialization of the component type by its container.
*/
public void initialize()
{
getLogger().debug( "initialize" );
getLogger().debug( "location: " + m_location );
getLogger().debug( "home: " + m_home );
getLogger().debug( "message: " + m_message );
}
//=======================================================================
// Startable
//=======================================================================
/**
* Start the component.
*/
public void start()
{
doPrimeObjective();
}
/**
* Stop the component.
*/
public void stop()
{
getLogger().info( "stopping" );
}
/**
* Dispose of the component.
*/
public void dispose()
{
getLogger().debug( "dispose" );
}
//=======================================================================
// BasicService
//=======================================================================
/**
* Service interface implementation.
*/
public void doPrimeObjective()
{
getLogger().info( m_message + " from '" + m_location + "'." );
}
}
1.1
avalon-sandbox/merlin/src/test/org/apache/avalon/playground/BasicComponent.xconfig
Index: BasicComponent.xconfig
===================================================================
<?xml version="1.0"?>
<!--
Copyright (C) The Apache Software Foundation. All rights reserved.
This software is published under the terms of the Apache Software License
version 1.1, a copy of which has been included with this distribution in
the LICENSE.txt file.
@author Avalon Development Team
@version 1.0 12/03/2001
-->
<!--
The .xconfig file contains the default configuration for the component.
-->
<configuration>
<message>Hello</message>
</configuration>
1.1
avalon-sandbox/merlin/src/test/org/apache/avalon/playground/BasicComponent.xinfo
Index: BasicComponent.xinfo
===================================================================
<?xml version="1.0"?>
<!DOCTYPE type
PUBLIC "-//AVALON/Component Type DTD Version 1.0//EN"
"http://jakarta.apache.org/avalon/dtds/meta/type_1_1.dtd" >
<!--
Copyright (C) The Apache Software Foundation. All rights reserved.
This software is published under the terms of the Apache Software License
version 1.1, a copy of which has been included with this distribution in
the LICENSE.txt file.
@author Avalon Development Team
@version 1.0 12/03/2001
-->
<type>
<info>
<name>basic</name>
<!--
<attributes>
<attribute key="urn:assembly:appliance.factory-service"
value="org.apache.avalon.merlin.block.BlockFactory"/>
<attribute key="urn:assembly:appliance.factory-version"
value="1.0"/>
</attributes>
-->
</info>
<context type="org.apache.avalon.playground.BasicContextInterface">
<entry key="location"/>
<entry key="home" type="java.io.File"/>
</context>
<services>
<service>
<reference type="org.apache.avalon.playground.BasicService" version="1.1"/>
</service>
</services>
</type>
1.1
avalon-sandbox/merlin/src/test/org/apache/avalon/playground/BasicComponent.xprofile
Index: BasicComponent.xprofile
===================================================================
<?xml version="1.0"?>
<!--
Copyright (C) The Apache Software Foundation. All rights reserved.
This software is published under the terms of the Apache Software License
version 1.1, a copy of which has been included with this distribution in
the LICENSE.txt file.
@author Avalon Development Team
@version 1.0 12/03/2001
-->
<profiles>
<!--
A packaged profile is equivalent to a component declaration inside a container,
except that it is provided by a component type. A PACKAGED profiles take priority
over an IMPLICIT profile. An EXPLICIT profile declared inside a container
definition
will take priority over PACKAGED profiles.
-->
<component name="basic">
<context class="org.apache.avalon.playground.BasicContext">
<import name="urn:avalon:home" key="home" />
<entry key="location">Paris</entry>
</context>
</component>
</profiles>
1.1
avalon-sandbox/merlin/src/test/org/apache/avalon/playground/BasicContext.java
Index: BasicContext.java
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, 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", "Avalon", 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 (INCLUDING, 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.playground;
import java.io.File;
import java.util.Map;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.DefaultContext;
/**
* This is example of a custom context class. It is used in the demonsteation
* of a context management fraework to show how a context class can be
* supplied to a component declaring a context interface criteria.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development Team</a>
*/
public class BasicContext extends DefaultContext implements BasicContextInterface
{
/**
* Creation of a new custom context instance.
* @param map the context name/value map
* @param parent a possibly parent context
*/
public BasicContext( Map map, Context parent )
{
super( map, parent );
}
/**
* @return the location
*/
public String getLocation()
{
try
{
return (String)super.get( "location" );
}
catch( Throwable e )
{
return "Unknown";
}
}
/**
* @return the working directory
*/
public File getWorkingDirectory()
{
try
{
return (File)super.get( "home" );
}
catch( Throwable e )
{
throw new RuntimeException( "context object does not provide required
home entry." );
}
}
}
1.1
avalon-sandbox/merlin/src/test/org/apache/avalon/playground/BasicContextInterface.java
Index: BasicContextInterface.java
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, 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", "Avalon", 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 (INCLUDING, 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.playground;
import java.io.File;
import org.apache.avalon.framework.context.Context;
/**
* Simple non-standard Context interface to demonstration context
* management at the level of different context types.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development Team</a>
*/
public interface BasicContextInterface extends Context
{
/**
* @return a string containing a location value
*/
String getLocation();
/**
* @return a file representing the working directory
*/
File getWorkingDirectory();
}
1.1
avalon-sandbox/merlin/src/test/org/apache/avalon/playground/BasicService.java
Index: BasicService.java
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, 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", "Avalon", 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 (INCLUDING, 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.playground;
/**
* The <code>BasicService</code> executes a prime objective.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development Team</a>
*/
public interface BasicService
{
/**
* Execute the prime objective of this services.
*/
void doPrimeObjective();
}
1.1
avalon-sandbox/merlin/src/test/org/apache/avalon/playground/BasicService.xservice
Index: BasicService.xservice
===================================================================
<?xml version="1.0"?>
<!DOCTYPE type
PUBLIC "-//AVALON/Component Type DTD Version 1.0//EN"
"http://jakarta.apache.org/avalon/dtds/meta/type_1_1.dtd" >
<!--
Copyright (C) The Apache Software Foundation. All rights reserved.
This software is published under the terms of the Apache Software License
version 1.1, a copy of which has been included with this distribution in
the LICENSE.txt file.
@author Avalon Development Team
@version 1.0 12/03/2001
-->
<service>
<version>1.1</version>
<attributes>
<attribute key="urn:avalon:service.name" value="basic"/>
<attribute key="urn:avalon:service.description">
A demonstration service used within the scope of the
Avalon playground package for educational and unit
testing purposes.
</attribute>
</attributes>
</service>
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>