diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java index ff9dbdb02..bbadf49c8 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java @@ -27,7 +27,6 @@ import org.apache.myrmidon.interfaces.configurer.Configurer; import org.apache.myrmidon.interfaces.converter.MasterConverter; import org.apache.myrmidon.interfaces.role.RoleInfo; import org.apache.myrmidon.interfaces.role.RoleManager; -import org.apache.myrmidon.interfaces.type.TypeException; import org.apache.myrmidon.interfaces.type.TypeFactory; import org.apache.myrmidon.interfaces.type.TypeManager; @@ -83,16 +82,36 @@ public class DefaultConfigurer final Context context ) throws ConfigurationException { - configureObject( object, configuration, context ); + try + { + // Configure the object + configureObject( object, configuration, context ); + } + catch( final ReportableConfigurationException e ) + { + // Already have a reasonable error message - so rethrow + throw e.getCause(); + } + catch( final Exception e ) + { + // Wrap all other errors with general purpose error message + final String message = REZ.getString( "bad-configure-element.error", configuration.getName() ); + throw new ConfigurationException( message, e ); + } } /** * Does the work of configuring an object. + * + * @throws ReportableConfigurationException On error. This exception + * indicates that the error has been wrapped with an appropriate + * error message. + * @throws Exception On error */ private void configureObject( final Object object, final Configuration configuration, final Context context ) - throws ConfigurationException + throws Exception { if( object instanceof Configurable ) { @@ -101,12 +120,9 @@ public class DefaultConfigurer } else { + // Start configuration of the object final String elemName = configuration.getName(); - - // Locate the configurer for this object final ObjectConfigurer configurer = getConfigurer( object.getClass() ); - - // Start configuring this object final ConfigurationState state = configurer.startConfiguration( object ); // Set each of the attributes @@ -124,17 +140,13 @@ public class DefaultConfigurer { final String message = REZ.getString( "no-such-attribute.error", elemName, name ); - throw new ConfigurationException( message, nspe ); - } - catch( final ConfigurationException ce ) - { - throw ce; + throw new ReportableConfigurationException( message, nspe ); } catch( final Exception ce ) { final String message = REZ.getString( "bad-set-attribute.error", elemName, name ); - throw new ConfigurationException( message, ce ); + throw new ReportableConfigurationException( message, ce ); } } @@ -145,24 +157,19 @@ public class DefaultConfigurer try { // Set the content - final PropertyConfigurer contentConfigurer = state.getConfigurer().getContentConfigurer(); - setValue( contentConfigurer, state, content, context ); + setContent( state, content, context ); } catch( final NoSuchPropertyException nspe ) { final String message = REZ.getString( "no-content.error", elemName ); - throw new ConfigurationException( message, nspe ); - } - catch( final ConfigurationException ce ) - { - throw ce; + throw new ReportableConfigurationException( message ); } catch( final Exception ce ) { final String message = REZ.getString( "bad-set-content.error", elemName ); - throw new ConfigurationException( message, ce ); + throw new ReportableConfigurationException( message, ce ); } } @@ -180,17 +187,17 @@ public class DefaultConfigurer { final String message = REZ.getString( "no-such-element.error", elemName, name ); - throw new ConfigurationException( message, nspe ); + throw new ReportableConfigurationException( message, nspe ); } - catch( final ConfigurationException ce ) + catch( final ReportableConfigurationException ce ) { throw ce; } catch( final Exception ce ) { final String message = - REZ.getString( "bad-set-element.error", elemName, name ); - throw new ConfigurationException( message, ce ); + REZ.getString( "bad-configure-element.error", name ); + throw new ReportableConfigurationException( message, ce ); } } @@ -240,6 +247,25 @@ public class DefaultConfigurer configurer.finishConfiguration( state ); } + /** + * Sets the text content for the element. + */ + private void setContent( final ConfigurationState state, + final String content, + final Context context ) + throws Exception + { + // Locate the content configurer + final PropertyConfigurer contentConfigurer = state.getConfigurer().getContentConfigurer(); + if( contentConfigurer == null ) + { + throw new NoSuchPropertyException(); + } + + // Set the content + setValue( contentConfigurer, state, content, context ); + } + /** * Configures a property from a nested element. */ @@ -323,7 +349,7 @@ public class DefaultConfigurer = getConfigurerFromName( state.getConfigurer(), name, false ); // Resolve any props in the id - Object id = resolveProperty( unresolvedId, context ); + Object id = PropertyUtil.resolveProperty( unresolvedId, context, false ); // Locate the referenced object Object ref = null; @@ -331,10 +357,10 @@ public class DefaultConfigurer { ref = context.get( id ); } - catch( final ContextException exc ) + catch( final ContextException e ) { final String message = REZ.getString( "get-ref.error", id ); - throw new ConfigurationException( message, exc ); + throw new ConfigurationException( message, e ); } // Check the types @@ -349,13 +375,6 @@ public class DefaultConfigurer childConfigurer.addValue( state, ref ); } - private Object resolveProperty( final String unresolvedId, - final Context context ) - throws Exception - { - return PropertyUtil.resolveProperty( unresolvedId, context, false ); - } - /** * Sets an attribute value. */ @@ -428,7 +447,7 @@ public class DefaultConfigurer final Configuration element, final Context context, final PropertyConfigurer childConfigurer ) - throws ConfigurationException + throws Exception { final String name = element.getName(); final Class type = childConfigurer.getType(); @@ -472,30 +491,33 @@ public class DefaultConfigurer throws Exception { // Try a named property - final NoSuchPropertyException exc; - try + PropertyConfigurer propertyConfigurer = configurer.getProperty( name ); + if( propertyConfigurer != null ) { - return configurer.getProperty( name ); - } - catch( NoSuchPropertyException e ) - { - // Keep for later - exc = e; + return propertyConfigurer; } // Try a typed property - final PropertyConfigurer propertyConfigurer = configurer.getTypedProperty(); - if( !ignoreRoleName ) + propertyConfigurer = configurer.getTypedProperty(); + if( propertyConfigurer != null ) { - final RoleInfo roleInfo = m_roleManager.getRoleByType( propertyConfigurer.getType() ); - if( roleInfo == null || !name.equalsIgnoreCase( roleInfo.getShorthand() ) ) + if( ignoreRoleName ) { - // Rethrow the original exception - throw exc; + return propertyConfigurer; + } + else + { + // Check the role name + final RoleInfo roleInfo = m_roleManager.getRoleByType( propertyConfigurer.getType() ); + if( roleInfo != null && name.equalsIgnoreCase( roleInfo.getShorthand() ) ) + { + return propertyConfigurer; + } } } - return propertyConfigurer; + // Unknown prop + throw new NoSuchPropertyException(); } /** @@ -504,13 +526,13 @@ public class DefaultConfigurer */ private Object createdTypedObject( final String name, final Class type ) - throws ConfigurationException + throws Exception { // Attempt to create the object final Object obj; try { - final TypeFactory factory = getTypeFactory( DataType.class ); + final TypeFactory factory = m_typeManager.getFactory( DataType.class ); obj = factory.create( name ); } catch( final Exception e ) @@ -537,7 +559,7 @@ public class DefaultConfigurer * Utility method to instantiate an instance of the specified class. */ private Object createObject( final Class type ) - throws ConfigurationException + throws Exception { try { @@ -551,21 +573,4 @@ public class DefaultConfigurer throw new ConfigurationException( message, e ); } } - - /** - * Locates a type factory. - */ - protected final TypeFactory getTypeFactory( final Class role ) - throws ConfigurationException - { - try - { - return m_typeManager.getFactory( role ); - } - catch( final TypeException te ) - { - final String message = REZ.getString( "no-factory-for-role.error", role.getName() ); - throw new ConfigurationException( message, te ); - } - } } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java index b3c94695e..d490a0094 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java @@ -353,53 +353,24 @@ class DefaultObjectConfigurer * Returns a configurer for an element of this class. */ public PropertyConfigurer getProperty( final String name ) - throws NoSuchPropertyException { - PropertyConfigurer configurer = (PropertyConfigurer)m_props.get( name ); - if( null != configurer ) - { - return configurer; - } - - // Unknown property - final String message = REZ.getString( "unknown-property.error", m_class.getName(), name ); - throw new NoSuchPropertyException( message ); + return (PropertyConfigurer)m_props.get( name ); } /** * Returns a configurer for the typed property of this class. */ public PropertyConfigurer getTypedProperty() - throws NoSuchPropertyException { - if( null != m_typedPropConfigurer ) - { - return m_typedPropConfigurer; - } - else - { - // No typed property - final String message = REZ.getString( "no-typed-property.error", m_class.getName() ); - throw new NoSuchPropertyException( message ); - } + return m_typedPropConfigurer; } /** * Returns a configurer for the content of this class. */ public PropertyConfigurer getContentConfigurer() - throws NoSuchPropertyException { - if( null != m_contentConfigurer ) - { - return m_contentConfigurer; - } - else - { - // Does not handle content - final String message = REZ.getString( "content-unsupported.error", m_class.getName() ); - throw new NoSuchPropertyException( message ); - } + return m_contentConfigurer; } /** diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/NoSuchPropertyException.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/NoSuchPropertyException.java index 758ff659e..f3162a5f8 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/NoSuchPropertyException.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/NoSuchPropertyException.java @@ -7,22 +7,15 @@ */ package org.apache.myrmidon.components.configurer; -import org.apache.avalon.framework.CascadingException; + /** - * An exception thrown when an unknown property is encountered. - * - * TODO - this should extend ConfigurationException, however - * ConfigurationException is final. + * A marker exception that is thrown when an unknown property is encountered. * * @author Adam Murdoch * @version $Revision$ $Date$ */ class NoSuchPropertyException - extends CascadingException + extends Exception { - public NoSuchPropertyException( String message ) - { - super( message ); - } } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java index 760374e7a..a50c34376 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java @@ -43,29 +43,24 @@ interface ObjectConfigurer * Returns a configurer for a property of this class. * * @param name The element name. Property names are case-insensitive. - * @return A configurer for the property. - * @throws NoSuchPropertyException If the property is not valid for this - * class + * @return A configurer for the property, or null if the property is not + * valid for this class. */ - PropertyConfigurer getProperty( String name ) - throws NoSuchPropertyException; + PropertyConfigurer getProperty( String name ); /** - * Returns a configurer for the content of this class. + * Returns a configurer for the text content of this class. * - * @return A configurer for the content. - * @throws NoSuchPropertyException If the class does not handle content. + * @return A configurer for the text content, or null if the class does not + * support text content. */ - PropertyConfigurer getContentConfigurer() - throws NoSuchPropertyException; + PropertyConfigurer getContentConfigurer(); /** * Returns a configurer for the typed property of this class. * - * @return A configurer for the typed property. - * @throws NoSuchPropertyException If the class does not have a typed - * property. + * @return A configurer for the typed property, or null if the class + * does not have a typed property. */ - PropertyConfigurer getTypedProperty() - throws NoSuchPropertyException; + PropertyConfigurer getTypedProperty(); } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/PropertyConfigurer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/PropertyConfigurer.java index 0ca8f43eb..bf9941e27 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/PropertyConfigurer.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/PropertyConfigurer.java @@ -11,7 +11,7 @@ import org.apache.avalon.framework.configuration.ConfigurationException; /** * Configures a property of an object. - * TODO - axe useCreator() and createValue(). + * TODO - axe createValue(). * * @author Adam Murdoch * @version $Revision$ $Date$ @@ -25,8 +25,7 @@ interface PropertyConfigurer /** * Creates a default value for this property. This value must be configured, - * and then attached to the object using {@link #setValue}. This - * method must be called if {@link #useCreator} returns true. + * and then attached to the object using {@link #addValue}. * * @param state The state object, representing the object being configured. * @return An object which is assignable to the type returned by diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ReportableConfigurationException.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ReportableConfigurationException.java new file mode 100644 index 000000000..27b19672d --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ReportableConfigurationException.java @@ -0,0 +1,39 @@ +/* + * 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.myrmidon.components.configurer; + +import org.apache.avalon.framework.configuration.ConfigurationException; + +/** + * A marker exception. + * + * TODO - this should extend ConfigurationException, except it is final. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +class ReportableConfigurationException + extends Exception +{ + private ConfigurationException m_cause; + + public ReportableConfigurationException( String s ) + { + m_cause = new ConfigurationException( s ); + } + + public ReportableConfigurationException( String s, Throwable throwable ) + { + m_cause = new ConfigurationException( s, throwable ); + } + + public ConfigurationException getCause() + { + return m_cause; + } +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties index c3e748a2a..9e239fc44 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties @@ -1,14 +1,11 @@ create-object.error=Could not create an object of class {0}. extra-config-for-ref.error=A reference element can only include an "id" attribute. -get-ref.error=Could not locate reference "{0}". mismatch-ref-types.error=Mismatched type for reference "{0}". Was expecting an object of type {1}, instead found an object of type {2}. incompatible-element-types.error=Incompatible creator and adder/setter methods found in class {0} for property "{1}". multiple-adder-methods-for-element.error=Multiple add{1}() or set{1}() methods found in class {0}. multiple-creator-methods-for-element.error=Multiple {1}() methods found in class {0}. multiple-content-setter-methods.error=Multiple content setter methods found in class {0}. pending-property-value.error=An object created using the creator method has not been set using the adder/setter method. -unknown-property.error=Class {0} does not have a "{1}" property. -content-not-supported.error=Class {0} does not support text content. must-be-element.error=This property must be configured using a nested element. too-many-values.error=Too many values for this property. no-complex-type.error=Can not get complex type for non-primitive type {0}. @@ -16,13 +13,12 @@ no-such-attribute.error=Attribute "{1}" is not allowed for element <{0}>. bad-set-attribute.error=Could not set attribute "{1}" for element <{0}>. bad-set-class-attribute.error=Could not set attribute "{0}" for object of class {1}. no-such-element.error=Nested <{1}> elements are not allowed for element <{0}>. -bad-set-element.error=Could not handle element <{1}>, nested in element <{0}>. -no-content.error=Text content is not allowed for element <{0}>. +no-content.error=Text content is not allowed in element <{0}>. bad-set-content.error=Could not set text content for element <{0}>. typed-adder-non-interface.error=The typed adder for class "{0}" must have a single parameter that is an interface rather than {1} which defines a class. -no-factory-for-role.error=Unable to locate type factory for role "{0}" create-typed-object.error=Could not create an object of type "{0}" of class {1}. -no-typed-property.error=Class {0} does not have a typed property. +unknown-reference.error=Could not find referenced object "{0}". +bad-configure-element.error=Could not configure element <{0}>. prop.mismatched-braces.error=Malformed property with mismatched }'s. -prop.missing-value.error=Unable to find "{0}" to expand during property resolution. \ No newline at end of file +prop.missing-value.error=Unable to find "{0}" to expand during property resolution. diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java index 0f2d0aef4..861580d11 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java @@ -26,7 +26,6 @@ import org.apache.myrmidon.interfaces.deployer.TypeDefinition; import org.apache.myrmidon.interfaces.deployer.TypeDeployer; import org.apache.myrmidon.interfaces.role.RoleInfo; import org.apache.myrmidon.interfaces.role.RoleManager; -import org.apache.myrmidon.interfaces.service.AntServiceManager; import org.apache.myrmidon.interfaces.service.ServiceFactory; import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; import org.apache.myrmidon.interfaces.type.TypeManager; @@ -53,7 +52,6 @@ public class DefaultDeployer /** Map from ClassLoader to the deployer for that class loader. */ private final Map m_classLoaderDeployers = new HashMap(); - private AntServiceManager m_serviceManager; /** * Retrieve relevent services needed to deploy. @@ -68,7 +66,6 @@ public class DefaultDeployer m_typeManager = (TypeManager)serviceManager.lookup( TypeManager.ROLE ); m_roleManager = (RoleManager)serviceManager.lookup( RoleManager.ROLE ); m_classLoaderManager = (ClassLoaderManager)serviceManager.lookup( ClassLoaderManager.ROLE ); - m_serviceManager = (AntServiceManager)serviceManager.lookup( AntServiceManager.ROLE ); } /** @@ -148,9 +145,9 @@ public class DefaultDeployer throws Exception { final String roleShorthand = definition.getRoleShorthand(); - final Class serviceType = getRoleType( roleShorthand ); + final String roleName = getRole( roleShorthand ).getName(); final String factoryClassName = definition.getFactoryClass(); - handleType( deployment, ServiceFactory.class, serviceType.getName(), factoryClassName ); + handleType( deployment, ServiceFactory.class, roleName, factoryClassName ); } /** @@ -205,7 +202,7 @@ public class DefaultDeployer } // Deploy general-purpose type - final Class roleType = getRoleType( roleShorthand ); + final Class roleType = getRole( roleShorthand ).getType(); handleType( deployment, roleType, typeName, className ); if( getLogger().isDebugEnabled() ) @@ -275,9 +272,9 @@ public class DefaultDeployer } /** - * Determines the type for a role, from its shorthand. + * Locates a role, from its shorthand. */ - private Class getRoleType( final String roleShorthand ) + private RoleInfo getRole( final String roleShorthand ) throws DeploymentException { final RoleInfo roleInfo = m_roleManager.getRoleByShorthandName( roleShorthand ); @@ -286,6 +283,6 @@ public class DefaultDeployer final String message = REZ.getString( "unknown-role4name.error", roleShorthand ); throw new DeploymentException( message ); } - return roleInfo.getType(); + return roleInfo; } } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java index 9555fa0d4..b6929f6e1 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java @@ -22,6 +22,7 @@ import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.parameters.Parameterizable; 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.framework.service.Serviceable; import org.apache.myrmidon.components.deployer.ClassLoaderManager; import org.apache.myrmidon.interfaces.aspect.AspectManager; @@ -37,7 +38,7 @@ import org.apache.myrmidon.interfaces.executor.Executor; import org.apache.myrmidon.interfaces.extensions.ExtensionManager; import org.apache.myrmidon.interfaces.model.Project; import org.apache.myrmidon.interfaces.role.RoleManager; -import org.apache.myrmidon.interfaces.service.AntServiceManager; +import org.apache.myrmidon.interfaces.service.MultiSourceServiceManager; import org.apache.myrmidon.interfaces.type.TypeFactory; import org.apache.myrmidon.interfaces.type.TypeManager; import org.apache.myrmidon.interfaces.workspace.Workspace; @@ -62,6 +63,7 @@ public class DefaultEmbeddor private Deployer m_deployer; private TypeManager m_typeManager; + private MultiSourceServiceManager m_workspaceServiceManager; private List m_components = new ArrayList(); private DefaultServiceManager m_serviceManager = new DefaultServiceManager(); @@ -110,7 +112,7 @@ public class DefaultEmbeddor final TypeFactory factory = m_typeManager.getFactory( ProjectBuilder.class ); final ProjectBuilder builder = (ProjectBuilder)factory.create( type ); - setupObject( builder, parameters ); + setupObject( builder, m_workspaceServiceManager, parameters ); return builder; } @@ -120,10 +122,9 @@ public class DefaultEmbeddor public Workspace createWorkspace( final Parameters parameters ) throws Exception { - final String component = getParameter( Workspace.ROLE ); final Workspace workspace = - (Workspace)createService( component, Workspace.class ); - setupObject( workspace, parameters ); + (Workspace)createService( Workspace.class, PREFIX + "workspace.DefaultWorkspace" ); + setupObject( workspace, m_workspaceServiceManager, parameters ); return workspace; } @@ -148,18 +149,27 @@ public class DefaultEmbeddor public void initialize() throws Exception { - //setup default properties + // setup default properties m_defaults = createDefaultParameters(); - //create all the components - createComponents(); - - //setup the components + // setup the root components setupComponents(); + // locate the components we need m_deployer = (Deployer)m_serviceManager.lookup( Deployer.ROLE ); m_typeManager = (TypeManager)m_serviceManager.lookup( TypeManager.ROLE ); + // setup a service manager that creates the project services + final ServiceManager projServiceManager + = (ServiceManager)createService( ServiceManager.class, PREFIX + "service.InstantiatingServiceManager" ); + setupObject( projServiceManager, m_serviceManager, m_parameters ); + + // setup a service manager to be used by workspaces + m_workspaceServiceManager = new MultiSourceServiceManager(); + m_workspaceServiceManager.add( projServiceManager ); + m_workspaceServiceManager.add( m_serviceManager ); + + // setup setupFiles(); } @@ -224,18 +234,16 @@ public class DefaultEmbeddor defaults.setParameter( "myrmidon.bin.path", "bin" ); defaults.setParameter( "myrmidon.lib.path", "lib" ); - // Default workspace implementation - defaults.setParameter( Workspace.ROLE, PREFIX + "workspace.DefaultWorkspace" ); - return defaults; } /** * Create all required components. */ - private void createComponents() + private void setupComponents() throws Exception { + // Create the components createComponent( ConverterRegistry.class, PREFIX + "converter.DefaultConverterRegistry" ); createComponent( ExtensionManager.class, PREFIX + "extensions.DefaultExtensionManager" ); createComponent( MasterConverter.class, PREFIX + "converter.DefaultMasterConverter" ); @@ -246,7 +254,13 @@ public class DefaultEmbeddor createComponent( Deployer.class, PREFIX + "deployer.DefaultDeployer" ); createComponent( ClassLoaderManager.class, PREFIX + "deployer.DefaultClassLoaderManager" ); createComponent( Executor.class, PREFIX + "executor.AspectAwareExecutor" ); - createComponent( AntServiceManager.class, PREFIX + "service.DefaultAntServiceManager" ); + + // Setup the components + for( Iterator iterator = m_components.iterator(); iterator.hasNext(); ) + { + final Object component = iterator.next(); + setupObject( component, m_serviceManager, m_parameters ); + } } /** @@ -255,28 +269,11 @@ public class DefaultEmbeddor private void createComponent( Class roleType, String defaultImpl ) throws Exception { - final String role = roleType.getName(); - final String className = m_parameters.getParameter( role, defaultImpl ); - final Object component = createService( className, roleType ); - m_serviceManager.put( role, component ); + final Object component = createService( roleType, defaultImpl ); + m_serviceManager.put( roleType.getName(), component ); m_components.add( component ); } - /** - * Setup all the components. (ir run all required lifecycle methods). - * - * @exception Exception if an error occurs - */ - private void setupComponents() - throws Exception - { - for( Iterator iterator = m_components.iterator(); iterator.hasNext(); ) - { - final Object component = iterator.next(); - setupObject( component, m_parameters ); - } - } - /** * Setup all the files attributes. */ @@ -354,21 +351,24 @@ public class DefaultEmbeddor /** * Create a component that implements an interface. * - * @param component the name of the component - * @param clazz the name of interface/type + * @param roleType the name of interface/type + * @param defaultImpl the classname of the default implementation * @return the created object * @exception Exception if an error occurs */ - private Object createService( final String component, final Class clazz ) + private Object createService( final Class roleType, final String defaultImpl ) throws Exception { + final String role = roleType.getName(); + final String className = m_parameters.getParameter( role, defaultImpl ); + try { - final Object object = Class.forName( component ).newInstance(); + final Object object = Class.forName( className ).newInstance(); - if( !clazz.isInstance( object ) ) + if( !roleType.isInstance( object ) ) { - final String message = REZ.getString( "bad-type.error", component, clazz.getName() ); + final String message = REZ.getString( "bad-type.error", className, roleType.getName() ); throw new Exception( message ); } @@ -376,19 +376,19 @@ public class DefaultEmbeddor } catch( final IllegalAccessException iae ) { - final String message = REZ.getString( "bad-ctor.error", clazz.getName(), component ); + final String message = REZ.getString( "bad-ctor.error", roleType.getName(), className ); throw new Exception( message ); } catch( final InstantiationException ie ) { final String message = - REZ.getString( "no-instantiate.error", clazz.getName(), component ); + REZ.getString( "no-instantiate.error", roleType.getName(), className ); throw new Exception( message ); } catch( final ClassNotFoundException cnfe ) { final String message = - REZ.getString( "no-class.error", clazz.getName(), component ); + REZ.getString( "no-class.error", roleType.getName(), className ); throw new Exception( message ); } } @@ -398,6 +398,7 @@ public class DefaultEmbeddor * parameterise and initialise lifecycle stages. */ private void setupObject( final Object object, + final ServiceManager serviceManager, final Parameters parameters ) throws Exception { @@ -405,7 +406,7 @@ public class DefaultEmbeddor if( object instanceof Serviceable ) { - ( (Serviceable)object ).service( m_serviceManager ); + ( (Serviceable)object ).service( serviceManager ); } if( object instanceof Parameterizable ) diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/DefaultAntServiceManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/DefaultAntServiceManager.java deleted file mode 100644 index 7d2f063e3..000000000 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/DefaultAntServiceManager.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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.myrmidon.components.service; - -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.activity.Disposable; -import org.apache.avalon.framework.service.ServiceException; -import org.apache.avalon.framework.service.ServiceManager; -import org.apache.avalon.framework.service.Serviceable; -import org.apache.myrmidon.interfaces.service.AntServiceException; -import org.apache.myrmidon.interfaces.service.AntServiceManager; -import org.apache.myrmidon.interfaces.service.ServiceFactory; -import org.apache.myrmidon.interfaces.type.TypeException; -import org.apache.myrmidon.interfaces.type.TypeFactory; -import org.apache.myrmidon.interfaces.type.TypeManager; - -/** - * A service manager implementation. This implementation takes care of - * creating service instances, using a {@link ServiceFactory}, and running the - * service instances through the service lifecycle. Service creation happens - * on demand. - * - *
This implementation uses a TypeManager to locate the service factories.
- *
- * @author Adam Murdoch
- * @version $Revision$ $Date$
- */
-public class DefaultAntServiceManager
- implements AntServiceManager, Serviceable, Disposable
-{
- private final static Resources REZ =
- ResourceManager.getPackageResources( DefaultAntServiceManager.class );
-
- /** Map from service class -> service object. */
- private Map m_services = new HashMap();
-
- private TypeFactory m_typeFactory;
-
- /**
- * Pass the ServiceManager
to the servicable
.
- * The Servicable
implementation should use the specified
- * ServiceManager
to acquire the components it needs for
- * execution.
- *
- * @param manager The ServiceManager
which this
- * Servicable
uses.
- */
- public void service( ServiceManager manager )
- throws ServiceException
- {
- final TypeManager typeManager = (TypeManager)manager.lookup( TypeManager.ROLE );
- try
- {
- m_typeFactory = typeManager.getFactory( ServiceFactory.class );
- }
- catch( final TypeException e )
- {
- throw new ServiceException( e.getMessage(), e );
- }
- }
-
- /**
- * Disposes this service manager, and all services created by it.
- */
- public void dispose()
- {
- // Dispose the services
- for( Iterator iterator = m_services.values().iterator(); iterator.hasNext(); )
- {
- final Object object = iterator.next();
- if( object instanceof Disposable )
- {
- ( (Disposable)object ).dispose();
- }
- }
-
- // Ditch state
- m_services = null;
- m_typeFactory = null;
- }
-
- /**
- * Determines if this service manager contains a particular service.
- */
- public boolean hasService( Class serviceType )
- {
- // If we have already instantiated the service, or if we know how
- // to instantiate it, then return true
- if( m_services.containsKey( serviceType ) )
- {
- return true;
- }
- if( m_typeFactory.canCreate( serviceType.getName() ) )
- {
- return true;
- }
-
- return false;
- }
-
- /**
- * Locates a service instance.
- */
- public Object getService( Class serviceType )
- throws AntServiceException
- {
- Object service = m_services.get( serviceType );
- if( service == null )
- {
- // Create the service
- service = createService( serviceType );
- m_services.put( serviceType, service );
- }
-
- return service;
- }
-
- /**
- * Creates the service object for a service class.
- */
- private Object createService( Class serviceType ) throws AntServiceException
- {
- try
- {
- final ServiceFactory factory = (ServiceFactory)m_typeFactory.create( serviceType.getName() );
-
- // Create the service
- final Object service = factory.createService();
- if( !serviceType.isInstance( service ) )
- {
- final String message = REZ.getString( "mismatched-service-type.error", serviceType.getName(), service.getClass().getName() );
- throw new AntServiceException( message );
- }
- return service;
- }
- catch( final Exception e )
- {
- final String message = REZ.getString( "create-service.error", serviceType.getName() );
- throw new AntServiceException( message, e );
- }
- }
-}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/InstantiatingServiceManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/InstantiatingServiceManager.java
new file mode 100644
index 000000000..fa86d726b
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/InstantiatingServiceManager.java
@@ -0,0 +1,222 @@
+/*
+ * 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.myrmidon.components.service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+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.logger.AbstractLogEnabled;
+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.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.myrmidon.interfaces.role.RoleInfo;
+import org.apache.myrmidon.interfaces.role.RoleManager;
+import org.apache.myrmidon.interfaces.service.ServiceFactory;
+import org.apache.myrmidon.interfaces.type.TypeException;
+import org.apache.myrmidon.interfaces.type.TypeFactory;
+import org.apache.myrmidon.interfaces.type.TypeManager;
+
+/**
+ * A service manager implementation, which creates service instances on demand.
+ *
+ *
This manager creates service instances, using a {@link ServiceFactory}, + * and running the service instances through the service lifecycle: + *
ServiceManager
to the servicable
.
+ * The Servicable
implementation should use the specified
+ * ServiceManager
to acquire the components it needs for
+ * execution.
+ *
+ * @param manager The ServiceManager
which this
+ * Servicable
uses.
+ */
+ public void service( final ServiceManager manager )
+ throws ServiceException
+ {
+ m_serviceManager = manager;
+ m_roleManager = (RoleManager)manager.lookup( RoleManager.ROLE );
+ final TypeManager typeManager = (TypeManager)manager.lookup( TypeManager.ROLE );
+ try
+ {
+ m_typeFactory = typeManager.getFactory( ServiceFactory.class );
+ }
+ catch( final TypeException e )
+ {
+ throw new ServiceException( e.getMessage(), e );
+ }
+ }
+
+ /**
+ * Disposes this service manager, and all services created by it.
+ */
+ public void dispose()
+ {
+ // Dispose the services
+ for( Iterator iterator = m_objects.iterator(); iterator.hasNext(); )
+ {
+ final Object object = iterator.next();
+ if( object instanceof Disposable )
+ {
+ ( (Disposable)object ).dispose();
+ }
+ }
+
+ // Ditch state
+ m_services = null;
+ m_typeFactory = null;
+ m_objects = null;
+ m_parameters = null;
+ m_roleManager = null;
+ m_serviceManager = null;
+ }
+
+ /**
+ * Determines if this service manager contains a particular service.
+ */
+ public boolean hasService( final String serviceRole )
+ {
+ // If we have already instantiated the service, or if we know how
+ // to instantiate it, then return true
+ if( m_services.containsKey( serviceRole ) )
+ {
+ return true;
+ }
+ if( m_typeFactory.canCreate( serviceRole ) )
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Locates a service instance.
+ */
+ public Object lookup( final String serviceRole )
+ throws ServiceException
+ {
+ Object service = m_services.get( serviceRole );
+ if( service == null )
+ {
+ // Create the service
+ service = createService( serviceRole );
+ m_services.put( serviceRole, service );
+ }
+
+ return service;
+ }
+
+ /**
+ * Releases a service.
+ */
+ public void release( final Object service )
+ {
+ }
+
+ /**
+ * Creates the service object for a service role.
+ */
+ private Object createService( final String serviceRole ) throws ServiceException
+ {
+ try
+ {
+ // Create the factory
+ final ServiceFactory factory = (ServiceFactory)m_typeFactory.create( serviceRole );
+ setupObject( factory );
+
+ // Create the service
+ final Object service = factory.createService();
+
+ // Check the service is assignable to the role type
+ final RoleInfo roleInfo = m_roleManager.getRole( serviceRole );
+ final Class serviceType = roleInfo.getType();
+ if( serviceType != null && !serviceType.isInstance( service ) )
+ {
+ final String message = REZ.getString( "mismatched-service-type.error", serviceRole, service.getClass().getName() );
+ throw new ServiceException( message );
+ }
+
+ setupObject( service );
+ return service;
+ }
+ catch( final Exception e )
+ {
+ final String message = REZ.getString( "create-service.error", serviceRole );
+ throw new ServiceException( message, e );
+ }
+ }
+
+ /**
+ * Sets-up an object, taking it through the lifecycle steps.
+ */
+ private void setupObject( final Object object )
+ throws Exception
+ {
+ setupLogger( object );
+
+ if( object instanceof Serviceable )
+ {
+ ( (Serviceable)object ).service( m_serviceManager );
+ }
+
+ if( object instanceof Parameterizable )
+ {
+ ( (Parameterizable)object ).parameterize( m_parameters );
+ }
+
+ if( object instanceof Initializable )
+ {
+ ( (Initializable)object ).initialize();
+ }
+
+ m_objects.add( object );
+ }
+}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties b/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties
index 09d9d6492..fdc7b03bd 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties
@@ -1,3 +1,3 @@
-unknown-service-type.error=Unknown service type {0}.
-mismatched-service-type.error=Service factory for type {0} produced an object of unexpected type {1}.
-create-service.error=Could not create service {0}.
\ No newline at end of file
+unknown-service-type.error=Unknown service "{0}".
+mismatched-service-type.error=Service factory for service "{0}" produced an object of unexpected type {1}.
+create-service.error=Could not create service "{0}".
\ No newline at end of file
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java
index 12eafb7b8..4d64598db 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java
@@ -14,13 +14,13 @@ import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.excalibur.io.FileUtil;
import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
-import org.apache.myrmidon.components.configurer.PropertyUtil;
import org.apache.myrmidon.components.configurer.PropertyException;
+import org.apache.myrmidon.components.configurer.PropertyUtil;
import org.apache.myrmidon.interfaces.configurer.TaskContextAdapter;
-import org.apache.myrmidon.interfaces.service.AntServiceException;
-import org.apache.myrmidon.interfaces.service.AntServiceManager;
/**
* Default implementation of TaskContext.
@@ -36,7 +36,7 @@ public class DefaultTaskContext
private final Map m_contextData = new Hashtable();
private final TaskContext m_parent;
- private AntServiceManager m_serviceManager;
+ private ServiceManager m_serviceManager;
/**
* Constructor for Context with no parent contexts.
@@ -57,7 +57,7 @@ public class DefaultTaskContext
/**
* Constructor that specifies the service directory for context.
*/
- public DefaultTaskContext( final AntServiceManager serviceManager )
+ public DefaultTaskContext( final ServiceManager serviceManager )
{
this( null, serviceManager );
}
@@ -66,7 +66,7 @@ public class DefaultTaskContext
* Constructor that takes both parent context and a service directory.
*/
public DefaultTaskContext( final TaskContext parent,
- final AntServiceManager serviceManager )
+ final ServiceManager serviceManager )
{
m_parent = parent;
m_serviceManager = serviceManager;
@@ -153,13 +153,13 @@ public class DefaultTaskContext
{
// Try this context first
final String name = serviceClass.getName();
- if( m_serviceManager != null && m_serviceManager.hasService( serviceClass ) )
+ if( m_serviceManager != null && m_serviceManager.hasService( name ) )
{
try
{
- return m_serviceManager.getService( serviceClass );
+ return m_serviceManager.lookup( name );
}
- catch( final AntServiceException se )
+ catch( final ServiceException se )
{
throw new TaskException( se.getMessage(), se );
}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java
index 8d0f92cca..935d88504 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java
@@ -21,10 +21,10 @@ import org.apache.avalon.framework.logger.Logger;
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.framework.service.DefaultServiceManager;
+import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.log.Hierarchy;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
@@ -37,8 +37,6 @@ import org.apache.myrmidon.interfaces.executor.Executor;
import org.apache.myrmidon.interfaces.model.Project;
import org.apache.myrmidon.interfaces.model.Target;
import org.apache.myrmidon.interfaces.model.TypeLib;
-import org.apache.myrmidon.interfaces.service.MultiSourceServiceManager;
-import org.apache.myrmidon.interfaces.service.AntServiceManager;
import org.apache.myrmidon.interfaces.type.TypeManager;
import org.apache.myrmidon.interfaces.workspace.Workspace;
import org.apache.myrmidon.listeners.ProjectListener;
@@ -258,15 +256,9 @@ public class DefaultWorkspace
serviceManager.put( Project.ROLE + "/" + name, other );
}
- // Create a service manager that aggregates the contents of the context's
- // component manager, and service manager
- final MultiSourceServiceManager msServiceManager = new MultiSourceServiceManager();
- msServiceManager.add( (AntServiceManager)serviceManager.lookup( AntServiceManager.ROLE ) );
- msServiceManager.add( new ServiceManagerAdaptor( serviceManager ) );
-
// Create and configure the context
final DefaultTaskContext context =
- new DefaultTaskContext( m_baseContext, msServiceManager );
+ new DefaultTaskContext( m_baseContext, serviceManager );
context.setProperty( TaskContext.BASE_DIRECTORY, project.getBaseDirectory() );
// Create a logger
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ServiceManagerAdaptor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ServiceManagerAdaptor.java
deleted file mode 100644
index c5f6a7507..000000000
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ServiceManagerAdaptor.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.myrmidon.components.workspace;
-
-import org.apache.myrmidon.interfaces.service.AntServiceException;
-import org.apache.myrmidon.interfaces.service.AntServiceManager;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.ServiceException;
-
-/**
- * An adaptor from {@link ServiceManager} to {@link AntServiceManager}.
- *
- * @author Adam Murdoch
- * @version $Revision$ $Date$
- */
-class ServiceManagerAdaptor
- implements AntServiceManager
-{
- private final ServiceManager m_serviceManager;
-
- public ServiceManagerAdaptor( final ServiceManager componentManager )
- {
- m_serviceManager = componentManager;
- }
-
- /**
- * Determines if this service manager contains a particular service.
- */
- public boolean hasService( Class serviceType )
- {
- return m_serviceManager.hasService( serviceType.getName() );
- }
-
- /**
- * Locates a service instance.
- */
- public Object getService( Class serviceType )
- throws AntServiceException
- {
- try
- {
- return m_serviceManager.lookup( serviceType.getName() );
- }
- catch( final ServiceException se )
- {
- throw new AntServiceException( se.getMessage(), se );
- }
- }
-}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/AntServiceManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/AntServiceManager.java
deleted file mode 100644
index ea138ef75..000000000
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/AntServiceManager.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.myrmidon.interfaces.service;
-
-/**
- * Manages a set of services.
- *
- * @author Adam Murdoch
- * @version $Revision$ $Date$
- */
-public interface AntServiceManager
-{
- String ROLE = AntServiceManager.class.getName();
-
- /**
- * Determines if this service manager contains a particular service.
- *
- * @param serviceType The service interface.
- */
- boolean hasService( Class serviceType );
-
- /**
- * Locates a service instance.
- *
- * @param serviceType The service interface.
- * @return The service instance. The returned object is guaranteed to
- * implement the service interface.
- * @throws AntServiceException If the service does not exist.
- */
- Object getService( Class serviceType )
- throws AntServiceException;
-}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/MultiSourceServiceManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/MultiSourceServiceManager.java
index 5968b99b4..54d1f08f0 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/MultiSourceServiceManager.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/MultiSourceServiceManager.java
@@ -10,16 +10,18 @@ package org.apache.myrmidon.interfaces.service;
import java.util.ArrayList;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
/**
* A service manager that aggregates services from several
- * {@link AntServiceManager} objects.
+ * {@link ServiceManager} objects.
*
* @author Adam Murdoch
* @version $Revision$ $Date$
*/
public class MultiSourceServiceManager
- implements AntServiceManager
+ implements ServiceManager
{
private final static Resources REZ
= ResourceManager.getPackageResources( MultiSourceServiceManager.class );
@@ -30,23 +32,21 @@ public class MultiSourceServiceManager
/**
* Adds a service manager to the end of the source list.
*/
- public void add( final AntServiceManager mgr )
+ public void add( final ServiceManager mgr )
{
m_sources.add( mgr );
}
/**
* Determines if this service manager contains a particular service.
- *
- * @param serviceType The service interface.
*/
- public boolean hasService( final Class serviceType )
+ public boolean hasService( final String serviceRole )
{
final int size = m_sources.size();
for( int i = 0; i < size; i++ )
{
- final AntServiceManager serviceManager = (AntServiceManager)m_sources.get( i );
- if( serviceManager.hasService( serviceType ) )
+ final ServiceManager serviceManager = (ServiceManager)m_sources.get( i );
+ if( serviceManager.hasService( serviceRole ) )
{
return true;
}
@@ -57,25 +57,32 @@ public class MultiSourceServiceManager
/**
* Locates a service instance.
*
- * @param serviceType The service interface.
+ * @param serviceRole The service interface.
* @return The service instance. The returned object is guaranteed to
* implement the service interface.
- * @throws AntServiceException If the service does not exist.
+ * @throws ServiceException If the service does not exist.
*/
- public Object getService( final Class serviceType )
- throws AntServiceException
+ public Object lookup( final String serviceRole )
+ throws ServiceException
{
final int size = m_sources.size();
for( int i = 0; i < size; i++ )
{
- final AntServiceManager serviceManager = (AntServiceManager)m_sources.get( i );
- if( serviceManager.hasService( serviceType ) )
+ final ServiceManager serviceManager = (ServiceManager)m_sources.get( i );
+ if( serviceManager.hasService( serviceRole ) )
{
- return serviceManager.getService( serviceType );
+ return serviceManager.lookup( serviceRole );
}
}
- final String message = REZ.getString( "unknown-service.error", serviceType.getName() );
- throw new AntServiceException( message );
+ final String message = REZ.getString( "unknown-service.error", serviceRole );
+ throw new ServiceException( message );
+ }
+
+ /**
+ * Releases a service.
+ */
+ public void release( final Object service )
+ {
}
}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceFactory.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceFactory.java
index 72b938fda..a704e9c71 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceFactory.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceFactory.java
@@ -20,7 +20,7 @@ public interface ServiceFactory
String ROLE = ServiceFactory.class.getName();
/**
- * Create a service that coresponds to this factory.
+ * Create a service that corresponds to this factory.
* This method is usually called after the factory has been
* prepared and configured as appropriate.
*/
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java
index 7820722de..1627e7a7a 100644
--- a/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java
@@ -10,6 +10,7 @@ package org.apache.myrmidon;
import java.io.File;
import java.io.IOException;
import junit.framework.TestCase;
+import org.apache.avalon.framework.CascadingThrowable;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.log.Hierarchy;
@@ -96,11 +97,31 @@ public abstract class AbstractMyrmidonTest
return new LogKitLogger( targetLogger );
}
+ /**
+ * Asserts that an exception chain contains the expected messages.
+ */
+ protected void assertSameMessage( final String[] messages, final Throwable throwable )
+ {
+ Throwable current = throwable;
+ for( int i = 0; i < messages.length; i++ )
+ {
+ String message = messages[ i ];
+ assertNotNull( current );
+ assertEquals( message, current.getMessage() );
+
+ if( current instanceof CascadingThrowable )
+ {
+ current = ( (CascadingThrowable)current ).getCause();
+ }
+ else
+ {
+ current = null;
+ }
+ }
+ }
+
/**
* Asserts that an exception contains the expected message.
- *
- * TODO - should take the expected exception, rather than the message,
- * to check the entire cause chain.
*/
protected void assertSameMessage( final String message, final Throwable throwable )
{
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java
index d48facb27..8c37267db 100644
--- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java
@@ -26,7 +26,6 @@ import org.apache.myrmidon.components.deployer.DefaultClassLoaderManager;
import org.apache.myrmidon.components.deployer.DefaultDeployer;
import org.apache.myrmidon.components.extensions.DefaultExtensionManager;
import org.apache.myrmidon.components.role.DefaultRoleManager;
-import org.apache.myrmidon.components.service.DefaultAntServiceManager;
import org.apache.myrmidon.components.type.DefaultTypeManager;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
@@ -34,7 +33,6 @@ import org.apache.myrmidon.interfaces.converter.MasterConverter;
import org.apache.myrmidon.interfaces.deployer.Deployer;
import org.apache.myrmidon.interfaces.extensions.ExtensionManager;
import org.apache.myrmidon.interfaces.role.RoleManager;
-import org.apache.myrmidon.interfaces.service.AntServiceManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeManager;
@@ -117,10 +115,6 @@ public abstract class AbstractComponentTest
m_serviceManager.put( RoleManager.ROLE, component );
components.add( component );
- component = new DefaultAntServiceManager();
- m_serviceManager.put( AntServiceManager.ROLE, component );
- components.add( component );
-
// Log enable the components
for( Iterator iterator = components.iterator(); iterator.hasNext(); )
{
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
index 0fb598d61..074489d65 100644
--- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
@@ -20,8 +20,8 @@ import org.apache.myrmidon.components.workspace.DefaultTaskContext;
import org.apache.myrmidon.framework.DataType;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.configurer.TaskContextAdapter;
-import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.role.RoleInfo;
+import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
/**
@@ -339,8 +339,11 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
- final String message = REZ.getString( "extra-config-for-ref.error" );
- assertSameMessage( message, e );
+ final String[] messages = {
+ REZ.getString( "bad-configure-element.error", "some-prop-ref" ),
+ REZ.getString( "extra-config-for-ref.error" )
+ };
+ assertSameMessage( messages, e );
}
}
@@ -364,10 +367,13 @@ public class DefaultConfigurerTest
}
catch( final ConfigurationException ce )
{
- final String message = REZ.getString( "typed-adder-non-interface.error",
- ConfigTest4.class.getName(),
- Integer.class.getName() );
- assertSameMessage( message, ce );
+ final String[] messages = {
+ REZ.getString( "bad-configure-element.error", "test" ),
+ REZ.getString( "typed-adder-non-interface.error",
+ ConfigTest4.class.getName(),
+ Integer.class.getName() )
+ };
+ assertSameMessage( messages, ce );
}
}
@@ -390,10 +396,13 @@ public class DefaultConfigurerTest
}
catch( final ConfigurationException ce )
{
- final String message = REZ.getString( "multiple-adder-methods-for-element.error",
- ConfigTest5.class.getName(),
- "");
- assertSameMessage( message, ce );
+ final String[] messages = {
+ REZ.getString( "bad-configure-element.error", "test" ),
+ REZ.getString( "multiple-adder-methods-for-element.error",
+ ConfigTest5.class.getName(),
+ "")
+ };
+ assertSameMessage( messages, ce );
}
}
@@ -566,9 +575,11 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
- final String message = REZ.getString( "get-ref.error",
- "unknown-prop" );
- assertSameMessage( message, e );
+ final String[] messages = {
+ REZ.getString( "bad-set-attribute.error", "test", "some-prop-ref" ),
+ REZ.getString( "unknown-reference.error", "unknown-prop" )
+ };
+ assertSameMessage( messages, e );
}
}
@@ -594,11 +605,14 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
- final String message = REZ.getString( "mismatch-ref-types.error",
- "prop-a",
- String.class.getName(),
- ConfigTest2.class.getName() );
- assertSameMessage( message, e );
+ final String[] messages = {
+ REZ.getString( "bad-set-attribute.error", "test", "some-prop-ref" ),
+ REZ.getString( "mismatch-ref-types.error",
+ "prop-a",
+ String.class.getName(),
+ ConfigTest2.class.getName() )
+ };
+ assertSameMessage( messages, e );
}
}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/InstantiatingServiceManagerTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/InstantiatingServiceManagerTest.java
new file mode 100644
index 000000000..75dc65aa4
--- /dev/null
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/InstantiatingServiceManagerTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.myrmidon.components.service;
+
+import org.apache.avalon.excalibur.i18n.ResourceManager;
+import org.apache.avalon.excalibur.i18n.Resources;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.myrmidon.components.AbstractComponentTest;
+import org.apache.myrmidon.interfaces.role.RoleInfo;
+import org.apache.myrmidon.interfaces.role.RoleManager;
+import org.apache.myrmidon.interfaces.service.ServiceFactory;
+import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
+import org.apache.myrmidon.interfaces.type.TypeManager;
+
+/**
+ * Test cases for the default service manager.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class InstantiatingServiceManagerTest
+ extends AbstractComponentTest
+{
+ private final static Resources REZ
+ = ResourceManager.getPackageResources( InstantiatingServiceManagerTest.class );
+
+ private InstantiatingServiceManager m_serviceManager;
+ private Parameters m_parameters = new Parameters();
+
+ public InstantiatingServiceManagerTest( final String name )
+ {
+ super( name );
+ }
+
+ /**
+ * Setup the test case - prepares the set of components.
+ */
+ protected void setUp()
+ throws Exception
+ {
+ super.setUp();
+
+ // Set-up the service manager
+ m_serviceManager = new InstantiatingServiceManager();
+ m_serviceManager.enableLogging( createLogger() );
+ m_serviceManager.service( getServiceManager() );
+ m_serviceManager.parameterize( m_parameters );
+ }
+
+ /**
+ * Tests service instantiation.
+ */
+ public void testCreateService() throws Exception
+ {
+ final String serviceRoleName = "test-service";
+
+ // Setup the test service
+ registerFactory( serviceRoleName, TestService.class, TestServiceFactory1.class );
+
+ // Create the service
+ Object service = m_serviceManager.lookup( serviceRoleName );
+
+ // Check service is of the expected class (don't use instanceof)
+ assertTrue( service.getClass() == TestServiceImpl1.class );
+ }
+
+ /**
+ * Tests service lookup.
+ */
+ public void testLookup() throws Exception
+ {
+ final String serviceRoleName = "test-service";
+
+ // Setup the test service
+ registerFactory( serviceRoleName, TestService.class, TestServiceFactory1.class );
+
+ // Check whether the service can be instantiated
+ boolean hasService = m_serviceManager.hasService( serviceRoleName );
+ assertTrue( hasService );
+ }
+
+ /**
+ * Tests that a service factory and service instance are taken through
+ * the lifecycle steps.
+ */
+ public void testLifecycle() throws Exception
+ {
+ final String serviceRoleName = "test-service";
+
+ // Setup the test service
+ registerFactory( serviceRoleName, TestService.class, TestServiceFactory2.class );
+
+ // Create the service
+ TestService service = (TestService)m_serviceManager.lookup( serviceRoleName );
+
+ // Check service is of the expected class (don't use instanceof)
+ assertTrue( service.getClass() == TestServiceImpl2.class );
+
+ // Assert the service has been setup correctly
+ service.doWork();
+ }
+
+ /**
+ * Tests looking up an unknown service.
+ */
+ public void testUnknownService() throws Exception
+ {
+ // Make sure that hasService() works correctly
+ final String serviceRole = "some-unknown-service";
+ assertTrue( ! m_serviceManager.hasService( serviceRole ) );
+
+ // Make sure that lookup() fails
+ try
+ {
+ m_serviceManager.lookup( serviceRole );
+ fail();
+ }
+ catch( ServiceException e )
+ {
+ final String message = REZ.getString( "create-service.error", serviceRole );
+ assertSameMessage( message, e );
+ }
+ }
+
+ /**
+ * Registers a service factory.
+ */
+ private void registerFactory( final String serviceRoleName,
+ final Class serviceType,
+ final Class factoryClass )
+ throws Exception
+ {
+ // TODO - add stuff to TypeDeployer to do this instead
+ final RoleManager roleManager = (RoleManager)getServiceManager().lookup( RoleManager.ROLE );
+ roleManager.addRole( new RoleInfo( serviceRoleName, null, serviceType ) );
+ final DefaultTypeFactory typeFactory = new DefaultTypeFactory( getClass().getClassLoader() );
+ typeFactory.addNameClassMapping( serviceRoleName, factoryClass.getName() );
+ final TypeManager typeManager = (TypeManager)getServiceManager().lookup( TypeManager.ROLE );
+ typeManager.registerType( ServiceFactory.class, serviceRoleName, typeFactory );
+ }
+}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/LifecycleValidator.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/LifecycleValidator.java
new file mode 100644
index 000000000..916f268cd
--- /dev/null
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/LifecycleValidator.java
@@ -0,0 +1,67 @@
+/*
+ * 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.myrmidon.components.service;
+
+import junit.framework.Assert;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.logger.LogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+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.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+
+/**
+ * A basic class that asserts that the object is correctly set-up.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class LifecycleValidator
+ extends Assert
+ implements LogEnabled, Serviceable, Parameterizable, Initializable
+{
+ private String m_state = STATE_NOT_INIT;
+
+ private final static String STATE_NOT_INIT = "not-prepared";
+ private final static String STATE_LOG_ENABLED = "log-enabled";
+ private final static String STATE_SERVICED = "serviced";
+ private final static String STATE_PARAMETERISED = "parameterised";
+ protected final static String STATE_INITIALISED = "initialised";
+
+ public void enableLogging( final Logger logger )
+ {
+ assertEquals( STATE_NOT_INIT, m_state );
+ m_state = STATE_LOG_ENABLED;
+ }
+
+ public void service( final ServiceManager serviceManager ) throws ServiceException
+ {
+ assertEquals( STATE_LOG_ENABLED, m_state );
+ m_state = STATE_SERVICED;
+ }
+
+ public void parameterize( Parameters parameters ) throws ParameterException
+ {
+ assertEquals( STATE_SERVICED, m_state );
+ m_state = STATE_PARAMETERISED;
+ }
+
+ public void initialize() throws Exception
+ {
+ assertEquals( STATE_PARAMETERISED, m_state );
+ m_state = STATE_INITIALISED;
+ }
+
+ protected void assertSetup()
+ {
+ assertEquals( STATE_INITIALISED, m_state );
+ }
+}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestService.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestService.java
new file mode 100644
index 000000000..4c0485a52
--- /dev/null
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestService.java
@@ -0,0 +1,19 @@
+/*
+ * 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.myrmidon.components.service;
+
+/**
+ * A service interface.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public interface TestService
+{
+ void doWork();
+}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceFactory1.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceFactory1.java
new file mode 100644
index 000000000..bccf1dd98
--- /dev/null
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceFactory1.java
@@ -0,0 +1,30 @@
+/*
+ * 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.myrmidon.components.service;
+
+import org.apache.myrmidon.interfaces.service.AntServiceException;
+import org.apache.myrmidon.interfaces.service.ServiceFactory;
+
+/**
+ * A test service factory.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class TestServiceFactory1
+ implements ServiceFactory
+{
+ /**
+ * Create a service that coresponds to this factory.
+ */
+ public Object createService()
+ throws AntServiceException
+ {
+ return new TestServiceImpl1();
+ }
+}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceFactory2.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceFactory2.java
new file mode 100644
index 000000000..8cae19da6
--- /dev/null
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceFactory2.java
@@ -0,0 +1,33 @@
+/*
+ * 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.myrmidon.components.service;
+
+import org.apache.myrmidon.interfaces.service.AntServiceException;
+import org.apache.myrmidon.interfaces.service.ServiceFactory;
+
+/**
+ * A test service factory, which asserts that the factory has been properly
+ * set-up before it is used.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class TestServiceFactory2
+ extends LifecycleValidator
+ implements ServiceFactory
+{
+ /**
+ * Create a service that corresponds to this factory.
+ */
+ public Object createService()
+ throws AntServiceException
+ {
+ assertSetup();
+ return new TestServiceImpl2();
+ }
+}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceImpl1.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceImpl1.java
new file mode 100644
index 000000000..69c393ab1
--- /dev/null
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceImpl1.java
@@ -0,0 +1,22 @@
+/*
+ * 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.myrmidon.components.service;
+
+/**
+ * A test service implementation.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class TestServiceImpl1
+ implements TestService
+{
+ public void doWork()
+ {
+ }
+}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceImpl2.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceImpl2.java
new file mode 100644
index 000000000..d715cf6dc
--- /dev/null
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceImpl2.java
@@ -0,0 +1,24 @@
+/*
+ * 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.myrmidon.components.service;
+
+/**
+ * A test service that asserts it has been set-up correctly.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class TestServiceImpl2
+ extends LifecycleValidator
+ implements TestService
+{
+ public void doWork()
+ {
+ assertSetup();
+ }
+}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java
index 7820722de..1627e7a7a 100644
--- a/proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java
@@ -10,6 +10,7 @@ package org.apache.myrmidon;
import java.io.File;
import java.io.IOException;
import junit.framework.TestCase;
+import org.apache.avalon.framework.CascadingThrowable;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.log.Hierarchy;
@@ -96,11 +97,31 @@ public abstract class AbstractMyrmidonTest
return new LogKitLogger( targetLogger );
}
+ /**
+ * Asserts that an exception chain contains the expected messages.
+ */
+ protected void assertSameMessage( final String[] messages, final Throwable throwable )
+ {
+ Throwable current = throwable;
+ for( int i = 0; i < messages.length; i++ )
+ {
+ String message = messages[ i ];
+ assertNotNull( current );
+ assertEquals( message, current.getMessage() );
+
+ if( current instanceof CascadingThrowable )
+ {
+ current = ( (CascadingThrowable)current ).getCause();
+ }
+ else
+ {
+ current = null;
+ }
+ }
+ }
+
/**
* Asserts that an exception contains the expected message.
- *
- * TODO - should take the expected exception, rather than the message,
- * to check the entire cause chain.
*/
protected void assertSameMessage( final String message, final Throwable throwable )
{
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java
index d48facb27..8c37267db 100644
--- a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java
@@ -26,7 +26,6 @@ import org.apache.myrmidon.components.deployer.DefaultClassLoaderManager;
import org.apache.myrmidon.components.deployer.DefaultDeployer;
import org.apache.myrmidon.components.extensions.DefaultExtensionManager;
import org.apache.myrmidon.components.role.DefaultRoleManager;
-import org.apache.myrmidon.components.service.DefaultAntServiceManager;
import org.apache.myrmidon.components.type.DefaultTypeManager;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
@@ -34,7 +33,6 @@ import org.apache.myrmidon.interfaces.converter.MasterConverter;
import org.apache.myrmidon.interfaces.deployer.Deployer;
import org.apache.myrmidon.interfaces.extensions.ExtensionManager;
import org.apache.myrmidon.interfaces.role.RoleManager;
-import org.apache.myrmidon.interfaces.service.AntServiceManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeManager;
@@ -117,10 +115,6 @@ public abstract class AbstractComponentTest
m_serviceManager.put( RoleManager.ROLE, component );
components.add( component );
- component = new DefaultAntServiceManager();
- m_serviceManager.put( AntServiceManager.ROLE, component );
- components.add( component );
-
// Log enable the components
for( Iterator iterator = components.iterator(); iterator.hasNext(); )
{
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
index 0fb598d61..074489d65 100644
--- a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
@@ -20,8 +20,8 @@ import org.apache.myrmidon.components.workspace.DefaultTaskContext;
import org.apache.myrmidon.framework.DataType;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.configurer.TaskContextAdapter;
-import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.role.RoleInfo;
+import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
/**
@@ -339,8 +339,11 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
- final String message = REZ.getString( "extra-config-for-ref.error" );
- assertSameMessage( message, e );
+ final String[] messages = {
+ REZ.getString( "bad-configure-element.error", "some-prop-ref" ),
+ REZ.getString( "extra-config-for-ref.error" )
+ };
+ assertSameMessage( messages, e );
}
}
@@ -364,10 +367,13 @@ public class DefaultConfigurerTest
}
catch( final ConfigurationException ce )
{
- final String message = REZ.getString( "typed-adder-non-interface.error",
- ConfigTest4.class.getName(),
- Integer.class.getName() );
- assertSameMessage( message, ce );
+ final String[] messages = {
+ REZ.getString( "bad-configure-element.error", "test" ),
+ REZ.getString( "typed-adder-non-interface.error",
+ ConfigTest4.class.getName(),
+ Integer.class.getName() )
+ };
+ assertSameMessage( messages, ce );
}
}
@@ -390,10 +396,13 @@ public class DefaultConfigurerTest
}
catch( final ConfigurationException ce )
{
- final String message = REZ.getString( "multiple-adder-methods-for-element.error",
- ConfigTest5.class.getName(),
- "");
- assertSameMessage( message, ce );
+ final String[] messages = {
+ REZ.getString( "bad-configure-element.error", "test" ),
+ REZ.getString( "multiple-adder-methods-for-element.error",
+ ConfigTest5.class.getName(),
+ "")
+ };
+ assertSameMessage( messages, ce );
}
}
@@ -566,9 +575,11 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
- final String message = REZ.getString( "get-ref.error",
- "unknown-prop" );
- assertSameMessage( message, e );
+ final String[] messages = {
+ REZ.getString( "bad-set-attribute.error", "test", "some-prop-ref" ),
+ REZ.getString( "unknown-reference.error", "unknown-prop" )
+ };
+ assertSameMessage( messages, e );
}
}
@@ -594,11 +605,14 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
- final String message = REZ.getString( "mismatch-ref-types.error",
- "prop-a",
- String.class.getName(),
- ConfigTest2.class.getName() );
- assertSameMessage( message, e );
+ final String[] messages = {
+ REZ.getString( "bad-set-attribute.error", "test", "some-prop-ref" ),
+ REZ.getString( "mismatch-ref-types.error",
+ "prop-a",
+ String.class.getName(),
+ ConfigTest2.class.getName() )
+ };
+ assertSameMessage( messages, e );
}
}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/InstantiatingServiceManagerTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/InstantiatingServiceManagerTest.java
new file mode 100644
index 000000000..75dc65aa4
--- /dev/null
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/InstantiatingServiceManagerTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.myrmidon.components.service;
+
+import org.apache.avalon.excalibur.i18n.ResourceManager;
+import org.apache.avalon.excalibur.i18n.Resources;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.myrmidon.components.AbstractComponentTest;
+import org.apache.myrmidon.interfaces.role.RoleInfo;
+import org.apache.myrmidon.interfaces.role.RoleManager;
+import org.apache.myrmidon.interfaces.service.ServiceFactory;
+import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
+import org.apache.myrmidon.interfaces.type.TypeManager;
+
+/**
+ * Test cases for the default service manager.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class InstantiatingServiceManagerTest
+ extends AbstractComponentTest
+{
+ private final static Resources REZ
+ = ResourceManager.getPackageResources( InstantiatingServiceManagerTest.class );
+
+ private InstantiatingServiceManager m_serviceManager;
+ private Parameters m_parameters = new Parameters();
+
+ public InstantiatingServiceManagerTest( final String name )
+ {
+ super( name );
+ }
+
+ /**
+ * Setup the test case - prepares the set of components.
+ */
+ protected void setUp()
+ throws Exception
+ {
+ super.setUp();
+
+ // Set-up the service manager
+ m_serviceManager = new InstantiatingServiceManager();
+ m_serviceManager.enableLogging( createLogger() );
+ m_serviceManager.service( getServiceManager() );
+ m_serviceManager.parameterize( m_parameters );
+ }
+
+ /**
+ * Tests service instantiation.
+ */
+ public void testCreateService() throws Exception
+ {
+ final String serviceRoleName = "test-service";
+
+ // Setup the test service
+ registerFactory( serviceRoleName, TestService.class, TestServiceFactory1.class );
+
+ // Create the service
+ Object service = m_serviceManager.lookup( serviceRoleName );
+
+ // Check service is of the expected class (don't use instanceof)
+ assertTrue( service.getClass() == TestServiceImpl1.class );
+ }
+
+ /**
+ * Tests service lookup.
+ */
+ public void testLookup() throws Exception
+ {
+ final String serviceRoleName = "test-service";
+
+ // Setup the test service
+ registerFactory( serviceRoleName, TestService.class, TestServiceFactory1.class );
+
+ // Check whether the service can be instantiated
+ boolean hasService = m_serviceManager.hasService( serviceRoleName );
+ assertTrue( hasService );
+ }
+
+ /**
+ * Tests that a service factory and service instance are taken through
+ * the lifecycle steps.
+ */
+ public void testLifecycle() throws Exception
+ {
+ final String serviceRoleName = "test-service";
+
+ // Setup the test service
+ registerFactory( serviceRoleName, TestService.class, TestServiceFactory2.class );
+
+ // Create the service
+ TestService service = (TestService)m_serviceManager.lookup( serviceRoleName );
+
+ // Check service is of the expected class (don't use instanceof)
+ assertTrue( service.getClass() == TestServiceImpl2.class );
+
+ // Assert the service has been setup correctly
+ service.doWork();
+ }
+
+ /**
+ * Tests looking up an unknown service.
+ */
+ public void testUnknownService() throws Exception
+ {
+ // Make sure that hasService() works correctly
+ final String serviceRole = "some-unknown-service";
+ assertTrue( ! m_serviceManager.hasService( serviceRole ) );
+
+ // Make sure that lookup() fails
+ try
+ {
+ m_serviceManager.lookup( serviceRole );
+ fail();
+ }
+ catch( ServiceException e )
+ {
+ final String message = REZ.getString( "create-service.error", serviceRole );
+ assertSameMessage( message, e );
+ }
+ }
+
+ /**
+ * Registers a service factory.
+ */
+ private void registerFactory( final String serviceRoleName,
+ final Class serviceType,
+ final Class factoryClass )
+ throws Exception
+ {
+ // TODO - add stuff to TypeDeployer to do this instead
+ final RoleManager roleManager = (RoleManager)getServiceManager().lookup( RoleManager.ROLE );
+ roleManager.addRole( new RoleInfo( serviceRoleName, null, serviceType ) );
+ final DefaultTypeFactory typeFactory = new DefaultTypeFactory( getClass().getClassLoader() );
+ typeFactory.addNameClassMapping( serviceRoleName, factoryClass.getName() );
+ final TypeManager typeManager = (TypeManager)getServiceManager().lookup( TypeManager.ROLE );
+ typeManager.registerType( ServiceFactory.class, serviceRoleName, typeFactory );
+ }
+}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/LifecycleValidator.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/LifecycleValidator.java
new file mode 100644
index 000000000..916f268cd
--- /dev/null
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/LifecycleValidator.java
@@ -0,0 +1,67 @@
+/*
+ * 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.myrmidon.components.service;
+
+import junit.framework.Assert;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.logger.LogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+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.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+
+/**
+ * A basic class that asserts that the object is correctly set-up.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class LifecycleValidator
+ extends Assert
+ implements LogEnabled, Serviceable, Parameterizable, Initializable
+{
+ private String m_state = STATE_NOT_INIT;
+
+ private final static String STATE_NOT_INIT = "not-prepared";
+ private final static String STATE_LOG_ENABLED = "log-enabled";
+ private final static String STATE_SERVICED = "serviced";
+ private final static String STATE_PARAMETERISED = "parameterised";
+ protected final static String STATE_INITIALISED = "initialised";
+
+ public void enableLogging( final Logger logger )
+ {
+ assertEquals( STATE_NOT_INIT, m_state );
+ m_state = STATE_LOG_ENABLED;
+ }
+
+ public void service( final ServiceManager serviceManager ) throws ServiceException
+ {
+ assertEquals( STATE_LOG_ENABLED, m_state );
+ m_state = STATE_SERVICED;
+ }
+
+ public void parameterize( Parameters parameters ) throws ParameterException
+ {
+ assertEquals( STATE_SERVICED, m_state );
+ m_state = STATE_PARAMETERISED;
+ }
+
+ public void initialize() throws Exception
+ {
+ assertEquals( STATE_PARAMETERISED, m_state );
+ m_state = STATE_INITIALISED;
+ }
+
+ protected void assertSetup()
+ {
+ assertEquals( STATE_INITIALISED, m_state );
+ }
+}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestService.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestService.java
new file mode 100644
index 000000000..4c0485a52
--- /dev/null
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestService.java
@@ -0,0 +1,19 @@
+/*
+ * 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.myrmidon.components.service;
+
+/**
+ * A service interface.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public interface TestService
+{
+ void doWork();
+}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceFactory1.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceFactory1.java
new file mode 100644
index 000000000..bccf1dd98
--- /dev/null
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceFactory1.java
@@ -0,0 +1,30 @@
+/*
+ * 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.myrmidon.components.service;
+
+import org.apache.myrmidon.interfaces.service.AntServiceException;
+import org.apache.myrmidon.interfaces.service.ServiceFactory;
+
+/**
+ * A test service factory.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class TestServiceFactory1
+ implements ServiceFactory
+{
+ /**
+ * Create a service that coresponds to this factory.
+ */
+ public Object createService()
+ throws AntServiceException
+ {
+ return new TestServiceImpl1();
+ }
+}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceFactory2.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceFactory2.java
new file mode 100644
index 000000000..8cae19da6
--- /dev/null
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceFactory2.java
@@ -0,0 +1,33 @@
+/*
+ * 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.myrmidon.components.service;
+
+import org.apache.myrmidon.interfaces.service.AntServiceException;
+import org.apache.myrmidon.interfaces.service.ServiceFactory;
+
+/**
+ * A test service factory, which asserts that the factory has been properly
+ * set-up before it is used.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class TestServiceFactory2
+ extends LifecycleValidator
+ implements ServiceFactory
+{
+ /**
+ * Create a service that corresponds to this factory.
+ */
+ public Object createService()
+ throws AntServiceException
+ {
+ assertSetup();
+ return new TestServiceImpl2();
+ }
+}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceImpl1.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceImpl1.java
new file mode 100644
index 000000000..69c393ab1
--- /dev/null
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceImpl1.java
@@ -0,0 +1,22 @@
+/*
+ * 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.myrmidon.components.service;
+
+/**
+ * A test service implementation.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class TestServiceImpl1
+ implements TestService
+{
+ public void doWork()
+ {
+ }
+}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceImpl2.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceImpl2.java
new file mode 100644
index 000000000..d715cf6dc
--- /dev/null
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceImpl2.java
@@ -0,0 +1,24 @@
+/*
+ * 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.myrmidon.components.service;
+
+/**
+ * A test service that asserts it has been set-up correctly.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+public class TestServiceImpl2
+ extends LifecycleValidator
+ implements TestService
+{
+ public void doWork()
+ {
+ assertSetup();
+ }
+}