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/07/08 11:57:37 UTC
cvs commit: jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/doc-files LifecycleHelper.gif ResourceProvider.gif lifecycle.gif
mcconnell 2002/07/08 02:57:37
Modified: assembly README.TXT build.xml
assembly/src/etc kernel.xml merlin.html
assembly/src/java/org/apache/excalibur/merlin/kernel
Container.java DefaultContainer.java
DefaultKernel.java Resources.properties
assembly/src/java/org/apache/excalibur/merlin/registry
ProfileRegistry.java Registry.java
TypeRegistry.java
Added: assembly/src/java/org/apache/excalibur/merlin/kernel
ContainerException.java
ContainerRuntimeException.java DefaultProvider.java
DependencyGraph.java
assembly/src/java/org/apache/excalibur/meta/lifecycle
LifecycleException.java LifecycleHelper.java
ResourceProvider.java Resources.properties
package.html
assembly/src/java/org/apache/excalibur/meta/lifecycle/doc-files
LifecycleHelper.gif ResourceProvider.gif
lifecycle.gif
Removed: assembly/src/java/org/apache/excalibur/merlin/kernel
Map.java
Log:
component instantiation and lifecycle processing in place and validated
against inital test suite
Revision Changes Path
1.8 +11 -1 jakarta-avalon-excalibur/assembly/README.TXT
Index: README.TXT
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/README.TXT,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- README.TXT 7 Jul 2002 05:02:21 -0000 1.7
+++ README.TXT 8 Jul 2002 09:57:35 -0000 1.8
@@ -12,6 +12,9 @@
Status
------
+08-JUL-2002.
+Instantion of components based on profile criteria in place and operational.
+
07-JUL-2002.
Added support for the resolution of dependency solutions using the container hierarchy. Forked a sub-set of the containerkit model to provide support for more dynamic style resolution of association at the meta data level. Improved API and class naming. Expanded complexity of the test case (component declarations across multiple containers, cross container dependency resolution, and resolution of conflicting candidate supplier components).
@@ -21,6 +24,8 @@
To-Do
-----
+Addition of pooled support under a service manager variant as part Merlin 1.
+
The kernel should take advantage of Excalibur LogKit extensions (logging configuration etc.). Functional operation of the container as a node in a container hierarchy is still very much work-in-progress.
The component instantiation and lifecycle management is not included at this stage. Before proceeding with actual component instantiation - more playing around is required with the containerkit abstractions.
@@ -29,8 +34,13 @@
Management of defaults using the CascadingConfiguration need to be included. The original Merlin approach was to include the default configuration information inside the .xinfo file. The approach taken here will be to separate default information into a <classname>.xconfig for default information and a <classname>.xprofile containing default deployment descriptors.
-Introduction of component factories will be required as a complement to the <component/> directive.
+Introduction of component factories will be required as a complement to the <component/> directive - e.g <factory/>.
+
+Addition of support for compoents that are not declared in the manifest.
+
+Upgrading of error handling against classic fail scenarios (class not in classpath, manafest errors, informative configuration errors).
+Gentle degrade of service deployment profile on error - if a component cannot be deployed, disable the activation of all of the dependent but continue on with deployment of the rest.
Stephen McConnell
mcconnell@apache.org
1.14 +1 -1 jakarta-avalon-excalibur/assembly/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/build.xml,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- build.xml 8 Jul 2002 01:14:01 -0000 1.13
+++ build.xml 8 Jul 2002 09:57:36 -0000 1.14
@@ -253,7 +253,7 @@
</target>
<target name="patch">
- <replace token="getServiceDesignator" value="getService" dir="src/java">
+ <replace token="AssociationMap" value="DependencyGraph" dir="src/java">
<include name="**/*.*"/>
</replace>
</target>
1.5 +4 -1 jakarta-avalon-excalibur/assembly/src/etc/kernel.xml
Index: kernel.xml
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/etc/kernel.xml,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- kernel.xml 7 Jul 2002 04:27:31 -0000 1.4
+++ kernel.xml 8 Jul 2002 09:57:36 -0000 1.5
@@ -93,8 +93,10 @@
Declaration of an embedded container. A container will be instantiated, initialized
and a validation request will be invoked. In the container is an instance of Container,
the reference to parent container will be supplied.
+ ## pending context inport from container ##
-->
+ <!--
<component name="test" class="org.apache.excalibur.merlin.kernel.DefaultContainer">
<configuration>
<container>
@@ -105,7 +107,8 @@
</classpath>
</container>
</configuration>
- </component>
+ </component>
+ -->
<!--
including the next entry demonstrates the resolution of a dependency via a profile
1.2 +1 -1 jakarta-avalon-excalibur/assembly/src/etc/merlin.html
Index: merlin.html
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/etc/merlin.html,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- merlin.html 7 Jul 2002 23:09:09 -0000 1.1
+++ merlin.html 8 Jul 2002 09:57:36 -0000 1.2
@@ -67,7 +67,7 @@
<h3>Current Status</h3>
<p>
-The implementation provides full support for hierachical containers and profiles management including resolution of dependecies cross containers. The implemetation does not support instantation of componets at this time (expect this soon).
+The implementation provides full support for hierachical containers and profiles management including resolution of dependecies cross containers. Processing of singleton components throught the component lifecycle is in place and will be expanded to included adaptive managers in the near future. For a list of TO-DO items, please refer to the README document.
</p>
</body>
1.7 +1 -12 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Container.java
Index: Container.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Container.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Container.java 7 Jul 2002 23:15:42 -0000 1.6
+++ Container.java 8 Jul 2002 09:57:36 -0000 1.7
@@ -25,17 +25,6 @@
*/
public interface Container extends Manageable, Verifiable
{
-
- /**
- * Return the profile of an installed component matching a dependency.
- * @param type a component exposing the depenency
- * @param dependency a consumer component dependecy declaration
- * @return the supplier profile
- * @exception UnresolvedProviderException if no provider available
- */
- //Profile getProvider( Type type, DependencyDescriptor dependency )
- // throws UnresolvedProviderException;
-
/**
* Return the set of potential profiles of installed component matching a dependency.
* @param dependency a consumer component dependecy declaration
1.9 +50 -27 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultContainer.java
Index: DefaultContainer.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultContainer.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- DefaultContainer.java 7 Jul 2002 23:20:45 -0000 1.8
+++ DefaultContainer.java 8 Jul 2002 09:57:36 -0000 1.9
@@ -68,7 +68,7 @@
import org.apache.log.output.io.StreamTarget;
import org.apache.excalibur.merlin.registry.UnresolvedProviderException;
-import org.apache.excalibur.merlin.kernel.Map;
+import org.apache.excalibur.merlin.kernel.DependencyGraph;
/**
* Default container implementation that manages a registry of componet providers and
@@ -104,7 +104,9 @@
private Logger m_logger;
- private Map m_map;
+ private DependencyGraph m_map;
+
+ private DefaultProvider m_provider;
//=======================================================================
// Contextualizable
@@ -120,15 +122,21 @@
try
{
m_parent = (Container) context.get( CONTAINER_KEY );
- m_map = (Map) context.get( MAP_KEY );
+ m_map = (DependencyGraph) context.get( MAP_KEY );
+ m_provider = (DefaultProvider) context.get( PROVIDER_KEY );
super.contextualize( context );
}
catch( ContextException e )
{
- // root container
+ // this is root container - setup the context for the supertype
+ // (which includes a null container)
+
DefaultContext c = new DefaultContext( context );
- m_map = new Map();
+ m_map = new DependencyGraph();
+ m_provider = new DefaultProvider( m_classloader );
+ m_provider.enableLogging( getLogger().getChildLogger( "provider" ) );
c.put( MAP_KEY, m_map );
+ c.put( PROVIDER_KEY, m_provider );
c.makeReadOnly();
super.contextualize( c );
}
@@ -200,6 +208,7 @@
// before starting up any of the nested containers
//
+ getLogger().debug("startup");
start();
Iterator iterator = m_containers.iterator();
while( iterator.hasNext() )
@@ -226,15 +235,6 @@
}
//=======================================================================
- // DefaultContainer
- //=======================================================================
-
- public Container[] getContainers()
- {
- return (Container[]) m_containers.toArray( new Container[0] );
- }
-
- //=======================================================================
// private
//=======================================================================
@@ -249,18 +249,41 @@
loaderLogger
);
- DefaultContext context = new DefaultContext();
- context.put( CLASSLOADER_KEY, loader );
- context.put( CONTAINER_KEY, this );
- Map map = new Map( m_map );
- m_map.addChild( map );
- context.put( MAP_KEY, map );
-
+ String name = conf.getAttribute("name","untitled");
DefaultContainer container = new DefaultContainer();
- container.enableLogging( logger );
- container.contextualize( context );
- container.configure( conf );
- container.initialize( );
- return container;
+ try
+ {
+ DependencyGraph map = new DependencyGraph( m_map );
+ m_map.addChild( map );
+ DefaultProvider provider = new DefaultProvider( m_provider, m_classloader );
+ provider.enableLogging( getLogger().getChildLogger( "provider" ) );
+ DefaultContext context = new DefaultContext();
+ context.put( CLASSLOADER_KEY, loader );
+ context.put( CONTAINER_KEY, this );
+ context.put( MAP_KEY, map );
+ context.put( PROVIDER_KEY, provider );
+
+ container.enableLogging( logger );
+ container.contextualize( context );
+ container.configure( conf );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unexpected exception while creating subsidiary container '" + name + "'.";
+ throw new ContainerException( error, e );
+ }
+
+ try
+ {
+ container.initialize( );
+ return container;
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unexpected exception while creating subsidiary container '" + name + "'.";
+ throw new ContainerException( error, e );
+ }
}
}
1.8 +1 -5 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.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- DefaultKernel.java 7 Jul 2002 23:18:17 -0000 1.7
+++ DefaultKernel.java 8 Jul 2002 09:57:36 -0000 1.8
@@ -63,7 +63,6 @@
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.meta.data.Profile;
-import org.apache.excalibur.merlin.kernel.Map;
import org.apache.log.Hierarchy;
import org.apache.log.Priority;
import org.apache.log.output.io.StreamTarget;
@@ -89,8 +88,6 @@
private boolean m_verified = false;
- private Map m_map = new Map();
-
//=======================================================================
// Configurable
//=======================================================================
@@ -124,7 +121,6 @@
DefaultContext context = new DefaultContext();
context.put( DefaultContainer.CLASSLOADER_KEY, loader );
- context.put( DefaultContainer.MAP_KEY, m_map );
m_container.enableLogging( getLogger().getChildLogger("container") );
m_container.contextualize( context );
m_container.configure( m_config.getChild("container" ) );
1.5 +9 -0 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Resources.properties
Index: Resources.properties
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Resources.properties,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Resources.properties 7 Jul 2002 04:28:31 -0000 1.4
+++ Resources.properties 8 Jul 2002 09:57:36 -0000 1.5
@@ -18,3 +18,12 @@
required-extensions=The list of required extensions for application includes: {0}
optional-packages-added=The list of "Optional Packages" added to the application include: {0}
classpath-entries=The list of classpath entrys for the application include: {0}
+
+resource.missing-context-value.error=Missing {0,choice,1#Optional|2#Required} Context Entry with key "{1}" for component named "{2}".
+resource.bad-value-type.error=Bad value retrieved for {0,choice,1#Optional|2#Required} Context Entry with key "{1}" for component named "{2}". Expected to be of type "{3}" but was of type "{4}".
+resource.bad-context-type.error=The class of Contex object for component named "{2}" was expected to be of type {0} but was of tpye {1}.
+resource.service-not-a-component.error=The service with role "0" and implemenation class "{1}" does not implement the Component interface but is being exposed via ComponentManager.
+resource.missing-dependency.error=Missing {0,choice,1#Optional|2#Required} dependency with role "{1}" for component named {2}.
+resource.missing-parameters.error=Missing Parameters object for component named "{0}".
+resource.missing-parameters.error=Missing Configuration for component named "{0}".
+
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/ContainerException.java
Index: ContainerException.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.kernel;
import org.apache.avalon.framework.CascadingException;
/**
* Exception to indicate that there was a repository related error.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/08 09:57:36 $
*/
public final class ContainerException
extends CascadingException
{
/**
* Construct a new <code>ContainerException</code> instance.
*
* @param message The detail message for this exception.
*/
public ContainerException( final String message )
{
this( message, null );
}
/**
* Construct a new <code>ContainerException</code> instance.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public ContainerException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/ContainerRuntimeException.java
Index: ContainerRuntimeException.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.kernel;
import org.apache.avalon.framework.CascadingRuntimeException;
/**
* Exception to indicate that there was a repository related runtime error.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/08 09:57:36 $
*/
public final class ContainerRuntimeException
extends CascadingRuntimeException
{
/**
* Construct a new <code>RegistryRuntimeException</code> instance.
*
* @param message The detail message for this exception.
*/
public ContainerRuntimeException( final String message )
{
this( message, null );
}
/**
* Construct a new <code>ContainerRuntimeException</code> instance.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public ContainerRuntimeException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultProvider.java
Index: DefaultProvider.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.kernel;
import java.io.InputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.JarURLConnection;
import java.net.URLClassLoader;
import java.util.Map;
import java.util.List;
import java.util.LinkedList;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;
import java.util.Iterator;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.security.Policy;
import java.io.FileInputStream;
import java.util.HashMap;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.excalibur.configuration.ConfigurationUtil;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.AvalonFormatter;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Executable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.DefaultComponentManager;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.ExceptionUtil;
import org.apache.avalon.excalibur.extension.PackageRepository;
import org.apache.avalon.excalibur.extension.Extension;
import org.apache.avalon.excalibur.extension.OptionalPackage;
import org.apache.avalon.excalibur.extension.DefaultPackageRepository;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.info.DefaultType;
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.meta.data.Profile;
import org.apache.excalibur.meta.data.Association;
import org.apache.excalibur.meta.lifecycle.ResourceProvider;
import org.apache.excalibur.meta.verifier.VerifyException;
import org.apache.excalibur.merlin.registry.Registry;
import org.apache.log.Hierarchy;
import org.apache.log.Priority;
import org.apache.log.output.io.StreamTarget;
/**
* Internal class that handles the establishment of component instances based on a supplied
* type profile.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/08 09:57:36 $
*/
public class DefaultProvider extends AbstractLogEnabled implements ResourceProvider
{
//=======================================================================
// state
//=======================================================================
private final static Resources REZ =
ResourceManager.getPackageResources( DefaultProvider.class );
//=======================================================================
// state
//=======================================================================
/**
* The container that this provider is assigned to.
*/
private final ClassLoader m_classloader;
/**
* The parent provider.
*/
private final DefaultProvider m_parent;
/**
* A hashtable of service implemenentation object references keyed by profile.
*/
private final Hashtable m_singletons = new Hashtable();
//=======================================================================
// constructor
//=======================================================================
DefaultProvider( ClassLoader loader )
{
this( null, loader );
}
DefaultProvider( DefaultProvider parent, ClassLoader loader )
{
m_parent = parent;
m_classloader = loader;
}
//=======================================================================
// ResourceProvider
//=======================================================================
/**
* Create an object specified by profile.
*
* @param profile the profile
* @return the new object
* @throws Exception if unable to resolve resource
*/
public Object createObject( Profile profile )
throws Exception
{
Object object = getSingletonInstance( profile );
if( object == null )
{
Class clazz = null;
String classname = null;
try
{
classname = profile.getType().getInfo().getImplementationKey();
clazz = m_classloader.loadClass( classname );
}
catch( Throwable e )
{
final String error =
"Unexpected exception while attempting to load class '"
+ classname + "' for the profile: " + profile;
throw new ContainerException( error, e );
}
try
{
object = clazz.newInstance();
putSingletonInstance( profile, object );
}
catch( Throwable e )
{
final String error =
"Unexpected exception while attempting to instantiate an instance from profile: " + profile;
throw new ContainerException( error, e );
}
}
return object;
}
/**
* Create a new Logger for component.
*
* @param profile the profile
* @return a new Logger for service
* @throws Exception if unable to create the logger
*/
public Logger createLogger( Profile profile )
throws Exception
{
return getLogger().getChildLogger( profile.getName() );
}
/**
* Create a new Context for component.
*
* @param profile the profile
* @return a new Context for service
* @throws Exception if unable to create context
*/
public Context createContext( Profile profile )
throws Exception
{
return profile.getContext();
}
/**
* Create a new ComponentManager for component.
*
* @param profile the profile
* @return a new ComponentManager for component
* @throws Exception if unable to create the component manager
*/
public ComponentManager createComponentManager( Profile profile )
throws Exception
{
final Map services = getServices( profile );
final DefaultComponentManager componentManager = new DefaultComponentManager();
final Iterator keys = services.keySet().iterator();
while( keys.hasNext() )
{
final String key = (String)keys.next();
final Object service = services.get( key );
if( !Component.class.isInstance( service ) )
{
final String message =
REZ.getString( "resource.service-not-a-component.error",
key,
service.getClass().getName() );
throw new Exception( message );
}
componentManager.put( key, (Component)service );
}
componentManager.makeReadOnly();
return componentManager;
}
/**
* Create a new ServiceManager for component.
*
* @param entry the entry
* @return a new ServiceManager for component
* @throws Exception if unable to create resource
*/
public ServiceManager createServiceManager( Profile profile )
throws Exception
{
final Map services = getServices( profile );
final DefaultServiceManager serviceManager = new DefaultServiceManager();
final Iterator keys = services.keySet().iterator();
while( keys.hasNext() )
{
final String key = (String)keys.next();
final Object service = services.get( key );
serviceManager.put( key, service );
}
serviceManager.makeReadOnly();
return serviceManager;
}
/**
* Create a new Configuration object for component.
*
* @param entry the entry
* @return a new Configuration object for component
* @throws Exception if unable to create resource
*/
public Configuration createConfiguration( Profile profile )
throws Exception
{
Configuration config = profile.getConfiguration();
if( config == null )
config = new DefaultConfiguration("configuration", null );
return config;
}
/**
* Create a new Parameters object for component.
*
* @param entry the entry
* @return a new Parameters object for component
* @throws Exception if unable to create resource
*/
public Parameters createParameters( Profile profile )
throws Exception
{
final Parameters parameters = profile.getParameters();
if( null == parameters )
{
final String message =
REZ.getString( "resource.missing-parameters.error",
profile.getName() );
throw new Exception( message );
}
parameters.makeReadOnly();
return parameters;
}
public Object getSingletonInstance( Profile profile )
{
return m_singletons.get( profile );
}
private void putSingletonInstance( Profile profile, Object object )
{
m_singletons.put( profile, object );
}
/**
* Requests to release all references to a profile and associated
* service instances.
* @param profile the profile to release
*/
public void release( Profile profile )
{
m_singletons.remove( profile );
}
/**
* Prepare a map of the dependent services keyed by role name.
* @param profile the profile referencing a type declaring dependecies
* @return a map of the services
*/
private Map getServices( Profile profile ) throws Exception
{
final Type type = profile.getType();
final DependencyDescriptor[] dependencies = type.getDependencies();
final HashMap services = new HashMap();
for( int i = 0; i < dependencies.length; i++ )
{
DependencyDescriptor dependency = dependencies[i];
final String role = dependency.getRole();
final Association association = profile.getAssociation( role );
final Profile provider = association.getProvider();
final boolean required = type.getDependency( role ).isRequired();
final String classname = type.getDependency( role ).getService().getClassname();
final Object service = getServiceInstance( provider, classname );
if(( null == service ) && ( required ))
{
final String message =
REZ.getString( "resource.missing-dependency.error",
!required ? "1" : "2",
role,
profile.getName() );
throw new Exception( message );
}
services.put( role, service );
}
return services;
}
/**
* Get a service instance from the instance tables using the supplied
* provider as the key, and validate that the returned service instance
* implements the supplied service classname.
* @param provider the key to the provider instance
* @param service the classname of the service requested
*/
private Object getServiceInstance( Profile provider, String service ) throws Exception
{
Object object = lookupInstance( provider );
if( objectImplementsType( object, service ) )
return object;
final String error =
"Unable to locate an instantiated service instance implementing the interface: "
+ service + ", from the provider: " + provider;
throw new ContainerException( error );
}
private Object lookupInstance( Profile provider )
{
Object object = getSingletonInstance( provider );
if( object != null )
return object;
if( m_parent != null )
return m_parent.lookupInstance( provider );
return null;
}
/**
* Check whether the specified value is compatible with specified type.
*
* @param value the value
* @param type the desired type
* @return true if value is compatible with type, false otherwise
*/
private boolean objectImplementsType( final Object value, final String type ) throws Exception
{
if( value == null )
return false;
try
{
final Class clazz = value.getClass();
final ClassLoader classLoader = clazz.getClassLoader();
final Class typeClass = classLoader.loadClass( type );
if( typeClass.isAssignableFrom( clazz ) )
{
return true;
}
}
catch( final ClassNotFoundException cnfe )
{
}
return false;
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DependencyGraph.java
Index: DependencyGraph.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.kernel;
import java.util.ArrayList;
import org.apache.excalibur.meta.data.Profile;
import org.apache.excalibur.meta.data.Association;
import org.apache.excalibur.meta.info.DependencyDescriptor;
/**
* <p>Utility class to help aquire a ordered graph of
* consumers and providers for specific components.</p>
* <p><b>UML</b></p>
* <p><image src="doc-files/Map.gif" border="0"/></p>
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/08 09:57:36 $
*/
public class DependencyGraph
{
/**
* Parent Map. Components in parent
* Map are potential Providers for services
* if no profile in current assembly satisfies dependency.
*/
private final DependencyGraph m_parent;
/**
* The container providing the componenent.
*/
private Container m_container;
/**
* The set of components declared by the container as available.,
* Used when searching for providers/consumers.
*/
private final ArrayList m_components = new ArrayList();
/**
* The child {@link DependencyGraph} objects.
* Possible consumers of services in this assembly.
*/
private final ArrayList m_children = new ArrayList();
public DependencyGraph()
{
this( null );
}
public DependencyGraph( final DependencyGraph parent )
{
m_parent = parent;
}
/**
* Add child dependency graph.
*
* @param child the child map
*/
public void addChild( final DependencyGraph child )
{
m_children.add( child );
}
/**
* Remove child dependency graph.
*
* @param child the child map
*/
public void removeChild( final DependencyGraph child )
{
m_children.remove( child );
}
/**
* Add a profile to current dependency graph.
*
* @param profile the profile
*/
public void add( final Profile profile )
{
if( !m_components.contains( profile ) )
m_components.add( profile );
}
/**
* Get the serilized graph of {@link Profile} objects
* required when starting up all the components. This makes sure
* that all providers occur before their coresponding
* consumers in graph.
*
* @return the ordered list of components
*/
public Profile[] getStartupGraph()
{
return walkGraph( true );
}
/**
* Get the serilized graph of {@link Profile} objects
* required when shutting down all the components. This makes
* sure that all consumers occur before their coresponding
* providers in graph.
*
* @return the ordered list of components
*/
public Profile[] getShutdownGraph()
{
return walkGraph( false );
}
/**
* Get the serilized graph of {@link Profile} objects
* that use services of specified profile.
*
* @param profile the profile
* @return the ordered list of consumers
*/
public Profile[] getConsumerGraph( final Profile profile )
{
return referencedProfiles( profile, getComponentGraph( profile, false ));
}
/**
* Get the serilized graph of {@link Profile} objects
* that provide specified profile with services.
*
* @param profile the profile
* @return the ordered list of providers
*/
public Profile[] getProviderGraph( final Profile profile )
{
return referencedProfiles( profile, getComponentGraph( profile, true ));
}
/**
* Return a profile array that does not include the provided profile.
*/
private Profile[] referencedProfiles( final Profile profile, Profile[] profiles )
{
ArrayList list = new ArrayList();
for( int i=0; i<profiles.length; i++ )
{
if( !profiles[i].equals( profile ) )
list.add( profiles[i] );
}
return (Profile[]) list.toArray( new Profile[0] );
}
/**
* Get the graph of a single profile.
*
* @param profile the profile
* @param providers true if traversing providers, false if consumers
* @return the list of components in graph
*/
private Profile[] getComponentGraph( final Profile profile, final boolean providers )
{
final ArrayList result = new ArrayList();
visitcomponent( profile,
providers,
new ArrayList(),
result );
final Profile[] returnValue = new Profile[ result.size() ];
return (Profile[])result.toArray( returnValue );
}
/**
* Method to generate an ordering of nodes to traverse.
* It is expected that the specified components have passed
* verification tests and are well formed.
*
* @param providers true if forward dependencys traced, false if dependencies reversed
* @return the ordered node names
*/
private Profile[] walkGraph( final boolean providers )
{
final ArrayList result = new ArrayList();
final ArrayList done = new ArrayList();
final int size = m_components.size();
for( int i = 0; i < size; i++ )
{
final Profile profile =
(Profile)m_components.get( i );
visitcomponent( profile,
providers,
done,
result );
}
final Profile[] returnValue = new Profile[ result.size() ];
return (Profile[])result.toArray( returnValue );
}
/**
* Visit a profile when traversing dependencies.
*
* @param profile the profile
* @param providers true if walking tree looking for providers, else false
* @param done those nodes already traversed
* @param order the order in which nodes have already been
* traversed
*/
private void visitcomponent( final Profile profile,
final boolean providers,
final ArrayList done,
final ArrayList order )
{
//If already visited this profile then bug out early
if( done.contains( profile ) )
{
return;
}
done.add( profile );
if( providers )
{
visitProviders( profile, done, order );
}
else
{
visitConsumers( profile, done, order );
}
order.add( profile );
}
/**
* Traverse graph of components that provide services to
* the specified profile.
*
* @param profile the Profile
*/
private void visitProviders( final Profile profile,
final ArrayList done,
final ArrayList order )
{
final DependencyDescriptor[] descriptors =
profile.getType().getDependencies();
for( int i = 0; i < descriptors.length; i++ )
{
final Association assignment =
profile.getAssociation( descriptors[ i ].getRole() );
// added != null clause to catch cases where an optional
// dependency exists and the dependecy has not been bound
// to a provider
if( assignment != null )
{
final Profile provider = assignment.getProvider();
visitcomponent( provider, true, done, order );
}
else
{
if( descriptors[i].isRequired() )
throw new IllegalStateException(
"unresolved dependency for role: " + descriptors[i].getRole()
+ " in profile: " + profile );
}
}
}
/**
* Traverse all Consumers of profile. ie Anyone that uses
* service provided by profile.
*
* @param profile the Profile
*/
private void visitConsumers( final Profile profile,
final ArrayList done,
final ArrayList order )
{
final String name = profile.getName();
final int size = m_components.size();
for( int i = 0; i < size; i++ )
{
final Profile other =
(Profile)m_components.get( i );
final Association[] providers = other.getAssociations();
for( int j = 0; j < providers.length; j++ )
{
if( providers[ j ].getProvider().equals( profile ) )
{
visitcomponent( other, false, done, order );
}
}
}
final int childCount = m_children.size();
for( int i = 0; i < childCount; i++ )
{
final DependencyGraph map = (DependencyGraph)m_children.get( i );
map.visitConsumers( profile, done, order );
}
}
}
1.3 +12 -43 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/ProfileRegistry.java
Index: ProfileRegistry.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/ProfileRegistry.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ProfileRegistry.java 8 Jul 2002 01:14:01 -0000 1.2
+++ ProfileRegistry.java 8 Jul 2002 09:57:36 -0000 1.3
@@ -31,7 +31,7 @@
import org.apache.excalibur.meta.builder.TypeBuilder;
import org.apache.excalibur.meta.builder.ProfileBuilder;
import org.apache.excalibur.configuration.ConfigurationUtil;
-import org.apache.excalibur.merlin.kernel.Map;
+import org.apache.excalibur.merlin.kernel.DependencyGraph;
import org.apache.excalibur.merlin.kernel.Container;
import org.apache.excalibur.merlin.kernel.Selector;
@@ -42,7 +42,7 @@
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision$ $Date$
*/
-final class ProfileRegistry extends AbstractLogEnabled implements Startable
+final class ProfileRegistry extends AbstractLogEnabled
{
//=======================================================================
@@ -76,7 +76,7 @@
*/
private ArrayList m_installed = new ArrayList();
- private Map m_map;
+ private DependencyGraph m_map;
//=======================================================================
// constructor
@@ -89,7 +89,8 @@
* @param profiles the configuration fragment containing explicit component profiles
*/
public ProfileRegistry(
- Configuration[] directives, TypeRegistry registry, ClassLoader loader, Container parent, Map map )
+ Configuration[] directives, TypeRegistry registry, ClassLoader loader,
+ Container parent, DependencyGraph map )
{
m_classloader = loader;
m_types = registry;
@@ -98,34 +99,6 @@
m_map = map;
}
- //======================================================================
- // Startable
- //======================================================================
-
- public void start() throws Exception
- {
- Profile[] startup = m_map.getStartupGraph();
- getLogger().debug("startup");
- for( int i=0; i<startup.length; i++ )
- {
- Profile profile = startup[i];
- if( isLocalProfile( profile ) )
- getLogger().debug("start: " + profile.getName() );
- }
- }
-
- public void stop()
- {
- Profile[] shutdown = m_map.getShutdownGraph();
- for( int i=0; i<shutdown.length; i++ )
- {
- Profile profile = shutdown[i];
- if( isLocalProfile( profile ) )
- getLogger().debug("stop: " + profile.getName() );
- }
- }
-
-
//=======================================================================
// PrifileRegistry
//=======================================================================
@@ -187,17 +160,13 @@
Profile[] facilities = getFacilities( dependency.getService() );
Profile provider = selectProfile( dependency, facilities, candidates );
if( provider == null )
+ throw new UnresolvedProviderException("no available provider", dependency );
+ profile.addProvider( provider, role );
+ if( isLocalProfile( provider ) )
{
- throw new UnresolvedProviderException("no available provider", dependency );
- }
- else
- {
- profile.addProvider( provider, role );
- if( isLocalProfile( provider ) )
- {
- m_map.add( provider );
- m_installed.add( provider );
- }
+ getLogger().info("LOCAL: " + profile );
+ m_map.add( provider );
+ m_installed.add( provider );
}
}
}
1.9 +84 -15 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/Registry.java
Index: Registry.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/Registry.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- Registry.java 8 Jul 2002 02:51:54 -0000 1.8
+++ Registry.java 8 Jul 2002 09:57:36 -0000 1.9
@@ -71,15 +71,19 @@
import org.apache.excalibur.meta.verifier.AssemblyVerifier;
import org.apache.excalibur.meta.verifier.MetaDataVerifier;
import org.apache.excalibur.meta.verifier.VerifyException;
+import org.apache.excalibur.meta.lifecycle.LifecycleHelper;
+import org.apache.excalibur.meta.lifecycle.ResourceProvider;
+import org.apache.excalibur.meta.lifecycle.LifecycleException;
import org.apache.excalibur.configuration.ContextFactory;
import org.apache.log.output.io.StreamTarget;
import org.apache.log.Hierarchy;
import org.apache.log.Priority;
-import org.apache.excalibur.merlin.kernel.Map;
+import org.apache.excalibur.merlin.kernel.DependencyGraph;
import org.apache.excalibur.merlin.kernel.Container;
import org.apache.excalibur.merlin.kernel.ContainerClassLoader;
import org.apache.excalibur.merlin.kernel.Verifiable;
+import org.apache.excalibur.merlin.kernel.DefaultProvider;
/**
* Provides support for the maintenance of a registry of
@@ -112,6 +116,11 @@
*/
public static final String MAP_KEY = "map";
+ /**
+ * Context key used to locate the resource provider.
+ */
+ public static final String PROVIDER_KEY = "provider";
+
private static final Resources REZ =
ResourceManager.getPackageResources( Registry.class );
@@ -142,11 +151,6 @@
private Configuration m_config;
/**
- * Hashtable of all installed profiles keyed by profile name.
- */
- //private Hashtable m_profiles = new Hashtable();
-
- /**
* Internal class that maintains information about profile types.
*/
private ProfileRegistry m_profiles;
@@ -154,7 +158,18 @@
/**
* The depenecy map supplied by the parent container.
*/
- private Map m_map;
+ private DependencyGraph m_map;
+
+ /**
+ * The resource provider to handle resource creation during profile activation.
+ */
+ private DefaultProvider m_provider;
+
+ /**
+ * The lifecycle helper to use to process startup and shudown of services.
+ */
+ private LifecycleHelper m_helper = new LifecycleHelper();
+
//=======================================================================
// Contextualizable
@@ -167,14 +182,15 @@
public void contextualize( Context context ) throws ContextException
{
m_classloader = (ContainerClassLoader) context.get( CLASSLOADER_KEY );
- m_map = (Map) context.get( MAP_KEY );
+ m_map = (DependencyGraph) context.get( MAP_KEY );
+ m_provider = (DefaultProvider) context.get( PROVIDER_KEY );
try
{
m_parent = (Container) context.get( CONTAINER_KEY );
}
- catch( ContextException e )
+ catch( Throwable e )
{
- // root container
+ // this is the root container
}
}
@@ -205,6 +221,7 @@
public void initialize() throws Exception
{
getLogger().debug("registry initialization");
+ m_helper.enableLogging( getLogger().getChildLogger("lifecycle") );
m_types = new TypeRegistry( this, m_classloader );
m_types.enableLogging( getLogger().getChildLogger("types") );
String[] blocks = m_classloader.getComponentClassnames();
@@ -288,15 +305,67 @@
public void start() throws Exception
{
- m_profiles.start();
+ getLogger().debug("start");
+ Profile[] startup = m_map.getStartupGraph();
+ for( int i=0; i<startup.length; i++ )
+ {
+ Profile profile = startup[i];
+ if( m_profiles.isLocalProfile( profile ) )
+ {
+ final String name = profile.getName();
+ getLogger().debug(" > " + name );
+ try
+ {
+ m_helper.startup( name, profile, m_provider );
+ }
+ catch( LifecycleException le )
+ {
+ final String warning =
+ "Could not startup a service derived from profile: " + profile;
+ getLogger().warn( warning, le );
+
+ // need to retract all profiles dependent on this profile
+ }
+ /*
+ */
+ }
+ }
+ getLogger().debug("started");
}
public void stop()
{
- m_profiles.stop();
+ getLogger().debug("stop");
+ Profile[] shutdown = m_map.getShutdownGraph();
+ for( int i=0; i<shutdown.length; i++ )
+ {
+ Profile profile = shutdown[i];
+ if( m_profiles.isLocalProfile( profile ) )
+ {
+ final String name = profile.getName();
+ getLogger().debug( " < " + name );
+ Object object = m_provider.getSingletonInstance( profile );
+ if( object == null )
+ {
+ try
+ {
+ m_helper.shutdown( name, object );
+ m_provider.release( profile );
+ }
+ catch( LifecycleException le )
+ {
+ final String warning =
+ "Could not shutdown a service derived from profile: " + profile;
+ getLogger().warn( warning, le );
+ }
+ }
+ /*
+ */
+ }
+ }
+ getLogger().debug("stopped");
}
-
//=======================================================================
// Verifiable
//=======================================================================
@@ -374,7 +443,7 @@
}
}
- private void listProfile( int n, Profile profile, Map map, List reported )
+ private void listProfile( int n, Profile profile, DependencyGraph map, List reported )
{
if( !reported.contains( profile ) )
{
1.4 +1 -2 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/TypeRegistry.java
Index: TypeRegistry.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/TypeRegistry.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TypeRegistry.java 8 Jul 2002 01:14:01 -0000 1.3
+++ TypeRegistry.java 8 Jul 2002 09:57:36 -0000 1.4
@@ -25,7 +25,6 @@
import org.apache.excalibur.meta.verifier.ComponentVerifier;
import org.apache.excalibur.meta.builder.TypeBuilder;
import org.apache.excalibur.configuration.ConfigurationUtil;
-import org.apache.excalibur.merlin.kernel.Map;
/**
* Internal table that holds available component type keyed relative
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/LifecycleException.java
Index: LifecycleException.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.meta.lifecycle;
import org.apache.avalon.framework.CascadingException;
/**
* Exception to indicate error processing a component through its lifecycle.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/08 09:57:36 $
*/
public final class LifecycleException
extends CascadingException
{
/**
* Construct a new <code>VerifyException</code> instance.
*
* @param message The detail message for this exception.
*/
public LifecycleException( final String message )
{
this( message, null );
}
/**
* Construct a new <code>VerifyException</code> instance.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public LifecycleException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/LifecycleHelper.java
Index: LifecycleHelper.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.meta.lifecycle;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.excalibur.meta.data.Profile;
/**
* This is a class to help an Application manage the lifecycle of a component.
* The implementation provides support for the processing of a component through
* each lifecycle stage, and manage errors in a consistent way.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
*/
public class LifecycleHelper
extends AbstractLogEnabled
{
private static final Resources REZ =
ResourceManager.getPackageResources( LifecycleHelper.class );
//Constants to designate stages
private static final int STAGE_CREATE = 0;
private static final int STAGE_LOGGER = 1;
private static final int STAGE_CONTEXT = 2;
private static final int STAGE_COMPOSE = 3;
private static final int STAGE_CONFIG = 4;
private static final int STAGE_PARAMETER = 5;
private static final int STAGE_INIT = 6;
private static final int STAGE_START = 7;
private static final int STAGE_STOP = 8;
private static final int STAGE_DISPOSE = 9;
private static final int STAGE_DESTROY = 10;
/**
* Method to run a component through it's startup phase.
* Errors that occur during startup will be logged appropriately and
* cause exceptions with useful messages to be raised.
*
* @param name the name of the component
* @param profile representing the instance criteria
* @param provider the resource provider
* @throws LifecycleException if an error occurs when the component passes
* through a specific lifecycle stage
*/
public Object startup( final String name,
final Profile profile,
final ResourceProvider provider )
throws LifecycleException
{
int stage = 0;
try
{
//Creation stage
stage = STAGE_CREATE;
notice( name, stage );
final Object object = provider.createObject( profile );
//LogEnabled stage
stage = STAGE_LOGGER;
if( object instanceof LogEnabled )
{
notice( name, stage );
final Logger logger = provider.createLogger( profile );
ContainerUtil.enableLogging( object, logger );
}
//Contextualize stage
stage = STAGE_CONTEXT;
if( object instanceof Contextualizable )
{
notice( name, stage );
final Context context = provider.createContext( profile );
ContainerUtil.contextualize( object, context );
}
//Composition stage
stage = STAGE_COMPOSE;
if( object instanceof Serviceable )
{
notice( name, stage );
final ServiceManager manager =
provider.createServiceManager( profile);
ContainerUtil.service( object, manager );
}
else if( object instanceof Composable )
{
notice( name, stage );
final ComponentManager componentManager =
provider.createComponentManager( profile );
ContainerUtil.compose( object, componentManager );
}
//Configuring stage
stage = STAGE_CONFIG;
if( object instanceof Configurable )
{
notice( name, stage );
final Configuration configuration =
provider.createConfiguration( profile );
ContainerUtil.configure( object, configuration );
}
//Parameterizing stage
stage = STAGE_PARAMETER;
if( object instanceof Parameterizable )
{
notice( name, stage );
final Parameters parameters =
provider.createParameters( profile );
ContainerUtil.parameterize( object, parameters );
}
//Initialize stage
stage = STAGE_INIT;
if( object instanceof Initializable )
{
notice( name, stage );
ContainerUtil.initialize( profile );
}
//Start stage
stage = STAGE_START;
if( object instanceof Startable )
{
notice( name, stage );
ContainerUtil.start( profile );
}
return object;
}
catch( final Throwable t )
{
fail( name, stage, t );
//fail() throws an exception so next
//line will never be executed
return null;
}
}
/**
* Method to run a component through it's shutdown phase.
* Errors that occur during shutdown will be logged appropraitely.
*
* @param name the name of the component
* @param object the component to shutdown
*/
public void shutdown( final String name,
final Object object )
throws LifecycleException
{
//Stage at which failure occured
int stage = 0;
//Failure exception
Throwable failure = null;
//Stoppable stage
if( object instanceof Startable )
{
notice( name, STAGE_STOP );
try
{
ContainerUtil.stop( object );
}
catch( final Throwable t )
{
safeFail( name, STAGE_STOP, t );
failure = t;
stage = STAGE_STOP;
}
}
//Disposable stage
if( object instanceof Disposable )
{
notice( name, STAGE_DISPOSE );
try
{
ContainerUtil.dispose( object );
}
catch( final Throwable t )
{
safeFail( name, STAGE_DISPOSE, t );
failure = t;
stage = STAGE_DISPOSE;
}
}
notice( name, STAGE_DESTROY );
if( null != failure )
{
fail( name, stage, failure );
}
}
/**
* Utility method to report that a lifecycle stage is about to be processed.
*
* @param name the name of component that is the subject of the notice
* @param stage the lifecycle processing stage
*/
private void notice( final String name, final int stage )
{
if( getLogger().isDebugEnabled() )
{
final String message =
REZ.getString( "lifecycle.stage.notice",
name,
new Integer( stage ) );
getLogger().debug( message );
}
}
/**
* Utility method to report that there was an error processing
* specified lifecycle stage.
*
* @param name the name of component that caused failure
* @param stage the lefecycle stage
* @param t the exception thrown
*/
private void safeFail( final String name,
final int stage,
final Throwable t )
{
//final String reason = t.getMessage();
final String reason = t.toString();
final String message =
REZ.getString( "lifecycle.fail.error",
name,
new Integer( stage ),
reason );
getLogger().error( message );
}
/**
* Utility method to report that there was an error processing
* specified lifecycle stage. It will also re-throw an exception
* with a better error message.
*
* @param name the name of block that caused failure
* @param stage the stage
* @param t the exception thrown
* @throws LifecycleException containing error
*/
private void fail( final String name,
final int stage,
final Throwable t )
throws LifecycleException
{
//final String reason = t.getMessage();
final String reason = t.toString();
final String message =
REZ.getString( "lifecycle.fail.error",
name,
new Integer( stage ), reason );
getLogger().error( message );
throw new LifecycleException( message, t );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/ResourceProvider.java
Index: ResourceProvider.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.meta.lifecycle;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.excalibur.meta.data.Profile;
/**
* The interface via which resources required for a component
* are aquired based on a supplied {@link Profile}.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/08 09:57:36 $
*/
public interface ResourceProvider
{
/**
* Create an object specified by profile.
*
* @param profile the profile
* @return the new object
* @throws Exception if unable to create resource
*/
Object createObject( Profile profile )
throws Exception;
/**
* Create a new Logger for component.
*
* @param profile the profile
* @return a new Logger for component
* @throws Exception if unable to create resource
*/
Logger createLogger( Profile profile )
throws Exception;
/**
* Create a new Context for component.
*
* @param profile the profile
* @return a new Context for component
* @throws Exception if unable to create resource
*/
Context createContext( Profile profile )
throws Exception;
/**
* Create a new ComponentManager for component.
*
* @param profile the profile
* @return a new ComponentManager for component
* @throws Exception if unable to create resource
*/
ComponentManager createComponentManager( Profile profile )
throws Exception;
/**
* Create a new ServiceManager for component.
*
* @param profile the profile
* @return a new ServiceManager for component
* @throws Exception if unable to create resource
*/
ServiceManager createServiceManager( Profile profile )
throws Exception;
/**
* Create a new Configuration object for component.
*
* @param profile the profile
* @return a new Configuration object for component
* @throws Exception if unable to create resource
*/
Configuration createConfiguration( Profile profile )
throws Exception;
/**
* Create a new Parameters object for component.
*
* @param profile the profile
* @return a new Parameters object for component
* @throws Exception if unable to create resource
*/
Parameters createParameters( Profile profile )
throws Exception;
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/Resources.properties
Index: Resources.properties
===================================================================
lifecycle.stage.notice=Component named "{0}" is passing through the {1,choice,0#Creation|1#Logger initialization|2#Contextualization|3#Composing|4#Configuration|5#Parameterizing|6#Initialization|7#Starting|8#Stopping|9#Disposing|10#Destruction} stage.
lifecycle.fail.error=Component named "{0}" failed to pass through the {1,choice,0#Creation|1#Logger initialization|2#Contextualization|3#Composing|4#Configuration|5#Parameterizing|6#Initialization|7#Starting|8#Stopping|9#Disposing|10#Destruction} stage. (Reason: {2}).
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/package.html
Index: package.html
===================================================================
<body>
Helpers classes and interfaces supporting the declaration of a resource provider to a component during lifecycle processing.
<h3>Package Structure (UML)</h3>
<p><img src=doc-files/lifecycle.gif border=0></p>
</body>
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/doc-files/LifecycleHelper.gif
<<Binary file>>
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/doc-files/ResourceProvider.gif
<<Binary file>>
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/meta/lifecycle/doc-files/lifecycle.gif
<<Binary file>>
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>