mcconnell 2003/02/16 05:01:20
Modified: merlin .cvsignore build.xml
merlin/src/java/org/apache/avalon/merlin/block
BlockLoader.java
merlin/src/java/org/apache/avalon/merlin/block/impl
DefaultBlockLoader.java
merlin/src/java/org/apache/avalon/merlin/container/builder
XMLContainerCreator.java
merlin/src/java/org/apache/avalon/merlin/kernel/impl
DefaultKernel.java KernelLoader.java
Added: merlin/src/java/org/apache/avalon/merlin/block
BlockRuntimeException.java
Log:
Optimization of the kernel/block seperation and enhanced command line management.
Revision Changes Path
1.6 +3 -7 avalon-sandbox/merlin/.cvsignore
Index: .cvsignore
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/.cvsignore,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- .cvsignore 12 Feb 2003 16:28:18 -0000 1.5
+++ .cvsignore 16 Feb 2003 13:01:20 -0000 1.6
@@ -1,13 +1,9 @@
-ant.properties
build
-lib
dist
-checkstyle.cache
-kernel.log
-extensions
distributions
-common
-working
+merlin
+ant.properties
+checkstyle.cache
velocity.log
project.xml
project.properties
1.23 +2 -2 avalon-sandbox/merlin/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/build.xml,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- build.xml 16 Feb 2003 10:51:59 -0000 1.22
+++ build.xml 16 Feb 2003 13:01:20 -0000 1.23
@@ -401,7 +401,7 @@
<include name="playground*.jar"/>
</fileset>
</copy>
- <copy toDir="${merlin.home}/repository/demo/block-inf/lib">
+ <copy toDir="${merlin.home}/repository/demo">
<fileset dir="build/lib">
<include name="merlin-demo*.jar"/>
</fileset>
@@ -653,7 +653,7 @@
</copy>
<copy todir="${build.playground}" flatten="true">
- <fileset dir="${src.dir}/repository/demo/block-inf" includes="block.xml"/>
+ <fileset dir="${src.dir}/repository/demo" includes="block.xml"/>
</copy>
<copy todir="${build.dir}/tests">
1.12 +8 -13
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/block/BlockLoader.java
Index: BlockLoader.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/block/BlockLoader.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- BlockLoader.java 7 Feb 2003 15:39:33 -0000 1.11
+++ BlockLoader.java 16 Feb 2003 13:01:20 -0000 1.12
@@ -51,6 +51,7 @@
package org.apache.avalon.merlin.block;
import org.apache.avalon.framework.configuration.Configuration;
+import java.net.URL;
/**
* Helper that provides support for the loading a set of blocks
@@ -62,19 +63,13 @@
public interface BlockLoader
{
-
- public static final String BLOCK_XML_ENTRY = "BLOCK-INF/block.xml";
-
/**
- * Load all of the blocks declared in the supplied configuration.
- * The configuration contains an arbitary number of "block" elements
- * each containing the name and path of a jar file to be loaded together
- * with client supplied configuration data.
- *
- * @param conf the configuration loaded from the blocks.xml file
- * @param system the system context
- * @return the set of blocks
+ * Create a block.
+ * @param path a URL referencing the block defintion
+ * @param config a URL referencing an optional targets overrides
+ * @return the root block
*/
- public Block[] createBlocks() throws BlockException;
+ Block install( URL path, URL targets )
+ throws BlockException;
}
1.1
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/block/BlockRuntimeException.java
Index: BlockRuntimeException.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.merlin.block;
import org.apache.avalon.framework.CascadingRuntimeException;
/**
* RuntimeException to indicate that there was a block related error.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2003/02/16 13:01:20 $
*/
public final class BlockRuntimeException
extends CascadingRuntimeException
{
/**
* Construct a new <code>BlockRuntimeException</code> instance.
*
* @param message The detail message for this exception.
*/
public BlockRuntimeException( final String message )
{
this( message, null );
}
/**
* Construct a new <code>BlockRuntimeException</code> instance.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public BlockRuntimeException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}
1.10 +232 -301
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/block/impl/DefaultBlockLoader.java
Index: DefaultBlockLoader.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/block/impl/DefaultBlockLoader.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- DefaultBlockLoader.java 12 Feb 2003 16:28:20 -0000 1.9
+++ DefaultBlockLoader.java 16 Feb 2003 13:01:20 -0000 1.10
@@ -106,26 +106,19 @@
import org.apache.avalon.merlin.block.Block;
import org.apache.avalon.merlin.block.Library;
import org.apache.avalon.merlin.block.BlockException;
+import org.apache.avalon.merlin.block.BlockRuntimeException;
import org.apache.avalon.merlin.block.BlockLoader;
import org.apache.avalon.merlin.container.builder.XMLContainerCreator;
import org.apache.avalon.merlin.container.ContainerDescriptor;
import org.apache.avalon.merlin.container.Container;
import org.apache.avalon.merlin.container.ContainerException;
import org.apache.avalon.merlin.container.impl.DefaultContainer;
-//import org.apache.avalon.merlin.service.DefaultRegistry;
-//import org.apache.avalon.merlin.service.Registry;
import org.apache.avalon.meta.model.builder.XMLProfileCreator;
import org.apache.avalon.meta.model.LoggingDirective;
import org.apache.avalon.meta.model.Profile;
import org.apache.avalon.meta.info.Type;
import org.apache.excalibur.configuration.ConfigurationUtil;
-//import org.apache.excalibur.source.Source;
-//import org.apache.excalibur.source.SourceResolver;
-//import org.apache.excalibur.source.SourceFactory;
-//import org.apache.excalibur.source.impl.ResourceSourceFactory;
-//import org.apache.excalibur.source.impl.SourceResolverImpl;
-
/**
* Implementation of the block loader.
@@ -148,7 +141,7 @@
* @see DefaultBlock
*/
-public class DefaultBlockLoader extends AbstractLogEnabled implements
Contextualizable, Initializable, Configurable, Disposable, BlockLoader, Library
+public class DefaultBlockLoader extends AbstractLogEnabled implements
Contextualizable, Initializable, Disposable, BlockLoader, Library
{
//==============================================================
// static
@@ -171,11 +164,6 @@
//==============================================================
/**
- * The root registry.
- */
- //private Registry m_registry;
-
- /**
* The application home directory.
*/
private File m_home;
@@ -190,15 +178,8 @@
*/
private Locator m_system;
- //private SourceResolverImpl m_resolver;
-
- /**
- * The blocks cofiguration.
- */
- private Configuration m_config;
-
/**
- * Configuration framgments keyed by appliance path.
+ * Configuration fragments keyed by appliance path.
*/
private final Map m_library = new Hashtable();
@@ -213,35 +194,11 @@
public void contextualize( Locator context ) throws ContextException
{
m_engine = (EngineClassLoader) context.get( "urn:assembly:engine" );
- //m_registry = (Registry) context.get( "urn:assembly:registry" );
m_system = (Locator) context.get( "urn:assembly:system-context" );
m_home = (File) m_system.get( "urn:assembly:home" );
}
//==============================================================
- // Configurable
- //==============================================================
-
- public void configure( Configuration config ) throws ConfigurationException
- {
- m_config = config;
- Configuration[] blocks = config.getChildren("block");
- for( int i=0; i<blocks.length; i++ )
- {
- Configuration block = blocks[i];
- String name = block.getAttribute( "name" );
- Configuration[] entries = block.getChildren( "configuration" );
- for( int j=0; j<entries.length; j++ )
- {
- Configuration entry = entries[j];
- String key = "/" + name + "/" + entry.getAttribute( "target" );
- m_library.put( key, entry );
- getLogger().debug( "registering configuration for key: " + key );
- }
- }
- }
-
- //==============================================================
// Initializable
//==============================================================
@@ -263,7 +220,6 @@
public void dispose()
{
m_engine = null;
- //m_registry = null;
m_system = null;
m_home = null;
}
@@ -316,221 +272,169 @@
//==============================================================
/**
- * Load all of the blocks declared in the supplied configuration.
- * The configuration contains an arbitary number of "block" elements
- * each containing the name and path of a jar file to be loaded together
- * with client supplied configuration data.
+ * Load the blocks declared in the supplied configuration.
*
- * @param conf the configuration loaded from the blocks.xml file
- * @param system the system context
- * @return the set of blocks
+ * @param block the block defintion URL
+ * @param overrides the URL to a configuration containing configuration overrides
+ * @return the block
*/
- public Block[] createBlocks()
+ public Block install( URL path, URL overrides )
throws BlockException
{
- Configuration[] configs = m_config.getChildren("block");
- getLogger().info("block count = " + configs.length );
+ Configuration block = getBlockConfiguration( path );
+ Configuration config = getTargetsConfiguration( overrides );
+ String name = getBlockName( block );
- ArrayList blocks = new ArrayList();
- for( int i=0; i<configs.length; i++ )
+ Configuration[] targets = config.getChildren( "target" );
+
+ for( int j=0; j<targets.length; j++ )
{
- Configuration config = configs[i];
- String name = config.getAttribute( "name", null );
- boolean enabled = config.getAttributeAsBoolean( "enabled", true );
- if( enabled )
- {
- try
- {
- Block block = loadPhysicalBlock( config, m_system );
- blocks.add( block );
- }
- catch( Throwable e )
- {
- final String error =
- "Error during block deployment for block: " + (i+1) + " [" +
name + "]";
- throw new BlockException( error, e );
- }
+ Configuration target = targets[j];
+ try
+ {
+ String key = "/" + name + "/" + target.getAttribute( "name" );
+ m_library.put( key, target.getChild( "configuration" ) );
+ getLogger().debug( "registering configuration for key: " + key );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "A configuration target override does not declare a target."
+ + "\nURL: " + overrides
+ + ConfigurationUtil.list( target );
+ throw new BlockException( error, e );
}
}
- return (Block[]) blocks.toArray( new Block[0] );
- }
-
- //==============================================================
- // internals
- //==============================================================
- /**
- * Load a single block defintion. The defintion is a configuration
- * element named "block" that either:
- * <ul>
- * <li>a reference to a block configuration file</li>
- * <li>a reference to a package black in the form of a jar file</li>
- * </ul>
- *
- * The block name is defined by the block name attribute declared under the
- * block element in the blocks.xml configuration. In the case of the
- * configuration based block defintion, the configuration is derived from a
- * and explicit file reference. In the case of a packaged block, the
- * configuration is resolved from a packaged xmml file name
- * /BLOCK-INFO/block.xml with a jar file.
- *
- *
- * @param config the block declaration
- * @param system the system context
- * @return the block
- * @exception Exception if a block loading error occurs
- */
- private Block loadPhysicalBlock( Configuration config, Context system )
- throws BlockException
- {
- if( getLogger().isDebugEnabled() )
+ URL base = getBasePath( path );
+ Configuration implementation = block.getChild( "implementation" );
+ Configuration engineConfig = implementation.getChild( "engine" );
+ EngineClassLoader engine = null;
+ try
{
- getLogger().debug( "block configuration: \n" + ConfigurationUtil.list(
config ) );
+ engine = createEngine( m_engine, m_home, engineConfig, base, base );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Could not construct secondary engine for block: " + name;
+ throw new BlockException( error, e );
}
//
- // get the basic information for the block declaration
- // in the block.xml file
+ // create an appliance context
//
- URL url = null;
- Configuration base;
- String name = null;
+ String partition = name + Container.PATH_SEPERATOR;
+ ContainerDescriptor descriptor = createContainerDescriptor( name, engine,
implementation );
+ List list = createChildBlocks( engine, partition, implementation, config,
base, getLogger() );
+ return createBlock( engine, list, descriptor, name,
Container.PATH_SEPERATOR, config );
+ }
+
+ /**
+ * Read in the configuration file containing the customize configuration targets.
+ * @param url the url to the targets configuration file (normally config.xml)
+ * @return the configuration containing the targets
+ */
+ private Configuration getTargetsConfiguration( URL url ) throws BlockException
+ {
+ if( url == null )
+ {
+ return new DefaultConfiguration( "targets",
DefaultBlockLoader.class.getName() );
+ }
+ return createConfiguration( url.toString() );
+ }
+ /**
+ * Internal utilitity to read in a configuration from a uri.
+ * @param uri the uri to the configuration source
+ * @return the configuration object
+ */
+ private Configuration createConfiguration( final String uri ) throws
BlockException
+ {
+ DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
try
{
- name = config.getAttribute( "name" );
+ return builder.build( uri );
}
- catch( ConfigurationException e )
+ catch( Throwable e )
{
- final String error =
- "Block defintion is missing the required name attribute:"
- + ConfigurationUtil.list( config );
- throw new BlockException( error, e );
+ final String error =
+ "Unable to create configuration from source: " + uri;
+ throw new BlockException( error, e );
}
+ }
- if( config.getAttribute( "path", null ) != null )
+ /**
+ * The supplied URL is normally either a block.xml file URL or a jar url.
+ * If it is a jar url then simply return it but it is isn't then return
+ * the equivalent of the URL parent directory.
+ * @param url the URL to resolve a base path from
+ * @return the base URL
+ */
+ private URL getBasePath( final URL url )
+ {
+ if( url.getProtocol().equals( "jar" ) )
{
-
- //
- // It is a packaged block within a jar file.
- //
-
- String path = config.getAttribute("path", null );
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug(
- "assigning path to " + this
- + " path [" + path + "] as [" + name + "]");
- }
-
- //
- // load the jar file referenced by the block declaration and get its
- // manifest
- //
-
+ return url;
+ }
+ else
+ {
+ // its a block.xml file so we need to return the url with the
+ // filename stripped off it
try
{
- url = new File( m_home, path ).getCanonicalFile().toURL();
- JarFile jar = getJarFile( url );
-
- //
- // get the blocks packaged configuration and use that to establish
- // the engine to be supplied to the block
- //
-
- base = getBlockConfiguration( jar );
+ final String path = url.getPath();
+ final String base = path.substring( 0, ( path.lastIndexOf("/") + 1
) );
+ return new URL( url, base );
}
catch( Throwable e )
{
final String error =
- "Unable to resolve package block description on path: " + path;
- throw new BlockException( error, e );
+ "Unexpected error while resolviong base path from URL: " + url;
+ throw new BlockRuntimeException( error, e );
}
}
- else
- {
- //
- // The block configuration is declared in an external file.
- //
-
- String src = config.getAttribute( "src", null );
- if( src == null )
- {
- final String error =
- "Block does not contain a 'src' or 'path' attribute: \n"
- + ConfigurationUtil.list( config );
- throw new BlockException( error );
- }
+ }
- File file = new File( m_home, src );
- DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
- InputStream is = null;
+ private Configuration getBlockConfiguration( URL url ) throws BlockException
+ {
+ String uri = url.toString();
+ if( url.getProtocol().equals( "jar" ) )
+ {
try
{
- is = new FileInputStream( file );
+ JarFile jar = getJarFile( url );
+ return getBlockConfiguration( jar );
}
- catch( IOException ie )
+ catch( Throwable e )
{
final String error =
- "Unable to load external block definition from the file: " + file;
- throw new BlockException( error, ie );
- }
- if( is == null )
- {
- throw new BlockException(
- "Could not load the configuration resource \"" + file + "\"" );
+ "Unable to resolve packaged block description on path: " + url;
+ throw new BlockException( error, e );
}
-
+ }
+ else
+ {
+ // its a simulated block
+ //String source = appendName( uri, "block-inf/block.xml" );
try
{
- base = builder.build( is );
+ return createConfiguration( uri );
}
catch( Throwable e )
{
final String error =
- "Source related error while load external block definition from
file: " + file;
+ "Unable to resolve block description on path: " + uri;
throw new BlockException( error, e );
}
}
+ }
- Configuration implementation = base.getChild( "implementation" );
- Configuration engineConfig = implementation.getChild( "engine" );
- EngineClassLoader engine = null;
-
- try
- {
- engine = createChildEngine( m_engine, m_home, engineConfig, url,
getLogger() );
- }
- catch( Throwable ee )
- {
- final String error =
- "Could not construct secondary engine for block: " + name;
- throw new BlockException( error, ee );
- }
-
- //
- // create an appliance context
- //
-
- String partition = name + Container.PATH_SEPERATOR;
- ContainerDescriptor descriptor = createContainerDescriptor( name, engine,
implementation );
- //Registry registry = null;
-
- //try
- //{
- // registry = m_registry.createChild( name );
- //}
- //catch( Throwable ee )
- //{
- // final String error =
- // "Could not construct secondary registry for block: " + name;
- // throw new BlockException( error, ee );
- //}
- List list = createChildBlocks( engine, partition, implementation, config,
getLogger() );
- return createBlock( engine, list, descriptor, name,
Container.PATH_SEPERATOR, config );
- }
+ //==============================================================
+ // internals
+ //==============================================================
/**
* Create a descriptor of a container populated with the defintintion
@@ -587,19 +491,18 @@
}
}
-
/**
* Creation of a set of child blocks relative to a set of parent parameters.
*
* @param engine the parent classloader
* @param partition the partition to be applied to the child containers
- * @param config a confiuration containing a set of subsidiary container elements
+ * @param config the parent block configuration
* @param logger the logger from which child loggers shall be created
* @return a list of appliance instances each representing a container container
*/
private List createChildBlocks(
EngineClassLoader engine, String partition,
- Configuration config, Configuration custom, Logger logger )
+ Configuration config, Configuration custom, URL base, Logger logger )
throws BlockException
{
List list = new ArrayList();
@@ -608,39 +511,11 @@
for( int i=0; i<children.length; i++ )
{
Configuration child = children[i];
-
- //
- // get the block name
- //
-
- String name;
- try
- {
- name = child.getAttribute( "name" );
- }
- catch( ConfigurationException ce )
- {
- final String error =
- "Cannot create a subsidiary container due to missing name
attribute:\n"
- + ConfigurationUtil.list( child );
- throw new BlockException( error );
- }
-
- //
- // create the block classloader
- //
-
EngineClassLoader loader;
try
{
- loader = createChildEngine(
- engine, m_home, child.getChild("engine"), getLogger() );
- }
- catch( ConfigurationException ce )
- {
- final String error =
- "Cannot create a subsidiary container due to a configuration
error.";
- throw new BlockException( error, ce );
+ Configuration conf = child.getChild("engine");
+ loader = createEngine( engine, m_home, conf, base );
}
catch( EngineException ce )
{
@@ -649,20 +524,9 @@
throw new BlockException( error, ce );
}
- //Registry reg;
- //try
- //{
- // reg = registry.createChild( name );
- //}
- //catch( MalformedURLException e )
- //{
- // final String error =
- // "Cannot create a subsidiary container due to a url format
error.";
- // throw new BlockException( error, e );
- //}
-
+ String name = getBlockName( child );
Block block = createContainmentBlock(
- loader, partition, name, child, custom, getLogger() );
+ loader, partition, name, child, custom, base, getLogger() );
list.add( block );
}
@@ -682,11 +546,11 @@
*/
private Block createContainmentBlock(
EngineClassLoader engine, String partition, String name,
- Configuration config, Configuration custom, Logger logger )
+ Configuration config, Configuration custom, URL base, Logger logger )
throws BlockException
{
String subPartition = partition + name + Container.PATH_SEPERATOR;
- List list = createChildBlocks( engine, subPartition, config, custom, logger
);
+ List list = createChildBlocks( engine, subPartition, config, custom, base,
logger );
ContainerDescriptor descriptor;
try
@@ -707,10 +571,9 @@
* Create a block.
*
* @param engine the containers classloader
- * @param list the list of subsidiary container blocks
+ * @param containers the list of subsidiary blocks
* @param descriptor the container descriptor
* @param name the block name
- * @param registry the compoent registry to apply to the container
* @param partition the partition to assign to the container
* @param custom the custom configuration
* @return the block
@@ -744,7 +607,6 @@
context.setPartitionName( partition );
context.setApplianceClassname( DefaultBlock.class.getName() );
context.put("urn:merlin:container.descriptor", descriptor );
- //context.put("urn:merlin:container.registry", registry );
context.put("urn:merlin:container.library", this );
context.put("urn:merlin:container.containers", containers );
context.makeReadOnly();
@@ -874,6 +736,14 @@
}
}
+ /**
+ * Get the activation policy from a configuration. If no activation attribute
+ * is present the value return defaults to FALSE (i.e. activation is deferred).
+ *
+ * @param config a configuration fragment holding a activation attribute
+ * @return TRUE is the value of the activation attribute is 'true' or 'startup'
+ * otherwise the return value is FALSE
+ */
private boolean getActivationPolicy( Configuration config )
{
final String value = config.getAttribute( "activation", null );
@@ -889,24 +759,65 @@
return string.equals( "true" );
}
+ /**
+ * Creation of a subsidiary engine.
+ * @param parent the parent engine
+ * @param home the home directory
+ * @param config the engine configuration
+ * @param base the URL from which classpath entries shall be resolved
+ * @return the new engine
+ * @exception EngineException if an engine establishment failure occurs
+ */
+ private EngineClassLoader createEngine(
+ EngineClassLoader parent, File home, Configuration config, URL base )
+ throws EngineException
+ {
+ return createEngine( parent, home, config, base, null );
+ }
- protected EngineClassLoader createChildEngine(
- EngineClassLoader parent, File home, Configuration config, Logger logger )
- throws EngineException, ConfigurationException
+ /**
+ * Creation of a subsidiary engine.
+ * @param parent the parent engine
+ * @param home the home directory
+ * @param config the engine configuration
+ * @param base the URL from which classpath entries shall be resolved
+ * @param target the URL of an implicit entry to include in the engine
+ * @return the new engine
+ * @exception EngineException if an engine establishment failure occurs
+ */
+ private EngineClassLoader createEngine(
+ EngineClassLoader parent, File home, Configuration config, URL base, URL
target )
+ throws EngineException
{
- return createChildEngine( parent, home, config, null, logger );
+ LibraryDescriptor extensions =
+ createLibraryDescriptor( config.getChild( "library" ) );
+
+ ClasspathDescriptor classpath =
+ createClasspathDescriptor( config.getChild( "classpath" ) );
+
+ if( target != null )
+ {
+ return parent.newInstance( base, extensions, classpath, new URL[]{
target } );
+ }
+ else
+ {
+ return parent.newInstance( base, extensions, classpath );
+ }
}
- protected EngineClassLoader createChildEngine(
- EngineClassLoader parent, File home, Configuration config, URL url, Logger
logger )
- throws EngineException, ConfigurationException
+ /**
+ * Utility that handles the creation of a extension set descriptor from
+ * a configuration fragment.
+ * @param config the configuration
+ * @return the library descriptor
+ * @exception EngineException if an error occurs
+ */
+ private LibraryDescriptor createLibraryDescriptor( Configuration config )
+ throws EngineException
{
- LibraryDescriptor extensions;
try
{
- extensions =
- CREATOR.createLibraryDescriptor(
- config.getChild( "library" ) );
+ return CREATOR.createLibraryDescriptor( config );
}
catch( Throwable e )
{
@@ -914,45 +825,65 @@
+ ConfigurationUtil.list( config );
throw new EngineException( error, e );
}
+ }
- ClasspathDescriptor classpath;
+ /**
+ * Utility that handles the creation of a classpath descriptor from
+ * a configuration fragment.
+ * @param config the configuration
+ * @return the classpath descriptor
+ * @exception EngineException if an error occurs
+ */
+ private ClasspathDescriptor createClasspathDescriptor( Configuration config )
+ throws EngineException
+ {
try
{
- classpath =
- CREATOR.createClasspathDescriptor(
- config.getChild( "classpath" ) );
+ return CREATOR.createClasspathDescriptor( config );
}
catch( Throwable e )
{
- final String error = "Bad classpath descriptor.";
+ final String error = "Bad classpath descriptor: \n"
+ + ConfigurationUtil.list( config );
throw new EngineException( error, e );
}
+ }
+ /**
+ * Get the name of the block from the blockk configuration.
+ * @param config the block configuration
+ * @return the block name
+ */
+ private String getBlockName( Configuration config ) throws BlockException
+ {
try
{
- EngineClassLoader engine;
- if( url != null )
- {
- engine = new EngineClassLoader( new URL[]{ url }, parent );
- }
- else
- {
- engine = new EngineClassLoader( parent );
- }
- engine.enableLogging( logger );
- DefaultLocator context = new DefaultLocator();
- context.put( "urn:assembly:home", home );
- context.put( "urn:assembly:engine.extensions", extensions );
- context.put( "urn:assembly:engine.classpath", classpath );
- context.makeReadOnly();
- engine.contextualize( context );
- engine.initialize();
- return engine;
+ return config.getAttribute( "name" );
}
catch( Throwable e )
{
- final String error = "Engine bootstrap failure.";
- throw new EngineException( error, e );
+ final String error =
+ "Supplied block configuration does not conain the required name
attribute:\n"
+ + ConfigurationUtil.list( config );
+ throw new BlockException( error, e );
+ }
+ }
+
+ /**
+ * Return a uri based on a base uri and a path to be appended to the base.
+ * @param uri the base uri
+ * @param path the path to append to the base
+ * @return the full uri with path appended to the base uri
+ */
+ private String appendName( String uri, String path )
+ {
+ if( uri.endsWith( "/" ) )
+ {
+ return uri + path;
+ }
+ else
+ {
+ return uri + "/" + path;
}
}
}
1.10 +13 -5
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/builder/XMLContainerCreator.java
Index: XMLContainerCreator.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/builder/XMLContainerCreator.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- XMLContainerCreator.java 7 Feb 2003 15:39:35 -0000 1.9
+++ XMLContainerCreator.java 16 Feb 2003 13:01:20 -0000 1.10
@@ -208,7 +208,6 @@
return (ContainerDescriptor) getConstructor().newInstance(
new Object[]{
name, params, config, context, categories, type, mode } );
-
}
/**
@@ -314,12 +313,21 @@
* incomplete
*/
public LoggingDescriptor createLoggingDescriptor(
- Configuration config, String name )
+ Configuration config, String name, String level )
throws ConfigurationException
{
final String target = config.getAttribute(
"target", Category.DEFAULT_LOGGING_TARGET );
- final String priority = config.getAttribute( "priority", null );
+ String priority = null;
+ if( level != null )
+ {
+ priority = level;
+ }
+ else
+ {
+ priority = config.getAttribute( "priority", "" );
+ }
+
Category category = createCategory( config.getChild( "category" ) );
ArrayList list = new ArrayList();
@@ -333,7 +341,7 @@
(TargetDescriptor[])list.toArray(
new TargetDescriptor[ 0 ] );
return new LoggingDescriptor(
- name, priority, target, targets, category );
+ name, priority, target, targets, category );
}
/**
1.9 +132 -135
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/impl/DefaultKernel.java
Index: DefaultKernel.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/impl/DefaultKernel.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- DefaultKernel.java 12 Feb 2003 16:28:20 -0000 1.8
+++ DefaultKernel.java 16 Feb 2003 13:01:20 -0000 1.9
@@ -103,8 +103,6 @@
import org.apache.avalon.merlin.block.BlockException;
import org.apache.avalon.merlin.container.builder.XMLContainerCreator;
import org.apache.avalon.merlin.container.Container;
-//import org.apache.avalon.merlin.service.DefaultRegistry;
-//import org.apache.avalon.merlin.service.Registry;
import org.apache.avalon.merlin.kernel.Kernel;
import org.apache.avalon.merlin.kernel.KernelException;
import org.apache.avalon.merlin.kernel.KernelRuntimeException;
@@ -145,34 +143,37 @@
// static
//==============================================================
+ protected static final XMLContainerCreator CREATOR = new XMLContainerCreator();
+
+ //==============================================================
+ // state
+ //==============================================================
+
/**
* The logging manager that we use to construct logging catagories
* and logging channels.
*/
- private static LoggingManager LOGGING;
+ private LoggingManager m_logging;
/**
* The pool manager.
*/
- private static PoolManager POOL;
-
- protected static final String BLOCK_XML_ENTRY = "BLOCK-INF/block.xml";
-
- protected static final XMLContainerCreator CREATOR = new XMLContainerCreator();
-
- //==============================================================
- // state
- //==============================================================
+ private static PoolManager m_pool;
/**
* The kernel configuration profile.
*/
- private Configuration m_profile;
+ private Configuration m_config;
/**
- * The block configuration.
+ * The root block URL.
*/
- private Configuration m_configuration;
+ private URL m_url;
+
+ /**
+ * The optional configuration overrides.
+ */
+ private URL m_override;
/**
* The application home directory.
@@ -192,7 +193,7 @@
/**
* The bootstrap classloader.
*/
- private ClassLoader m_bootstrap;
+ private ClassLoader m_loader;
/**
* The common classloader.
@@ -215,16 +216,36 @@
private List m_blocks = new ArrayList();
/**
+ * The root block.
+ */
+ private Block m_block;
+
+ /**
* A map of root containers keyed by the block it is contained by.
*/
private Map m_containers = new Hashtable();
- //private DefaultRegistry m_registry;
-
+ /**
+ * The domain name of this host.
+ */
private String m_domain;
+ /**
+ * The root dependency graph.
+ */
private final DependencyGraph m_graph = new DependencyGraph();
+ /**
+ * The block loader.
+ */
+ private DefaultBlockLoader m_blockLoader;
+
+ /**
+ * The debug level.
+ */
+ private String m_debug;
+
+
//==============================================================
// Contextualizable
//==============================================================
@@ -238,9 +259,24 @@
* <td><b>key</b></td><td><b>type</b></td><td><b>description</b></td>
* </tr>
* <tr>
- * <td><code>urn:assembly:home</code></td>
+ * <td><code>urn:merlin:home</code></td>
* <td>{@link java.io.File}</td>
- * <td>The kernel home directory.</td>
+ * <td>The working home directory.</td>
+ * </tr>
+ * <tr>
+ * <td><code>urn:merlin:classloader.common</code></td>
+ * <td>{@link java.lang.ClassLoader}</td>
+ * <td>The shared classloader.</td>
+ * </tr>
+ * <tr>
+ * <td><code>urn:merlin:classloader.system</code></td>
+ * <td>{@link java.lang.ClassLoader}</td>
+ * <td>The internal system classloader.</td>
+ * </tr>
+ * <tr>
+ * <td><code>urn:merlin:block.configuration</code></td>
+ * <td>{@link org.apache.avalon.framework.configuration.Configuration}</td>
+ * <td>The block configuration that the kernel will manage.</td>
* </tr>
* </table>
* @param context the runtime context
@@ -250,7 +286,16 @@
{
m_home = (File) context.get( "urn:merlin:home" );
m_common = (ClassLoader) context.get( "urn:merlin:classloader.common" );
- m_bootstrap = (ClassLoader) context.get( "urn:merlin:classloader.system" );
+ m_loader = (ClassLoader) context.get( "urn:merlin:classloader.system" );
+ m_url = (URL) context.get( "urn:merlin:block.url" );
+ if( context.hasEntry( "urn:merlin:block.config" ) )
+ {
+ m_override = (URL) context.get( "urn:merlin:block.config" );
+ }
+ if( context.hasEntry( "urn:merlin:debug" ) )
+ {
+ m_debug = (String) context.get( "urn:merlin:debug" );
+ }
}
//==============================================================
@@ -263,7 +308,7 @@
*/
public void configure( Configuration config )
{
- m_profile = config;
+ m_config = config;
}
//==============================================================
@@ -280,33 +325,29 @@
*/
public void initialize() throws Exception
{
+
if( m_home == null )
{
throw new IllegalStateException("context");
}
//
- // load the kernel configuration
- //
-
- m_configuration = m_profile.getChild( "blocks" );
-
- //
// Setup the logging system
//
try
{
- if( LOGGING == null )
+ final String sys = "/sys";
+ if( m_logging == null )
{
- LOGGING = bootstrapLoggingManager( Container.PATH_SEPERATOR );
- Configuration categoriesConfig = m_profile.getChild( "categories" );
+ m_logging = bootstrapLoggingManager( Container.PATH_SEPERATOR, sys,
m_debug );
+ Configuration categoriesConfig = m_config.getChild( "categories" );
LoggingDirective categories =
- CREATOR.createLoggingDirective( Container.PATH_SEPERATOR,
categoriesConfig );
- LOGGING.addCategories( Container.PATH_SEPERATOR, categories );
+ CREATOR.createLoggingDirective(
+ Container.PATH_SEPERATOR, categoriesConfig );
+ m_logging.addCategories( Container.PATH_SEPERATOR, categories );
}
- final String sys = "/sys";
- m_local = LOGGING.getLoggerForCategory( sys );
+ m_local = m_logging.getLoggerForCategory( sys );
enableLogging( m_local );
}
catch( Throwable e )
@@ -320,14 +361,13 @@
// setup the thread pool
//
- POOL = getPoolManager( m_profile.getChild( "pool" ) );
+ m_pool = getPoolManager( m_config.getChild( "pool" ) );
//
- // setup the domain and service registry
+ // setup the domain
//
- m_domain = m_profile.getChild( "system" ).getAttribute( "host", "localhost"
);
- //m_registry = new DefaultRegistry( domain );
+ m_domain = m_config.getChild( "system" ).getAttribute( "host", "localhost"
);
//
// announce initialization
@@ -344,7 +384,7 @@
try
{
- m_engine = bootstrapEngine( LOGGING, POOL, m_profile.getChild( "engine"
) );
+ m_engine = bootstrapEngine( m_logging, m_pool, m_config.getChild(
"engine" ) );
}
catch( Throwable e )
{
@@ -360,8 +400,7 @@
}
//
- // we are now ready to assemble the blocks declared under the
- // kernel configuration
+ // we are now ready to assemble the block
//
if( getLogger().isInfoEnabled() )
@@ -369,34 +408,16 @@
getLogger().info( "\n\ncommencing block construction phase\n" );
}
- Block[] blocks;
-
+ DefaultBlockLoader loader = new DefaultBlockLoader();
try
{
- DefaultBlockLoader loader = new DefaultBlockLoader();
loader.enableLogging( getLogger() );
DefaultLocator context = new DefaultLocator();
context.put( "urn:assembly:engine", m_engine );
- //context.put( "urn:assembly:registry", m_registry );
context.put( "urn:assembly:system-context", getSystemContext() );
context.makeReadOnly();
loader.contextualize( context );
- loader.configure( m_configuration );
loader.initialize();
-
- blocks = loader.createBlocks();
-
- for( int i=0; i<blocks.length; i++ )
- {
- Block block = blocks[i];
- m_blocks.add( block );
- if( getLogger().isInfoEnabled() )
- {
- getLogger().info( block.toString() );
- }
- }
-
- loader.dispose();
}
catch( Throwable e )
{
@@ -409,51 +430,52 @@
throw new KernelException( error, e );
}
- //
- // Instantiate the root container in each block.
- //
-
if( getLogger().isInfoEnabled() )
{
- getLogger().info( "\n\ncommencing structural assembly phase\n" );
+ getLogger().info( "\n\ncommencing block installation phase\n" );
}
- for( int i=0; i<blocks.length; i++ )
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "installing block: " + m_url );
+ }
+
+ try
+ {
+ m_block = loader.install( m_url, m_override );
+ }
+ catch( Throwable e )
{
- Block block = blocks[i];
- try
+ final String error =
+ "Block install failure: " + m_url;
+ String log = ExceptionHelper.packException( error, e );
+ if( getLogger().isErrorEnabled() )
{
- block.assemble( new DependencyGraph( m_graph ) );
+ getLogger().error( log );
}
- catch( Throwable e )
+ throw new KernelException( error, e );
+ }
+
+ if( getLogger().isInfoEnabled() )
+ {
+ getLogger().info( "\n\ncommencing block assembly phase\n" );
+ }
+
+ try
+ {
+ m_block.assemble( new DependencyGraph( m_graph ) );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unable to deploy block: " + m_block.getName() + " due to an assembly
failure.";
+ String log = ExceptionHelper.packException( error, e );
+ if( getLogger().isErrorEnabled() )
{
- final String error =
- "Unable to deploy block: " + block + " due to a structural
assembly failure.";
- String log = ExceptionHelper.packException( error, e );
- if( getLogger().isErrorEnabled() )
- {
- getLogger().error( log );
- }
- throw new KernelException( error, e );
+ getLogger().error( log );
}
+ throw new KernelException( error, e );
}
-
- //
- // list the registered services
- //
-
- //URL[] appliances = m_registry.list();
- //if( appliances.length == 0 )
- //{
- // getLogger().info( "empty registry" );
- //}
- //else
- //{
- // for( int i=0; i<appliances.length; i++ )
- // {
- // getLogger().info("registry: " + appliances[i] );
- // }
- //}
}
//==============================================================
@@ -472,11 +494,9 @@
getLogger().info( "\n\ncommencing deployment phase\n" );
}
- Iterator iterator = m_blocks.iterator();
- while( iterator.hasNext() )
+ if( m_block != null )
{
- Block block = (Block) iterator.next();
- block.deploy();
+ m_block.deploy();
}
if( getLogger().isInfoEnabled() )
@@ -500,11 +520,9 @@
}
}
- Iterator iterator = m_blocks.iterator();
- while( iterator.hasNext() )
+ if( m_block != null )
{
- Block block = (Block) iterator.next();
- block.decommission();
+ m_block.decommission();
}
}
@@ -513,7 +531,7 @@
//==============================================================
/**
- * Disposal of the kernel.
+ * Disposal of the kernel.
*/
public void dispose()
{
@@ -525,11 +543,9 @@
}
}
- Iterator iterator = m_blocks.iterator();
- while( iterator.hasNext() )
+ if( m_block != null )
{
- Block block = (Block) iterator.next();
- block.terminate();
+ m_block.terminate();
}
if( getLogger() != null )
@@ -545,30 +561,11 @@
// internals
//==============================================================
- private Configuration getConfiguration( final File file ) throws
ConfigurationException
+ private LoggingManager bootstrapLoggingManager(
+ String root, String system, String level ) throws Exception
{
- 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 );
- }
- }
-
- private LoggingManager bootstrapLoggingManager( String root ) throws Exception
- {
- if( m_profile == null )
+ if( m_config == null )
{
throw new IllegalStateException( "configuration" );
}
@@ -587,7 +584,7 @@
LoggingDescriptor descriptor =
CREATOR.createLoggingDescriptor(
- m_profile.getChild( "logging" ), root );
+ m_config.getChild( "logging" ), root, level );
DefaultLocator context = new DefaultLocator();
context.put( "urn:assembly:home", m_home );
@@ -636,11 +633,12 @@
try
{
- EngineClassLoader engine = new EngineClassLoader( m_bootstrap );
+ EngineClassLoader engine = new EngineClassLoader( m_loader );
engine.enableLogging( getLogger() );
Locator system = getSystemContext();
DefaultLocator context = new DefaultLocator( system );
context.put( "urn:assembly:engine.bootstrap", "true" );
+ context.put( "urn:assembly:engine.base", m_url );
context.put( "urn:assembly:engine.extensions", extensions );
context.put( "urn:assembly:engine.classpath", classpath );
context.put( "urn:assembly:logging.manager", logging );
@@ -729,5 +727,4 @@
throw new Exception( error + e.toString() );
}
}
-
}
1.5 +44 -40
avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/impl/KernelLoader.java
Index: KernelLoader.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/impl/KernelLoader.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- KernelLoader.java 8 Feb 2003 08:51:52 -0000 1.4
+++ KernelLoader.java 16 Feb 2003 13:01:20 -0000 1.5
@@ -23,9 +23,12 @@
import java.net.MalformedURLException;
import java.net.JarURLConnection;
+import org.xml.sax.SAXException;
+
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.configuration.DefaultConfiguration;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.context.ContextException;
@@ -40,17 +43,26 @@
import org.apache.avalon.merlin.kernel.KernelRuntimeException;
/**
- * Merlin commandline bootstrap handler.
+ * The KernelLoader provides support for the establishment of a kernel
+ * instance assuming a file system deployment environment. A loader will
+ * typically handle the establishment of a kernel relative to an
+ * environment - for example, this loader deals with loading the kernel
+ * from a file system whereas another loader may deal with eestablishing
+ * a kernel inside a servlet.
+ *
* @see DefaultKernel
*/
public class KernelLoader
{
-
private DefaultKernel m_kernel;
- public KernelLoader( ClassLoader system, ClassLoader common, File base, File
profile )
+ public KernelLoader( Map map )
{
- m_kernel = new DefaultKernel();
+
+ //
+ // Create a shutdown hook to trigger clean disposal of the
+ // Merlin kernel
+ //
try
{
@@ -61,7 +73,10 @@
{
try
{
- m_kernel.stop();
+ if( m_kernel != null )
+ {
+ m_kernel.stop();
+ }
}
catch( Throwable e )
{
@@ -69,7 +84,10 @@
}
finally
{
- m_kernel.dispose();
+ if( m_kernel != null )
+ {
+ m_kernel.dispose();
+ }
}
}
}
@@ -95,30 +113,23 @@
return;
}
- DefaultLocator context = new DefaultLocator();
- context.put( "urn:merlin:home", base );
- context.put( "urn:merlin:classloader.common", common );
- context.put( "urn:merlin:classloader.system", system );
- context.put( "urn:merlin:kernel.profile", profile );
- context.makeReadOnly();
+ //
+ // get the kernel configuration profile
+ //
- Configuration config = null;
- try
- {
- config = getConfiguration( profile );
- }
- catch( ConfigurationException e )
- {
- final String error =
- "Unable to load kernel configuration from file: "
- + profile;
- throw new RuntimeException( error.toString() );
- }
+ File profile = (File) map.get( "urn:merlin:kernel.profile" );
+
+ //
+ // contextualize, configure, initialize and start the kernel
+ //
+ DefaultLocator context = new DefaultLocator( map );
+ context.makeReadOnly();
try
{
+ m_kernel = new DefaultKernel();
m_kernel.contextualize( context );
- m_kernel.configure( config );
+ m_kernel.configure( getKernelConfiguration( profile ) );
m_kernel.initialize();
m_kernel.start();
}
@@ -139,23 +150,16 @@
}
}
- private Configuration getConfiguration( final File file ) throws
ConfigurationException
+ private Configuration getKernelConfiguration( final File file )
+ throws ConfigurationException, IOException, SAXException
{
- 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 )
+ DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
+ InputStream is = new FileInputStream( file );
+ if( is == null )
{
- final String error = "Unable to create configuration from file: " +
file;
- throw new ConfigurationException( error, e );
+ throw new IOException(
+ "Could not load kernel configuration resource \"" + file + "\"" );
}
+ return builder.build( is );
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]