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/07 06:40:15 UTC
cvs commit: jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry ProfileRegistry.java ProfileTable.java TypeRegistry.java TypeTable.java ComponentDefinition.java ComponentType.java DefaultRegistry.xinfo Profile.java ServiceRegistry.java ServiceTable.java
mcconnell 2002/07/06 21:40:15
Added: assembly/src/java/org/apache/excalibur/merlin/registry
ProfileRegistry.java ProfileTable.java
TypeRegistry.java TypeTable.java
Removed: assembly/src/java/org/apache/excalibur/merlin/registry
ComponentDefinition.java ComponentType.java
DefaultRegistry.xinfo Profile.java
ServiceRegistry.java ServiceTable.java
Log:
rationalization of registry based on excalibur.meta.*
Revision Changes Path
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/ProfileRegistry.java
Index: ProfileRegistry.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.registry;
import java.util.List;
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.configuration.Configuration;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.data.Profile;
import org.apache.excalibur.meta.verifier.ComponentVerifier;
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.Container;
/**
* Internal table that holds available component type keyed relative
* to the service it provides.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/07 04:40:15 $
*/
final class ProfileRegistry extends AbstractLogEnabled implements Startable
{
//=======================================================================
// state
//=======================================================================
private ProfileBuilder m_builder = new ProfileBuilder();
private ClassLoader m_classloader;
private TypeRegistry m_types;
private Container m_parent;
/**
* Component profiles keyed by name.
*/
private Hashtable m_profiles = new Hashtable();
/**
* List of ServiceTable instances.
*/
private List m_services = new LinkedList();
private final Configuration[] m_directives;
/**
* The set of local explicitly declared profiles.
*/
private Vector m_assembly = new Vector();
/**
* The set of locally installed profiles.
*/
private ArrayList m_installed = new ArrayList();
private Map m_map;
//=======================================================================
// constructor
//=======================================================================
/**
* Creation of a new service registry.
* @param registry the registry that will be supplied to new component defintions
* @param loader the registry class loader
* @param profiles the configuration fragment containing explicit component profiles
*/
public ProfileRegistry(
Configuration[] directives, TypeRegistry registry, ClassLoader loader, Container parent, Map map )
{
m_classloader = loader;
m_types = registry;
m_directives = directives;
m_parent = parent;
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
//=======================================================================
public Profile[] getProviders( ServiceDesignator designator )
{
ArrayList list = new ArrayList();
Profile[] local = (Profile[]) m_installed.toArray( new Profile[0] );
for( int i=0; i<local.length; i++ )
{
Profile profile = local[i];
ServiceDescriptor[] services = profile.getType().getServices();
for( int j=0; j<services.length; j++ )
{
if( services[j].getServiceDesignator().matches( designator ) )
{
list.add( profile );
break;
}
}
}
return (Profile[]) list.toArray( new Profile[0] );
}
public int prepareProfiles() throws Exception
{
prepareDirectives();
prepareTypes();
return getProfiles().length;
}
public void assembleProfiles() throws Exception
{
Iterator iterator = m_assembly.iterator();
while( iterator.hasNext() )
{
Profile profile = (Profile) iterator.next();
getLogger().debug("assembly target: " + profile );
ArrayList visited = new ArrayList();
assemble( profile, visited, "" );
m_map.add( profile );
m_installed.add( profile );
}
}
private void assemble( Profile profile, List visited, String pad ) throws Exception
{
getLogger().debug( pad + "assemble: " + profile );
String pad2 = pad + " ";
visited.add( profile );
DependencyDescriptor[] dependencies = profile.getType().getDependencies();
for( int i=0; i<dependencies.length; i++ )
{
DependencyDescriptor dependency = dependencies[i];
String role = dependency.getRole();
if( profile.getAssociation( role ) == null )
{
Profile[] candidates = assemble( profile, dependency, visited, pad2 );
Profile[] facilities = getFacilities( dependency.getService() );
Profile provider = selectProfile( dependency, facilities, candidates );
if( provider == null )
{
throw new UnresolvedProviderException("no available provider", dependency );
}
else
{
profile.addProvider( provider, role );
if( isLocalProfile( provider ) )
{
m_map.add( provider );
m_installed.add( provider );
}
}
}
}
}
public boolean isLocalProfile( Profile profile )
{
return m_profiles.values().contains( profile );
}
private Profile[] assemble( Profile source, DependencyDescriptor dependency, List visited, String pad )
throws Exception
{
getLogger().debug( pad + "dependency: " + dependency.getRole() );
Vector vector = new Vector();
String pad2 = pad + " ";
Profile[] profiles = getProfiles( dependency.getService() );
for( int i=0; i<profiles.length; i++ )
{
Profile provider = profiles[i];
if( !provider.equals( source ) )
{
try
{
assemble( provider, visited, pad2 );
vector.add( provider );
getLogger().debug( pad + "candidate: " + provider );
}
catch( Throwable e )
{
// solution is not resolvable
}
}
}
return (Profile[]) vector.toArray( new Profile[0] );
}
private void prepareDirectives() throws Exception
{
for( int i=0; i<m_directives.length; i++ )
{
Profile profile = register( m_directives[i] );
m_assembly.add( profile );
}
}
private void prepareTypes() throws Exception
{
Type[] types = m_types.getTypes();
for( int i=0; i<types.length; i++ )
{
register( types[i] );
}
}
private Profile register( Configuration directive ) throws Exception
{
Type type = m_types.getType( directive.getAttribute("class") );
Profile profile = m_builder.build( type, directive );
return register( profile );
}
/**
* Register a potential supplier component type. The implementation will
* create a component type instance for the entry if not already known and
* return the existing or new instance to the invoking client.
*
* @param classname the component class name
* @return the component type
*/
public Profile[] register( Type type ) throws Exception
{
Profile[] profiles = m_builder.build( type, m_classloader );
for( int i=0; i<profiles.length; i++ )
{
Profile profile = profiles[i];
register( profile );
}
return profiles;
}
/**
* Returns the set of component types know to the registry.
* @return the set of component types registered with the registry
*/
public Profile[] getProfiles()
{
return (Profile[]) m_profiles.values().toArray( new Profile[0] );
}
/**
* Returns the set of component types know to the registry that are capable of
* supporting the supplied service.
* @return the set of candidate component types
*/
public Profile[] getProfiles( ServiceDesignator service )
{
return getTable( service ).getProfiles();
}
/**
* Returns a registered component type.
* @return the component type from the registry or null if the type is unknown
* @exception IllegalArgumentException if the classname does not correpond to a know component
*/
public Profile getProfile( String name ) throws IllegalArgumentException
{
return (Profile) m_profiles.get( name );
}
/**
* Register the type resulting in the cross-referencing of the type with the set of
* service tables that the type is is capable of supporting.
*/
private Profile register( Profile profile )
{
String name = profile.getName();
m_profiles.put( name, profile );
getLogger().debug( "" + profile );
ServiceDescriptor[] services = profile.getType().getServices();
for( int i=0; i<services.length; i++ )
{
register( services[i].getServiceDesignator(), profile );
}
return profile;
}
/**
* Register a type under a service cross-reference.
*/
private void register( ServiceDesignator service, Profile profile )
{
ProfileTable table = getTable( service );
table.add( profile );
}
/**
* Return a table holding table capable of supply the supplied service.
*/
private ProfileTable getTable( ServiceDesignator 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, getLogger().getChildLogger("table") );
m_services.add( table );
return table;
}
private Selector getSelector( DependencyDescriptor dependency )
{
// if the dependency declares a selector class then use that,
// otherwise, look for a default service type selector
String selectorName = dependency.getAttribute("avalon.service.selector");
if( selectorName == null )
selectorName = dependency.getService().getClassname() + "Selector";
try
{
Class clazz = m_classloader.loadClass( selectorName );
Selector selector = (Selector) clazz.newInstance();
if( selector instanceof LogEnabled )
{
((LogEnabled)selector).enableLogging( getLogger().getChildLogger("selector") );
}
return selector;
}
catch( Throwable e )
{
return null;
}
}
private Profile[] getFacilities( ServiceDesignator service )
{
if( m_parent != null )
{
return m_parent.getProviders( service );
}
else
{
return new Profile[0];
}
}
private Profile selectProfile( DependencyDescriptor dependency, Profile[] facilities, Profile[] profiles )
{
Selector selector = getSelector( dependency );
if( selector != null )
{
return selector.select( facilities, profiles );
}
else
{
// apply default selection policy
Profile profile = select( profiles, Profile.EXPLICIT );
if( profile == null )
{
profile = select( facilities );
}
if( profile == null )
{
profile = select( profiles );
}
return profile;
}
}
private Profile select( Profile[] profiles )
{
Profile profile = select( profiles, Profile.EXPLICIT );
if( profile == null ) profile = select( profiles, Profile.PACKAGED );
if( profile == null ) profile = select( profiles, Profile.IMPLICIT );
return profile;
}
private Profile select( Profile[] profiles, int mode )
{
for( int i=0; i<profiles.length; i++ )
{
if( profiles[i].getMode() == mode )
return profiles[i];
}
return null;
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/ProfileTable.java
Index: ProfileTable.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.registry;
import java.util.List;
import java.util.LinkedList;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.data.Profile;
/**
* Internal table that holds references to the available component types
* that represent candidate providers for a single service type.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/07 04:40:15 $
*/
final class ProfileTable extends AbstractLogEnabled
{
//=======================================================================
// state
//=======================================================================
/**
* Component type lists keyed by service designator.
*/
private List m_providers = new LinkedList();
/**
* Identification of the service type that this table is supporting.
*/
private ServiceDesignator m_designator;
public ProfileTable( ServiceDesignator designator, Logger logger )
{
m_designator = designator;
super.enableLogging( logger );
}
//=======================================================================
// ServiceTable
//=======================================================================
/**
* Add a service provider to the set of provider managed by this table.
*
* @param classname the component class name
* @return the component type
*/
public void add( Profile profile )
{
m_providers.add( profile );
}
/**
* Returns the set of providers currently registered in the table.
* @return the set of component types capable of acting as a provider for the
* service managed by the table
*/
public Profile[] getProfiles()
{
return (Profile[]) m_providers.toArray( new Profile[0] );
}
/**
* Return the service type for the table.
* @return the service designator
*/
public ServiceDesignator getService()
{
return m_designator;
}
/**
* Return the number of entries in the table.
* @return the number of providers
*/
public int getSize()
{
return m_providers.size();
}
/**
* Returns true if the table service designator matches the supplied designator.
* @param service a service type designator
* @return TRUE if the supplied service type matches the the service type for
* this table.
*/
public boolean matches( ServiceDesignator service )
{
return m_designator.matches( service );
}
public String toString()
{
return "ProfileTable:"
+ System.identityHashCode( this )
+ ", "
+ m_designator;
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/TypeRegistry.java
Index: TypeRegistry.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.registry;
import java.util.List;
import java.util.LinkedList;
import java.util.Hashtable;
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.configuration.Configuration;
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.data.Profile;
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
* to the service it provides.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/07 04:40:15 $
*/
final class TypeRegistry extends AbstractLogEnabled
{
//=======================================================================
// state
//=======================================================================
private TypeBuilder m_infoBuilder = new TypeBuilder();
private ClassLoader m_classloader;
private DefaultRegistry m_registry;
/**
* Component types keyed by classname.
*/
private Hashtable m_types = new Hashtable();
/**
* List of TypeTable instances.
*/
private List m_services = new LinkedList();
//=======================================================================
// constructor
//=======================================================================
/**
* Creation of a new service registry.
* @param registry the registry that will be supplied to new component defintions
* @param loader the registry class loader
* @param profiles the configuration fragment containing explicit component profiles
*/
public TypeRegistry(
DefaultRegistry registry, ClassLoader loader )
{
m_classloader = loader;
m_registry = registry;
}
//=======================================================================
// LogEnabled
//=======================================================================
/**
* Set the logging channel for the service registry.
* @param logger the logging channel
*/
public void enableLogging( Logger logger )
{
super.enableLogging( logger );
m_infoBuilder.enableLogging( logger.getChildLogger("builder") );
}
//=======================================================================
// ServiceRegistry
//=======================================================================
/**
* Register a potential supplier component type. The implementation will
* create a component type instance for the entry if not already known and
* return the existing or new instance to the invoking client.
*
* @param classname the component class name
* @return the component type
*/
public Type register( String classname ) throws Exception
{
Type type = getType( classname );
if( type == null )
{
type = m_infoBuilder.build( classname, m_classloader );
String name = type.getInfo().getName();
Class clazz = getComponentClass( type );
Class[] classes = getServiceClasses( type );
ComponentVerifier verifier = new ComponentVerifier();
verifier.enableLogging( getLogger().getChildLogger( "verifier" ));
verifier.verifyComponent( name, clazz, classes );
register( type );
}
return type;
}
private Class[] getServiceClasses( Type type )
{
Vector vector = new Vector();
ServiceDescriptor[] services = type.getServices();
for( int i=0; i<services.length; i++ )
{
vector.add( getServiceClass( services[i] ) );
}
return (Class[]) vector.toArray( new Class[0] );
}
/**
* Returns the component type implementation class.
* @param type the component type descriptor
* @return the class implementing the component type
*/
Class getComponentClass( Type type ) throws RegistryException
{
if( null == type )
throw new NullPointerException("Illegal null component type argument.");
final String classname = type.getInfo().getImplementationKey();
try
{
return m_classloader.loadClass( classname );
}
catch( Throwable e )
{
final String error = "Could not load implementation class for component type: "
+ classname;
throw new RegistryException( error, e );
}
}
/**
* Returns the service type implementation class.
* @param service the service type descriptor
* @return the class implementing the service type
*/
Class getServiceClass( ServiceDescriptor service ) throws RegistryRuntimeException
{
final String classname = service.getServiceDesignator().getClassname();
try
{
return m_classloader.loadClass( classname );
}
catch( Throwable e )
{
final String error = "Could not load implementation class for service type: "
+ classname;
throw new RegistryRuntimeException( error, e );
}
}
/**
* Returns the set of component types know to the registry.
* @return the set of component types registered with the registry
*/
public Type[] getTypes()
{
return (Type[]) m_types.values().toArray( new Type[0] );
}
/**
* Returns the set of component types know to the registry that are capable of
* supporting the supplied service.
* @return the set of candidate component types
*/
public Type[] getTypes( ServiceDesignator service )
{
return getTable( service ).getTypes();
}
/**
* Returns a registered component type.
* @return the component type from the registry or null if the type is unknown
* @exception IllegalArgumentException if the classname does not correpond to a know component
*/
public Type getType( String classname ) throws IllegalArgumentException
{
return (Type) m_types.get( classname );
}
/**
* Register the type resulting in the cross-referencing of the type with the set of
* service tables that the type is is capable of supporting.
*/
private void register( Type type )
{
String key = type.getInfo().getImplementationKey();
m_types.put( key, type );
getLogger().debug( "Type: '" + key + "' registered.");
ServiceDescriptor[] services = type.getServices();
for( int i=0; i<services.length; i++ )
{
register( services[i].getServiceDesignator(), type );
}
}
/**
* Register a type under a service cross-reference.
*/
private void register( ServiceDesignator service, Type type )
{
TypeTable table = getTable( service );
table.add( type );
}
/**
* Return a table holding table capable of supply the supplied service.
*/
private TypeTable getTable( ServiceDesignator service )
{
TypeTable table = null;
Iterator iterator = m_services.iterator();
while( iterator.hasNext() )
{
table = (TypeTable) iterator.next();
if( table.matches( service ) )
return table;
}
// otherwise create a new table
table = new TypeTable( service, getLogger().getChildLogger("table") );
m_services.add( table );
return table;
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/registry/TypeTable.java
Index: TypeTable.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.registry;
import java.util.List;
import java.util.LinkedList;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.meta.info.Type;
/**
* Internal table that holds references to the available component types
* that represent candidate providers for a single service type.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/07 04:40:15 $
*/
final class TypeTable extends AbstractLogEnabled
{
//=======================================================================
// state
//=======================================================================
/**
* Component type lists keyed by service designator.
*/
private List m_providers = new LinkedList();
/**
* Identification of the service type that this table is supporting.
*/
private ServiceDesignator m_designator;
public TypeTable( ServiceDesignator designator, Logger logger )
{
m_designator = designator;
super.enableLogging( logger );
}
//=======================================================================
// ServiceTable
//=======================================================================
/**
* Add a service provider to the set of provider managed by this table.
*
* @param classname the component class name
* @return the component type
*/
public void add( Type type )
{
//getLogger().debug("addition\n\ttype:" + type + "\n\ttable: " + this );
m_providers.add( type );
}
/**
* Returns the set of providers currently registered in the table.
* @return the set of component types capable of acting as a provider for the
* service managed by the table
*/
public Type[] getTypes()
{
return (Type[]) m_providers.toArray( new Type[0] );
}
/**
* Return the service type for the table.
* @return the service designator
*/
public ServiceDesignator getService()
{
return m_designator;
}
/**
* Return the number of entries in the table.
* @return the number of providers
*/
public int getSize()
{
return m_providers.size();
}
/**
* Returns true if the table service designator matches the supplied designator.
* @param service a service type designator
* @return TRUE if the supplied service type matches the the service type for
* this table.
*/
public boolean matches( ServiceDesignator service )
{
return m_designator.matches( service );
}
public String toString()
{
return "TypeTable:"
+ System.identityHashCode( this )
+ ", "
+ m_designator;
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>