You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by mc...@apache.org on 2002/08/03 11:29:06 UTC
cvs commit: jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/verifier ComponentVerifier.java
mcconnell 2002/08/03 02:29:06
Modified: assembly/src/java/org/apache/excalibur/merlin
DefaultController.java Main.java
assembly/src/java/org/apache/excalibur/merlin/assembly
ContainerManager.java TypeManager.java
assembly/src/java/org/apache/excalibur/merlin/container
DefaultContainer.java
assembly/src/java/org/apache/excalibur/merlin/kernel
DefaultKernel.java
assembly/src/java/org/apache/excalibur/meta/verifier
ComponentVerifier.java
Log:
Container updated so that it is executed as a thread and establishes the type manager as the local context classloader.
Revision Changes Path
1.11 +4 -14 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/DefaultController.java
Index: DefaultController.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/DefaultController.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- DefaultController.java 2 Aug 2002 06:36:09 -0000 1.10
+++ DefaultController.java 3 Aug 2002 09:29:05 -0000 1.11
@@ -246,20 +246,10 @@
*/
public void dispose()
{
- if( m_status < INITIALIZED )
+ if( m_kernel != null )
{
- return;
- }
- else if( m_status < STOPPED )
- {
- try
- {
- stop();
- }
- catch( Throwable e )
- {
- // ignore
- }
+ m_kernel.dispose();
+
}
m_status = DISPOSED;
}
1.12 +12 -2 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/Main.java
Index: Main.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/Main.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- Main.java 2 Aug 2002 06:36:09 -0000 1.11
+++ Main.java 3 Aug 2002 09:29:05 -0000 1.12
@@ -165,7 +165,17 @@
{
public void run()
{
- controller.stop();
+ try
+ {
+ controller.stop();
+ }
+ catch( Throwable e )
+ {
+ }
+ finally
+ {
+ controller.dispose();
+ }
}
}
);
1.2 +14 -1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ContainerManager.java
Index: ContainerManager.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ContainerManager.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ContainerManager.java 2 Aug 2002 06:31:29 -0000 1.1
+++ ContainerManager.java 3 Aug 2002 09:29:05 -0000 1.2
@@ -451,6 +451,19 @@
}
//===================================================================
+ // Disposable
+ //===================================================================
+
+ public void dispose()
+ {
+ // need to complete this ...
+ // if stop has ben invoked then disops has already been invoked on
+ // all of the component we are managing (see LifecycleHelper) - but
+ // aside from that, we should be going though and cleaning up state
+ // locally
+ }
+
+ //===================================================================
// ContainerManager
//===================================================================
1.4 +12 -2 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/TypeManager.java
Index: TypeManager.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/TypeManager.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TypeManager.java 2 Aug 2002 06:36:09 -0000 1.3
+++ TypeManager.java 3 Aug 2002 09:29:05 -0000 1.4
@@ -30,6 +30,7 @@
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.ContextException;
@@ -61,7 +62,7 @@
* @version $Revision$ $Date$
*/
public abstract class TypeManager extends URLClassLoader
- implements LogEnabled, Contextualizable, Initializable
+ implements LogEnabled, Contextualizable, Initializable, Disposable
{
//===================================================================
// static
@@ -323,6 +324,15 @@
final String error = "Unexpected exception while inspecting manifest on file: ";
throw new TypeRuntimeException( error + url, e );
}
+ }
+
+ //===================================================================
+ // Disposable
+ //===================================================================
+
+ public void dispose()
+ {
+ // need to complete this
}
//===================================================================
1.22 +264 -65 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/DefaultContainer.java
Index: DefaultContainer.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/DefaultContainer.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- DefaultContainer.java 3 Aug 2002 03:50:06 -0000 1.21
+++ DefaultContainer.java 3 Aug 2002 09:29:05 -0000 1.22
@@ -88,7 +88,7 @@
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision$ $Date$
*/
-public class DefaultContainer extends AbstractLogEnabled implements Container, Contextualizable, Configurable, Initializable, Disposable, Startable
+public class DefaultContainer extends AbstractLogEnabled implements Container, Contextualizable, Configurable, Initializable, Disposable, Runnable
{
//=======================================================================
// static
@@ -102,6 +102,16 @@
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultContainer.class );
+ /**
+ * Static enumerations used in m_action and m_last where m_action is the requested
+ * state of the container and m_last is the current state of the container.
+ */
+ private static final int UNKNOWN = 0;
+ private static final int INITIALIZE = 1;
+ private static final int STARTUP = 2;
+ private static final int SHUTDOWN = 3;
+ private static final int DISPOSE = 4;
+
//=======================================================================
// state
//=======================================================================
@@ -126,10 +136,41 @@
*/
private boolean m_initialized = false;
+ /**
+ * Flag showing started status.
+ */
+ private boolean m_started = false;
+
+ /**
+ * Flag showing stopped status.
+ */
+ private boolean m_stopped = false;
+
+
private Configuration m_configuration;
private XMLContainerUtil m_creator = new XMLContainerUtil();
+ /**
+ * The thread periodically checks for state change requests enter in
+ * the m_action state member and attemopts to bring the m_lst value to
+ * be equal to the m_action value and once achieved, goes off for a little
+ * rest.
+ */
+ private Integer m_action = new Integer( UNKNOWN );
+
+ /**
+ * The container is managed as a thread under which the current state
+ * is recorded in the m_last state member.
+ */
+ private Integer m_last = new Integer( UNKNOWN );
+
+ /**
+ * The thread group reference - used during dispose to wait for termaintaion
+ * of subsidiary threads.
+ */
+ private ThreadGroup m_group;
+
//=======================================================================
// Contextualizable
//=======================================================================
@@ -146,12 +187,18 @@
{
m_manager = (ContainerManager) context.get( MANAGER_KEY );
m_descriptor = m_manager.getContainerDescriptor();
+ m_group = new ThreadGroup( m_descriptor.getName() );
}
//=======================================================================
// Configurable
//=======================================================================
+ /**
+ * Provision of a configuration to the container that is used to establish
+ * the EXPLICIT components to be included and defintion of subcontainers.
+ * @param config the container configuration
+ */
public void configure( Configuration config )
{
m_configuration = config;
@@ -171,6 +218,19 @@
*/
public void initialize() throws Exception
{
+ synchronized( m_action )
+ {
+ m_action = new Integer( INITIALIZE );
+ }
+ }
+
+ /**
+ * Implementation of the initialization method. Initialization is handled after
+ * a thread is established so that we can assign the manager as the thread context
+ * classloader.
+ */
+ public void handleInitialize() throws Exception
+ {
getLogger().debug( "initialization" );
Configuration[] components = m_configuration.getChildren("component");
@@ -204,7 +264,7 @@
// creation of the subsidiary containers
//
- getLogger().debug("subsidiary container creation");
+ getLogger().debug("subsidiary container creation" );
final Configuration[] configs = m_configuration.getChildren("container");
for( int i=0; i<configs.length; i++ )
@@ -218,10 +278,59 @@
//
m_initialized = true;
+ m_last = new Integer( INITIALIZE );
}
//=======================================================================
+ // Runnable
+ //=======================================================================
+
+ /**
+ * Invoked by the parent to initiate the thread after which the thread will
+ * monitor action requests arrising from initize, startup, shutdown and dispose
+ * requests.
+ */
+ public void run()
+ {
+ if( m_manager == null )
+ throw new IllegalStateException("Container has not been contextualized.");
+ Thread.currentThread().setContextClassLoader( m_manager );
+
+ try
+ {
+ while( m_action.intValue() < DISPOSE )
+ {
+ synchronized( m_action )
+ {
+ if( m_last.intValue() != m_action.intValue() )
+ {
+ switch( m_action.intValue() )
+ {
+ case INITIALIZE:
+ handleInitialize();
+ break;
+ case STARTUP:
+ handleStartup();
+ break;
+ case SHUTDOWN:
+ handleShutdown();
+ break;
+ }
+ }
+ }
+ sleep();
+ }
+ handleDispose();
+ }
+ catch( Throwable e )
+ {
+ final String error = "Unexpected error during container execution.";
+ throw new ContainerRuntimeException( error, e );
+ }
+ }
+
+ //=======================================================================
// Verifiable
//=======================================================================
@@ -241,53 +350,61 @@
}
}
+
//======================================================================
- // Startable
+ // Controller
//======================================================================
/**
- * Method invoked by the container's container to signal the activation of
- * all components.
- *
- * @exception Exception if a start related error occurs
+ * Request the startup of the container.
*/
- public void start() throws Exception
+ public void startup() throws Exception
{
- if( getLogger().isInfoEnabled() )
+ synchronized( m_action )
{
- Profile[] profiles = m_manager.getStartupGraph( false );
- if( profiles.length > 0 )
- {
- StringBuffer buffer = new StringBuffer();
- for( int i=0; i<profiles.length; i++ )
- {
- Profile profile = profiles[i];
- buffer.append( profiles[i].getName() );
- if( i<(profiles.length-1) )
- buffer.append(", ");
- }
- getLogger().info("startup: " + buffer.toString() );
- }
- else
- {
- getLogger().info( "startup" );
- }
+ m_action = new Integer( STARTUP );
}
- m_manager.start();
}
/**
- * Method invoked by the container's container to signal the deactivation of
- * all components.
+ * Implementation of the container startup procedure.
+ */
+ private void handleStartup() throws Exception
+ {
+ if( !m_initialized )
+ handleInitialize();
+
+ if( getLogger().isDebugEnabled() )
+ getLogger().debug("container startup");
+
+ //
+ // startup all of the components in this container
+ // before starting up any of the nested containers
+ //
+
+ start();
+
+ Iterator iterator = m_containers.iterator();
+ while( iterator.hasNext() )
+ {
+ ((Controller)iterator.next()).startup();
+ }
+
+ getLogger().debug("container startup complete");
+ m_started = true;
+ m_last = new Integer( STARTUP );
+ }
+
+ /**
+ * Activate all local components.
*
- * @exception Exception if a stop related error occurs
+ * @exception Exception if a start related error occurs
*/
- public void stop()
+ private void start() throws Exception
{
if( getLogger().isInfoEnabled() )
{
- Profile[] profiles = m_manager.getShutdownGraph();
-
+ Profile[] profiles = m_manager.getStartupGraph( false );
if( profiles.length > 0 )
{
StringBuffer buffer = new StringBuffer();
@@ -298,50 +415,34 @@
if( i<(profiles.length-1) )
buffer.append(", ");
}
- getLogger().info("shutdown: " + buffer.toString() );
+ getLogger().info("startup: " + buffer.toString() );
}
else
{
- getLogger().info( "shutdown" );
+ getLogger().info( "startup" );
}
}
- m_manager.stop();
+ m_manager.start();
}
- //======================================================================
- // Controller
- //======================================================================
-
/**
- * Request the startup of the managable unit.
+ * Request the shutdown of the container.
*/
- public void startup() throws Exception
+ public void shutdown()
{
-
- if( getLogger().isDebugEnabled() )
- getLogger().debug("container startup");
-
- //
- // startup all of the components in this container
- // before starting up any of the nested containers
- //
-
- start();
-
- Iterator iterator = m_containers.iterator();
- while( iterator.hasNext() )
+ synchronized( m_action )
{
- ((Controller)iterator.next()).startup();
+ m_action = new Integer( SHUTDOWN );
}
-
- getLogger().debug("container startup complete");
}
/**
- * Request the shutdown of the managable unit.
+ * Impleementation of the container shutdown process.
*/
- public void shutdown()
+ public void handleShutdown()
{
+ if( !m_started )
+ return;
if( getLogger().isDebugEnabled() )
getLogger().debug("container shutdown");
@@ -360,8 +461,43 @@
stop();
getLogger().debug("container shutdown complete");
+ m_stopped = true;
+ m_last = new Integer( SHUTDOWN );
}
+ /**
+ * Method invoked by the container's container to signal the deactivation of
+ * all components.
+ *
+ * @exception Exception if a stop related error occurs
+ */
+ private void stop()
+ {
+ if( getLogger().isInfoEnabled() )
+ {
+ Profile[] profiles = m_manager.getShutdownGraph();
+
+ if( profiles.length > 0 )
+ {
+ StringBuffer buffer = new StringBuffer();
+ for( int i=0; i<profiles.length; i++ )
+ {
+ Profile profile = profiles[i];
+ buffer.append( profiles[i].getName() );
+ if( i<(profiles.length-1) )
+ buffer.append(", ");
+ }
+ getLogger().info("shutdown: " + buffer.toString() );
+ }
+ else
+ {
+ getLogger().info( "shutdown" );
+ }
+ }
+ m_manager.stop();
+ }
+
+
//=======================================================================
// Container
//=======================================================================
@@ -417,7 +553,40 @@
*/
public void dispose()
{
+ synchronized( m_action )
+ {
+ m_action = new Integer( DISPOSE );
+ }
+ }
+
+ /**
+ * Handle disposal of the container.
+ */
+ private void handleDispose()
+ {
+ if( m_started )
+ {
+ if( !m_stopped )
+ handleShutdown();
+ }
getLogger().debug("dispose");
+
+ //
+ // dispose of all of the nested containers
+ //
+
+ Iterator iterator = m_containers.iterator();
+ while( iterator.hasNext() )
+ {
+ ((Disposable)iterator.next()).dispose();
+ }
+
+ while( m_group.activeCount() > 0 )
+ sleep();
+
+ m_manager.dispose();
+
+ getLogger().info("done");
}
//=======================================================================
@@ -514,10 +683,9 @@
final String error = "Error establishing subsidiary container manager.";
throw new ContainerException( error, e );
}
-
+
try
{
-
getLogger().info("creating subsidiary container: " + name );
DefaultContext context = new DefaultContext();
context.put( MANAGER_KEY, manager );
@@ -526,11 +694,20 @@
final String classname =
config.getAttribute( "class", DefaultContainer.class.getName() );
DefaultContainer container = createContainerInstance( manager, classname );
-
final Logger logger = getLogger().getChildLogger( name );
container.enableLogging( logger );
container.contextualize( context );
container.configure( config );
+
+ Thread thread = new Thread( m_group, container, name );
+ thread.start();
+
+ //
+ // once the thread is started, the manager assigned to the context
+ // will be assigned as the thread's context classloader and we can
+ // initiate initialization with confidence
+ //
+
container.initialize( );
return container;
}
@@ -541,7 +718,15 @@
}
}
- private DefaultContainer createContainerInstance( ClassLoader loader, String classname ) throws ContainerException
+ /**
+ * Internel utility to create a new instance of a container based on a supplied classname.
+ * The clasname must be a type extending the DefaultContainer class.
+ * @param loader the classloader containing the class to be used as the container
+ * @param classname the name of the container class
+ * @return the new container
+ */
+ private DefaultContainer createContainerInstance( ClassLoader loader, String classname )
+ throws ContainerException
{
try
{
@@ -551,6 +736,20 @@
{
final String error = "Cannot create a container from the classname: " + classname;
throw new ContainerException( error, e );
+ }
+ }
+
+ /**
+ * Internel utility to sleep a bit.
+ */
+ private void sleep()
+ {
+ try
+ {
+ Thread.currentThread().sleep( 100 );
+ }
+ catch( Throwable wakeup )
+ {
}
}
}
1.27 +44 -6 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.java
Index: DefaultKernel.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.java,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- DefaultKernel.java 3 Aug 2002 03:50:06 -0000 1.26
+++ DefaultKernel.java 3 Aug 2002 09:29:06 -0000 1.27
@@ -151,8 +151,6 @@
private boolean m_verified = false;
- private boolean m_initialized = false;
-
/**
* The context entries available from the kernel post startup.
*/
@@ -173,6 +171,16 @@
private XMLContainerUtil m_creator = new XMLContainerUtil();
+ /**
+ * Internal reference to the thread within which the root container will execute.
+ */
+ private Thread m_thread;
+
+ private boolean m_initialized = false;
+ private boolean m_started = false;
+ private boolean m_stopped = false;
+ private boolean m_disposed = false;
+
//=======================================================================
// Contextualizable
//=======================================================================
@@ -227,6 +235,8 @@
m_manager.contextualize( ctx );
m_manager.initialize();
+ Thread.currentThread().setContextClassLoader( m_manager );
+
if( getLogger() == null )
{
enableLogging( m_manager.getLoggingManager().getLoggerForCategory( name ) );
@@ -244,6 +254,7 @@
m_container = createContainer( config );
/*
+ // ### need to resolve some problems here
getLogger().info( "listing exportable resources" );
Resource[] resources = getResources();
Logger export = getLogger().getChildLogger( "export" );
@@ -296,6 +307,10 @@
container.enableLogging( logger );
container.contextualize( context );
container.configure( config );
+
+ m_thread = new Thread( (Runnable) container );
+ m_thread.start();
+
container.initialize( );
return container;
}
@@ -332,6 +347,14 @@
if( m_container != null )
{
m_container.dispose();
+ try
+ {
+ m_thread.join();
+ getLogger().info("done");
+ }
+ catch( InterruptedException ie )
+ {
+ }
}
}
@@ -369,9 +392,8 @@
{
if( !m_initialized ) return;
if( getLogger().isInfoEnabled() )
- getLogger().info("shutdown");
+ getLogger().info("shutdown intiated");
m_container.shutdown();
- getLogger().info("shutdown complete");
}
//=======================================================================
@@ -380,12 +402,28 @@
public void startup() throws Exception
{
+ if( !m_initialized )
+ throw new IllegalStateException("not initialized");
+ if( m_stopped )
+ throw new IllegalStateException("already stopped");
+ if( m_started )
+ throw new IllegalStateException("already started");
+
start();
+ m_started = true;
}
public void shutdown()
- {
+ {
+ if( !m_initialized )
+ throw new IllegalStateException("not initialized");
+ if( m_stopped )
+ throw new IllegalStateException("already stopped");
+ if( !m_started )
+ throw new IllegalStateException("not started");
+
stop();
+ m_stopped = true;
}
//=======================================================================
1.2 +11 -3 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/verifier/ComponentVerifier.java
Index: ComponentVerifier.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/verifier/ComponentVerifier.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ComponentVerifier.java 5 Jul 2002 10:39:00 -0000 1.1
+++ ComponentVerifier.java 3 Aug 2002 09:29:06 -0000 1.2
@@ -166,9 +166,17 @@
final Class clazz )
throws VerifyException
{
- verifyServiceIsaInterface( name, clazz );
verifyServiceIsPublic( name, clazz );
- verifyServiceNotALifecycle( name, clazz );
+
+ //
+ // the following two validation points need more work
+ // (a) it is valid to pass a class as a service because the class may be a proxy
+ // (b) when (a) is a class, it may be implementing lifecycle interfaces which could
+ // could be hidden under another proxy - i.e. this more work needed
+ //
+
+ //verifyServiceIsaInterface( name, clazz );
+ //verifyServiceNotALifecycle( name, clazz );
}
/**
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>