hammant 2003/01/18 08:43:46 Modified: . build.xml src/java/org/apache/avalon/phoenix/components/application BlockResourceProvider.java DefaultApplication.java ListenerResourceProvider.java src/java/org/apache/avalon/phoenix/tools/punit PUnit.java PUnitBlockEntry.java PUnitHelper.java PUnitResourceProvider.java PUnitTestCase.java Added: src/java/org/apache/avalon/phoenix/containerkit/demo Resources.properties SimpleMetaDataBuilder.java SimpleResourceProvider.java SimpleServiceKernel.java src/java/org/apache/avalon/phoenix/containerkit/factory ComponentBundle.java ComponentFactory.java DefaultComponentBundle.java DefaultComponentFactory.java src/java/org/apache/avalon/phoenix/containerkit/kernel AbstractServiceKernel.java ComponentEntry.java ComponentReference.java ComponentStore.java Resources.properties package.html src/java/org/apache/avalon/phoenix/containerkit/kernel/processor DependencyMap.java src/java/org/apache/avalon/phoenix/containerkit/lifecycle LifecycleException.java LifecycleHelper.java ResourceProvider.java Resources.properties package.html src/java/org/apache/avalon/phoenix/containerkit/lifecycle/impl AbstractResourceProvider.java Resource.properties package.html src/java/org/apache/avalon/phoenix/containerkit/metadata ComponentMetaData.java DependencyMetaData.java MetaDataBuilder.java PartitionMetaData.java package.html src/java/org/apache/avalon/phoenix/containerkit/registry ComponentProfile.java PartitionProfile.java ProfileBuilder.java src/java/org/apache/avalon/phoenix/containerkit/verifier AssemblyVerifier.java Resources.properties package.html Removed: lib/container excalibur-containerkit-1.0.jar Log: ContainerKit moved to Phoenix. Revision Changes Path 1.194 +8 -1 jakarta-avalon-phoenix/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/jakarta-avalon-phoenix/build.xml,v retrieving revision 1.193 retrieving revision 1.194 diff -u -r1.193 -r1.194 --- build.xml 3 Jan 2003 19:39:24 -0000 1.193 +++ build.xml 18 Jan 2003 16:43:42 -0000 1.194 @@ -398,6 +398,10 @@ <include name="org/apache/avalon/phoenix/tools/punit/**"/> </jar> + <jar jarfile="${build.lib}/phoenix-containerkit.jar" basedir="${build.classes}"> + <include name="org/apache/avalon/phoenix/containerkit/**"/> + </jar> + </target> @@ -485,6 +489,9 @@ <fileset dir="${lib.dir}/container"> <include name="*.jar"/> </fileset> + <fileset dir="${build.lib}"> + <include name="phoenix-containerkit.jar"/> + </fileset> </copy> <copy file="${xerces.jar}" todir="${bin.dist.lib}"/> @@ -609,7 +616,7 @@ See http://cvs.apache.org/viewcvs/jakarta-avalon-apps/demo/build.xml for usage See http://jakarta.apache.org/avalon/phoenix/mx/index.html for documentation -phoenix-punit.jar needs to be used with excalibur-containerkit-1.0.jar +phoenix-punit.jar needs to be used with phoenix-containerkit-1.0.jar See http://cvs.apache.org/viewcvs/jakarta-avalon-phoenix/src/test/org/apache/avalon/phoenix/tools/punit/test/ for usage. See http://jakarta.apache.org/avalon/phoenix/punit/index.html for documentation 1.13 +2 -2 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/application/BlockResourceProvider.java Index: BlockResourceProvider.java =================================================================== RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/application/BlockResourceProvider.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- BlockResourceProvider.java 7 Nov 2002 16:37:16 -0000 1.12 +++ BlockResourceProvider.java 18 Jan 2003 16:43:42 -0000 1.13 @@ -34,7 +34,7 @@ import org.apache.avalon.phoenix.metadata.DependencyMetaData; import org.apache.avalon.phoenix.metainfo.DependencyDescriptor; import org.apache.avalon.phoenix.metainfo.ServiceDescriptor; -import org.apache.excalibur.containerkit.lifecycle.ResourceProvider; +import org.apache.avalon.phoenix.containerkit.lifecycle.ResourceProvider; /** * The accessor used to access resources for a particular 1.39 +2 -2 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/application/DefaultApplication.java Index: DefaultApplication.java =================================================================== RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/application/DefaultApplication.java,v retrieving revision 1.38 retrieving revision 1.39 diff -u -r1.38 -r1.39 --- DefaultApplication.java 23 Oct 2002 03:21:49 -0000 1.38 +++ DefaultApplication.java 18 Jan 2003 16:43:42 -0000 1.39 @@ -26,8 +26,8 @@ import org.apache.avalon.phoenix.metadata.BlockListenerMetaData; import org.apache.avalon.phoenix.metadata.BlockMetaData; import org.apache.avalon.phoenix.metadata.SarMetaData; -import org.apache.excalibur.containerkit.lifecycle.LifecycleException; -import org.apache.excalibur.containerkit.lifecycle.LifecycleHelper; +import org.apache.avalon.phoenix.containerkit.lifecycle.LifecycleException; +import org.apache.avalon.phoenix.containerkit.lifecycle.LifecycleHelper; import org.apache.excalibur.threadcontext.ThreadContext; /** 1.4 +2 -2 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/application/ListenerResourceProvider.java Index: ListenerResourceProvider.java =================================================================== RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/components/application/ListenerResourceProvider.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- ListenerResourceProvider.java 6 Aug 2002 11:57:39 -0000 1.3 +++ ListenerResourceProvider.java 18 Jan 2003 16:43:42 -0000 1.4 @@ -19,7 +19,7 @@ import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.phoenix.interfaces.ApplicationContext; import org.apache.avalon.phoenix.metadata.BlockListenerMetaData; -import org.apache.excalibur.containerkit.lifecycle.ResourceProvider; +import org.apache.avalon.phoenix.containerkit.lifecycle.ResourceProvider; /** * The accessor used to access resources for a particular 1.5 +1 -1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/tools/punit/PUnit.java Index: PUnit.java =================================================================== RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/tools/punit/PUnit.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- PUnit.java 4 Dec 2002 13:48:21 -0000 1.4 +++ PUnit.java 18 Jan 2003 16:43:42 -0000 1.5 @@ -7,7 +7,7 @@ */ package org.apache.avalon.phoenix.tools.punit; -import org.apache.excalibur.containerkit.lifecycle.LifecycleException; +import org.apache.avalon.phoenix.containerkit.lifecycle.LifecycleException; import org.apache.avalon.framework.configuration.Configuration; /** 1.2 +1 -1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/tools/punit/PUnitBlockEntry.java Index: PUnitBlockEntry.java =================================================================== RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/tools/punit/PUnitBlockEntry.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- PUnitBlockEntry.java 12 Nov 2002 20:40:25 -0000 1.1 +++ PUnitBlockEntry.java 18 Jan 2003 16:43:42 -0000 1.2 @@ -7,7 +7,7 @@ */ package org.apache.avalon.phoenix.tools.punit; -import org.apache.excalibur.containerkit.lifecycle.ResourceProvider; +import org.apache.avalon.phoenix.containerkit.lifecycle.ResourceProvider; /** * PUnitBlockEntry contains the runtime state of a block. 1.2 +2 -2 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/tools/punit/PUnitHelper.java Index: PUnitHelper.java =================================================================== RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/tools/punit/PUnitHelper.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- PUnitHelper.java 4 Dec 2002 13:48:22 -0000 1.1 +++ PUnitHelper.java 18 Jan 2003 16:43:42 -0000 1.2 @@ -7,8 +7,8 @@ */ package org.apache.avalon.phoenix.tools.punit; -import org.apache.excalibur.containerkit.lifecycle.LifecycleHelper; -import org.apache.excalibur.containerkit.lifecycle.LifecycleException; +import org.apache.avalon.phoenix.containerkit.lifecycle.LifecycleHelper; +import org.apache.avalon.phoenix.containerkit.lifecycle.LifecycleException; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.logger.ConsoleLogger; import org.apache.avalon.framework.configuration.Configuration; 1.8 +1 -1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/tools/punit/PUnitResourceProvider.java Index: PUnitResourceProvider.java =================================================================== RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/tools/punit/PUnitResourceProvider.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- PUnitResourceProvider.java 12 Nov 2002 20:40:25 -0000 1.7 +++ PUnitResourceProvider.java 18 Jan 2003 16:43:42 -0000 1.8 @@ -14,7 +14,7 @@ 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.containerkit.lifecycle.ResourceProvider; +import org.apache.avalon.phoenix.containerkit.lifecycle.ResourceProvider; /** * PUnitResourceProvider 1.9 +2 -2 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/tools/punit/PUnitTestCase.java Index: PUnitTestCase.java =================================================================== RCS file: /home/cvs/jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/tools/punit/PUnitTestCase.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- PUnitTestCase.java 8 Jan 2003 02:17:51 -0000 1.8 +++ PUnitTestCase.java 18 Jan 2003 16:43:42 -0000 1.9 @@ -7,8 +7,8 @@ */ package org.apache.avalon.phoenix.tools.punit; -import org.apache.excalibur.containerkit.lifecycle.LifecycleHelper; -import org.apache.excalibur.containerkit.lifecycle.LifecycleException; +import org.apache.avalon.phoenix.containerkit.lifecycle.LifecycleHelper; +import org.apache.avalon.phoenix.containerkit.lifecycle.LifecycleException; import org.apache.avalon.framework.logger.ConsoleLogger; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.service.DefaultServiceManager; 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/demo/Resources.properties Index: Resources.properties =================================================================== provider-shutdown.error=Error shutting down ResourceProvider. 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/demo/SimpleMetaDataBuilder.java Index: SimpleMetaDataBuilder.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.avalon.phoenix.containerkit.demo; import java.util.ArrayList; import java.util.Map; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; import org.apache.avalon.framework.info.Attribute; import org.apache.avalon.phoenix.containerkit.metadata.ComponentMetaData; import org.apache.avalon.phoenix.containerkit.metadata.DependencyMetaData; import org.apache.avalon.phoenix.containerkit.metadata.MetaDataBuilder; import org.apache.avalon.phoenix.containerkit.metadata.PartitionMetaData; import org.xml.sax.InputSource; /** * Load metadata from some source. The source is usually * one or more xml config files. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:42 $ */ public class SimpleMetaDataBuilder implements MetaDataBuilder { public static final String CONFIG_LOCATION = "simple:location"; public PartitionMetaData buildAssembly( final Map parameters ) throws Exception { final String location = (String)parameters.get( CONFIG_LOCATION ); final ComponentMetaData[] components = loadMetaData( location ); return new PartitionMetaData( "main", new String[ 0 ], new PartitionMetaData[ 0 ], components, Attribute.EMPTY_SET ); } private ComponentMetaData[] loadMetaData( final String location ) throws Exception { final DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); final InputSource input = new InputSource( location ); final Configuration configuration = builder.build( input ); final Configuration[] children = configuration.getChildren( "component" ); return loadComponentDatas( children ); } private ComponentMetaData[] loadComponentDatas( final Configuration[] components ) throws Exception { final ArrayList profiles = new ArrayList(); for( int i = 0; i < components.length; i++ ) { final ComponentMetaData component = loadComponentData( components[ i ] ); profiles.add( component ); } return (ComponentMetaData[])profiles.toArray( new ComponentMetaData[ profiles.size() ] ); } private ComponentMetaData loadComponentData( final Configuration component ) throws Exception { final String name = component.getAttribute( "name" ); final String impl = component.getAttribute( "impl" ); final Configuration config = component.getChild( "config" ); final DependencyMetaData[] dependencies = parseAssociations( component.getChildren( "provide" ) ); return new ComponentMetaData( name, impl, dependencies, null, config, null ); } private DependencyMetaData[] parseAssociations( final Configuration[] provides ) throws ConfigurationException { final ArrayList associations = new ArrayList(); for( int i = 0; i < provides.length; i++ ) { final Configuration provide = provides[ i ]; final String key = provide.getAttribute( "key" ); final String provider = provide.getAttribute( "provider" ); final DependencyMetaData association = new DependencyMetaData( key, provider, key, Attribute.EMPTY_SET ); associations.add( association ); } return (DependencyMetaData[])associations.toArray( new DependencyMetaData[ associations.size() ] ); } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/demo/SimpleResourceProvider.java Index: SimpleResourceProvider.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.avalon.phoenix.containerkit.demo; import org.apache.avalon.framework.logger.Logger; import org.apache.avalon.phoenix.containerkit.factory.ComponentFactory; import org.apache.avalon.phoenix.containerkit.kernel.AbstractServiceKernel; import org.apache.avalon.phoenix.containerkit.kernel.ComponentEntry; import org.apache.avalon.phoenix.containerkit.lifecycle.impl.AbstractResourceProvider; import org.apache.avalon.phoenix.containerkit.metadata.ComponentMetaData; /** * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public class SimpleResourceProvider extends AbstractResourceProvider { private final AbstractServiceKernel m_serviceKernel; public SimpleResourceProvider( final AbstractServiceKernel serviceKernel, final ComponentFactory factory ) { super( factory ); m_serviceKernel = serviceKernel; } protected ComponentMetaData getMetaData( final Object entry ) { return ( (ComponentEntry)entry ).getProfile().getMetaData(); } protected Object getService( final String name, final Object entry ) { return m_serviceKernel.getComponent( name ); } protected Object getContextValue( final String name, final Object entry ) { //Should return classloaders that are available return null; } public Logger createLogger( final Object entry ) throws Exception { final ComponentMetaData component = getMetaData( entry ); return getLogger().getChildLogger( component.getName() ); } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/demo/SimpleServiceKernel.java Index: SimpleServiceKernel.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.avalon.phoenix.containerkit.demo; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; import org.apache.avalon.framework.parameters.ParameterException; import org.apache.avalon.framework.parameters.Parameterizable; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.phoenix.containerkit.factory.ComponentFactory; import org.apache.avalon.phoenix.containerkit.factory.DefaultComponentFactory; import org.apache.avalon.phoenix.containerkit.kernel.AbstractServiceKernel; import org.apache.avalon.phoenix.containerkit.lifecycle.ResourceProvider; import org.apache.avalon.phoenix.containerkit.metadata.ComponentMetaData; import org.apache.avalon.phoenix.containerkit.metadata.MetaDataBuilder; import org.apache.avalon.phoenix.containerkit.metadata.PartitionMetaData; import java.util.Map; import java.util.HashMap; /** * This is a simple ServiceKernel. * * <p>It loads components from the current ClassLoader. * The Assembly information is passed in via Configuration object * in a format similar to merged assembly.xml/config.xml from Phoenix.</p> * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public class SimpleServiceKernel extends AbstractServiceKernel implements Parameterizable { private final static Resources REZ = ResourceManager.getPackageResources( SimpleServiceKernel.class ); private MetaDataBuilder m_metaDataBuilder; private String m_configURL; public void parameterize( final Parameters parameters ) throws ParameterException { m_configURL = parameters.getParameter( "config-url" ); } public void initialize() throws Exception { super.initialize(); m_metaDataBuilder = new SimpleMetaDataBuilder(); setupLogger( getFactory(), "builder" ); final Map parameters = new HashMap(); parameters.put( SimpleMetaDataBuilder.CONFIG_LOCATION, m_configURL ); final PartitionMetaData partition = m_metaDataBuilder.buildAssembly( parameters ); final ComponentMetaData[] components = partition.getComponents(); for( int i = 0; i < components.length; i++ ) { final ComponentMetaData component = components[ i ]; addComponent( component ); } startupAllComponents(); } public void dispose() { try { shutdownAllComponents(); } catch( final Exception e ) { final String message = REZ.getString( "provider-shutdown.error" ); getLogger().warn( message, e ); } super.dispose(); } protected ComponentFactory prepareFactory() { final DefaultComponentFactory factory = new DefaultComponentFactory( getClass().getClassLoader() ); setupLogger( factory, "factory" ); return factory; } protected ResourceProvider prepareResourceProvider() { final SimpleResourceProvider resourceProvider = new SimpleResourceProvider( this, getFactory() ); setupLogger( resourceProvider, "provider" ); return resourceProvider; } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/factory/ComponentBundle.java Index: ComponentBundle.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.avalon.phoenix.containerkit.factory; import java.io.InputStream; import org.apache.avalon.framework.info.ComponentInfo; /** * The ComponentBundle gives access to the sum total of all the * metadata and resources about a component. This includes all * the resources associated with a particular component and the * associated [EMAIL PROTECTED] ComponentInfo}. * * <p>Additional resources that may be associated with a component * include but are not limited to;</p> * * <ul> * <li>Resource property files for i18n of [EMAIL PROTECTED] ComponentInfo}</li> * <li>XML schema or DTD that is used when validating a components * configuration, such as in Phoenix.</li> * <li>Descriptor used to define management interface of * component.</li> * <li>Prototype used to define a component profile.</li> * </ul> * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public interface ComponentBundle { /** * Return the [EMAIL PROTECTED] ComponentInfo} that describes the * component. * * @return the [EMAIL PROTECTED] ComponentInfo} that describes the component. */ ComponentInfo getComponentInfo(); /** * Return an input stream for a resource associated with * component. The resource name can be relative or absolute. * Absolute names being with a '/' character. * * <p>When the component is implemented via a Java class (as * opposed to a remote SOAP/RMI/JMX/other service), the resources * are loaded from the same <code>ClassLoader</code> as * implementation. The resources are loaded relative to the * implementaion classes package and are often named after the * classname of the component.</p> * * <p>For example, a component <code>com.biz.Foo</code> may have * resources such as <code>com/biz/Foo-schema.xsd</code>, * <code>com/biz/Foo.mxinfo</code> or * <code>com/biz/Foo-profile.xml</code>.</p> * * @return the input stream for associated resource, or null * if no such resource */ InputStream getResourceAsStream( String resource ); } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/factory/ComponentFactory.java Index: ComponentFactory.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.avalon.phoenix.containerkit.factory; /** * This interface defines the mechanism via which a * component or its associated [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.factory.ComponentBundle} can * be created. * * <p>Usually the component or ComponentBundle will just be loaded * from a particular ClassLoader. However if a developer wanted * to dynamically assemble applications they could implement * a custom factory that created components via non-standard * mechanisms (say by wrapping remote, CORBA, or other style * objects).</p> * * <p>The methods take a <code>implementationKey</code> parameter * and usually this represents the class name of the component. * However in alternative component systems this may designate * objects via different mechanisms.</p> * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public interface ComponentFactory { String ROLE = ComponentFactory.class.getName(); /** * Create a [EMAIL PROTECTED] ComponentBundle} for component * specified by implementationKey. * * @param implementationKey the key indicating type of component (usually classname) * @return the ComponentBundle for component * @throws Exception if unable to create Info object */ ComponentBundle createBundle( String implementationKey ) throws Exception; /** * Create an instance of component with specified * implementationKey. * * @param implementationKey the key indicating type of component (usually classname) * @return an instance of component * @throws Exception if unable to create component */ Object createComponent( String implementationKey ) throws Exception; } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/factory/DefaultComponentBundle.java Index: DefaultComponentBundle.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.avalon.phoenix.containerkit.factory; import java.io.InputStream; import org.apache.avalon.framework.info.ComponentInfo; /** * * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public class DefaultComponentBundle implements ComponentBundle { private final ComponentInfo m_componentInfo; private final ClassLoader m_classLoader; public DefaultComponentBundle( final ComponentInfo componentInfo, final ClassLoader classLoader ) { if( null == componentInfo ) { throw new NullPointerException( "componentInfo" ); } if( null == classLoader ) { throw new NullPointerException( "classLoader" ); } m_componentInfo = componentInfo; m_classLoader = classLoader; } public ComponentInfo getComponentInfo() { return m_componentInfo; } public InputStream getResourceAsStream( String resource ) { return m_classLoader.getResourceAsStream( resource ); } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/factory/DefaultComponentFactory.java Index: DefaultComponentFactory.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.avalon.phoenix.containerkit.factory; import java.util.Map; import java.util.WeakHashMap; import org.apache.avalon.framework.info.ComponentInfo; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.logger.Logger; import org.apache.avalon.framework.tools.infobuilder.InfoBuilder; /** * The default implementation of [EMAIL PROTECTED] ComponentFactory} * that simply creates components from a [EMAIL PROTECTED] java.lang.ClassLoader}. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public class DefaultComponentFactory extends AbstractLogEnabled implements ComponentFactory { /** * Cache of ComponentInfo objects. */ private final Map m_infos = new WeakHashMap(); /** * The utility class that is used when building info * objects for Components. */ private final InfoBuilder m_infoBuilder = new InfoBuilder(); /** * The classloader from which all resources are loaded. */ private final ClassLoader m_classLoader; /** * Create a Factory that loads from specified ClassLoader. * * @param classLoader the classLoader to use in factory, must not be null */ public DefaultComponentFactory( final ClassLoader classLoader ) { if( null == classLoader ) { throw new NullPointerException( "classLoader" ); } m_classLoader = classLoader; } public void enableLogging( final Logger logger ) { super.enableLogging( logger ); setupLogger( m_infoBuilder, "info" ); } /** * Create a component by creating info for class * with specified name and loaded from factorys ClassLoader. * * @see ComponentFactory#createBundle */ public ComponentBundle createBundle( final String implementationKey ) throws Exception { ComponentBundle bundle = (ComponentBundle)m_infos.get( implementationKey ); if( null == bundle ) { bundle = newBundle( implementationKey ); m_infos.put( implementationKey, bundle ); } return bundle; } /** * Create a component by creating instance of class * with specified name and loaded from factorys ClassLoader. * * @see ComponentFactory#createComponent */ public Object createComponent( final String implementationKey ) throws Exception { final Class clazz = getClassLoader().loadClass( implementationKey ); return clazz.newInstance(); } /** * Create a bundle for specified key. * Note that this does not cache bundle in any way. * * @param implementationKey the implementationKey * @return the new ComponentBundle * @throws Exception if unable to create bundle */ protected ComponentBundle newBundle( final String implementationKey ) throws Exception { ComponentBundle bundle; final ComponentInfo info = createComponentInfo( implementationKey ); bundle = new DefaultComponentBundle( info, getClassLoader() ); return bundle; } /** * Create a [EMAIL PROTECTED] ComponentInfo} for component with specified implementationKey. * * @param implementationKey the implementationKey * @return the created [EMAIL PROTECTED] ComponentInfo} * @throws Exception if unabel to create componentInfo */ protected ComponentInfo createComponentInfo( final String implementationKey ) throws Exception { return m_infoBuilder.buildComponentInfo( implementationKey, getClassLoader() ); } /** * Retrieve ClassLoader associated with ComponentFactory. * * @return */ protected ClassLoader getClassLoader() { return m_classLoader; } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/kernel/AbstractServiceKernel.java Index: AbstractServiceKernel.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.avalon.phoenix.containerkit.kernel; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; 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.container.ContainerUtil; import org.apache.avalon.framework.info.ComponentInfo; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.phoenix.containerkit.factory.ComponentBundle; import org.apache.avalon.phoenix.containerkit.factory.ComponentFactory; import org.apache.avalon.phoenix.containerkit.kernel.processor.DependencyMap; import org.apache.avalon.phoenix.containerkit.lifecycle.LifecycleHelper; import org.apache.avalon.phoenix.containerkit.lifecycle.ResourceProvider; import org.apache.avalon.phoenix.containerkit.metadata.ComponentMetaData; import org.apache.avalon.phoenix.containerkit.registry.ComponentProfile; /** * The <code>AbstractServiceKernel</code> defines an application scope through * the aggregation of a set of container entries and the exposure of operations * supporting the collective startup and shutdown of registered entries. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public abstract class AbstractServiceKernel extends AbstractLogEnabled implements Initializable, Disposable { private final static Resources REZ = ResourceManager.getPackageResources( AbstractServiceKernel.class ); /** * The factory to use when creating components. */ private ComponentFactory m_factory; /** * The resource provider to use to provide resources * for all the components. */ private ResourceProvider m_resourceProvider; /** * The component that is responsible for running components * through their lifecycle stages. */ private LifecycleHelper m_lifecycleHelper; /** * The map of all entrys present in application. */ private final ComponentStore m_store = new ComponentStore(); /** * The [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.processor.DependencyMap} via which dependency graph is * produced. */ private final DependencyMap m_dependencyMap = new DependencyMap(); /** * The resource provider to use to provide resources * for all the components. */ private Map m_entrySet = new HashMap(); //private PhaseProcessor m_processor; /** * Initialization of the kernel. The implementation will request * resource provider preparation via the [EMAIL PROTECTED] #prepareResourceProvider} * method that must be implemeted by a kernel derived from this abstract * class. * @throws Exception if an error occurs during kernel initialization */ public void initialize() throws Exception { m_factory = prepareFactory(); m_resourceProvider = prepareResourceProvider(); m_lifecycleHelper = prepareLifecycleHelper(); //m_processor = new PhaseProcessor(); //setupLogger( m_processor, "processor" ); } /** * Dispose the kernel and de-allocate any resources. * This method will just shutdown and null out the * [EMAIL PROTECTED] ResourceProvider} and [EMAIL PROTECTED] LifecycleHelper} * objects. */ public void dispose() { try { ContainerUtil.shutdown( m_resourceProvider ); } catch( final Exception e ) { final String message = REZ.getString( "provider-shutdown.error" ); getLogger().warn( message, e ); } try { ContainerUtil.shutdown( m_lifecycleHelper ); } catch( Exception e ) { final String message = REZ.getString( "lifecycle-shutdown.error" ); getLogger().warn( message, e ); } } protected abstract ComponentFactory prepareFactory(); protected abstract ResourceProvider prepareResourceProvider(); protected LifecycleHelper prepareLifecycleHelper() { final LifecycleHelper lifecycleHelper = new LifecycleHelper(); setupLogger( lifecycleHelper, "lifecycle" ); return lifecycleHelper; } /** * Request startup of all components. * @exception Exception if there is an error during startup */ protected final void startupAllComponents() throws Exception { final ComponentProfile[] components = m_dependencyMap.getStartupGraph( m_store ); processComponents( true, components ); } /** * Request shutdown of all components. * @exception Exception if there is an error during shutdown */ protected final void shutdownAllComponents() throws Exception { final ComponentProfile[] components = m_dependencyMap.getShutdownGraph( m_store ); processComponents( false, components ); } /** * Request startup of a named component. * @param name the name of the component to startup * @exception Exception if there is an error during component startup */ protected final void startupComponent( final String name ) throws Exception { final ComponentProfile entry = m_store.getComponent( name ); final ComponentProfile[] components = m_dependencyMap.getProviderGraph( entry, m_store ); processComponents( true, components ); } /** * Request shutdown of a named component. * @param name the name of the component to shutdown * @exception Exception if there is an error during component shutdown */ protected final void shutdownComponent( final String name ) throws Exception { final ComponentProfile entry = m_store.getComponent( name ); final ComponentProfile[] components = m_dependencyMap.getConsumerGraph( entry, m_store ); processComponents( false, components ); } /** * Return the [EMAIL PROTECTED] ComponentFactory} associated with kernel. * * @return the [EMAIL PROTECTED] ComponentFactory} associated with kernel. */ protected final ComponentFactory getFactory() { return m_factory; } /** * Add a Component to the container. * This Must be called before any components are started * or else an exception is raised. * * @param component the component */ protected final void addComponent( final ComponentMetaData component ) throws Exception { final ComponentBundle bundle = m_factory.createBundle( component.getImplementationKey() ); final ComponentInfo info = bundle.getComponentInfo(); final ComponentProfile profile = new ComponentProfile( info, component ); final ComponentEntry entry = new ComponentEntry( profile ); m_entrySet.put( component.getName(), entry ); m_store.addComponent( profile ); } public final Object getComponent( final String name ) { final ComponentEntry entry = (ComponentEntry)m_entrySet.get( name ); if( null != entry ) { return entry.getObject(); } else { return null; } } /** * Process a whole assembly through a lifecycle phase * (ie startup or shutdown). The components should be processed * in order specified by the dependency graph. * * @param startup true if application startup phase, false if shutdown phase * @throws Exception if there is error processing any of the components * through the phases */ private void processComponents( final boolean startup, final ComponentProfile[] components ) throws Exception { processComponentsNotice( components, startup ); Exception exception = null; for( int i = 0; i < components.length; i++ ) { try { processComponent( components[ i ], startup ); } catch( final Exception e ) { //during startup we should fail immediately //while during shutdown of component you need to shutdown //all components regardless of whether some of them don't //shutdown cleanly if( startup ) { throw e; } else { exception = e; } } } if( null != exception ) { throw exception; } } private void processComponent( final ComponentProfile component, final boolean startup ) throws Exception { final String name = component.getMetaData().getName(); final ComponentEntry entry = (ComponentEntry)m_entrySet.get( name ); processComponent( entry, startup ); } /** * Process a component through a lifecycle phase * (ie startup or shutdown). If it is startup phase then * it is expected that all the providers for the components * dependencies have been process. If it is the shutdown phase * it is expected that all of the consumers of services provided * by this component have already been shutdown. * * @param component the component * @param startup true if application startup phase, false if shutdown phase * @throws Exception if there is error processing any of the components * through the phases */ private void processComponent( final ComponentEntry component, final boolean startup ) throws Exception { final String name = component.getProfile().getMetaData().getName(); if( startup == component.isActive() ) { //If component is already started and we said start //or the component is already stopped and we said stop //then skip it. return; } processComponentNotice( startup, name, false ); try { if( startup ) { final Object object = m_lifecycleHelper.startup( name, component, m_resourceProvider ); component.setObject( object ); } else { final Object object = component.getObject(); component.setObject( null ); m_lifecycleHelper.shutdown( name, object ); } } catch( final Exception e ) { final String message = REZ.getString( "app.error.run-phase", startup ? "0":"1", name, e.getMessage() ); getLogger().error( message, e ); throw e; } processComponentNotice( startup, name, true ); } /** * Log message describing the number of components * the phase in and the order in which they will be * processed * * @param order the order the components will be processed in * @param startup true if application startup phase, false if shutdown phase */ private void processComponentsNotice( final ComponentProfile[] order, final boolean startup ) { if( getLogger().isInfoEnabled() ) { final Integer count = new Integer( order.length ); final List pathList = new ArrayList(); for( int i = 0; i < order.length; i++ ) { ComponentProfile componentEntry = order[ i ]; pathList.add( componentEntry.getMetaData().getName() ); } final String message = REZ.getString( "components-processing", count, startup ? "0":"1", pathList ); getLogger().info( message ); } } /** * Log processing of component. * * @param name the name of component processing * @param startup true if application startup phase, false if shutdown phase */ private void processComponentNotice( final boolean startup, final String name, final boolean completed ) { if( getLogger().isDebugEnabled() ) { final String key = completed ? "processed-component": "process-component"; final String message = REZ.getString( key, startup ? "0":"1", name ); getLogger().debug( message ); } } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/kernel/ComponentEntry.java Index: ComponentEntry.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.avalon.phoenix.containerkit.kernel; import org.apache.avalon.phoenix.containerkit.registry.ComponentProfile; /** * This is the structure that components are contained within when * loaded into a container. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public class ComponentEntry { /** * The [EMAIL PROTECTED] ComponentProfile} that describes * this component. */ private final ComponentProfile m_profile; /** * The instance of this component. */ private Object m_object; /** * Creation of a new <code>ComponentEntry</code> instance. * * @param profile the [EMAIL PROTECTED] ComponentProfile} instance defining the component. */ public ComponentEntry( final ComponentProfile profile ) { if( null == profile ) { throw new NullPointerException( "profile" ); } m_profile = profile; } /** * Returns the [EMAIL PROTECTED] ComponentProfile} for this component. * * @return the [EMAIL PROTECTED] ComponentProfile} for this component. */ public ComponentProfile getProfile() { return m_profile; } /** * Returns the the object associated with this entry. * @return the entry object */ public Object getObject() { return m_object; } /** * Set the object assoaiated to this entry. * @param object the object to associate with the entry */ public void setObject( final Object object ) { m_object = object; } /** * Returns TRUE is the object for this entry has been set. * @return the active status of this entry */ public boolean isActive() { return ( null != getObject() ); } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/kernel/ComponentReference.java Index: ComponentReference.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.avalon.phoenix.containerkit.kernel; import org.apache.avalon.framework.info.ComponentInfo; /** * This interface defines a resource returned from the * [EMAIL PROTECTED] ComponentDirectory}. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public interface ComponentReference { /** * Return the underlying object representing the Component. * * @return the underlying object representing the Component */ Object getComponent(); /** * @todo Determine if this is reallly needed. It is only * returned as a result of Directory lookup, hence should * know the type. * @todo Determine if this could be replace by getInfo() */ ComponentInfo getInfo(); /** * Invalidate the component reference. After the reference has been * invalidated, any calls made on the Compnent will have undefined * results. */ void invalidate(); } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/kernel/ComponentStore.java Index: ComponentStore.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.avalon.phoenix.containerkit.kernel; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.avalon.phoenix.containerkit.registry.ComponentProfile; /** * * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public class ComponentStore { /** * Parent [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.ComponentStore}. Components in parent * [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.ComponentStore} are potential Providers for services * if no component in current [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.ComponentStore} satisfies * dependency. */ private final ComponentStore m_parent; /** * The child [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.ComponentStore} objects. * Possible consumers of services in this assembly. */ private final ArrayList m_children = new ArrayList(); /** * The set of components in assembly. * Used when searching for providers/consumers. */ private final Map m_components = new HashMap(); /** * Create a root ComponentStore without any parent * ComponentStore. */ public ComponentStore() { this( null ); } /** * Return the parent ComponentStore (may be null). */ public ComponentStore getParent() { return m_parent; } /** * Create a root ComponentStore with specified parent * ComponentStore. */ public ComponentStore( final ComponentStore parent ) { m_parent = parent; } /** * Add child [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.ComponentStore}. * * @param child the child [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.ComponentStore}. */ public void addChildStore( final ComponentStore child ) { m_children.add( child ); } /** * Return the list of child [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.ComponentStore}s. * * @return the list of child [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.ComponentStore}s. */ public List getChildStores() { return m_children; } /** * Remove child [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.ComponentStore}. * * @param child the child [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.kernel.ComponentStore}. */ public void removeChildStore( final ComponentStore child ) { m_children.remove( child ); } /** * Add a component to store. * * @param component the component */ public void addComponent( final ComponentProfile component ) { final String name = component.getMetaData().getName(); m_components.put( name, component ); } /** * Remove a component from the store. * * @param component the component */ public void removeComponent( final ComponentProfile component ) { final String name = component.getMetaData().getName(); m_components.remove( name ); } /** * Return a component with specified name. * * @return a component with specified name */ public ComponentProfile getComponent( final String name ) { return (ComponentProfile)m_components.get( name ); } /** * Return a collection containing all the * names of components in store. No ordering of * components is guarenteed or mandated. * * @return the collection containing all component names */ public Collection getComponentNames() { final Collection collection = m_components.keySet(); final ArrayList components = new ArrayList(); components.addAll( collection ); return components; } /** * Return a collection containing all the * components in store. Noordering of * components is guarenteed or mandated. * * @return the collection containing all components */ public Collection getComponents() { final Collection collection = m_components.values(); final ArrayList components = new ArrayList(); components.addAll( collection ); return components; } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/kernel/Resources.properties Index: Resources.properties =================================================================== processed-component=Processed component {0}. components-processing=Processing component {0} in phase {1} from {2}. process-component=Processing component {0}, named "{1}". lifecycle-shutdown.error=Error shutting down LifecycleHelper. 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/kernel/package.html Index: package.html =================================================================== <body> Base and abstract classes supporting defintion of an interaction with a container kernel. </body> 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/kernel/processor/DependencyMap.java Index: DependencyMap.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.avalon.phoenix.containerkit.kernel.processor; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.avalon.framework.info.DependencyDescriptor; import org.apache.avalon.phoenix.containerkit.kernel.ComponentStore; import org.apache.avalon.phoenix.containerkit.metadata.ComponentMetaData; import org.apache.avalon.phoenix.containerkit.metadata.DependencyMetaData; import org.apache.avalon.phoenix.containerkit.registry.ComponentProfile; /** * Utility class to help aquire a ordered graph of * consumers and providers for specific components. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public class DependencyMap { /** * Get the serilized graph of [EMAIL PROTECTED] ComponentProfile} 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 ComponentProfile[] getStartupGraph( final ComponentStore store ) { return walkGraph( true, store ); } /** * Get the serilized graph of [EMAIL PROTECTED] ComponentProfile} 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 ComponentProfile[] getShutdownGraph( final ComponentStore store ) { return walkGraph( false, store ); } /** * Get the serilized graph of [EMAIL PROTECTED] ComponentProfile} objects * that use services of specified component. * * @param component the component * @return the ordered list of consumers */ public ComponentProfile[] getConsumerGraph( final ComponentProfile component, final ComponentStore store ) { return getComponentGraph( component, false, store ); } /** * Get the serilized graph of [EMAIL PROTECTED] ComponentProfile} objects * that provide specified component with services. * * @param component the component * @return the ordered list of providers */ public ComponentProfile[] getProviderGraph( final ComponentProfile component, final ComponentStore store ) { return getComponentGraph( component, true, store ); } /** * Get the graph of a single component. * * @param component the component * @param providers true if traversing providers, false if consumers * @return the list of components in graph */ private ComponentProfile[] getComponentGraph( final ComponentProfile component, final boolean providers, final ComponentStore store ) { final ArrayList result = new ArrayList(); visitcomponent( component, providers, new ArrayList(), result, store ); final ComponentProfile[] returnValue = new ComponentProfile[ result.size() ]; return (ComponentProfile[])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 ComponentProfile[] walkGraph( final boolean providers, final ComponentStore store ) { final ArrayList result = new ArrayList(); final ArrayList done = new ArrayList(); final Collection components = store.getComponents(); final ComponentProfile[] entrySet = (ComponentProfile[])components.toArray( new ComponentProfile[ components.size() ] ); for( int i = 0; i < entrySet.length; i++ ) { final ComponentProfile component = entrySet[ i ]; visitcomponent( component, providers, done, result, store ); } final ComponentProfile[] returnValue = new ComponentProfile[ result.size() ]; return (ComponentProfile[])result.toArray( returnValue ); } /** * Visit a component when traversing dependencies. * * @param component the component * @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 ComponentProfile component, final boolean providers, final ArrayList done, final ArrayList order, final ComponentStore store ) { //If already visited this component then bug out early if( done.contains( component ) ) { return; } done.add( component ); if( providers ) { visitProviders( component, done, order, store ); } else { visitConsumers( component, done, order, store ); } order.add( component ); } /** * Traverse graph of components that provide services to * the specified component. * * @param component the ComponentProfile */ private void visitProviders( final ComponentProfile component, final ArrayList done, final ArrayList order, final ComponentStore store ) { final DependencyDescriptor[] descriptors = component.getInfo().getDependencies(); final ComponentMetaData metaData = component.getMetaData(); for( int i = 0; i < descriptors.length; i++ ) { final DependencyMetaData dependency = metaData.getDependency( descriptors[ i ].getKey() ); // added != null clause to catch cases where an optional // dependency exists and the dependecy has not been bound // to a provider if( dependency != null ) { final ComponentProfile other = getComponent( dependency.getProviderName(), store ); visitcomponent( other, true, done, order, store ); } } } /** * Traverse all Consumers of component. ie Anyone that uses * service provided by component. * * @param component the ComponentProfile */ private void visitConsumers( final ComponentProfile component, final ArrayList done, final ArrayList order, final ComponentStore store ) { final String name = component.getMetaData().getName(); final Collection components = store.getComponents(); final ComponentProfile[] entrySet = (ComponentProfile[])components.toArray( new ComponentProfile[ components.size() ] ); for( int i = 0; i < entrySet.length; i++ ) { final ComponentProfile other = entrySet[ i ]; final DependencyMetaData[] dependencies = other.getMetaData().getDependencies(); for( int j = 0; j < dependencies.length; j++ ) { final String depends = dependencies[ j ].getProviderName(); if( depends.equals( name ) ) { visitcomponent( other, false, done, order, store ); } } } final List childStores = store.getChildStores(); final int childCount = childStores.size(); for( int i = 0; i < childCount; i++ ) { final ComponentStore child = (ComponentStore)childStores.get( i ); visitConsumers( component, done, order, child ); } } /** * Utility method to get component with specified name from specified array. * * @param name the name of component * @return the component */ private ComponentProfile getComponent( final String name, final ComponentStore store ) { final ComponentProfile component = store.getComponent( name ); if( null != component ) { return component; } final ComponentStore parent = store.getParent(); if( null != parent ) { return parent.getComponent( name ); } //Should never happen if Verifier passed checks throw new IllegalStateException(); } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/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.avalon.phoenix.containerkit.lifecycle; import org.apache.avalon.framework.CascadingException; /** * Exception to indicate error processing a component through its lifecycle. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ 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-phoenix/src/java/org/apache/avalon/phoenix/containerkit/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.avalon.phoenix.containerkit.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; /** * 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 at apache.org">Peter Donald</a> * @author <a href="mailto:[EMAIL PROTECTED]">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 entry the entry representing object * @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 Object entry, final ResourceProvider provider ) throws LifecycleException { int stage = 0; try { //Creation stage stage = STAGE_CREATE; notice( name, stage ); final Object object = provider.createObject( entry ); //LogEnabled stage stage = STAGE_LOGGER; if( object instanceof LogEnabled ) { notice( name, stage ); final Logger logger = provider.createLogger( entry ); ContainerUtil.enableLogging( object, logger ); } //Contextualize stage stage = STAGE_CONTEXT; if( object instanceof Contextualizable ) { notice( name, stage ); final Context context = provider.createContext( entry ); ContainerUtil.contextualize( object, context ); } //Composition stage stage = STAGE_COMPOSE; if( object instanceof Serviceable ) { notice( name, stage ); final ServiceManager manager = provider.createServiceManager( entry ); ContainerUtil.service( object, manager ); } else if( object instanceof Composable ) { notice( name, stage ); final ComponentManager componentManager = provider.createComponentManager( entry ); ContainerUtil.compose( object, componentManager ); } //Configuring stage stage = STAGE_CONFIG; if( object instanceof Configurable ) { notice( name, stage ); final Configuration configuration = provider.createConfiguration( entry ); ContainerUtil.configure( object, configuration ); } //Parameterizing stage stage = STAGE_PARAMETER; if( object instanceof Parameterizable ) { notice( name, stage ); final Parameters parameters = provider.createParameters( entry ); ContainerUtil.parameterize( object, parameters ); } //Initialize stage stage = STAGE_INIT; if( object instanceof Initializable ) { notice( name, stage ); ContainerUtil.initialize( object ); } //Start stage stage = STAGE_START; if( object instanceof Startable ) { notice( name, stage ); ContainerUtil.start( object ); } 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-phoenix/src/java/org/apache/avalon/phoenix/containerkit/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.avalon.phoenix.containerkit.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; /** * The interface via which resources required for a component * are aquired. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:43 $ */ public interface ResourceProvider { String ROLE = ResourceProvider.class.getName(); /** * Create the object specified by entry. * * @param entry the entry * @return the new object * @throws Exception if unable to create resource */ Object createObject( Object entry ) throws Exception; /** * Create a new Logger for component. * * @param entry the entry * @return a new Logger for component * @throws Exception if unable to create resource */ Logger createLogger( Object entry ) throws Exception; /** * Create a new Context for component. * * @param entry the entry * @return a new Context for component * @throws Exception if unable to create resource */ Context createContext( Object entry ) throws Exception; /** * Create a new ComponentManager for component. * * @param entry the entry * @return a new ComponentManager for component * @throws Exception if unable to create resource */ ComponentManager createComponentManager( Object entry ) throws Exception; /** * Create a new ServiceManager for component. * * @param entry the entry * @return a new ServiceManager for component * @throws Exception if unable to create resource */ ServiceManager createServiceManager( Object entry ) throws Exception; /** * 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 */ Configuration createConfiguration( Object entry ) throws Exception; /** * 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 */ Parameters createParameters( Object entry ) throws Exception; } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/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-phoenix/src/java/org/apache/avalon/phoenix/containerkit/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/LifecycleHelper.gif border=0></p> <p><img src=doc-files/ResourceProvider.gif border=0></p> </body> 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/lifecycle/impl/AbstractResourceProvider.java Index: AbstractResourceProvider.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.avalon.phoenix.containerkit.lifecycle.impl; 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.info.ComponentInfo; import org.apache.avalon.framework.info.ContextDescriptor; import org.apache.avalon.framework.info.EntryDescriptor; 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.avalon.phoenix.containerkit.factory.ComponentBundle; import org.apache.avalon.phoenix.containerkit.factory.ComponentFactory; import org.apache.avalon.phoenix.containerkit.lifecycle.ResourceProvider; import org.apache.avalon.phoenix.containerkit.metadata.ComponentMetaData; import org.apache.avalon.phoenix.containerkit.metadata.DependencyMetaData; /** * This is a base object via which the * [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.lifecycle.LifecycleHelper} * 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. * * <p>Note that this class assumes that the dependency graph * has been validated (presumably via * [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.verifier.AssemblyVerifier}</p> * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:44 $ */ public abstract class AbstractResourceProvider extends AbstractLogEnabled implements ResourceProvider { private final static Resources REZ = ResourceManager.getPackageResources( AbstractResourceProvider.class ); private final ComponentFactory m_factory; protected AbstractResourceProvider( final ComponentFactory factory ) { if( null == factory ) { throw new NullPointerException( "factory" ); } m_factory = factory; } /** * Utility method via which the provider aquires services to place * in ServiceManager for a particular component. * * <p>Must be implemented in subclass.</p> * * @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 provider aquires a context value * to place in Context for a particular component. * * <p>Must be implemented in subclass.</p> * * @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 ); /** * Create a component for a particular entry. * This implementation uses the associated * [EMAIL PROTECTED] ComponentFactory} to create instance of * component. * * @param entry the entry * @return the newly created component * @throws Exception if unable to create component */ public Object createObject( final Object entry ) throws Exception { final ComponentMetaData component = getMetaData( entry ); final String implementationKey = component.getImplementationKey(); return m_factory.createComponent( implementationKey ); } /** * 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 ComponentMetaData component = getMetaData( entry ); final Parameters parameters = component.getParameters(); if( null == parameters ) { final String message = REZ.getString( "resource.missing-parameters.error", component.getName() ); throw new Exception( message ); } parameters.makeReadOnly(); return parameters; } /** * 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( Object entry ) throws Exception { final ComponentMetaData component = getMetaData( entry ); final Configuration configuration = component.getConfiguration(); if( null == configuration ) { final String message = REZ.getString( "resource.missing-configuration.error", component.getName() ); throw new Exception( message ); } return configuration; } /** * Create a [EMAIL PROTECTED] 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 [EMAIL PROTECTED] ComponentMetaData} for specified component entry. * This implementation assumes that entry is instance of [EMAIL PROTECTED] org.apache.avalon.phoenix.containerkit.metadata.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 ) { return (ComponentMetaData)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( componentEntry ); final String componentName = component.getName(); final String impl = component.getImplementationKey(); final ComponentBundle bundle = m_factory.createBundle( impl ); final ComponentInfo info = bundle.getComponentInfo(); final ContextDescriptor descriptor = info.getContext(); final Map contextData = new HashMap(); final EntryDescriptor[] entrys = descriptor.getEntrys(); for( int i = 0; i < entrys.length; i++ ) { final EntryDescriptor entry = entrys[ i ]; final String key = entry.getKey(); final String type = entry.getType(); final boolean optional = entry.isOptional(); final Object value = getContextValue( key, componentEntry ); if( null == value ) { final String message = REZ.getString( "resource.missing-context-value.error", optional ? "1" : "2", key, componentName ); if( !optional ) { throw new Exception( message ); } else { getLogger().warn( message ); continue; } } final boolean typeValid = objectImplementsType( value, type ); if( !typeValid ) { final String message = REZ.getString( "resource.bad-value-type.error", optional ? "1" : "2", key, componentName, type, value.getClass().getName() ); if( !optional ) { throw new Exception( message ); } else { getLogger().warn( message ); continue; } } contextData.put( key, value ); } final Context context = createContextImpl( contextData ); final String classname = descriptor.getType(); 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; } /** * Create a new ComponentManager for component. * * @param entry the entry * @return a new ComponentManager for component * @throws Exception if unable to create resource */ public final ComponentManager createComponentManager( final Object entry ) throws Exception { 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; } /** * Create a new ServiceManager for component. * * @param entry the entry * @return a new ServiceManager for component * @throws Exception if unable to create resource */ public final ServiceManager createServiceManager( final Object entry ) throws Exception { 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; } /** * Accessor for component factory for sub-classes. * * @return the componentFactory associated with ResourceProvider. */ protected final ComponentFactory getComponentFactory() { return m_factory; } /** * Create a Map of services for specified component. * The map maps key 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 String impl = component.getImplementationKey(); final ComponentBundle bundle = m_factory.createBundle( impl ); final ComponentInfo info = bundle.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 key = dependency.getKey(); final String providerName = dependency.getProviderName(); final boolean optional = info.getDependency( key ).isOptional(); final Object service = getService( providerName, componentEntry ); if( null == service ) { final String message = REZ.getString( "resource.missing-dependency.error", optional ? "1" : "2", key, component.getName() ); if( !optional ) { throw new Exception( message ); } else { getLogger().warn( message ); continue; } } services.put( key, 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-phoenix/src/java/org/apache/avalon/phoenix/containerkit/lifecycle/impl/Resource.properties Index: Resource.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 key "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 key "{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-phoenix/src/java/org/apache/avalon/phoenix/containerkit/lifecycle/impl/package.html Index: package.html =================================================================== <body> Implementation of a abstract resource provider. </body> 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/metadata/ComponentMetaData.java Index: ComponentMetaData.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.avalon.phoenix.containerkit.metadata; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.info.Attribute; import org.apache.avalon.framework.info.FeatureDescriptor; import org.apache.avalon.framework.parameters.Parameters; /** * Each component declared in the application is represented by * a ComponentMetaData. Note that this does not necessarily imply * that there is only one instance of actual component. The * ComponentMetaData could represent a pool of components, a single * component or a component prototype that is reused to create * new components as needed. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:44 $ */ public class ComponentMetaData extends FeatureDescriptor { /** * The name of the component. This is an * abstract name used during assembly. */ private final String m_name; /** * The implementationKey for this component. * Usually this represents a classname but * alternative mechanisms could be used (ie URL * of webservice). */ private final String m_implementationKey; /** * The resolution of any dependencies required by * the component type. */ private final DependencyMetaData[] m_dependencies; /** * The parameters for component (if any). */ private final Parameters m_parameters; /** * The configuration for component (if any). */ private final Configuration m_configuration; /** * Create a ComponentMetaData. * * @param name the abstract name of component meta data instance * @param implementationKey the key used to create component (usually a classname) * @param dependencies the meta data for any dependencies * @param parameters the parameters that the component will be provided (may be null) * @param configuration the configuration that the component will be provided (may be null) * @param attributes the extra attributes that are used to describe component */ public ComponentMetaData( final String name, final String implementationKey, final DependencyMetaData[] dependencies, final Parameters parameters, final Configuration configuration, final Attribute[] attributes ) { super( attributes ); if( null == name ) { throw new NullPointerException( "name" ); } if( null == dependencies ) { throw new NullPointerException( "dependencies" ); } if( null == implementationKey ) { throw new NullPointerException( "implementationKey" ); } m_name = name; m_dependencies = dependencies; m_parameters = parameters; m_configuration = configuration; m_implementationKey = implementationKey; } /** * Return the name of component metadata. * * @return the name of the component metadata. */ public String getName() { return m_name; } /** * Return the implementationKey for component. * * @return the implementationKey for component. */ public String getImplementationKey() { return m_implementationKey; } /** * Return the dependency for component. * * @return the dependency for component. */ public DependencyMetaData[] getDependencies() { return m_dependencies; } /** * Return the Parameters for Component (if any). * * @return the Parameters for Component (if any). */ public Parameters getParameters() { return m_parameters; } /** * Return the Configuration for Component (if any). * * @return the Configuration for Component (if any). */ public Configuration getConfiguration() { return m_configuration; } /** * Return the dependency for component with specified key. * * @return the dependency for component with specified key. */ public DependencyMetaData getDependency( final String key ) { for( int i = 0; i < m_dependencies.length; i++ ) { if( m_dependencies[ i ].getKey().equals( key ) ) { return m_dependencies[ i ]; } } return null; } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/metadata/DependencyMetaData.java Index: DependencyMetaData.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.avalon.phoenix.containerkit.metadata; import org.apache.avalon.framework.info.FeatureDescriptor; import org.apache.avalon.framework.info.Attribute; /** * The [EMAIL PROTECTED] DependencyMetaData} is the mapping of a component as a dependency * of another component. Each component declares dependencies (via * [EMAIL PROTECTED] org.apache.avalon.framework.info.ComponentInfo}) * and for each dependency there must be a coressponding DependencyMetaData which * has a matching key. The name value in [EMAIL PROTECTED] DependencyMetaData} object must refer * to another Component that implements a service as specified in DependencyInfo. * * <p>Note that it is invalid to have circular dependencies.</p> * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:44 $ */ public final class DependencyMetaData extends FeatureDescriptor { /** * The key that the client component will use to access a dependency. */ private final String m_key; /** * the name of the component profile that represents a component * type that is capable of fullfilling the dependency. */ private final String m_providerName; /** * The key that is used when the dependency is a map dependency. * Usually this defaults to the same value as the key. */ private final String m_alias; /** * Create Association between key and provider. * * @param key the key the client uses to access component * @param providerName the name of [EMAIL PROTECTED] ComponentMetaData} * that is associated as a service provider */ public DependencyMetaData( final String key, final String providerName, final String alias, final Attribute[] attributes ) { super( attributes ); if( null == key ) { throw new NullPointerException( "key" ); } if( null == providerName ) { throw new NullPointerException( "providerName" ); } if( null == alias ) { throw new NullPointerException( "alias" ); } m_key = key; m_providerName = providerName; m_alias = alias; } /** * Return the key that will be used by a component instance to access a * dependent service. * * @return the name that the client component will use to access dependency. * @see org.apache.avalon.framework.service.ServiceManager#lookup( String ) */ public String getKey() { return m_key; } /** * Return the name of a [EMAIL PROTECTED] ComponentMetaData} instance that will used to * fulfill the dependency. * * @return the name of the Component that will provide the dependency. */ public String getProviderName() { return m_providerName; } /** * The key under which the dependency is placed in map if dependency is * a Map dependency. * * @return the key under which the dependency is placed in map if dependency is * a Map dependency. */ public String getAlias() { return m_alias; } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/metadata/MetaDataBuilder.java Index: MetaDataBuilder.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.avalon.phoenix.containerkit.metadata; import java.util.Map; /** * Load metadata for an Assembly from some source. * The source is usually one or more xml config files. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:44 $ */ public interface MetaDataBuilder { /** * Load metadata from a particular source * using specified map of parameters. The content * of the parameters is left unspecified. * * @param parameters the parameters indicating method to load meta data source * @return the set of components in metadata * @throws Exception if unable to load or resolve * meta data for any reason */ PartitionMetaData buildAssembly( Map parameters ) throws Exception; } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/metadata/PartitionMetaData.java Index: PartitionMetaData.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.avalon.phoenix.containerkit.metadata; import org.apache.avalon.framework.info.Attribute; import org.apache.avalon.framework.info.FeatureDescriptor; /** * In each Assembly there may be groups of components that * are activated together and treated as a group. These * components are all "visible" to each other as peers. * The group will have a name and may use resources from * other partitions. Partitions can also be nested one inside * each other. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:44 $ */ public class PartitionMetaData extends FeatureDescriptor { /** * Constant for an empty set of partitions. */ public static final PartitionMetaData[] EMPTY_SET = new PartitionMetaData[ 0 ]; /** * The name of the partition. This is an * abstract name used during assembly. */ private final String m_name; /** * An array listing the set of other partitions required by * this partition. The required partitions must be initialized * and in ready state prior to this partition starting and this * partition must be shutdown prior */ private final String[] m_depends; /** * AN array of partitions that are contained by this * object. */ private final PartitionMetaData[] m_partitions; /** * AN array of components that are contained by this * object. */ private final ComponentMetaData[] m_components; /** * Create a PartitionMetaData. * * @param name the abstract name of component meta data instance * @param depends the partitions depended upon by this parition * @param partitions the partitions contained by this partition * @param components the components contained by this partition * @param attributes the extra attributes that are used to describe component */ public PartitionMetaData( final String name, final String[] depends, final PartitionMetaData[] partitions, final ComponentMetaData[] components, final Attribute[] attributes ) { super( attributes ); if( null == name ) { throw new NullPointerException( "name" ); } if( null == depends ) { throw new NullPointerException( "depends" ); } if( null == partitions ) { throw new NullPointerException( "partitions" ); } if( null == components ) { throw new NullPointerException( "components" ); } m_name = name; m_depends = depends; m_partitions = partitions; m_components = components; } /** * Return the name of component profile. * * @return the name of the component profile. */ public String getName() { return m_name; } /** * Return the set of prereqs for this partition. * * @return the set of prereqs for this partition. */ public String[] getDepends() { return m_depends; } /** * Return the set of partitions contained in this partition. * * @return the set of partitions contained in this partition. */ public PartitionMetaData[] getPartitions() { return m_partitions; } /** * Return the set of components contained in this partition. * * @return the set of components contained in this partition. */ public ComponentMetaData[] getComponents() { return m_components; } /** * Return the partition with specified name. * * @return the partition with specified name. */ public PartitionMetaData getPartition( final String name ) { for( int i = 0; i < m_partitions.length; i++ ) { final PartitionMetaData partition = m_partitions[ i ]; if( partition.getName().equals( name ) ) { return partition; } } return null; } /** * Return the component with specified name. * * @return the component with specified name. */ public ComponentMetaData getComponent( final String name ) { for( int i = 0; i < m_components.length; i++ ) { final ComponentMetaData component = m_components[ i ]; if( component.getName().equals( name ) ) { return component; } } return null; } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/metadata/package.html Index: package.html =================================================================== <body> A set of classes supporting the representation of information about a component assembly. </body> 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/registry/ComponentProfile.java Index: ComponentProfile.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.avalon.phoenix.containerkit.registry; import org.apache.avalon.framework.info.ComponentInfo; import org.apache.avalon.phoenix.containerkit.metadata.ComponentMetaData; /** * The ComponentProfile defines a component as a conjunction * of the [EMAIL PROTECTED] ComponentInfo} and [EMAIL PROTECTED] ComponentMetaData}. * The [EMAIL PROTECTED] ComponentInfo} defines the type of the component * and the [EMAIL PROTECTED] ComponentMetaData} defines the data required to * construct a specific instance of the component. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:44 $ */ public class ComponentProfile { /** * The [EMAIL PROTECTED] ComponentInfo} that describes * the type of this component. */ private final ComponentInfo m_info; /** * The [EMAIL PROTECTED] ComponentMetaData} that describes * this component. */ private final ComponentMetaData m_metaData; /** * Creation of a new <code>ComponentProfile</code> instance. * * @param metaData the [EMAIL PROTECTED] ComponentMetaData} instance defining the component. */ public ComponentProfile( final ComponentInfo info, final ComponentMetaData metaData ) { m_info = info; m_metaData = metaData; } /** * Returns the underlying [EMAIL PROTECTED] ComponentInfo} instance. * * @return the component info instance */ public ComponentInfo getInfo() { return m_info; } /** * Returns the underlying [EMAIL PROTECTED] ComponentMetaData} instance. * @return the component meta data instance */ public ComponentMetaData getMetaData() { return m_metaData; } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/registry/PartitionProfile.java Index: PartitionProfile.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.avalon.phoenix.containerkit.registry; import org.apache.avalon.phoenix.containerkit.metadata.PartitionMetaData; /** * The PartitionProfile contains the set of data required * to construct a specific instance of a Profile. It contains * a set of child PartitionProfile and [EMAIL PROTECTED] ComponentProfile} * objects. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:44 $ */ public class PartitionProfile { /** * Constant for an empty set of partitions. */ public static final PartitionProfile[] EMPTY_SET = new PartitionProfile[ 0 ]; /** * The [EMAIL PROTECTED] PartitionMetaData} for this partition. */ private final PartitionMetaData m_metaData; /** * An array of partitions that are contained by this * object. */ private final PartitionProfile[] m_partitions; /** * An array of partitions that are contained by this * object. */ private final ComponentProfile[] m_components; /** * Create a PartitionProfile. * * @param metaData the meta data about this profile * @param partitions the partitions contained by this partition * @param components the components contained by this partition */ public PartitionProfile( final PartitionMetaData metaData, final PartitionProfile[] partitions, final ComponentProfile[] components ) { if( null == metaData ) { throw new NullPointerException( "metaData" ); } if( null == partitions ) { throw new NullPointerException( "partitions" ); } if( null == components ) { throw new NullPointerException( "components" ); } m_metaData = metaData; m_partitions = partitions; m_components = components; } /** * Return the metaData about this profile. * * @return the metaData about this profile. */ public PartitionMetaData getMetaData() { return m_metaData; } /** * Return the set of partitions contained in this partition. * * @return the set of partitions contained in this partition. */ public PartitionProfile[] getPartitions() { return m_partitions; } /** * Return the set of components contained in this partition. * * @return the set of components contained in this partition. */ public ComponentProfile[] getComponents() { return m_components; } /** * Return the partition with specified name. * * @return the partition with specified name. */ public PartitionProfile getPartition( final String name ) { for( int i = 0; i < m_partitions.length; i++ ) { final PartitionProfile partition = m_partitions[ i ]; if( partition.getMetaData().getName().equals( name ) ) { return partition; } } return null; } /** * Return the component with specified name. * * @return the component with specified name. */ public ComponentProfile getComponent( final String name ) { for( int i = 0; i < m_components.length; i++ ) { final ComponentProfile component = m_components[ i ]; if( component.getMetaData().getName().equals( name ) ) { return component; } } return null; } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/registry/ProfileBuilder.java Index: ProfileBuilder.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.avalon.phoenix.containerkit.registry; import java.util.Map; /** * Load metadata for an Assembly from some source. * The source is usually one or more xml config files. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:44 $ */ public interface ProfileBuilder { /** * Load metadata from a particular source * using specified map of parameters. The content * of the parameters is left unspecified. * * @param parameters the parameters indicating method to load meta data source * @return the set of components in metadata * @throws Exception if unable to load or resolve * meta data for any reason */ PartitionProfile buildProfile( Map parameters ) throws Exception; } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/verifier/AssemblyVerifier.java Index: AssemblyVerifier.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.avalon.phoenix.containerkit.verifier; import java.util.ArrayList; import java.util.Stack; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; import org.apache.avalon.framework.info.ComponentInfo; import org.apache.avalon.framework.info.DependencyDescriptor; import org.apache.avalon.framework.info.ServiceDescriptor; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.tools.verifier.VerifyException; import org.apache.avalon.phoenix.containerkit.metadata.DependencyMetaData; import org.apache.avalon.phoenix.containerkit.registry.ComponentProfile; /** * This Class verifies that Sars are valid. It performs a number * of checks to make sure that the Sar represents a valid * application and excluding runtime errors will start up validly. * Some of the checks it performs include; * * <ul> * <li>Verify names of Components contain only * letters, digits or the '_' character.</li> * <li>Verify that the names of the Components are unique to the * Assembly.</li> * <li>Verify that the specified dependeny mapping correspond to * dependencies specified in ComponentInfo files.</li> * <li>Verify that the inter-Component dependendencies are valid. * This essentially means that if Component A requires Service S * from Component B then Component B must provide Service S.</li> * <li>Verify that there are no circular dependendencies between * components.</li> * <li>Verify that the Class objects for component implement the * service interfaces.</li> * <li>Verify that the Class is a valid Avalon Component as per the * rules in [EMAIL PROTECTED] org.apache.avalon.framework.tools.verifier.ComponentVerifier} object.</li> * </ul> * * @author <a href="mailto:peter at apache.org">Peter Donald</a> * @version $Revision: 1.1 $ $Date: 2003/01/18 16:43:44 $ */ public class AssemblyVerifier extends AbstractLogEnabled { private static final Resources REZ = ResourceManager.getPackageResources( AssemblyVerifier.class ); /** * Validate and Verify the specified assembly (ie organization * of components). See the Class Javadocs for the rules and * regulations of assembly. * * @param components the Components that make up assembly * @throws org.apache.avalon.framework.tools.verifier.VerifyException if an error occurs */ public void verifyAssembly( final ComponentProfile[] components ) throws VerifyException { String message = null; message = REZ.getString( "assembly.valid-names.notice" ); getLogger().info( message ); verifyValidNames( components ); message = REZ.getString( "assembly.unique-names.notice" ); getLogger().info( message ); checkNamesUnique( components ); message = REZ.getString( "assembly.dependencies-mapping.notice" ); getLogger().info( message ); verifyValidDependencies( components ); message = REZ.getString( "assembly.dependency-references.notice" ); getLogger().info( message ); verifyDependencyReferences( components ); message = REZ.getString( "assembly.nocircular-dependencies.notice" ); getLogger().info( message ); verifyNoCircularDependencies( components ); } /** * Verfiy that all Components have the needed dependencies specified correctly. * * @param components the ComponentEntry objects for the components * @throws org.apache.avalon.framework.tools.verifier.VerifyException if an error occurs */ public void verifyValidDependencies( final ComponentProfile[] components ) throws VerifyException { for( int i = 0; i < components.length; i++ ) { verifyDependenciesMap( components[ i ] ); } } /** * Verfiy that there are no circular references between Components. * * @param components the ComponentEntry objects for the components * @throws org.apache.avalon.framework.tools.verifier.VerifyException if an circular dependency error occurs */ protected void verifyNoCircularDependencies( final ComponentProfile[] components ) throws VerifyException { for( int i = 0; i < components.length; i++ ) { final ComponentProfile component = components[ i ]; final Stack stack = new Stack(); stack.push( component ); verifyNoCircularDependencies( component, components, stack ); stack.pop(); } } /** * Verfiy that there are no circular references between Components. * * @param component ??? * @param components the ComponentEntry objects for the components * @param stack the ??? * @throws org.apache.avalon.framework.tools.verifier.VerifyException if an error occurs */ protected void verifyNoCircularDependencies( final ComponentProfile component, final ComponentProfile[] components, final Stack stack ) throws VerifyException { final ComponentProfile[] dependencies = getDependencies( component, components ); for( int i = 0; i < dependencies.length; i++ ) { final ComponentProfile dependency = dependencies[ i ]; if( stack.contains( dependency ) ) { final String trace = getDependencyTrace( dependency, stack ); final String message = REZ.getString( "assembly.circular-dependency.error", component.getMetaData().getName(), trace ); throw new VerifyException( message ); } stack.push( dependency ); verifyNoCircularDependencies( dependency, components, stack ); stack.pop(); } } /** * Get a string defining path from top of stack till * it reaches specified component. * * @param component the component * @param stack the Stack * @return the path of dependency */ protected String getDependencyTrace( final ComponentProfile component, final Stack stack ) { final StringBuffer sb = new StringBuffer(); sb.append( "[ " ); final String name = component.getMetaData().getName(); final int size = stack.size(); final int top = size - 1; for( int i = top; i >= 0; i-- ) { final ComponentProfile other = (ComponentProfile)stack.get( i ); if( top != i ) { sb.append( ", " ); } sb.append( other.getMetaData().getName() ); if( other.getMetaData().getName().equals( name ) ) { break; } } sb.append( ", " ); sb.append( name ); sb.append( " ]" ); return sb.toString(); } /** * Get array of dependencies for specified Component from specified * Component array. * * @param component the component to get dependencies of * @param components the total set of components in application * @return the dependencies of component */ protected ComponentProfile[] getDependencies( final ComponentProfile component, final ComponentProfile[] components ) { final ArrayList dependencies = new ArrayList(); final DependencyMetaData[] deps = component.getMetaData().getDependencies(); for( int i = 0; i < deps.length; i++ ) { final String name = deps[ i ].getProviderName(); final ComponentProfile other = getComponentProfile( name, components ); dependencies.add( other ); } return (ComponentProfile[])dependencies.toArray( new ComponentProfile[ 0 ] ); } /** * Verfiy that the inter-Component dependencies are valid. * * @param components the ComponentProfile objects for the components * @throws org.apache.avalon.framework.tools.verifier.VerifyException if an error occurs */ protected void verifyDependencyReferences( final ComponentProfile[] components ) throws VerifyException { for( int i = 0; i < components.length; i++ ) { verifyDependencyReferences( components[ i ], components ); } } /** * Verfiy that the inter-Component dependencies are valid for specified Component. * * @param component the ComponentProfile object for the component * @param others the ComponentProfile objects for the other components * @throws org.apache.avalon.framework.tools.verifier.VerifyException if an error occurs */ protected void verifyDependencyReferences( final ComponentProfile component, final ComponentProfile[] others ) throws VerifyException { final ComponentInfo info = component.getInfo(); final DependencyMetaData[] dependencies = component.getMetaData().getDependencies(); for( int i = 0; i < dependencies.length; i++ ) { final DependencyMetaData dependency = dependencies[ i ]; final String providerName = dependency.getProviderName(); final String key = dependency.getKey(); final String type = info.getDependency( key ).getType(); //Get the other component that is providing service final ComponentProfile provider = getComponentProfile( providerName, others ); if( null == provider ) { final String message = REZ.getString( "assembly.missing-dependency.error", key, providerName, component.getMetaData().getName() ); throw new VerifyException( message ); } //make sure that the component offers service //that user expects it to be providing final ComponentInfo providerInfo = provider.getInfo(); final ServiceDescriptor[] services = providerInfo.getServices(); if( !hasMatchingService( type, services ) ) { final String message = REZ.getString( "assembly.dependency-missing-service.error", providerName, type, component.getMetaData().getName() ); throw new VerifyException( message ); } } } /** * Get component with specified name from specified Component array. * * @param name the name of component to get * @param components the array of components to search * @return the Component if found, else null */ protected ComponentProfile getComponentProfile( final String name, final ComponentProfile[] components ) { for( int i = 0; i < components.length; i++ ) { ComponentProfile ComponentProfile = components[ i ]; if( ComponentProfile.getMetaData().getName().equals( name ) ) { return components[ i ]; } } return null; } /** * Verify that the names of the specified Components are valid. * * @param components the Components Profile * @throws org.apache.avalon.framework.tools.verifier.VerifyException if an error occurs */ protected void verifyValidNames( final ComponentProfile[] components ) throws VerifyException { for( int i = 0; i < components.length; i++ ) { ComponentProfile ComponentProfile = components[ i ]; final String name = ComponentProfile.getMetaData().getName(); if( !isValidName( name ) ) { final String message = REZ.getString( "assembly.bad-name.error", name ); throw new VerifyException( message ); } } } /** * Return true if specified name is valid. * Valid names consist of letters, digits or the '_' character. * * @param name the name to check * @return true if valid, false otherwise */ protected boolean isValidName( final String name ) { final int size = name.length(); for( int i = 0; i < size; i++ ) { final char ch = name.charAt( i ); if( !Character.isLetterOrDigit( ch ) && '-' != ch ) { return false; } } return true; } /** * Verify that the names of the specified components and listeners are unique. * It is not valid for the same name to be used in multiple components. * * @param components the Components * @throws org.apache.avalon.framework.tools.verifier.VerifyException if an error occurs */ protected void checkNamesUnique( final ComponentProfile[] components ) throws VerifyException { for( int i = 0; i < components.length; i++ ) { ComponentProfile ComponentProfile = components[ i ]; final String name = ComponentProfile.getMetaData().getName(); verifyUniqueName( components, name, i ); } } /** * Verfify that specified name is unique among the specified components. * * @param components the array of components to check * @param name the name of component * @param index the index of component in array (so we can skip it) * @throws org.apache.avalon.framework.tools.verifier.VerifyException if names are not unique */ private void verifyUniqueName( final ComponentProfile[] components, final String name, final int index ) throws VerifyException { for( int i = 0; i < components.length; i++ ) { ComponentProfile ComponentProfile = components[ i ]; final String other = ComponentProfile.getMetaData().getName(); if( index != i && other.equals( name ) ) { final String message = REZ.getString( "assembly.duplicate-name.error", name ); throw new VerifyException( message ); } } } /** * Retrieve a list of DependencyMetaData objects for ComponentProfile * and verify that there is a 1 to 1 map with dependencies specified * in ComponentInfo. * * @param component the ComponentProfile describing the component * @throws org.apache.avalon.framework.tools.verifier.VerifyException if an error occurs */ protected void verifyDependenciesMap( final ComponentProfile component ) throws VerifyException { //Make sure all dependency entries specified in config file are valid final DependencyMetaData[] dependencySet = component.getMetaData().getDependencies(); for( int i = 0; i < dependencySet.length; i++ ) { final String key = dependencySet[ i ].getKey(); final ComponentInfo info = component.getInfo(); final DependencyDescriptor descriptor = info.getDependency( key ); //If there is no dependency descriptor in ComponentInfo then //user has specified an uneeded dependency. if( null == descriptor ) { final String message = REZ.getString( "assembly.unknown-dependency.error", key, key, component.getMetaData().getName() ); throw new VerifyException( message ); } } //Make sure all dependencies in ComponentInfo file are satisfied final ComponentInfo info = component.getInfo(); final DependencyDescriptor[] dependencies = info.getDependencies(); for( int i = 0; i < dependencies.length; i++ ) { final DependencyDescriptor dependency = dependencies[ i ]; final DependencyMetaData dependencyMetaData = component.getMetaData().getDependency( dependency.getKey() ); //If there is no metaData then the user has failed //to specify a needed dependency. if( null == dependencyMetaData && !dependency.isOptional() ) { final String message = REZ.getString( "assembly.unspecified-dependency.error", dependency.getKey(), component.getMetaData().getName() ); throw new VerifyException( message ); } } } /** * Return true if specified service reference matches any of the * candidate services. * * @param type the service type * @param candidates an array of candidate services * @return true if candidate services contains a service that matches * specified service, false otherwise */ protected boolean hasMatchingService( final String type, final ServiceDescriptor[] candidates ) { for( int i = 0; i < candidates.length; i++ ) { final String otherClassname = candidates[ i ].getType(); if( otherClassname.equals( type ) ) { return true; } } return false; } } 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/verifier/Resources.properties Index: Resources.properties =================================================================== #Assembly Verifier assembly.valid-names.notice=Verifying that the names specified for Component are valid. assembly.unique-names.notice=Verifying that the names specified for the Components are unique. assembly.dependencies-mapping.notice=Verifying that the dependency mapping is valid according to ComponentInfos. assembly.dependency-references.notice=Verifying that the dependency mapping for every Component is valid with respect to other components. assembly.nocircular-dependencies.notice=Verifying that there are no circular dependencies between Components. assembly.component-type.notice=Verifying that the specified Components have valid types. assembly.circular-dependency.error=Component named "{0}" has a circular dependency via path: {1}. assembly.missing-dependency.error=Component "{1}" that satisfies the dependency with key "{0}" of Component "{2}" does not exist. assembly.dependency-missing-service.error=Dependency "{0}" of Block "{2}" does not offer the required service "{1}". assembly.bad-class.error=Unable to load class "{1}" for Component named "{0}". (Reason: {2}). assembly.bad-name.error=The Component name "{0}" is invalid. Valid names contain only letters, digits and the '-' character. assembly.duplicate-name.error=The name "{0}" is used by multiple Components in assembly. assembly.unknown-dependency.error=Unknown dependency named "{0}" with key "{1}" declared for Component {2}. assembly.unspecified-dependency.error=Dependency for key "{0}" not specified for the Component named "{1}". error=Component named "{0}" of type "{1}" is not Contextualizable but declares Context Entrys. 1.1 jakarta-avalon-phoenix/src/java/org/apache/avalon/phoenix/containerkit/verifier/package.html Index: package.html =================================================================== <body> A set of classes supporting verification of components and component assemblies using class and component meta-data information. <h3>Overview</h3> <p>This package includes a set of classes supporting the verification of the integrity of a component class and the verification of the integrity of a relationships and inter-dependecies based on supplied meta-data. The [EMAIL PROTECTED] org.apache.excalibur.containerkit.verifier.ComponentVerifier} provides support for the validation of a component class. It includes validation functions that check for structural and best-practice integrity related to the class, lifecycle patterns and service. The [EMAIL PROTECTED] org.apache.excalibur.containerkit.verifier.AssemblyVerifier} performs validation of the structural integrity of a set component assembly based on assembly meta-data. </body>
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>