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:[EMAIL PROTECTED]">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:[EMAIL PROTECTED]">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:[EMAIL PROTECTED]">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:[EMAIL PROTECTED]">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: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>