mcconnell 2003/12/02 00:00:40
Modified: kernel/impl/src/java/org/apache/avalon/merlin/impl
DefaultCriteria.java DefaultFactory.java
Added: kernel/impl/src/java/org/apache/avalon/merlin/impl
DefaultKernel.java DefaultKernelMBean.java
Log:
Refactoring of the MerlinKernel to seperate system establishment from runtime
application logic.
Revision Changes Path
1.2 +206 -24
avalon-sandbox/kernel/impl/src/java/org/apache/avalon/merlin/impl/DefaultCriteria.java
Index: DefaultCriteria.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/kernel/impl/src/java/org/apache/avalon/merlin/impl/DefaultCriteria.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DefaultCriteria.java 30 Nov 2003 05:55:30 -0000 1.1
+++ DefaultCriteria.java 2 Dec 2003 08:00:39 -0000 1.2
@@ -58,9 +58,10 @@
import java.util.Hashtable;
import java.util.Properties;
import java.util.ArrayList;
+import java.util.StringTokenizer;
import java.util.Map;
-import org.apache.avalon.merlin.criteria.KernelCriteria;
+import org.apache.avalon.merlin.KernelCriteria;
import org.apache.avalon.merlin.KernelRuntimeException;
import org.apache.avalon.repository.RepositoryException;
@@ -76,6 +77,10 @@
import org.apache.avalon.util.env.EnvAccessException;
import org.apache.avalon.util.exception.ExceptionHelper;
+import org.apache.avalon.repository.criteria.Parameter;
+
+
+
/**
* A Criteria is a class holding the values supplied by a user
* for application to a factory.
@@ -92,26 +97,134 @@
private static final String AVALON = "/avalon.properties";
private static final String MERLIN = "/merlin.properties";
- private static final String [] SINGLE_KEYS = {
- MERLIN_REPOSITORY.getKey(),
- MERLIN_HOME.getKey(),
- MERLIN_SYSTEM.getKey(),
- MERLIN_CONFIG.getKey(),
- MERLIN_KERNEL.getKey(),
- MERLIN_DIR.getKey(),
- MERLIN_CONTEXT.getKey(),
- MERLIN_EXT.getKey(),
- MERLIN_INFO.getKey(),
- MERLIN_DEBUG.getKey(),
- MERLIN_SERVER.getKey() };
+ private static final File USER_DIR = new File( System.getProperty( "user.dir" )
);
+ private static final File TEMP_DIR = new File( System.getProperty(
"java.io.tmpdir" ) );
+ private static final File AVALON_HOME_DIR = new File( USER_DIR, ".avalon" );
+ private static final File MERLIN_HOME_DIR = new File( USER_DIR, ".merlin" );
- private static final String[] MULTI_VALUE_KEYS = new String[0];
+ /**
+ * Shared application repository root directory.
+ */
+ public static final String MERLIN_REPOSITORY =
+ "merlin.repository";
- //--------------------------------------------------------------
- // state
- //--------------------------------------------------------------
+ /**
+ * Repository parameter descriptor.
+ */
+ public static final String MERLIN_HOME =
+ "merlin.home";
- private final Hashtable m_bindings = new Hashtable();
+ /**
+ * Repository parameter descriptor.
+ */
+ public static final String MERLIN_SYSTEM =
+ "merlin.system";
+
+ /**
+ * Repository parameter descriptor.
+ */
+ public static final String MERLIN_CONFIG =
+ "merlin.config";
+
+ /**
+ * Repository parameter descriptor.
+ */
+ public static final String MERLIN_DEPLOYMENT =
+ "merlin.deployment";
+
+ /**
+ * Library path parameter descriptor.
+ */
+ public static final String MERLIN_KERNEL =
+ "merlin.kernel";
+
+ /**
+ * Home directory parameter descriptor.
+ */
+ public static final String MERLIN_DIR =
+ "merlin.dir";
+
+ /**
+ * The temp directory parameter descriptor.
+ */
+ public static final String MERLIN_TEMP =
+ "merlin.temp";
+
+ /**
+ * Base directory parameter descriptor.
+ */
+ public static final String MERLIN_CONTEXT =
+ "merlin.context";
+
+ /**
+ * Anchor directory for extension and classpath
+ * relative references.
+ */
+ public static final String MERLIN_ANCHOR =
+ "merlin.anchor";
+
+ /**
+ * Info policy parameter descriptor.
+ */
+ public static final String MERLIN_INFO =
+ "merlin.info";
+
+ /**
+ * Debug policy parameter descriptor.
+ */
+ public static final String MERLIN_DEBUG =
+ "merlin.debug";
+
+ /**
+ * Server model parameter descriptor.
+ */
+ public static final String MERLIN_SERVER =
+ "merlin.server";
+
+
+ /**
+ * The factory parameters template.
+ */
+ private static final Parameter[] PARAMS =
+ new Parameter[]{
+ new Parameter(
+ MERLIN_REPOSITORY,
+ File.class, AVALON_HOME_DIR ),
+ new Parameter(
+ MERLIN_HOME,
+ File.class, MERLIN_HOME_DIR ),
+ new Parameter(
+ MERLIN_SYSTEM,
+ File.class, new File( MERLIN_HOME_DIR, "system" ) ),
+ new Parameter(
+ MERLIN_CONFIG,
+ File.class, new File( MERLIN_HOME_DIR, "config" ) ),
+ new URLTokenizer(
+ MERLIN_DEPLOYMENT, ",", new URL[0] ),
+ new Parameter(
+ MERLIN_KERNEL, URL.class, null ),
+ new Parameter(
+ MERLIN_DIR, File.class, USER_DIR ),
+ new Parameter(
+ MERLIN_TEMP, File.class, TEMP_DIR ),
+ new Parameter(
+ MERLIN_CONTEXT,
+ File.class, new File( USER_DIR, "home" ) ),
+ new Parameter(
+ MERLIN_ANCHOR, File.class, USER_DIR ),
+ new Parameter(
+ MERLIN_INFO, Boolean.class, new Boolean( false ) ),
+ new Parameter(
+ MERLIN_DEBUG, Boolean.class, new Boolean( false ) ),
+ new Parameter(
+ MERLIN_SERVER, Boolean.class, new Boolean( false ) )
+ };
+
+ private static final String [] SINGLE_KEYS =
+ Parameter.getKeys( PARAMS );
+
+ private static final String[] MULTI_VALUE_KEYS =
+ new String[0];
//--------------------------------------------------------------
// constructor
@@ -166,7 +279,7 @@
final String key = param.getKey();
try
{
- put( key, defaults.getProperty( key ));
+ put( key, defaults.getProperty( key ) );
}
catch( Exception re )
{
@@ -236,6 +349,15 @@
}
/**
+ * Return the sequence of deployment urls
+ * @return the block urls
+ */
+ public URL[] getDeploymentURLs()
+ {
+ return (URL[]) get( MERLIN_DEPLOYMENT );
+ }
+
+ /**
* Return the root directory to the merlin configurations
* @return the merlin configuration directory
*/
@@ -285,13 +407,13 @@
/**
* Return the anchor directory to be used when resolving
- * library declarations in classload specifciations.
+ * library declarations in classload specifications.
*
- * @return the jar extension anchor directory
+ * @return the anchor directory
*/
- public File getExtensionDirectory()
+ public File getAnchorDirectory()
{
- return (File) get( MERLIN_EXT );
+ return (File) get( MERLIN_ANCHOR );
}
/**
@@ -395,5 +517,65 @@
"Failed to load implementation defaults resource: "
+ path, e );
}
+ }
+
+ private static class URLTokenizer extends Parameter
+ {
+ private final Class m_base = URL[].class;
+ private final String m_delimiter;
+
+ /**
+ * Transform a string to a url array.
+ * @param object the value to transform
+ * @return the transformed object
+ */
+ public URLTokenizer(
+ final String key, final String delimiter, URL[] defaults )
+ {
+ super( key, URL[].class, defaults );
+ m_delimiter = delimiter;
+ }
+
+ public Object resolve( Object value )
+ throws ValidationException
+ {
+ if( value == null ) return null;
+ if( value instanceof URL[] )
+ {
+ return value;
+ }
+ else if( value instanceof String )
+ {
+ ArrayList list = new ArrayList();
+ String s = (String) value;
+ StringTokenizer tokenizer =
+ new StringTokenizer( s, m_delimiter );
+ while( tokenizer.hasMoreTokens() )
+ {
+ String v = tokenizer.nextToken();
+ try
+ {
+ list.add( new URL( v ) );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unable to transform the token: ["
+ + v
+ + " due to an unexpected error.";
+ throw new ValidationException( error, e );
+ }
+ }
+ return list.toArray( new URL[0] );
+ }
+ else
+ {
+ final String error =
+ "Don't know how to transform an instance of ["
+ + value.getClass().getName()
+ + " to a URL[].";
+ throw new ValidationException( error );
+ }
+ }
}
}
1.2 +155 -73
avalon-sandbox/kernel/impl/src/java/org/apache/avalon/merlin/impl/DefaultFactory.java
Index: DefaultFactory.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/kernel/impl/src/java/org/apache/avalon/merlin/impl/DefaultFactory.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DefaultFactory.java 30 Nov 2003 05:55:30 -0000 1.1
+++ DefaultFactory.java 2 Dec 2003 08:00:39 -0000 1.2
@@ -28,8 +28,15 @@
import org.apache.avalon.composition.model.ContainmentContext;
import org.apache.avalon.composition.model.ContainmentModel;
import org.apache.avalon.composition.model.ModelFactory;
+import org.apache.avalon.composition.model.SystemContext;
+import org.apache.avalon.composition.model.ClassLoaderContext;
+import org.apache.avalon.composition.model.ClassLoaderModel;
import org.apache.avalon.composition.model.impl.DefaultSystemContext;
import org.apache.avalon.composition.model.impl.DefaultModelFactory;
+import org.apache.avalon.composition.model.impl.DefaultContainmentContext;
+import org.apache.avalon.composition.model.impl.DefaultContainmentModel;
+import org.apache.avalon.composition.model.impl.DefaultClassLoaderModel;
+import org.apache.avalon.composition.model.impl.DefaultClassLoaderContext;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
@@ -41,7 +48,7 @@
import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.avalon.merlin.KernelException;
-import org.apache.avalon.merlin.criteria.KernelCriteria;
+import org.apache.avalon.merlin.KernelCriteria;
import org.apache.avalon.repository.Repository;
import org.apache.avalon.repository.InitialContext;
@@ -51,7 +58,6 @@
import org.apache.avalon.repository.criteria.Factory;
import org.apache.excalibur.configuration.ConfigurationUtil;
-import org.apache.excalibur.mpool.PoolManager;
import org.xml.sax.InputSource;
@@ -69,8 +75,6 @@
private static Resources REZ =
ResourceManager.getPackageResources( DefaultFactory.class );
- private static final String CATEGORY_NAME = "context";
-
private static final XMLDeploymentProfileCreator CREATOR =
new XMLDeploymentProfileCreator();
@@ -83,23 +87,13 @@
private Logger m_logger;
- private Logger m_kernelLogger;
-
private LoggingManager m_logging;
- private Repository m_repository;
-
private InitialContext m_context;
- private PoolManager m_pool;
-
- private ContainmentContext m_root;
+ private Block m_application;
- private ModelFactory m_modelFactory;
-
- private ContainmentModel m_model;
-
- private Block m_block;
+ private Block m_system;
//--------------------------------------------------------------------------
// constructor
@@ -173,14 +167,15 @@
URL kernelURL = (URL) criteria.getKernelURL();
Configuration kernelConfig = getKernelConfiguration( kernelURL );
String listing = ConfigurationUtil.list( kernelConfig );
- System.out.println( listing );
//
// create the logging subsystem
//
- Configuration loggingConfig = kernelConfig.getChild( "logging" );
- LoggingDescriptor loggingDescriptor = createLoggingDescriptor(
loggingConfig );
+ Configuration loggingConfig =
+ kernelConfig.getChild( "logging" );
+ LoggingDescriptor loggingDescriptor =
+ createLoggingDescriptor( loggingConfig );
m_logging =
new DefaultLoggingManager(
@@ -188,103 +183,132 @@
loggingDescriptor,
criteria.isDebugEnabled() );
- m_kernelLogger = m_logging.getLoggerForCategory(
loggingDescriptor.getName() );
- m_logger = m_kernelLogger.getChildLogger( CATEGORY_NAME );
- getLogger().info( "logging system established" );
+ m_logger =
+ m_logging.getLoggerForCategory(
+ loggingDescriptor.getName() );
+ getLogger().debug( "logging system established" );
+
+ if( criteria.isDebugEnabled() )
+ {
+ getLogger().debug( "kernel configuration:\n\n" + listing );
+ }
//
// create the common repository
//
- Configuration repositoryConfig = kernelConfig.getChild( "repository" );
+ Configuration repositoryConfig =
+ kernelConfig.getChild( "repository" );
File cache = criteria.getRepositoryDirectory();
- m_repository = createRepository( m_context, cache, repositoryConfig );
- getLogger().debug( "repository established: " + m_repository );
+ Repository repository =
+ createRepository( m_context, cache, repositoryConfig );
+ getLogger().debug(
+ "repository established: " + repository );
//
- // setup the pool manager
- // TODO: an implementation following more thinking (pools should
- // probably be declared at the component directive level)
+ // create the system context
//
- PoolManager m_pool = null;
+ File anchor = criteria.getAnchorDirectory();
+ SystemContext systemContext =
+ new DefaultSystemContext(
+ m_logging,
+ anchor,
+ criteria.getContextDirectory(),
+ criteria.getTempDirectory(),
+ repository,
+ loggingDescriptor.getName(),
+ criteria.isDebugEnabled() );
//
- // setup the model factory
+ // create the system model and block
//
- try
- {
- m_modelFactory = new DefaultModelFactory(
- new DefaultSystemContext(
- m_logging,
- criteria.getExtensionDirectory(),
- criteria.getContextDirectory(),
- criteria.getTempDirectory(),
- m_repository,
- loggingDescriptor.getName(),
- criteria.isDebugEnabled() ) );
- getLogger().info( "model factory established" );
- }
- catch( Throwable e )
- {
- final String error =
- "Unexpected exception while creating internal model factory.";
- throw new KernelException( error, e );
- }
+ final Logger systemLogger = getLogger();
+
+ ClassLoader impl =
+ Thread.currentThread().getContextClassLoader();
+ ContainmentModel system =
+ new DefaultContainmentModel(
+ createContainmentContext(
+ systemContext, systemLogger, impl,
+ getContainmentProfile(
+ kernelConfig.getChild( "system" ) ) ) );
//
- // create the root containment context
+ // TODO: now that the system context is established we
+ // need to create a block and supply the system block
+ // (perhaps under a service manager) to the new model
+ // model factory to ensure that new system services
+ // established under system scope override the bootstrap
+ // facilities
//
+ DefaultServiceContext services = new DefaultServiceContext();
+ services.put( LoggingManager.KEY, m_logging );
+
try
{
- final ContainmentProfile profile =
- CONTAINER_CREATOR.createContainmentProfile(
- kernelConfig.getChild( "container" ) );
- m_root = m_modelFactory.createContainmentContext( profile );
- Thread.currentThread().setContextClassLoader( m_root.getClassLoader() );
+ m_system = AbstractBlock.createRootBlock( services, system );
+ if( m_system instanceof Composite )
+ {
+ try
+ {
+ getLogger().debug( "system assembly" );
+ ((Composite)m_system).assemble();
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Facilities assembly failure.";
+ throw new KernelException( error, e );
+ }
+ }
}
catch( Throwable e )
{
final String error =
- "Internal error while build default containment context.";
+ "Facilities composition failure.";
throw new KernelException( error, e );
}
- //
- // create the root containment model
- //
-
try
{
- getLogger().debug( "construction phase" );
- m_model = m_modelFactory.createContainmentModel( m_root );
+ getLogger().debug( "system deployment" );
+ m_system.deploy();
+ getLogger().debug( "system ready" );
}
catch( Throwable e )
{
final String error =
- "Internal error while build default containment model.";
+ "System deployment failure.";
throw new KernelException( error, e );
}
//
- // we now have everything established such that we can add urls
- // to the root model
+ // create the application model
+ //
+
+ final Logger applicationLogger = m_logging.getLoggerForCategory("");
+ ClassLoader api = systemContext.getCommonClassLoader();
+ ContainmentModel application =
+ new DefaultContainmentModel(
+ createContainmentContext(
+ systemContext, applicationLogger, api,
+ getContainmentProfile(
+ kernelConfig.getChild( "container" ) ) ) );
try
{
- DefaultServiceContext services = new DefaultServiceContext();
- services.put( PoolManager.ROLE, m_pool );
- services.put( LoggingManager.KEY, m_logging );
- m_block = AbstractBlock.createRootBlock( services, m_model );
- if( m_block instanceof Composite )
+ m_application = AbstractBlock.createRootBlock( services, application );
+ /*
+ if( m_application instanceof Composite )
{
try
{
- getLogger().debug( "assembly phase" );
- ((Composite)m_block).assemble();
+ getLogger().debug( "application assembly" );
+ ((Composite)m_application).assemble();
}
catch( Throwable e )
{
@@ -293,6 +317,7 @@
throw new KernelException( error, e );
}
}
+ */
}
catch( Throwable e )
{
@@ -301,7 +326,64 @@
throw new KernelException( error, e );
}
- return m_block;
+ try
+ {
+ return new DefaultKernel( getLogger(), criteria, m_system,
m_application );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Kernel establishment failure.";
+ throw new KernelException( error, e );
+ }
+ }
+
+ /**
+ * Creation of a new containment context.
+ *
+ * @param profile a containment profile
+ * @return the containment context
+ */
+ private ContainmentContext createContainmentContext(
+ SystemContext context, Logger logger, ClassLoader parent, ContainmentProfile
profile )
+ throws Exception
+ {
+ LoggingManager logging = context.getLoggingManager();
+ logging.addCategories( profile.getCategories() );
+
+ ClassLoaderContext classLoaderContext =
+ new DefaultClassLoaderContext(
+ logger,
+ context.getRepository(),
+ context.getBaseDirectory(),
+ parent,
+ profile.getClassLoaderDirective() );
+
+ ClassLoaderModel classLoaderModel =
+ new DefaultClassLoaderModel( classLoaderContext );
+
+ return new DefaultContainmentContext(
+ logger,
+ context,
+ classLoaderModel,
+ profile );
+ }
+
+
+ private ContainmentProfile getContainmentProfile( Configuration config )
+ throws KernelException
+ {
+ try
+ {
+ return CONTAINER_CREATOR.createContainmentProfile( config );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Internal error while build a containment profile."
+ + ConfigurationUtil.list( config );
+ throw new KernelException( error, e );
+ }
}
private Repository createRepository(
1.1
avalon-sandbox/kernel/impl/src/java/org/apache/avalon/merlin/impl/DefaultKernel.java
Index: DefaultKernel.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.impl;
import java.net.URL;
import javax.management.NotificationBroadcasterSupport;
import javax.management.AttributeChangeNotification;
import org.apache.avalon.merlin.Kernel;
import org.apache.avalon.merlin.KernelCriteria;
import org.apache.avalon.merlin.KernelException;
import org.apache.avalon.merlin.KernelRuntimeException;
import org.apache.avalon.activation.appliance.Appliance;
import org.apache.avalon.activation.appliance.Block;
import org.apache.avalon.activation.appliance.Composite;
import org.apache.avalon.activation.appliance.impl.AbstractBlock;
import org.apache.avalon.activation.appliance.impl.DefaultServiceContext;
import org.apache.avalon.composition.data.TargetDirective;
import org.apache.avalon.composition.logging.LoggingManager;
import org.apache.avalon.composition.model.ContainmentContext;
import org.apache.avalon.composition.model.ContainmentModel;
import org.apache.avalon.composition.model.DeploymentModel;
import org.apache.avalon.composition.util.StringHelper;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.logger.Logger;
/**
* Implementation of the default Merlin Kernel.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development Team</a>
* @version $Revision: 1.1 $ $Date: 2003/12/02 08:00:40 $
*/
public class DefaultKernel extends NotificationBroadcasterSupport
implements Kernel, DefaultKernelMBean
{
//--------------------------------------------------------------
// static
//--------------------------------------------------------------
private static final String INITIALIZING = "initializing";
private static final String INITIALIZED = "initialized";
private static final String STARTING = "starting";
private static final String COMPOSITION = "model composition";
private static final String ASSEMBLY = "model assembly";
private static final String DEPLOYMENT = "block deployment";
private static final String STARTED = "started";
private static final String STOPPING = "stopping";
private static final String DECOMMISSIONING = "decommissioning";
private static final String DISSASSEMBLY = "dissassembly";
private static final String BLOCK_DISPOSAL = "block disposal";
private static final String STOPPED = "stopped";
//--------------------------------------------------------------
// immutable state
//--------------------------------------------------------------
private final Logger m_logger;
private final KernelCriteria m_criteria;
private final Block m_system;
private final Block m_application;
private final DefaultState m_self = new DefaultState();
private final DefaultState m_start = new DefaultState();
//--------------------------------------------------------------
// mutable state
//--------------------------------------------------------------
private String m_stateString = INITIALIZING;
private long m_stateChangeSequenceId = 0;
//--------------------------------------------------------------
// constructor
//--------------------------------------------------------------
/**
* Creation of a new Merlin Kernel.
* @param context the kernel context
* @exception KernelException if a kernel creation error occurs
*/
public DefaultKernel(
final Logger logger,
final KernelCriteria criteria,
final Block system,
final Block application ) throws KernelException
{
if( criteria == null )
throw new NullPointerException( "criteria" );
if( system == null )
throw new NullPointerException( "system" );
if( application == null )
throw new NullPointerException( "application" );
m_criteria = criteria;
m_system = system;
m_application = application;
m_logger = logger;
//
// install any block declared within the kernel context
//
getLogger().debug( "install phase" );
ContainmentModel model = (ContainmentModel) m_application.getModel();
URL[] urls = m_criteria.getDeploymentURLs();
for( int i=0; i<urls.length; i++ )
{
URL url = urls[i];
if( getLogger().isInfoEnabled() )
{
getLogger().info(
"installing: "
+ StringHelper.toString( url ) );
}
try
{
model.addModel( url );
}
catch( Throwable e )
{
final String error =
"Block install failure: " + url;
throw new KernelException( error, e );
}
}
//
// apply any customization to the models using a supplied
// targets directive
//
/*
getLogger().debug( "customization phase" );
TargetDirective[] targets = context.getTargetDirectives();
for( int i=0; i<targets.length; i++ )
{
TargetDirective target = targets[i];
final String path = target.getPath();
Object model = m_model.getModel( path );
if( model != null )
{
if( model instanceof DeploymentModel )
{
DeploymentModel deployment = (DeploymentModel) model;
if( target.getConfiguration() != null )
{
deployment.setConfiguration( target.getConfiguration() );
}
if( target.getCategoriesDirective() != null )
{
deployment.setCategories( target.getCategoriesDirective() );
}
}
else if( model instanceof ContainmentModel )
{
ContainmentModel containment = (ContainmentModel) model;
if( target.getCategoriesDirective() != null )
{
containment.setCategories( target.getCategoriesDirective() );
}
}
}
else
{
final String warning =
"Ignoring target directive as the path does not refer to a known
component: "
+ path;
getLogger().warn( warning );
}
}
*/
setState( INITIALIZED );
getLogger().debug( "kernel established" );
}
//--------------------------------------------------------------
// DefaultKernelMBean
//--------------------------------------------------------------
/**
* Return the state of the kernel.
* @return a string representing the kernel state
*/
public String getKernelState()
{
return m_stateString;
}
/**
* Return an approximation to the total amount of memory currently
* available for future allocated objects, measured in bytes.
* @return the number of bytes of estimated free memory
*/
public long getMemoryFree()
{
return Runtime.getRuntime().freeMemory();
}
/**
* Returns the total amount of memory in the Java virtual machine. The value
* returned by this method may vary over time, depending on the host environment.
*
* @return the total amount of memory currently available for current and future
* objects, measured in bytes.
*/
public long getMemoryTotal()
{
return Runtime.getRuntime().totalMemory();
}
/**
* Return the percentage of free memory available.
* @return the free memory percentage
*/
public int getMemoryVariableRatio()
{
return (int) ((Runtime.getRuntime().freeMemory() * 100) /
Runtime.getRuntime().totalMemory());
}
/**
* Return the number of active threads.
* @return the active thread count
*/
public int getThreadCount()
{
return Thread.activeCount();
}
/**
* Return the root directory to the shared repository.
* @return the avalon home root repository directory
*/
public String getRepositoryDirectory()
{
return m_criteria.getRepositoryDirectory().toString();
}
/**
* Return the root directory to the merlin installation
* @return the merlin home directory
*/
public String getHomePath()
{
return m_criteria.getHomeDirectory().toString();
}
/**
* Return the root directory to the merlin system repository
* @return the merlin system repository directory
*/
public String getSystemPath()
{
return m_criteria.getSystemDirectory().toString();
}
/**
* Return the root directory to the merlin configurations
* @return the merlin configuration directory
*/
public String getConfigPath()
{
return m_criteria.getConfigDirectory().toString();
}
/**
* Return the url to the kernel confiuration
* @return the kernel configuration url
*/
public String getKernelPath()
{
return m_criteria.getKernelURL().toString();
}
/**
* Return the working client directory.
* @return the working directory
*/
public String getWorkingPath()
{
return m_criteria.getWorkingDirectory().toString();
}
/**
* Return the temporary directory.
* @return the temp directory
*/
public String getTempPath()
{
return m_criteria.getTempDirectory().toString();
}
/**
* Return the context directory from which relative
* runtime home directories will be established for
* components referencing urn:avalon:home
*
* @return the working directory
*/
public String getContextPath()
{
return m_criteria.getContextDirectory().toString();
}
/**
* Return the anchor directory to be used when resolving
* library declarations in classload specifications.
*
* @return the anchor directory
*/
public String getAnchorPath()
{
return m_criteria.getAnchorDirectory().toString();
}
/**
* Return info generation policy. If TRUE the parameters
* related to deployment will be listed on startup.
*
* @return the info policy
*/
public boolean isInfoEnabled()
{
return m_criteria.isInfoEnabled();
}
/**
* Return debug policy. If TRUE all logging channels will be
* set to debug level (useful for debugging).
*
* @return the debug policy
*/
public boolean isDebugEnabled()
{
return m_criteria.isDebugEnabled();
}
//--------------------------------------------------------------
// Kernel
//--------------------------------------------------------------
/**
* Return the block matching the supplied path.
* @param model a containment model
* @return the containment block
*/
public Appliance locate( String path ) throws KernelException
{
if( !m_self.isEnabled() ) throw new IllegalStateException( "kernel" );
try
{
return m_application.locate( path );
}
catch( Throwable e )
{
final String error =
"Unable to resolve appliance relative to the path: ["
+ path + "].";
throw new KernelException( error, e );
}
}
/**
* Return the root application block.
* @return the application containment block
*/
public Block getBlock()
{
return m_application;
}
//--------------------------------------------------------------
// DefaultKernel
//--------------------------------------------------------------
/**
* Initiate the establishment of the root container.
* @exception Exception if a startup error occurs
*/
public void startup() throws Exception
{
synchronized( m_self )
{
if( m_self.isEnabled() ) return;
//
// we have a model established and we now need to go though the process
// of appliance establishment
//
if( m_application instanceof Composite )
{
setState( ASSEMBLY );
try
{
getLogger().debug( "assembly phase" );
((Composite)m_application).assemble();
}
catch( Throwable e )
{
setState( INITIALIZED );
final String error =
"Application assembly failure.";
throw new KernelException( error, e );
}
}
Throwable cause = null;
setState( DEPLOYMENT );
try
{
getLogger().debug( "application deployment" );
m_application.deploy();
m_self.setEnabled( true );
}
catch( Throwable e )
{
setState( INITIALIZED );
cause = e;
final String error =
"Application deployment failure.";
throw new KernelException( error, e );
}
finally
{
if( cause != null )
{
shutdown();
}
else if( !m_criteria.isServerEnabled() )
{
setState( STARTED );
// TODO: add pause parameter
shutdown();
}
else
{
setState( STARTED );
}
}
}
}
/**
* Shutdown the kernel during which orderly shutdown of all
* installed blocks is undertaken.
*/
public void shutdown()
{
synchronized( m_self )
{
if( !m_self.isEnabled() ) return;
setState( STOPPING );
if( m_application != null )
{
try
{
setState( DECOMMISSIONING );
m_application.decommission();
}
catch( Throwable e )
{
if( getLogger().isWarnEnabled() )
{
final String error =
"Ignoring block decommissioning error.";
getLogger().warn( error, e );
}
}
try
{
if( m_application instanceof Composite )
{
setState( DISSASSEMBLY );
getLogger().info( "dissassembly phase" );
((Composite)m_application).disassemble();
}
}
catch( Throwable e )
{
if( getLogger().isWarnEnabled() )
{
final String error =
"Ignoring block dissassembly error.";
getLogger().warn( error, e );
}
}
}
if( getLogger().isDebugEnabled() )
{
int n = Thread.activeCount();
getLogger().debug( "active threads (" + n + ")" );
}
setState( STOPPED );
m_self.setEnabled( false );
}
}
/*
setState( BLOCK_DISPOSAL );
try
{
if( m_block instanceof Disposable )
{
getLogger().info( "disposal phase" );
((Disposable)m_block).dispose();
}
}
catch( Throwable e )
{
if( getLogger().isWarnEnabled() )
{
final String error =
"Ignoring block disposal error.";
getLogger().warn( error, e );
}
}
*/
//--------------------------------------------------------------
// internal
//--------------------------------------------------------------
/**
* Set the state of the kernel. The method also triggers the
* emmission of a attribute change notification containing the
* old and new state value.
*
* @param state a string representing the new kernel state
*/
private void setState( String state )
{
if( m_stateString.equals( state ) ) return;
getLogger().debug( "state: " + state );
String old = m_stateString;
m_stateString = state;
long id = m_stateChangeSequenceId++;
AttributeChangeNotification notification =
new AttributeChangeNotification(
this, id, System.currentTimeMillis(),
"State change", "state", "string", old, state );
sendNotification( notification );
}
private class DefaultState
{
private boolean m_enabled = false;
/**
* Return the enabled state of the state.
* @return TRUE if the state has been enabled else FALSE
*/
public boolean isEnabled()
{
return m_enabled;
}
/**
* Set the enabled state of the state.
* @param enabled the enabled state to assign
*/
public void setEnabled( boolean enabled )
{
m_enabled = enabled;
}
}
private Logger getLogger()
{
return m_logger;
}
}
1.1
avalon-sandbox/kernel/impl/src/java/org/apache/avalon/merlin/impl/DefaultKernelMBean.java
Index: DefaultKernelMBean.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.impl;
import org.apache.avalon.merlin.KernelController;
/**
* Management interface for the Merlin Kernel.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development Team</a>
* @version $Revision: 1.1 $ $Date: 2003/12/02 08:00:40 $
*/
public interface DefaultKernelMBean extends KernelController
{
/**
* Return an approximation to the total amount of memory currently
* available for future allocated objects, measured in bytes.
* @return the number of bytes of estimated free memory
*/
long getMemoryFree();
/**
* Returns the total amount of memory in the Java virtual machine. The value
* returned by this method may vary over time, depending on the host environment.
*
* @return the total amount of memory currently available for current and
* future objects, measured in bytes.
*/
long getMemoryTotal();
/**
* Return the percentage of free memory available.
* @return the free memory percentage
*/
int getMemoryVariableRatio();
/**
* Return the number of active threads.
* @return the active thread count
*/
int getThreadCount();
/**
* Return the state of the kernel.
* @return a string representing the kernel state
*/
String getKernelState();
/**
* Return the root directory to the shared repository.
* @return the avalon home root repository directory
*/
String getRepositoryDirectory();
/**
* Return the root directory to the merlin installation
* @return the merlin home directory
*/
String getHomePath();
/**
* Return the root directory to the merlin system repository
* @return the merlin system repository directory
*/
String getSystemPath();
/**
* Return the root directory to the merlin configurations
* @return the merlin configuration directory
*/
String getConfigPath();
/**
* Return the url to the kernel confiuration
* @return the kernel configuration url
*/
String getKernelPath();
/**
* Return the working client directory.
* @return the working directory
*/
String getWorkingPath();
/**
* Return the temporary directory.
* @return the temp directory
*/
String getTempPath();
/**
* Return the context directory from which relative
* runtime home directories will be established for
* components referencing urn:avalon:home
*
* @return the working directory
*/
String getContextPath();
/**
* Return the anchor directory to be used when resolving
* library declarations in classload specifications.
*
* @return the anchor directory
*/
String getAnchorPath();
/**
* Return info generation policy. If TRUE the parameters
* related to deployment will be listed on startup.
*
* @return the info policy
*/
boolean isInfoEnabled();
/**
* Return debug policy. If TRUE all logging channels will be
* set to debug level (useful for debugging).
*
* @return the debug policy
*/
boolean isDebugEnabled();
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]