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/02 08:31:30 UTC
cvs commit: jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly ContainerManager.java ProfileManager.java
mcconnell 2002/08/01 23:31:30
Added: assembly/src/java/org/apache/excalibur/merlin/assembly
ContainerManager.java
Removed: assembly/src/java/org/apache/excalibur/merlin/assembly
ProfileManager.java
Log:
replacement of ProfileManager with ContainerManager
Revision Changes Path
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ContainerManager.java
Index: ContainerManager.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.assembly;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Hashtable;
import java.util.ArrayList;
import java.util.Vector;
import java.util.Iterator;
import org.apache.avalon.framework.CascadingException;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.excalibur.configuration.ConfigurationUtil;
import org.apache.excalibur.merlin.assembly.resource.LifecycleHelper;
import org.apache.excalibur.merlin.assembly.resource.ResourceProvider;
import org.apache.excalibur.merlin.assembly.resource.ProfileDesignator;
import org.apache.excalibur.merlin.model.ContainerDescriptor;
import org.apache.excalibur.merlin.model.ClasspathDescriptor;
import org.apache.excalibur.merlin.container.Container;
import org.apache.excalibur.merlin.container.DefaultContainer;
import org.apache.excalibur.merlin.model.LoggingDescriptor;
import org.apache.excalibur.merlin.model.builder.XMLContainerUtil;
import org.apache.excalibur.merlin.model.Category;
import org.apache.excalibur.merlin.model.CategoriesDescriptor;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Resource;
import org.apache.excalibur.merlin.model.builder.ProfileBuilder;
import org.apache.excalibur.meta.info.PhaseDescriptor;
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.ReferenceDescriptor;
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.ExtensionDescriptor;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.info.Facility;
import org.apache.excalibur.meta.info.builder.TypeBuilder;
import org.apache.excalibur.meta.verifier.ComponentVerifier;
/**
* Classloader for an assembly of components.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/08/02 06:31:29 $
*/
public class ContainerManager extends TypeManager implements Startable
{
//===================================================================
// static
//===================================================================
private static final Resources REZ =
ResourceManager.getPackageResources( ContainerManager.class );
public static final String DELIMITER = "/";
/**
* Context key used by the kernel to access the kernel meta-data descriptor.
*/
public static final String LOGGING_DESCRIPTOR_KEY = "logging";
/**
* Context key used by the kernel to access the kernel meta-data descriptor.
*/
public static final String CATEGORIES_DESCRIPTOR_KEY = "categories";
//===================================================================
// state
//===================================================================
/**
* The default selector.
*/
private LifecycleHelper m_helper = new LifecycleHelper();
/**
* The default selector.
*/
private DefaultSelector m_selector = new DefaultSelector();
/**
* Profiles keyed by name.
*/
private Hashtable m_profiles = new Hashtable();
/**
* List of ServiceTable instances.
*/
private List m_services = new LinkedList();
/**
* Utility class used to create type meta info for components not explicity declared
* in the meta data model.
*/
private ProfileBuilder m_builder = new ProfileBuilder();
/**
* Utility class that manages supply of context, config, services, etc. during
* startup of a profile.
*/
private ResourceProvider m_provider;
/**
* The manager name from which the manager path is resolved.
*/
private String m_name;
/**
* The manager's path.
*/
private String m_path;
/**
* The parent manager.
*/
private ContainerManager m_parent;
/**
* Mapping of established resource designators keyed by profile.
*/
private Hashtable m_resources = new Hashtable();
/**
* The dependency map.
*/
private DependencyGraph m_map;
/**
* Utility class to handle assembly.
*/
private ProfileRegistry m_registry;
/**
* Internal reference to the supplied context object.
*/
private Context m_context;
private DefaultLoggerManager m_logging;
private Logger m_logger;
private ContainerDescriptor m_descriptor;
/**
* The component described within the scope of the container.
*/
private final ArrayList m_managers = new ArrayList();
private final ArrayList m_containers = new ArrayList();
private LoggingDescriptor m_loggingDescriptor;
private CategoriesDescriptor m_categories;
private final boolean m_root;
//===================================================================
// constructor
//===================================================================
/**
* Creation of a new Profile Manager.
* @param parent the parent classloader
* @param name the name to assign to this classloader (used with logging)
* @param root if TRUE, logging catagories are top level, otherwise logging
* catagories are subsidary to the parent
*/
public ContainerManager( )
{
this( "root" );
}
/**
* Creation of a new <code>ContainerManager</code>.
* @param name the name to assign to this classloader (used with logging)
*/
public ContainerManager( String name )
{
this( Thread.currentThread().getContextClassLoader(), name );
}
/**
* Creation of a new <code>KernelManager</code>.
* @param classloader the parent classloader
* @param name the name to assign to this classloader (used with logging)
*/
public ContainerManager( ClassLoader classloader, String name )
{
this( classloader, new ContainerDescriptor( name ) , true );
}
/**
* Creation of a new Profile Manager.
* @param parent the parent classloader
* @param name the name to assign to this classloader (used with logging)
* @param root if TRUE, logging catagories are top level, otherwise logging
* catagories are subsidary to the parent
*/
public ContainerManager( ClassLoader parent, ContainerDescriptor descriptor, boolean root )
{
super( parent );
m_root = root;
m_descriptor = descriptor;
m_name = descriptor.getName();
if( parent instanceof ContainerManager )
{
m_parent = (ContainerManager) parent;
m_map = new DependencyGraph( m_parent.getDependencyMap() );
}
else
{
m_map = new DependencyGraph();
}
if( !root )
{
m_path = m_parent.getPath() + DELIMITER + m_name;
}
else
{
m_path = DELIMITER + m_name;
}
}
//=======================================================================
// Contextualizable
//=======================================================================
/**
* Declaration of the logging manager.
* @param context the context object containing the inital parameters
*/
public void contextualize( Context context ) throws ContextException
{
m_context = context;
try
{
m_loggingDescriptor = (LoggingDescriptor) context.get( LOGGING_DESCRIPTOR_KEY );
}
catch( ContextException f )
{
// optional
}
try
{
m_categories = (CategoriesDescriptor) context.get( CATEGORIES_DESCRIPTOR_KEY );
}
catch( ContextException e )
{
// optional
}
super.contextualize( context );
}
//=======================================================================
// Initializable
//=======================================================================
public void initialize() throws Exception
{
XMLContainerUtil creator = new XMLContainerUtil();
//
// setup the logging if we are root
//
try
{
getLoggingManager();
}
catch( Throwable e )
{
if( m_loggingDescriptor == null )
m_loggingDescriptor = new LoggingDescriptor();
try
{
m_logging = new DefaultLoggerManager( m_loggingDescriptor );
}
catch( Throwable g )
{
throw new ContextException(
"logging establishment failure", g );
}
}
//
// take care of logging category declarations from the configuration
// if not already supplied under the context
//
if( m_categories == null )
{
Category loader = new Category( "loader", "WARN", null );
Category assembly = new Category( "loader.assembly" );
Category types = new Category( "loader.types" );
m_categories = new CategoriesDescriptor(
m_name, "INFO", null, new Category[]{ loader, assembly, types } );
}
String path = getPath().replace('/','.').substring(1);
getLoggingManager().addCategories( path, m_categories );
if( getLogger() == null )
{
enableLogging( getLoggingManager().getLoggerForCategory( path ) );
getLocalLogger().info("logging established: " + getPath() );
}
//
// start internal initialization
//
super.initialize();
getLocalLogger().debug("manager initialization");
m_selector.enableLogging( getLocalLogger().getChildLogger("selector") );
m_helper.enableLogging( getLocalLogger().getChildLogger("lifecycle") );
//
// setup the resource provider
//
m_provider = new ResourceProvider( this, m_context, getLoggingManager() );
m_provider.enableLogging( getLocalLogger().getChildLogger("provider") );
//
// setup the assembly sub-system
//
m_registry = new ProfileRegistry( this, m_map );
m_registry.enableLogging( getLocalLogger().getChildLogger( "assembly") );
//
// build the packaged and implicit profiles
//
getLocalLogger().debug("packaged and implicit profile registration");
Type[] types = getTypes();
getLocalLogger().debug("type count: " + types.length );
for( int i=0; i<types.length; i++ )
{
Profile[] profiles = m_builder.build( this, types[i] );
for( int j=0; j<profiles.length; j++ )
{
addProfile( profiles[j] );
}
}
}
//======================================================================
// Startable
//======================================================================
/**
* Method invoked by the container's container to signal the activation of
* all components.
*
* @exception Exception if a start related error occurs
*/
public void start() throws Exception
{
Profile[] profiles = m_map.getStartupGraph();
if( profiles.length == 0 )
{
getLocalLogger().debug("nothing to start");
return;
}
for( int i=0; i<profiles.length; i++ )
{
Profile profile = profiles[i];
if( profile.getActivationPolicy() )
{
Resource resource = getResource( profile );
if( resource.getState() == Resource.NOT_STARTED )
{
getLocalLogger().info( profile + " [activating]");
resource.access();
}
else
{
getLocalLogger().info( profile + " [already running]");
}
}
else
{
getLocalLogger().info( profile + " [deferred]");
}
}
}
public void stop()
{
Profile[] profiles = m_map.getShutdownGraph();
if( profiles.length == 0 )
return;
for( int i=0; i<profiles.length; i++ )
{
Profile profile = profiles[i];
if( isLocal( profile ) )
{
try
{
Resource resource = getResource( profile );
if( resource.getState() == Resource.STARTED )
{
getLocalLogger().info( "stopping: " + profile );
resource.destroy();
}
}
catch ( Throwable e )
{
final String warning =
"Could not shutdown a service derived from profile: '"
+ profile.getName() + "'.";
getLocalLogger().warn( warning, e );
}
}
}
}
//===================================================================
// ContainerManager
//===================================================================
public ContainerManager createContainerManager( ContainerDescriptor descriptor, boolean root )
{
try
{
ContainerManager loader = new ContainerManager( this, descriptor, root );
DefaultContext context = new DefaultContext( m_context );
context.put( ContainerManager.CATEGORIES_DESCRIPTOR_KEY, descriptor.getCategories() );
context.put( TypeManager.CLASSPATH_DESCRIPTOR_KEY, descriptor.getClasspath() );
context.makeReadOnly();
if( root )
{
Logger logger = getLoggingManager().getLoggerForCategory( descriptor.getName() );
loader.enableLogging( logger );
}
else
{
loader.enableLogging( getLogger().getChildLogger( descriptor.getName() ) );
}
loader.contextualize( context );
loader.initialize();
m_managers.add( loader );
return loader;
}
catch( Throwable e )
{
final String error = "error creating manager for container descriptor: "
+ descriptor.getName()
+ " in manager: " + getPath();
throw new TypeRuntimeException( error, e );
}
}
/**
* Return the container descriptor that this manager is managing.
*/
public ContainerDescriptor getContainerDescriptor()
{
return m_descriptor;
}
/**
* Returns the path name of this manager.
* @return the manager's path
*/
public String getPath()
{
return m_path;
}
public DefaultLoggerManager getLoggingManager()
{
if( m_logging != null )
{
return m_logging;
}
else
{
ContainerManager parent = getParentManager();
if( parent != null )
{
return parent.getLoggingManager();
}
else
{
throw new NullPointerException("logging");
}
}
}
/**
* Add a type profile to the manager.
*
* @param profile the profile to add to the manager.
*/
public void addProfile( Profile profile )
{
final String name = profile.getName();
final String classname = profile.getType().getInfo().getImplementationKey();
getLocalLogger().debug("adding: " + profile );
if( m_profiles.get( name ) != null )
throw new IllegalArgumentException(
"Profile named '" + name + "' already registered.");
m_profiles.put( profile.getName(), profile );
ServiceDescriptor[] services = profile.getType().getServices();
for( int i=0; i<services.length; i++ )
{
//
// register the profile against the service it provides
// so we can lookup the profile later based on the supplied
// service descriptor
//
addProfile( services[i].getService(), profile );
}
if( profile.getType() instanceof Facility )
{
//
// the profile is a facility so we need to
// cross reference it against the extension support it
// provides
//
Facility facility = (Facility) profile.getType();
addProfile( facility.getExtensions(), profile );
}
getLocalLogger().debug("added: " + profile );
}
public boolean isLocal( Profile profile )
{
return m_profiles.containsKey( profile.getName() );
}
/**
* Return the set of profiles matching a version interface.
* @param reference a consumer component dependency declaration
* @return the set of available potential supplier profiles
*/
public Profile[] getProfiles( ReferenceDescriptor reference )
{
Profile[] local = getLocalProfiles( reference );
ContainerManager parent = getParentManager();
if( parent != null )
{
ArrayList list = new ArrayList();
for( int i=0; i<local.length; i++ )
{
list.add( local[i] );
}
Profile[] profiles = parent.getProfiles( reference );
for( int i=0; i<profiles.length; i++ )
{
list.add( profiles[i] );
}
return (Profile[]) list.toArray( new Profile[0] );
}
return local;
}
public Profile[] getProfiles( PhaseDescriptor phase )
{
Profile[] local = getLocalProfiles( phase );
ContainerManager parent = getParentManager();
if( parent != null )
{
ArrayList list = new ArrayList();
for( int i=0; i<local.length; i++ )
{
list.add( local[i] );
}
Profile[] profiles = parent.getProfiles( phase );
for( int i=0; i<profiles .length; i++ )
{
list.add( profiles[i] );
}
return (Profile[]) list.toArray( new Profile[0] );
}
return local;
}
/**
* Return a single profile matching a supplied phase spec.
*
* @param phase the phase specification
* @return the selected profile
*/
public Profile getProfile( PhaseDescriptor phase )
{
Profile[] profiles = getProfiles( phase );
return getSelector( phase ).select( profiles );
}
/**
* Return a single profile matching a supplied versioned interface spec
* using a supplied selector.
*
* @param reference a consumer component dependency declaration
* @return the selected profile
*/
public Profile getProfile( DependencyDescriptor dependency )
{
Selector selector = getSelector( dependency );
return getProfile( dependency.getService(), selector );
}
/**
* Return a single profile matching a supplied versioned interface spec
* using a supplied selector.
*
* @param reference a consumer component dependency declaration
* @return the selected profile
*/
public Profile getProfile( ReferenceDescriptor reference, Selector selector )
{
Profile[] profiles = getProfiles( reference );
return selector.select( profiles );
}
public Resource getResource( Profile profile ) throws TypeException
{
return getResource( profile, false );
}
public Resource getResource( Profile profile, boolean create ) throws TypeException
{
if( isLocal( profile ) )
{
Resource resource = getLocalResource( profile );
if(( resource == null ) && create )
{
final String name = getPath() + DELIMITER + profile.getName();
ProfileDesignator designator = new ProfileDesignator( name, profile, m_helper, m_provider );
designator.enableLogging( getLocalLogger().getChildLogger( "resource" ) );
m_resources.put( profile, designator );
resource = designator;
}
return resource;
}
else
{
ContainerManager parent = getParentManager();
if( parent != null )
{
return parent.getResource( profile, create );
}
else
{
final String error = "Unknown profile: " + profile;
throw new TypeException( error );
}
}
}
/**
* Assemble a set of profiles into a consistent application. This method
* attempts to establish associations between all dependencies in order to
* resolve an operational application context.
*
* @param profiles the set of profiles constituting the core components
* from which the associations between components will be based
*/
public void assemble( Profile[] profiles ) throws Exception
{
m_registry.assemble( profiles );
}
/**
* Returns an order sequence of profiles under the management of this instance.
* @param activate if TRUE, only return profiles with activation on startup
* otherwise, return all local profiles
* @return the resource sequence
*/
public Profile[] getStartupGraph( boolean activate )
{
Profile[] startup = m_map.getStartupGraph();
ArrayList list = new ArrayList();
for( int i=0; i<startup.length; i++ )
{
Profile profile = startup[i];
if( isLocal( profile ) )
{
if( activate )
{
if( profile.getActivationPolicy() )
{
list.add( profile );
}
}
else
{
list.add( profile );
}
}
}
return (Profile[]) list.toArray( new Profile[ list.size() ] );
}
/**
* Returns an order sequence of resource designators for shutdown.
*
* @return the resource sequence
*/
public Profile[] getShutdownGraph()
{
Profile[] shutdown = m_map.getShutdownGraph();
ArrayList list = new ArrayList();
for( int i=0; i<shutdown.length; i++ )
{
Profile profile = shutdown[i];
if( isLocal( profile ) )
{
list.add( profile );
}
}
return (Profile[]) list.toArray( new Profile[ list.size() ] );
}
/**
* Returns a child dependency graph.
* @return a new dependency graph
*/
protected DependencyGraph getDependencyMap()
{
return new DependencyGraph( m_map );
}
/**
* Returns the set of exportable resources.
*
* @return the resource sequence
*/
public Resource[] getExport()
{
ArrayList list = new ArrayList();
Profile[] startup = m_map.getStartupGraph();
for( int i=0; i<startup.length; i++ )
{
Profile profile = startup[i];
try
{
list.add( getResource( profile ) );
}
catch( Throwable e )
{
final String warning = "Missing resource for profile: " + profile;
getLocalLogger().warn( warning );
}
}
return (Resource[]) list.toArray( new Resource[ list.size() ] );
}
//=============================================================================
// private
//=============================================================================
private Resource getLocalResource( Profile profile )
{
return (Resource) m_resources.get( profile );
}
/**
* Returns the set of profiles capable of supporting the supplied service.
* @return the set of candidate component types
*/
private Profile[] getLocalProfiles( ReferenceDescriptor service )
{
return getTable( service ).getProfiles();
}
/**
* Returns the set of profiles capable of supporting the supplied phase.
* @return the set of candidate profiles
*/
private Profile[] getLocalProfiles( PhaseDescriptor phase )
{
return getTable( phase.getReference() ).getProfiles();
}
/**
* Returns the parent profile manager or null if this is the root manager.
* @return the parent
*/
private ContainerManager getParentManager()
{
return m_parent;
}
private void addProfile( ReferenceDescriptor reference, Profile profile )
{
ProfileTable table = getTable( reference );
table.add( profile );
}
/**
* Add a profile and cross-reference this relative to the extensions it
* is capable of supporting.
*
* @param extensions the set of extensions the facility supports
* @param profile the profile
*/
private void addProfile( ExtensionDescriptor[] extensions, Profile profile )
{
for( int i=0; i<extensions.length; i++ )
{
getLocalLogger().debug("adding profile against extension: " + extensions[i].getReference() );
ProfileTable table = getTable( extensions[i].getReference() );
table.add( profile );
}
}
/**
* Return a table that holds profiles supporting the supplied service reference.
*/
private ProfileTable getTable( ReferenceDescriptor service )
{
ProfileTable table = null;
Iterator iterator = m_services.iterator();
while( iterator.hasNext() )
{
table = (ProfileTable) iterator.next();
if( table.matches( service ) )
return table;
}
// otherwise create a new table
table = new ProfileTable( service );
m_services.add( table );
return table;
}
private Selector getSelector( PhaseDescriptor phase )
{
// if the phase declares a selector class then use that,
// otherwise, look for a default phase type selector - if none
// use the DefaultSelector
String selectorName = phase.getAttribute("avalon:selector");
if( selectorName == null )
selectorName = phase.getReference().getClassname() + "Selector";
try
{
Class clazz = loadClass( selectorName );
Selector selector = (Selector) clazz.newInstance();
if( selector instanceof LogEnabled )
{
((LogEnabled)selector).enableLogging( getLocalLogger().getChildLogger("selector") );
}
return selector;
}
catch( Throwable e )
{
return m_selector;
}
}
private Selector getSelector( DependencyDescriptor dependency )
{
// if the dependency declares a selector class then use that,
// otherwise, look for a default service type selector - if none
// use the DefaultSelector
String selectorName = dependency.getAttribute("avalon:selector");
if( selectorName == null )
selectorName = dependency.getService().getClassname() + "Selector";
try
{
Class clazz = loadClass( selectorName );
Selector selector = (Selector) clazz.newInstance();
if( selector instanceof LogEnabled )
{
((LogEnabled)selector).enableLogging( getLocalLogger().getChildLogger("selector") );
}
return selector;
}
catch( Throwable e )
{
return m_selector;
}
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>