Return-Path:
Utility class supporting the establishment of a new Controller
+ * based on a filename supplied under the command line line.
UML
+ *Example commmand line:
+ * After building the Merlin suite usingant deploy
a directory
+ * will be created containing all of the jar files needed to run the kernel.
+ * The following command line executes the establishment of the kernel and a
+ * a set of demonstration components declared (and implied) in the kernel.xml
+ * assembly profile.
+ *
+ * + * $ java -jar .\extensions\merlin.jar src\etc\kernel.xml + *+ * + *
Aborting the process will result in a clean server shutdown.
+ * + * @see DefaultController * @author Stephen McConnell * @version $Revision$ $Date$ */ @@ -88,189 +106,78 @@ //======================================================================= /** - * Creation of a root type registry. + * Entry point for command line based creation of a newController
+ * instance.
*/
public static void main( String[] args )
{
+ //
+ // get the filename from the command line arguments and check it
+ // for existance and general integrity
+ //
- // get a configuration object containing the kernel profile
- // from which we can establish the logger and extensions directory
-
- String path = null;
- Configuration config = null;
+ File path = null;
if( args.length > 0 )
{
- path = args[0];
- config = getProfile( new File( path ) );
+ String filename = args[0];
+ path = new File( filename );
+ if( !path.exists() )
+ {
+ final String error = "Supplied filename does not exist. (" + filename + ")";
+ throw new ControllerRuntimeException( error );
+ }
+
+ if( path.isDirectory() )
+ {
+ final String error = "Supplied filename is not a file. (" + filename + ")";
+ throw new ControllerRuntimeException( error );
+ }
+
+ if( !path.canRead() )
+ {
+ final String error = "Cannot read the file. (" + filename + ")";
+ throw new ControllerRuntimeException( error );
+ }
}
else
{
throw new RuntimeException("Missing kernel configuration path argument.");
}
- XMLKernelCreator creator = new XMLKernelCreator();
- ClasspathDescriptor classpath = null;
- ExtensionsDescriptor extensions = null;
- LoggingDescriptor loggingDescriptor = null;
- try
- {
- classpath = creator.createClasspathDescriptor( config.getChild("classpath") );
- extensions = creator.createExtensionsDescriptor( config.getChild("extensions") );
- loggingDescriptor = creator.createLoggingDescriptor( config.getChild("logging"), "kernel" );
- }
- catch( Throwable e )
- {
- e.printStackTrace();
- System.exit(0);
- }
-
- final DefaultKernel kernel = new DefaultKernel();
-
//
- // add a shutdown hook so we can stop services and target and invoke shutdown
+ // add a shutdown hook so we can stop the controller on a command line
+ // invoked abort
//
+ final DefaultController controller = new DefaultController();
+ DefaultContext context = new DefaultContext();
+ context.put( DefaultController.CONTROLLER_PATH_KEY, path );
+ context.makeReadOnly();
Runtime.getRuntime().addShutdownHook(
new Thread()
{
public void run()
{
- if( kernel != null )
- kernel.shutdown();
+ controller.stop();
}
}
);
//
- // log manager
- //
-
- DefaultLoggerManager logging = null;
- Logger logger = null;
- try
- {
- logging = new DefaultLoggerManager( loggingDescriptor );
- logger = logging.getLoggerForCategory( "kernel" );
- logger.info("commencing type installation");
- }
- catch( Throwable e )
- {
- System.out.println("Unexpected error while preparing log manager.");
- e.printStackTrace();
- System.exit(0);
- }
-
- //
- // root classloader
- //
-
- final ContainerClassLoader loader = new ContainerClassLoader();
- try
- {
- loader.enableLogging( logger.getChildLogger( "loader" ) );
- DefaultContext context = new DefaultContext();
- context.put(
- ContainerClassLoader.EXTENSIONS_DESCRIPTOR_KEY,
- extensions );
- context.put(
- ContainerClassLoader.CLASSPATH_DESCRIPTOR_KEY,
- classpath );
- context.makeReadOnly();
- loader.contextualize( context );
- loader.initialize();
- }
- catch( Throwable e )
- {
- System.out.println("Unexpected error while preparing classloader.");
- e.printStackTrace();
- System.exit(0);
- }
-
- //
- // installer classloader
+ // launch the controler
//
- final ContainerClassLoader installer = new ContainerClassLoader( loader );
- try
- {
- installer.enableLogging( logger.getChildLogger( "installer" ) );
- DefaultContext context = new DefaultContext();
- installer.contextualize( context );
- installer.initialize();
- }
- catch( Throwable e )
- {
- System.out.println("Unexpected error while preparing classloader.");
- e.printStackTrace();
- System.exit(0);
- }
-
- ContainerDescriptor container = null;
- try
- {
- container = creator.createContainerDescriptor( config.getChild("container"), installer );
- }
- catch( Throwable e )
- {
- System.out.println("Unexpected error while preparing metamodel.");
- e.printStackTrace();
- System.exit(0);
- }
-
- // run it up
-
- logger.info("commencing kernel deployment");
- DefaultContext context = new DefaultContext();
- context.put( DefaultKernel.ROOT_CONTAINER_DESCRIPTOR_KEY, container );
- context.put( DefaultKernel.CLASSLOADER_KEY, loader );
- context.put( DefaultKernel.LOG_MANAGER_KEY, logging );
- context.makeReadOnly();
try
{
- kernel.enableLogging( logger );
- kernel.contextualize( context );
- kernel.initialize( );
- }
- catch( KernelException e )
- {
- System.exit(0);
+ controller.contextualize( context );
+ controller.initialize();
+ controller.start();
}
catch( Throwable e )
{
- System.out.println("Unexpected error while initilizing kernel.");
+ System.out.println("Controller deployment failure.");
e.printStackTrace();
- System.exit(0);
- }
-
- // invoke the registry demo
- try
- {
- kernel.startup();
- }
- catch( Throwable e )
- {
- System.exit(0);
- }
- }
-
- private static Configuration getProfile( final File file )
- {
- try
- {
- DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
- InputStream is = new FileInputStream( file );
- if( is == null )
- {
- throw new RuntimeException(
- "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 CascadingRuntimeException( error, e );
+ controller.dispose();
}
}
-
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/ControllerException.java
Index: ControllerException.java
===================================================================
/*
* 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.
*/
package org.apache.excalibur.merlin;
import org.apache.avalon.framework.CascadingException;
/**
* Exception to indicate that there was a controller related error.
*
* @author Stephen McConnell
* @version $Revision: 1.1 $ $Date: 2002/07/13 00:09:44 $
*/
public final class ControllerException
extends CascadingException
{
/**
* Construct a new ControllerException
instance.
*
* @param message The detail message for this exception.
*/
public ControllerException( final String message )
{
this( message, null );
}
/**
* Construct a new ControllerException
instance.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public ControllerException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/ControllerRuntimeException.java
Index: ControllerRuntimeException.java
===================================================================
/*
* 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.
*/
package org.apache.excalibur.merlin;
import org.apache.avalon.framework.CascadingRuntimeException;
/**
* Exception to indicate that there was a controller related runtime error.
*
* @author Stephen McConnell
* @version $Revision: 1.1 $ $Date: 2002/07/13 00:09:44 $
*/
public final class ControllerRuntimeException
extends CascadingRuntimeException
{
/**
* Construct a new ControllerRuntimeException
instance.
*
* @param message The detail message for this exception.
*/
public ControllerRuntimeException( final String message )
{
this( message, null );
}
/**
* Construct a new ControllerRuntimeException
instance.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public ControllerRuntimeException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/DefaultController.java
Index: DefaultController.java
===================================================================
/*
* 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.
*/
package org.apache.excalibur.merlin;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.activity.Disposable;
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.Configurable;
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.framework.logger.Logger;
import org.apache.excalibur.merlin.kernel.DefaultKernel;
import org.apache.excalibur.merlin.kernel.DefaultLoggerManager;
import org.apache.excalibur.merlin.kernel.ContainerClassLoader;
import org.apache.excalibur.merlin.kernel.KernelException;
import org.apache.excalibur.merlin.model.builder.XMLKernelCreator;
import org.apache.excalibur.merlin.model.KernelDescriptor;
import org.apache.excalibur.merlin.model.ClasspathDescriptor;
import org.apache.excalibur.merlin.model.ExtensionsDescriptor;
import org.apache.excalibur.merlin.model.LoggingDescriptor;
import org.apache.excalibur.merlin.model.ContainerDescriptor;
/**
* The DefaultControler
provides support for the establishment
* of the criteria for the creation of a new Kernel
using a
* supplied file referencing a kernel configuration source.
UML
*Code example:
*The following code example demonstrates the creation of an embedded controller * using a file based deployment descriptor. The example shows the creation of rhe * required application context following by lifecycle processing of the kernel service. *
** // * // create the execution context * // * * File file = new File( "src/etc/kernel.xml" ); * DefaultContext context = new DefaultContext(); * context.put( DefaultController.CONTROLLER_PATH_KEY, file ); * context.makeReadOnly(); * * // * // deploy the kernel * // * * DefaultController controller = new DefaultController(); * controller.contextualize( context ); * controller.initialize(); * controller.start(); * ** * @see Main * @author Stephen McConnell * @version $Revision: 1.1 $ $Date: 2002/07/13 00:09:44 $ */ public class DefaultController implements Controller, Initializable, Startable, Disposable { //======================================================================= // static //======================================================================= private static final int NOT_READY = -1; private static final int CONTEXTUALIZED = 0; private static final int INITIALIZED = 1; private static final int STARTED = 2; private static final int STOPPED = 3; private static final int DISPOSED = 4; public static final String CONTROLLER_PATH_KEY = "path"; //======================================================================= // state //======================================================================= private File m_path; private final DefaultKernel m_kernel = new DefaultKernel(); private int m_status = NOT_READY; //======================================================================= // Contextualizable //======================================================================= /** * Invoked by the bootstrap process to supply the path to the kernel configuration. * @param context the context object containing the inital path * @exception ContextException if the supplied does not contain a CONTROLLER_PATH_KEY value */ public void contextualize( Context context ) throws ContextException { m_path = (File) context.get( CONTROLLER_PATH_KEY ); m_status = CONTEXTUALIZED; } //======================================================================= // Initializable //======================================================================= public void initialize() throws Exception { if( m_status < CONTEXTUALIZED ) throw new ControllerException( "Controller has not been contextualized." ); Configuration config = null; XMLKernelCreator creator = new XMLKernelCreator(); ClasspathDescriptor classpath = null; ExtensionsDescriptor extensions = null; LoggingDescriptor loggingDescriptor = null; try { config = getProfile( m_path ); classpath = creator.createClasspathDescriptor( config.getChild("classpath") ); extensions = creator.createExtensionsDescriptor( config.getChild("extensions") ); loggingDescriptor = creator.createLoggingDescriptor( config.getChild("logging"), "kernel" ); } catch( Throwable e ) { final String error = "Controller model internalization failure."; throw new ControllerException( error, e ); } // // log manager // DefaultLoggerManager logging = null; Logger logger = null; try { logging = new DefaultLoggerManager( loggingDescriptor ); logger = logging.getLoggerForCategory( "kernel" ); logger.info("commencing type installation"); } catch( Throwable e ) { final String error = "Logging manager establishment failure."; throw new ControllerException( error, e ); } // // root classloader // final ContainerClassLoader loader = new ContainerClassLoader(); try { loader.enableLogging( logger.getChildLogger( "loader" ) ); DefaultContext context = new DefaultContext(); context.put( ContainerClassLoader.EXTENSIONS_DESCRIPTOR_KEY, extensions ); context.put( ContainerClassLoader.CLASSPATH_DESCRIPTOR_KEY, classpath ); context.makeReadOnly(); loader.contextualize( context ); loader.initialize(); } catch( Throwable e ) { final String error = "Classloader establishment failure."; throw new ControllerException( error, e ); } // // create a temporary installer classloader that we will use to build // a complete kernel and contain model // ContainerClassLoader installer = new ContainerClassLoader( loader ); try { installer.enableLogging( logger.getChildLogger( "installer" ) ); DefaultContext context = new DefaultContext(); installer.contextualize( context ); installer.initialize(); } catch( Throwable e ) { installer = null; final String error = "Model installation failure."; throw new ControllerException( error, e ); } ContainerDescriptor container = null; try { container = creator.createContainerDescriptor( config.getChild("container"), installer ); installer = null; } catch( Throwable e ) { installer = null; final String error = "Root container model establishment failure."; throw new ControllerException( error, e ); } // run it up logger.info("commencing kernel deployment"); DefaultContext context = new DefaultContext(); context.put( DefaultKernel.ROOT_CONTAINER_DESCRIPTOR_KEY, container ); context.put( DefaultKernel.CLASSLOADER_KEY, loader ); context.put( DefaultKernel.LOG_MANAGER_KEY, logging ); context.makeReadOnly(); try { m_kernel.enableLogging( logger ); m_kernel.contextualize( context ); m_kernel.initialize( ); } catch( KernelException e ) { final String error = "Kernel initialization failure."; throw new ControllerException( error, e ); } catch( Throwable e ) { final String error = "Unexpected initialization failure."; throw new ControllerException( error, e ); } m_status = INITIALIZED; } //======================================================================= // Startable //======================================================================= /** * Invoked by a contrainer to request startup of the controller. Thie implementation * simply invokes the {@link #startup} operation. */ public void start() throws Exception { startup(); } /** * Invoked by a contrainer to request shutdown of the controller. Thie implementation * simply invokes the {@link #startup} operation. */ public void stop() { shutdown(); } //======================================================================= // Disposable //======================================================================= /** * Invoked by a contrainer to requested disposal of the controller and all * consumed resources. */ public void dispose() { if( m_status < INITIALIZED ) { return; } else if( m_status < STOPPED ) { try { stop(); } catch( Throwable e ) { // ignore } } m_kernel.dispose(); m_status = DISPOSED; } //======================================================================= // Controller //======================================================================= /** * Request the startup of the managable unit. */ public void startup() throws Exception { if( m_status < INITIALIZED ) throw new ControllerException( "Controller has not been initialized." ); if( m_status > STARTED ) { if( m_status < STOPPED ) throw new ControllerException( "Controller already running." ); if( m_status == STOPPED ) throw new ControllerException( "Controller was stopped." ); if( m_status == DISPOSED ) throw new ControllerException( "Controller was disposed." ); } m_kernel.startup(); m_status = STARTED; } /** * Request the shutdown of the managable unit. */ public void shutdown() { if( m_status == STARTED ) { m_kernel.shutdown(); m_status = STOPPED; } } //======================================================================= // private //======================================================================= private Configuration getProfile( final File file ) throws ControllerException { try { DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); InputStream is = new FileInputStream( file ); if( is == null ) { throw new RuntimeException( "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 ControllerException( error, e ); } } } 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/DefaultController.xinfo Index: DefaultController.xinfo ===================================================================
Resources supporting the creation of a {@link org.apache.excalibur.meta.info.Type} instance from a serialized form.
+External Form (XML)
+
Configuration instances supplied to the builder shall correspond to the component-info DTD. +The structure of a component-info XML document is is described below:
+ ++ +<!-- +Example of a component meta info external XML form. +The element contains the information required to construct an instance of +org.apache.excalibur.containerkit.metainfo.ComponentInfo. It includes +information about the component type, the service it provides, and the +services it is dependent on. +--> + +<component-info> + + + <!-- + Defintion of a single component descriptor. + --> + + <component> + + <!-- the name of the component (character restriction appply) --> + + <name>my-component</name> + + <!-- the implementation version --> + + <version>1.2.1</version> + + <!-- the set of attribibutes associated with the type + (attribute names and values are examples only) --> + + <attributes> + + <attribute key="avalon:display-name-i18n" value="display-name"/> + <attribute key="avalon:lifestyle" value="THREAD_SAFE"/> + + </attributes> + + </component> + + <!-- + The set of logging catagories the component uses. + --> + + <loggers> + + <logger name="store"/> + <logger name="store.cache"/> + <logger name="verifier"/> + + </loggers> + + + <!-- + Declaration of the context constraints for the compoent type. + The "type" attribute is the name of an interface derived from the default + contenxt interface org.apache.avalon.framework.context.Context + --> + + <context type="MyContextInterface"> + + <!-- + Declaration of an entry in a context object, the "key" is + the key used by a component to locate the context entry, + the "type" is the classname of value (typically an interface) + or primative type. The default value is java.lang.String. + The "optional" attribute is a boolean value derived from the + TRUE or FALSE that indicates if the context value must be + provided or not (default is FALSE). + --> + + <entry key="base" type="java.io.File"/> + <entry key="mode" optional="TRUE"/> + + </context> + + <!-- + Declaration of the set of services that this component is capable + of supplying. Each service declarared under the services element + may be referenced by other component info descriptions as a + dependecy. A container is responsible for the assemably of + components based on the connection of supply components to + consumer components via a common service description. + --> + + <services> + + <!-- + The service type is the classname of an interface and the + version identifier qualifes the interface version. The + default version value is 1.0. + --> + + <service> + + <service-ref type="SimpleService" version="3.2"> + + <attributes> + + <!-- + Service type attributes go here. + Need some relevant examples. + --> + + </attributes> + + </service> + + </services> + + + <!-- + Declaration of the set of dependecies that this component type has on + component suppliers. Dependency declarations define the role name + that the component will use to access a service via a service + or component manager. The service element identifies a service + descriptor that is publised by a potential supplier component. + A dependecy may be declared as optional by setting the optional + attribute value to TRUE. The default value for optional is FALSE. + --> + + <dependencies> + + <!-- + A dependecy declaration. In the following example the optional + attribute is redundant as it is equivalent to the default value + but is included here for completness. + --> + + <dependency optional="FALSE"> + + <!-- + The role name that the component will use as the argument to + lookup. The default value is the value of the service type + attribute listed below. + --> + + <role>my-transformer</role> + + <!-- + service reference containing the classname of the service interface + and the version value where version defaults to 1.0 + --> + + <service-ref type="org.apache.cocoon.api.Transformer" version="1.1"/> + + <!-- the set of attributes associated with the dependecy --> + + <attributes> + + <!-- + Service type constraints go here. + Need some relevant examples. + --> + + </attributes> + + </dependency> + + </dependencies> + +</component-info> + ++ -- To unsubscribe, e-mail: