Return-Path: Delivered-To: apmail-jakarta-avalon-cvs-archive@apache.org Received: (qmail 8604 invoked from network); 18 Jun 2002 03:41:55 -0000 Received: from unknown (HELO nagoya.betaversion.org) (192.18.49.131) by daedalus.apache.org with SMTP; 18 Jun 2002 03:41:55 -0000 Received: (qmail 15181 invoked by uid 97); 18 Jun 2002 03:42:09 -0000 Delivered-To: qmlist-jakarta-archive-avalon-cvs@jakarta.apache.org Received: (qmail 15094 invoked by uid 97); 18 Jun 2002 03:42:08 -0000 Mailing-List: contact avalon-cvs-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Avalon CVS List" Reply-To: "Avalon Developers List" Delivered-To: mailing list avalon-cvs@jakarta.apache.org Received: (qmail 15083 invoked by uid 97); 18 Jun 2002 03:42:07 -0000 X-Antivirus: nagoya (v4198 created Apr 24 2002) Date: 18 Jun 2002 03:41:49 -0000 Message-ID: <20020618034149.70981.qmail@icarus.apache.org> From: donaldp@apache.org To: jakarta-avalon-excalibur-cvs@apache.org Subject: cvs commit: jakarta-avalon-excalibur/containerkit/src/java/org/apache/excalibur/containerkit/kernel Resources.properties KernelResourceAccessor.java X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N donaldp 2002/06/17 20:41:49 Modified: containerkit/src/java/org/apache/excalibur/containerkit/kernel KernelResourceAccessor.java Added: containerkit/src/java/org/apache/excalibur/containerkit/kernel Resources.properties Log: Update Accessor to be more fully implemented Revision Changes Path 1.2 +250 -31 jakarta-avalon-excalibur/containerkit/src/java/org/apache/excalibur/containerkit/kernel/KernelResourceAccessor.java Index: KernelResourceAccessor.java =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/containerkit/src/java/org/apache/excalibur/containerkit/kernel/KernelResourceAccessor.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- KernelResourceAccessor.java 14 Jun 2002 08:00:47 -0000 1.1 +++ KernelResourceAccessor.java 18 Jun 2002 03:41:49 -0000 1.2 @@ -8,40 +8,129 @@ package org.apache.excalibur.containerkit.kernel; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; +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.configuration.Configuration; import org.apache.avalon.framework.context.Context; +import org.apache.avalon.framework.context.DefaultContext; +import org.apache.avalon.framework.logger.AbstractLogEnabled; +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.service.DefaultServiceManager; import org.apache.avalon.framework.service.ServiceManager; import org.apache.excalibur.containerkit.lifecycle.ResourceAccessor; import org.apache.excalibur.containerkit.metadata.ComponentMetaData; +import org.apache.excalibur.containerkit.metadata.DependencyMetaData; +import org.apache.excalibur.containerkit.metainfo.ComponentInfo; import org.apache.excalibur.containerkit.metainfo.ContextDescriptor; import org.apache.excalibur.containerkit.metainfo.EntryDescriptor; /** + * This is the bas object via which the kernel aquires + * resources for each component. This base implementation + * will aquire components and make sure that all required + * components are present. It will also make sure that the types + * of values returned from context are valid. * + *

Note that this class assumes that the dependency graph + * has been validated (presumably via + * {@link org.apache.excalibur.containerkit.verifier.AssemblyVerifier}

* * @author Peter Donald * @version $Revision$ $Date$ */ public abstract class KernelResourceAccessor + extends AbstractLogEnabled implements ResourceAccessor { private final static Resources REZ = ResourceManager.getPackageResources( KernelResourceAccessor.class ); - private final AbstractServiceKernel m_kernel; + /** + * Utility method via which the {@link KernelResourceAccessor) + * aquires services to place in ServiceManager for a particular + * component. + * + *

Must be implemented in subclass.

+ * + * @param name the name of service + * @param entry the entry for component aquiring service + * @return the service object for specified name + */ + protected abstract Object getService( String name, Object entry ); + + /** + * Utility method via which the {@link KernelResourceAccessor) + * aquires a context value to place in Context for a particular + * component. + * + *

Must be implemented in subclass.

+ * + * @param name the name of service + * @param entry the entry for component aquiring service + * @return the context value for specified name + */ + protected abstract Object getContextValue( String name, Object entry ); - public KernelResourceAccessor( final AbstractServiceKernel kernel ) + /** + * Create a Parameters object by Creating configuration object and converting that. + * + * @param entry the entry + * @return a new Parameters object for component + * @throws Exception if unable to create resource + */ + public Parameters createParameters( Object entry ) + throws Exception + { + final Configuration configuration = createConfiguration( entry ); + return Parameters.fromConfiguration( configuration ); + } + + /** + * Create a {@link Context} object that contains values specified in map. + * The default implementation creates a basic Context object but different + * containers may choose to overide this to provide their own subclass of context. + * + * @param contextData the data to place in context + * @return the Context object + */ + protected Context createContextImpl( final Map contextData ) + { + final DefaultContext context = new DefaultContext( contextData ); + context.makeReadOnly(); + return context; + } + + /** + * Return the {@link ComponentMetaData} for specified component entry. + * This implementation assumes that entry is instance of {@link ComponentMetaData} + * but subclasses should overide this method if this assumption does not hold true. + * + * @param entry the component entry + * @return the ComponentMetaData + */ + protected ComponentMetaData getMetaData( final Object entry ) { - m_kernel = kernel; + return (ComponentMetaData)entry; } - public Context createContext( Object entry ) + /** + * Create a context object for specified component. + * + * @param componentEntry the entry representing component + * @return the created Context + * @throws Exception if unable to create context or entrys in context + */ + public final Context createContext( final Object componentEntry ) throws Exception { - final ComponentMetaData component = getMetaData( entry ); + final ComponentMetaData component = getMetaData( componentEntry ); + final String componentName = component.getName(); + final ContextDescriptor descriptor = component.getComponentInfo().getContextDescriptor(); @@ -50,49 +139,70 @@ final EntryDescriptor[] entrys = descriptor.getEntrys(); for( int i = 0; i < entrys.length; i++ ) { - final String key = entrys[ i ].getKey(); - final String type = entrys[ i ].getType(); - final boolean optional = entrys[ i ].isOptional(); + final EntryDescriptor entry = entrys[ i ]; + final String key = entry.getKey(); + final String type = entry.getType(); + final boolean optional = entry.isOptional(); final Object value = - m_kernel.getContextValue( key, entry ); - + getContextValue( key, componentEntry ); - if( null == value && !optional ) + if( null == value ) { + final String message = + REZ.getString( "resource.missing-context-value.error", + optional ? "1" : "2", + key, + componentName ); if( !optional ) { - final String message = - REZ.getString( "resource.missing-context-value.error", - key, - component.getName() ); throw new Exception( message ); } else { + getLogger().warn( message ); continue; } } - final Class clazz = value.getClass(); - final Class typeClass = clazz.getClassLoader().loadClass( type ); - if( !typeClass.isAssignableFrom( clazz ) ) + final boolean typeValid = objectImplementsType( value, type ); + if( !typeValid ) { final String message = REZ.getString( "resource.bad-value-type.error", + optional ? "1" : "2", key, + componentName, type, - clazz.getName(), - component.getName() ); - throw new Exception( message ); + value.getClass().getName() ); + if( !optional ) + { + throw new Exception( message ); + } + else + { + getLogger().warn( message ); + continue; + } } + + contextData.put( key, value ); } - return null; - } + final Context context = createContextImpl( contextData ); + final String classname = descriptor.getClassname(); - protected ComponentMetaData getMetaData( final Object entry ) - { - return (ComponentMetaData)entry; + final boolean validContextClass = objectImplementsType( context, classname ); + if( !validContextClass ) + { + final String message = + REZ.getString( "resource.bad-context-type.error", + classname, + context.getClass().getName(), + componentName ); + throw new Exception( message ); + } + + return context; } /** @@ -102,10 +212,31 @@ * @return a new ComponentManager for component * @throws Exception if unable to create resource */ - public ComponentManager createComponentManager( Object entry ) + public final ComponentManager createComponentManager( final Object entry ) throws Exception { - return null; + final Map services = createServiceMap( entry ); + + 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; } /** @@ -115,9 +246,97 @@ * @return a new ServiceManager for component * @throws Exception if unable to create resource */ - public ServiceManager createServiceManager( Object entry ) + public final ServiceManager createServiceManager( final Object entry ) throws Exception { - return null; + final Map services = createServiceMap( entry ); + + 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 Map of services for specified component. + * The map maps role name to service provider. + * + * @param componentEntry the component entry creating map for + * @return the map + * @throws Exception if error aquiring a service to place in map + */ + private Map createServiceMap( final Object componentEntry ) + throws Exception + { + final ComponentMetaData component = getMetaData( componentEntry ); + final ComponentInfo info = component.getComponentInfo(); + final DependencyMetaData[] dependencies = component.getDependencies(); + + final HashMap services = new HashMap(); + + for( int i = 0; i < dependencies.length; i++ ) + { + final DependencyMetaData dependency = dependencies[ i ]; + final String role = dependency.getRole(); + final String providerName = dependency.getProviderName(); + final boolean optional = info.getDependency( role ).isOptional(); + + final Object service = + getService( providerName, componentEntry ); + if( null == service ) + { + final String message = + REZ.getString( "resource.missing-dependency.error", + optional ? "1" : "2", + role, + component.getName() ); + if( !optional ) + { + throw new Exception( message ); + } + else + { + getLogger().warn( message ); + continue; + } + } + + services.put( role, service ); + } + + return services; + } + + /** + * 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 ) + { + 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/containerkit/src/java/org/apache/excalibur/containerkit/kernel/Resources.properties Index: Resources.properties =================================================================== 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}. -- To unsubscribe, e-mail: For additional commands, e-mail: