* Renamed DefaultAntServiceManager to InstantiatingServiceManager. This implementation now sets-up the service factories and service instances (log enable, service, parameterise, initialise). * Rearranged the service heirarchy, so that services deployed from a service descriptor are visible in the root context (passed to workspaces and project builders). * Service factories are registered using the role name, not the role class name. * Added unit tests for InstantiatingServiceManager. Changes to DefaultConfigurer error messages: * All exceptions thrown by DefaultConfigurer indicate which configuration element the error happened in. * Updated DefaultConfigurer test cases, to check nested error messages where appropriate. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271529 13f79535-47bb-0310-9956-ffa450edef68master
@@ -27,7 +27,6 @@ import org.apache.myrmidon.interfaces.configurer.Configurer; | |||||
import org.apache.myrmidon.interfaces.converter.MasterConverter; | import org.apache.myrmidon.interfaces.converter.MasterConverter; | ||||
import org.apache.myrmidon.interfaces.role.RoleInfo; | import org.apache.myrmidon.interfaces.role.RoleInfo; | ||||
import org.apache.myrmidon.interfaces.role.RoleManager; | 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.TypeFactory; | ||||
import org.apache.myrmidon.interfaces.type.TypeManager; | import org.apache.myrmidon.interfaces.type.TypeManager; | ||||
@@ -83,16 +82,36 @@ public class DefaultConfigurer | |||||
final Context context ) | final Context context ) | ||||
throws ConfigurationException | 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. | * 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, | private void configureObject( final Object object, | ||||
final Configuration configuration, | final Configuration configuration, | ||||
final Context context ) | final Context context ) | ||||
throws ConfigurationException | |||||
throws Exception | |||||
{ | { | ||||
if( object instanceof Configurable ) | if( object instanceof Configurable ) | ||||
{ | { | ||||
@@ -101,12 +120,9 @@ public class DefaultConfigurer | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
// Start configuration of the object | |||||
final String elemName = configuration.getName(); | final String elemName = configuration.getName(); | ||||
// Locate the configurer for this object | |||||
final ObjectConfigurer configurer = getConfigurer( object.getClass() ); | final ObjectConfigurer configurer = getConfigurer( object.getClass() ); | ||||
// Start configuring this object | |||||
final ConfigurationState state = configurer.startConfiguration( object ); | final ConfigurationState state = configurer.startConfiguration( object ); | ||||
// Set each of the attributes | // Set each of the attributes | ||||
@@ -124,17 +140,13 @@ public class DefaultConfigurer | |||||
{ | { | ||||
final String message = | final String message = | ||||
REZ.getString( "no-such-attribute.error", elemName, name ); | 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 ) | catch( final Exception ce ) | ||||
{ | { | ||||
final String message = | final String message = | ||||
REZ.getString( "bad-set-attribute.error", elemName, name ); | 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 | try | ||||
{ | { | ||||
// Set the content | // Set the content | ||||
final PropertyConfigurer contentConfigurer = state.getConfigurer().getContentConfigurer(); | |||||
setValue( contentConfigurer, state, content, context ); | |||||
setContent( state, content, context ); | |||||
} | } | ||||
catch( final NoSuchPropertyException nspe ) | catch( final NoSuchPropertyException nspe ) | ||||
{ | { | ||||
final String message = | final String message = | ||||
REZ.getString( "no-content.error", elemName ); | 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 ) | catch( final Exception ce ) | ||||
{ | { | ||||
final String message = | final String message = | ||||
REZ.getString( "bad-set-content.error", elemName ); | 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 = | final String message = | ||||
REZ.getString( "no-such-element.error", elemName, name ); | 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; | throw ce; | ||||
} | } | ||||
catch( final Exception ce ) | catch( final Exception ce ) | ||||
{ | { | ||||
final String message = | 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 ); | 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. | * Configures a property from a nested element. | ||||
*/ | */ | ||||
@@ -323,7 +349,7 @@ public class DefaultConfigurer | |||||
= getConfigurerFromName( state.getConfigurer(), name, false ); | = getConfigurerFromName( state.getConfigurer(), name, false ); | ||||
// Resolve any props in the id | // Resolve any props in the id | ||||
Object id = resolveProperty( unresolvedId, context ); | |||||
Object id = PropertyUtil.resolveProperty( unresolvedId, context, false ); | |||||
// Locate the referenced object | // Locate the referenced object | ||||
Object ref = null; | Object ref = null; | ||||
@@ -331,10 +357,10 @@ public class DefaultConfigurer | |||||
{ | { | ||||
ref = context.get( id ); | ref = context.get( id ); | ||||
} | } | ||||
catch( final ContextException exc ) | |||||
catch( final ContextException e ) | |||||
{ | { | ||||
final String message = REZ.getString( "get-ref.error", id ); | final String message = REZ.getString( "get-ref.error", id ); | ||||
throw new ConfigurationException( message, exc ); | |||||
throw new ConfigurationException( message, e ); | |||||
} | } | ||||
// Check the types | // Check the types | ||||
@@ -349,13 +375,6 @@ public class DefaultConfigurer | |||||
childConfigurer.addValue( state, ref ); | 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. | * Sets an attribute value. | ||||
*/ | */ | ||||
@@ -428,7 +447,7 @@ public class DefaultConfigurer | |||||
final Configuration element, | final Configuration element, | ||||
final Context context, | final Context context, | ||||
final PropertyConfigurer childConfigurer ) | final PropertyConfigurer childConfigurer ) | ||||
throws ConfigurationException | |||||
throws Exception | |||||
{ | { | ||||
final String name = element.getName(); | final String name = element.getName(); | ||||
final Class type = childConfigurer.getType(); | final Class type = childConfigurer.getType(); | ||||
@@ -472,30 +491,33 @@ public class DefaultConfigurer | |||||
throws Exception | throws Exception | ||||
{ | { | ||||
// Try a named property | // 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 | // 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, | private Object createdTypedObject( final String name, | ||||
final Class type ) | final Class type ) | ||||
throws ConfigurationException | |||||
throws Exception | |||||
{ | { | ||||
// Attempt to create the object | // Attempt to create the object | ||||
final Object obj; | final Object obj; | ||||
try | try | ||||
{ | { | ||||
final TypeFactory factory = getTypeFactory( DataType.class ); | |||||
final TypeFactory factory = m_typeManager.getFactory( DataType.class ); | |||||
obj = factory.create( name ); | obj = factory.create( name ); | ||||
} | } | ||||
catch( final Exception e ) | catch( final Exception e ) | ||||
@@ -537,7 +559,7 @@ public class DefaultConfigurer | |||||
* Utility method to instantiate an instance of the specified class. | * Utility method to instantiate an instance of the specified class. | ||||
*/ | */ | ||||
private Object createObject( final Class type ) | private Object createObject( final Class type ) | ||||
throws ConfigurationException | |||||
throws Exception | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
@@ -551,21 +573,4 @@ public class DefaultConfigurer | |||||
throw new ConfigurationException( message, e ); | 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 ); | |||||
} | |||||
} | |||||
} | } |
@@ -353,53 +353,24 @@ class DefaultObjectConfigurer | |||||
* Returns a configurer for an element of this class. | * Returns a configurer for an element of this class. | ||||
*/ | */ | ||||
public PropertyConfigurer getProperty( final String name ) | 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. | * Returns a configurer for the typed property of this class. | ||||
*/ | */ | ||||
public PropertyConfigurer getTypedProperty() | 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. | * Returns a configurer for the content of this class. | ||||
*/ | */ | ||||
public PropertyConfigurer getContentConfigurer() | 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; | |||||
} | } | ||||
/** | /** | ||||
@@ -7,22 +7,15 @@ | |||||
*/ | */ | ||||
package org.apache.myrmidon.components.configurer; | 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 | * @author Adam Murdoch | ||||
* @version $Revision$ $Date$ | * @version $Revision$ $Date$ | ||||
*/ | */ | ||||
class NoSuchPropertyException | class NoSuchPropertyException | ||||
extends CascadingException | |||||
extends Exception | |||||
{ | { | ||||
public NoSuchPropertyException( String message ) | |||||
{ | |||||
super( message ); | |||||
} | |||||
} | } |
@@ -43,29 +43,24 @@ interface ObjectConfigurer | |||||
* Returns a configurer for a property of this class. | * Returns a configurer for a property of this class. | ||||
* | * | ||||
* @param name The element name. Property names are case-insensitive. | * @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. | * 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(); | |||||
} | } |
@@ -11,7 +11,7 @@ import org.apache.avalon.framework.configuration.ConfigurationException; | |||||
/** | /** | ||||
* Configures a property of an object. | * Configures a property of an object. | ||||
* TODO - axe useCreator() and createValue(). | |||||
* TODO - axe createValue(). | |||||
* | * | ||||
* @author <a href="mailto:adammurdoch_ml@yahoo.com">Adam Murdoch</a> | * @author <a href="mailto:adammurdoch_ml@yahoo.com">Adam Murdoch</a> | ||||
* @version $Revision$ $Date$ | * @version $Revision$ $Date$ | ||||
@@ -25,8 +25,7 @@ interface PropertyConfigurer | |||||
/** | /** | ||||
* Creates a default value for this property. This value must be configured, | * 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. | * @param state The state object, representing the object being configured. | ||||
* @return An object which is assignable to the type returned by | * @return An object which is assignable to the type returned by | ||||
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @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; | |||||
} | |||||
} |
@@ -1,14 +1,11 @@ | |||||
create-object.error=Could not create an object of class {0}. | 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. | 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}. | 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}". | 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-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-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}. | 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. | 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. | must-be-element.error=This property must be configured using a nested element. | ||||
too-many-values.error=Too many values for this property. | too-many-values.error=Too many values for this property. | ||||
no-complex-type.error=Can not get complex type for non-primitive type {0}. | 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-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}. | 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}>. | 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}>. | 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. | 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}. | 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.mismatched-braces.error=Malformed property with mismatched }'s. | ||||
prop.missing-value.error=Unable to find "{0}" to expand during property resolution. | |||||
prop.missing-value.error=Unable to find "{0}" to expand during property resolution. |
@@ -26,7 +26,6 @@ import org.apache.myrmidon.interfaces.deployer.TypeDefinition; | |||||
import org.apache.myrmidon.interfaces.deployer.TypeDeployer; | import org.apache.myrmidon.interfaces.deployer.TypeDeployer; | ||||
import org.apache.myrmidon.interfaces.role.RoleInfo; | import org.apache.myrmidon.interfaces.role.RoleInfo; | ||||
import org.apache.myrmidon.interfaces.role.RoleManager; | 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.service.ServiceFactory; | ||||
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | ||||
import org.apache.myrmidon.interfaces.type.TypeManager; | import org.apache.myrmidon.interfaces.type.TypeManager; | ||||
@@ -53,7 +52,6 @@ public class DefaultDeployer | |||||
/** Map from ClassLoader to the deployer for that class loader. */ | /** Map from ClassLoader to the deployer for that class loader. */ | ||||
private final Map m_classLoaderDeployers = new HashMap(); | private final Map m_classLoaderDeployers = new HashMap(); | ||||
private AntServiceManager m_serviceManager; | |||||
/** | /** | ||||
* Retrieve relevent services needed to deploy. | * Retrieve relevent services needed to deploy. | ||||
@@ -68,7 +66,6 @@ public class DefaultDeployer | |||||
m_typeManager = (TypeManager)serviceManager.lookup( TypeManager.ROLE ); | m_typeManager = (TypeManager)serviceManager.lookup( TypeManager.ROLE ); | ||||
m_roleManager = (RoleManager)serviceManager.lookup( RoleManager.ROLE ); | m_roleManager = (RoleManager)serviceManager.lookup( RoleManager.ROLE ); | ||||
m_classLoaderManager = (ClassLoaderManager)serviceManager.lookup( ClassLoaderManager.ROLE ); | m_classLoaderManager = (ClassLoaderManager)serviceManager.lookup( ClassLoaderManager.ROLE ); | ||||
m_serviceManager = (AntServiceManager)serviceManager.lookup( AntServiceManager.ROLE ); | |||||
} | } | ||||
/** | /** | ||||
@@ -148,9 +145,9 @@ public class DefaultDeployer | |||||
throws Exception | throws Exception | ||||
{ | { | ||||
final String roleShorthand = definition.getRoleShorthand(); | final String roleShorthand = definition.getRoleShorthand(); | ||||
final Class serviceType = getRoleType( roleShorthand ); | |||||
final String roleName = getRole( roleShorthand ).getName(); | |||||
final String factoryClassName = definition.getFactoryClass(); | 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 | // Deploy general-purpose type | ||||
final Class roleType = getRoleType( roleShorthand ); | |||||
final Class roleType = getRole( roleShorthand ).getType(); | |||||
handleType( deployment, roleType, typeName, className ); | handleType( deployment, roleType, typeName, className ); | ||||
if( getLogger().isDebugEnabled() ) | 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 | throws DeploymentException | ||||
{ | { | ||||
final RoleInfo roleInfo = m_roleManager.getRoleByShorthandName( roleShorthand ); | final RoleInfo roleInfo = m_roleManager.getRoleByShorthandName( roleShorthand ); | ||||
@@ -286,6 +283,6 @@ public class DefaultDeployer | |||||
final String message = REZ.getString( "unknown-role4name.error", roleShorthand ); | final String message = REZ.getString( "unknown-role4name.error", roleShorthand ); | ||||
throw new DeploymentException( message ); | throw new DeploymentException( message ); | ||||
} | } | ||||
return roleInfo.getType(); | |||||
return roleInfo; | |||||
} | } | ||||
} | } |
@@ -22,6 +22,7 @@ import org.apache.avalon.framework.logger.AbstractLogEnabled; | |||||
import org.apache.avalon.framework.parameters.Parameterizable; | import org.apache.avalon.framework.parameters.Parameterizable; | ||||
import org.apache.avalon.framework.parameters.Parameters; | import org.apache.avalon.framework.parameters.Parameters; | ||||
import org.apache.avalon.framework.service.DefaultServiceManager; | import org.apache.avalon.framework.service.DefaultServiceManager; | ||||
import org.apache.avalon.framework.service.ServiceManager; | |||||
import org.apache.avalon.framework.service.Serviceable; | import org.apache.avalon.framework.service.Serviceable; | ||||
import org.apache.myrmidon.components.deployer.ClassLoaderManager; | import org.apache.myrmidon.components.deployer.ClassLoaderManager; | ||||
import org.apache.myrmidon.interfaces.aspect.AspectManager; | 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.extensions.ExtensionManager; | ||||
import org.apache.myrmidon.interfaces.model.Project; | import org.apache.myrmidon.interfaces.model.Project; | ||||
import org.apache.myrmidon.interfaces.role.RoleManager; | 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.TypeFactory; | ||||
import org.apache.myrmidon.interfaces.type.TypeManager; | import org.apache.myrmidon.interfaces.type.TypeManager; | ||||
import org.apache.myrmidon.interfaces.workspace.Workspace; | import org.apache.myrmidon.interfaces.workspace.Workspace; | ||||
@@ -62,6 +63,7 @@ public class DefaultEmbeddor | |||||
private Deployer m_deployer; | private Deployer m_deployer; | ||||
private TypeManager m_typeManager; | private TypeManager m_typeManager; | ||||
private MultiSourceServiceManager m_workspaceServiceManager; | |||||
private List m_components = new ArrayList(); | private List m_components = new ArrayList(); | ||||
private DefaultServiceManager m_serviceManager = new DefaultServiceManager(); | private DefaultServiceManager m_serviceManager = new DefaultServiceManager(); | ||||
@@ -110,7 +112,7 @@ public class DefaultEmbeddor | |||||
final TypeFactory factory = m_typeManager.getFactory( ProjectBuilder.class ); | final TypeFactory factory = m_typeManager.getFactory( ProjectBuilder.class ); | ||||
final ProjectBuilder builder = (ProjectBuilder)factory.create( type ); | final ProjectBuilder builder = (ProjectBuilder)factory.create( type ); | ||||
setupObject( builder, parameters ); | |||||
setupObject( builder, m_workspaceServiceManager, parameters ); | |||||
return builder; | return builder; | ||||
} | } | ||||
@@ -120,10 +122,9 @@ public class DefaultEmbeddor | |||||
public Workspace createWorkspace( final Parameters parameters ) | public Workspace createWorkspace( final Parameters parameters ) | ||||
throws Exception | throws Exception | ||||
{ | { | ||||
final String component = getParameter( Workspace.ROLE ); | |||||
final Workspace workspace = | 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; | return workspace; | ||||
} | } | ||||
@@ -148,18 +149,27 @@ public class DefaultEmbeddor | |||||
public void initialize() | public void initialize() | ||||
throws Exception | throws Exception | ||||
{ | { | ||||
//setup default properties | |||||
// setup default properties | |||||
m_defaults = createDefaultParameters(); | m_defaults = createDefaultParameters(); | ||||
//create all the components | |||||
createComponents(); | |||||
//setup the components | |||||
// setup the root components | |||||
setupComponents(); | setupComponents(); | ||||
// locate the components we need | |||||
m_deployer = (Deployer)m_serviceManager.lookup( Deployer.ROLE ); | m_deployer = (Deployer)m_serviceManager.lookup( Deployer.ROLE ); | ||||
m_typeManager = (TypeManager)m_serviceManager.lookup( TypeManager.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(); | setupFiles(); | ||||
} | } | ||||
@@ -224,18 +234,16 @@ public class DefaultEmbeddor | |||||
defaults.setParameter( "myrmidon.bin.path", "bin" ); | defaults.setParameter( "myrmidon.bin.path", "bin" ); | ||||
defaults.setParameter( "myrmidon.lib.path", "lib" ); | defaults.setParameter( "myrmidon.lib.path", "lib" ); | ||||
// Default workspace implementation | |||||
defaults.setParameter( Workspace.ROLE, PREFIX + "workspace.DefaultWorkspace" ); | |||||
return defaults; | return defaults; | ||||
} | } | ||||
/** | /** | ||||
* Create all required components. | * Create all required components. | ||||
*/ | */ | ||||
private void createComponents() | |||||
private void setupComponents() | |||||
throws Exception | throws Exception | ||||
{ | { | ||||
// Create the components | |||||
createComponent( ConverterRegistry.class, PREFIX + "converter.DefaultConverterRegistry" ); | createComponent( ConverterRegistry.class, PREFIX + "converter.DefaultConverterRegistry" ); | ||||
createComponent( ExtensionManager.class, PREFIX + "extensions.DefaultExtensionManager" ); | createComponent( ExtensionManager.class, PREFIX + "extensions.DefaultExtensionManager" ); | ||||
createComponent( MasterConverter.class, PREFIX + "converter.DefaultMasterConverter" ); | createComponent( MasterConverter.class, PREFIX + "converter.DefaultMasterConverter" ); | ||||
@@ -246,7 +254,13 @@ public class DefaultEmbeddor | |||||
createComponent( Deployer.class, PREFIX + "deployer.DefaultDeployer" ); | createComponent( Deployer.class, PREFIX + "deployer.DefaultDeployer" ); | ||||
createComponent( ClassLoaderManager.class, PREFIX + "deployer.DefaultClassLoaderManager" ); | createComponent( ClassLoaderManager.class, PREFIX + "deployer.DefaultClassLoaderManager" ); | ||||
createComponent( Executor.class, PREFIX + "executor.AspectAwareExecutor" ); | 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 ) | private void createComponent( Class roleType, String defaultImpl ) | ||||
throws Exception | 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 ); | 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. | * Setup all the files attributes. | ||||
*/ | */ | ||||
@@ -354,21 +351,24 @@ public class DefaultEmbeddor | |||||
/** | /** | ||||
* Create a component that implements an interface. | * 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 | * @return the created object | ||||
* @exception Exception if an error occurs | * @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 | throws Exception | ||||
{ | { | ||||
final String role = roleType.getName(); | |||||
final String className = m_parameters.getParameter( role, defaultImpl ); | |||||
try | 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 ); | throw new Exception( message ); | ||||
} | } | ||||
@@ -376,19 +376,19 @@ public class DefaultEmbeddor | |||||
} | } | ||||
catch( final IllegalAccessException iae ) | 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 ); | throw new Exception( message ); | ||||
} | } | ||||
catch( final InstantiationException ie ) | catch( final InstantiationException ie ) | ||||
{ | { | ||||
final String message = | final String message = | ||||
REZ.getString( "no-instantiate.error", clazz.getName(), component ); | |||||
REZ.getString( "no-instantiate.error", roleType.getName(), className ); | |||||
throw new Exception( message ); | throw new Exception( message ); | ||||
} | } | ||||
catch( final ClassNotFoundException cnfe ) | catch( final ClassNotFoundException cnfe ) | ||||
{ | { | ||||
final String message = | final String message = | ||||
REZ.getString( "no-class.error", clazz.getName(), component ); | |||||
REZ.getString( "no-class.error", roleType.getName(), className ); | |||||
throw new Exception( message ); | throw new Exception( message ); | ||||
} | } | ||||
} | } | ||||
@@ -398,6 +398,7 @@ public class DefaultEmbeddor | |||||
* parameterise and initialise lifecycle stages. | * parameterise and initialise lifecycle stages. | ||||
*/ | */ | ||||
private void setupObject( final Object object, | private void setupObject( final Object object, | ||||
final ServiceManager serviceManager, | |||||
final Parameters parameters ) | final Parameters parameters ) | ||||
throws Exception | throws Exception | ||||
{ | { | ||||
@@ -405,7 +406,7 @@ public class DefaultEmbeddor | |||||
if( object instanceof Serviceable ) | if( object instanceof Serviceable ) | ||||
{ | { | ||||
( (Serviceable)object ).service( m_serviceManager ); | |||||
( (Serviceable)object ).service( serviceManager ); | |||||
} | } | ||||
if( object instanceof Parameterizable ) | if( object instanceof Parameterizable ) | ||||
@@ -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. | |||||
* | |||||
* <p>This implementation uses a TypeManager to locate the service factories. | |||||
* | |||||
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @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 <code>ServiceManager</code> to the <code>servicable</code>. | |||||
* The <code>Servicable</code> implementation should use the specified | |||||
* <code>ServiceManager</code> to acquire the components it needs for | |||||
* execution. | |||||
* | |||||
* @param manager The <code>ServiceManager</code> which this | |||||
* <code>Servicable</code> 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 ); | |||||
} | |||||
} | |||||
} |
@@ -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. | |||||
* | |||||
* <p>This manager creates service instances, using a {@link ServiceFactory}, | |||||
* and running the service instances through the service lifecycle: | |||||
* <ul> | |||||
* <li>log enable | |||||
* <li>service | |||||
* <li>parameterise | |||||
* <li>initialise | |||||
* </ul> | |||||
* | |||||
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @version $Revision$ $Date$ | |||||
*/ | |||||
public class InstantiatingServiceManager | |||||
extends AbstractLogEnabled | |||||
implements ServiceManager, Parameterizable, Serviceable, Disposable | |||||
{ | |||||
private final static Resources REZ = | |||||
ResourceManager.getPackageResources( InstantiatingServiceManager.class ); | |||||
/** Map from service class -> service object. */ | |||||
private Map m_services = new HashMap(); | |||||
/** The objects (services and factories) that have been created by this mgr. */ | |||||
private List m_objects = new ArrayList(); | |||||
/** Other services used by this service manager. */ | |||||
private TypeFactory m_typeFactory; | |||||
private RoleManager m_roleManager; | |||||
private ServiceManager m_serviceManager; | |||||
private Parameters m_parameters; | |||||
public void parameterize( Parameters parameters ) throws ParameterException | |||||
{ | |||||
m_parameters = parameters; | |||||
} | |||||
/** | |||||
* Pass the <code>ServiceManager</code> to the <code>servicable</code>. | |||||
* The <code>Servicable</code> implementation should use the specified | |||||
* <code>ServiceManager</code> to acquire the components it needs for | |||||
* execution. | |||||
* | |||||
* @param manager The <code>ServiceManager</code> which this | |||||
* <code>Servicable</code> 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 ); | |||||
} | |||||
} |
@@ -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}. | |||||
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}". |
@@ -14,13 +14,13 @@ import org.apache.avalon.excalibur.i18n.ResourceManager; | |||||
import org.apache.avalon.excalibur.i18n.Resources; | import org.apache.avalon.excalibur.i18n.Resources; | ||||
import org.apache.avalon.excalibur.io.FileUtil; | import org.apache.avalon.excalibur.io.FileUtil; | ||||
import org.apache.avalon.framework.context.ContextException; | 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.TaskContext; | ||||
import org.apache.myrmidon.api.TaskException; | 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.PropertyException; | ||||
import org.apache.myrmidon.components.configurer.PropertyUtil; | |||||
import org.apache.myrmidon.interfaces.configurer.TaskContextAdapter; | 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. | * Default implementation of TaskContext. | ||||
@@ -36,7 +36,7 @@ public class DefaultTaskContext | |||||
private final Map m_contextData = new Hashtable(); | private final Map m_contextData = new Hashtable(); | ||||
private final TaskContext m_parent; | private final TaskContext m_parent; | ||||
private AntServiceManager m_serviceManager; | |||||
private ServiceManager m_serviceManager; | |||||
/** | /** | ||||
* Constructor for Context with no parent contexts. | * Constructor for Context with no parent contexts. | ||||
@@ -57,7 +57,7 @@ public class DefaultTaskContext | |||||
/** | /** | ||||
* Constructor that specifies the service directory for context. | * Constructor that specifies the service directory for context. | ||||
*/ | */ | ||||
public DefaultTaskContext( final AntServiceManager serviceManager ) | |||||
public DefaultTaskContext( final ServiceManager serviceManager ) | |||||
{ | { | ||||
this( null, serviceManager ); | this( null, serviceManager ); | ||||
} | } | ||||
@@ -66,7 +66,7 @@ public class DefaultTaskContext | |||||
* Constructor that takes both parent context and a service directory. | * Constructor that takes both parent context and a service directory. | ||||
*/ | */ | ||||
public DefaultTaskContext( final TaskContext parent, | public DefaultTaskContext( final TaskContext parent, | ||||
final AntServiceManager serviceManager ) | |||||
final ServiceManager serviceManager ) | |||||
{ | { | ||||
m_parent = parent; | m_parent = parent; | ||||
m_serviceManager = serviceManager; | m_serviceManager = serviceManager; | ||||
@@ -153,13 +153,13 @@ public class DefaultTaskContext | |||||
{ | { | ||||
// Try this context first | // Try this context first | ||||
final String name = serviceClass.getName(); | final String name = serviceClass.getName(); | ||||
if( m_serviceManager != null && m_serviceManager.hasService( serviceClass ) ) | |||||
if( m_serviceManager != null && m_serviceManager.hasService( name ) ) | |||||
{ | { | ||||
try | 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 ); | throw new TaskException( se.getMessage(), se ); | ||||
} | } | ||||
@@ -21,10 +21,10 @@ import org.apache.avalon.framework.logger.Logger; | |||||
import org.apache.avalon.framework.parameters.ParameterException; | import org.apache.avalon.framework.parameters.ParameterException; | ||||
import org.apache.avalon.framework.parameters.Parameterizable; | import org.apache.avalon.framework.parameters.Parameterizable; | ||||
import org.apache.avalon.framework.parameters.Parameters; | 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.ServiceManager; | ||||
import org.apache.avalon.framework.service.Serviceable; | 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.log.Hierarchy; | ||||
import org.apache.myrmidon.api.TaskContext; | import org.apache.myrmidon.api.TaskContext; | ||||
import org.apache.myrmidon.api.TaskException; | 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.Project; | ||||
import org.apache.myrmidon.interfaces.model.Target; | import org.apache.myrmidon.interfaces.model.Target; | ||||
import org.apache.myrmidon.interfaces.model.TypeLib; | 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.type.TypeManager; | ||||
import org.apache.myrmidon.interfaces.workspace.Workspace; | import org.apache.myrmidon.interfaces.workspace.Workspace; | ||||
import org.apache.myrmidon.listeners.ProjectListener; | import org.apache.myrmidon.listeners.ProjectListener; | ||||
@@ -258,15 +256,9 @@ public class DefaultWorkspace | |||||
serviceManager.put( Project.ROLE + "/" + name, other ); | 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 | // Create and configure the context | ||||
final DefaultTaskContext context = | final DefaultTaskContext context = | ||||
new DefaultTaskContext( m_baseContext, msServiceManager ); | |||||
new DefaultTaskContext( m_baseContext, serviceManager ); | |||||
context.setProperty( TaskContext.BASE_DIRECTORY, project.getBaseDirectory() ); | context.setProperty( TaskContext.BASE_DIRECTORY, project.getBaseDirectory() ); | ||||
// Create a logger | // Create a logger | ||||
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @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 ); | |||||
} | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @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; | |||||
} |
@@ -10,16 +10,18 @@ package org.apache.myrmidon.interfaces.service; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import org.apache.avalon.excalibur.i18n.ResourceManager; | import org.apache.avalon.excalibur.i18n.ResourceManager; | ||||
import org.apache.avalon.excalibur.i18n.Resources; | 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 | * A service manager that aggregates services from several | ||||
* {@link AntServiceManager} objects. | |||||
* {@link ServiceManager} objects. | |||||
* | * | ||||
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | ||||
* @version $Revision$ $Date$ | * @version $Revision$ $Date$ | ||||
*/ | */ | ||||
public class MultiSourceServiceManager | public class MultiSourceServiceManager | ||||
implements AntServiceManager | |||||
implements ServiceManager | |||||
{ | { | ||||
private final static Resources REZ | private final static Resources REZ | ||||
= ResourceManager.getPackageResources( MultiSourceServiceManager.class ); | = ResourceManager.getPackageResources( MultiSourceServiceManager.class ); | ||||
@@ -30,23 +32,21 @@ public class MultiSourceServiceManager | |||||
/** | /** | ||||
* Adds a service manager to the end of the source list. | * 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 ); | m_sources.add( mgr ); | ||||
} | } | ||||
/** | /** | ||||
* Determines if this service manager contains a particular service. | * 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(); | final int size = m_sources.size(); | ||||
for( int i = 0; i < size; i++ ) | 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; | return true; | ||||
} | } | ||||
@@ -57,25 +57,32 @@ public class MultiSourceServiceManager | |||||
/** | /** | ||||
* Locates a service instance. | * Locates a service instance. | ||||
* | * | ||||
* @param serviceType The service interface. | |||||
* @param serviceRole The service interface. | |||||
* @return The service instance. The returned object is guaranteed to | * @return The service instance. The returned object is guaranteed to | ||||
* implement the service interface. | * 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(); | final int size = m_sources.size(); | ||||
for( int i = 0; i < size; i++ ) | 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 ) | |||||
{ | |||||
} | } | ||||
} | } |
@@ -20,7 +20,7 @@ public interface ServiceFactory | |||||
String ROLE = ServiceFactory.class.getName(); | 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 | * This method is usually called after the factory has been | ||||
* prepared and configured as appropriate. | * prepared and configured as appropriate. | ||||
*/ | */ | ||||
@@ -10,6 +10,7 @@ package org.apache.myrmidon; | |||||
import java.io.File; | import java.io.File; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.avalon.framework.CascadingThrowable; | |||||
import org.apache.avalon.framework.logger.LogKitLogger; | import org.apache.avalon.framework.logger.LogKitLogger; | ||||
import org.apache.avalon.framework.logger.Logger; | import org.apache.avalon.framework.logger.Logger; | ||||
import org.apache.log.Hierarchy; | import org.apache.log.Hierarchy; | ||||
@@ -96,11 +97,31 @@ public abstract class AbstractMyrmidonTest | |||||
return new LogKitLogger( targetLogger ); | 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. | * 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 ) | protected void assertSameMessage( final String message, final Throwable throwable ) | ||||
{ | { | ||||
@@ -26,7 +26,6 @@ import org.apache.myrmidon.components.deployer.DefaultClassLoaderManager; | |||||
import org.apache.myrmidon.components.deployer.DefaultDeployer; | import org.apache.myrmidon.components.deployer.DefaultDeployer; | ||||
import org.apache.myrmidon.components.extensions.DefaultExtensionManager; | import org.apache.myrmidon.components.extensions.DefaultExtensionManager; | ||||
import org.apache.myrmidon.components.role.DefaultRoleManager; | 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.components.type.DefaultTypeManager; | ||||
import org.apache.myrmidon.interfaces.configurer.Configurer; | import org.apache.myrmidon.interfaces.configurer.Configurer; | ||||
import org.apache.myrmidon.interfaces.converter.ConverterRegistry; | 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.deployer.Deployer; | ||||
import org.apache.myrmidon.interfaces.extensions.ExtensionManager; | import org.apache.myrmidon.interfaces.extensions.ExtensionManager; | ||||
import org.apache.myrmidon.interfaces.role.RoleManager; | 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.DefaultTypeFactory; | ||||
import org.apache.myrmidon.interfaces.type.TypeException; | import org.apache.myrmidon.interfaces.type.TypeException; | ||||
import org.apache.myrmidon.interfaces.type.TypeManager; | import org.apache.myrmidon.interfaces.type.TypeManager; | ||||
@@ -117,10 +115,6 @@ public abstract class AbstractComponentTest | |||||
m_serviceManager.put( RoleManager.ROLE, component ); | m_serviceManager.put( RoleManager.ROLE, component ); | ||||
components.add( component ); | components.add( component ); | ||||
component = new DefaultAntServiceManager(); | |||||
m_serviceManager.put( AntServiceManager.ROLE, component ); | |||||
components.add( component ); | |||||
// Log enable the components | // Log enable the components | ||||
for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | ||||
{ | { | ||||
@@ -20,8 +20,8 @@ import org.apache.myrmidon.components.workspace.DefaultTaskContext; | |||||
import org.apache.myrmidon.framework.DataType; | import org.apache.myrmidon.framework.DataType; | ||||
import org.apache.myrmidon.interfaces.configurer.Configurer; | import org.apache.myrmidon.interfaces.configurer.Configurer; | ||||
import org.apache.myrmidon.interfaces.configurer.TaskContextAdapter; | 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.RoleInfo; | ||||
import org.apache.myrmidon.interfaces.role.RoleManager; | |||||
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | ||||
/** | /** | ||||
@@ -339,8 +339,11 @@ public class DefaultConfigurerTest | |||||
} | } | ||||
catch( ConfigurationException e ) | 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 ) | 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 ) | 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 ) | 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 ) | 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 ); | |||||
} | } | ||||
} | } | ||||
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @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 ); | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @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 ); | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @version $Revision$ $Date$ | |||||
*/ | |||||
public interface TestService | |||||
{ | |||||
void doWork(); | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @version $Revision$ $Date$ | |||||
*/ | |||||
public class TestServiceFactory1 | |||||
implements ServiceFactory | |||||
{ | |||||
/** | |||||
* Create a service that coresponds to this factory. | |||||
*/ | |||||
public Object createService() | |||||
throws AntServiceException | |||||
{ | |||||
return new TestServiceImpl1(); | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @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(); | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @version $Revision$ $Date$ | |||||
*/ | |||||
public class TestServiceImpl1 | |||||
implements TestService | |||||
{ | |||||
public void doWork() | |||||
{ | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @version $Revision$ $Date$ | |||||
*/ | |||||
public class TestServiceImpl2 | |||||
extends LifecycleValidator | |||||
implements TestService | |||||
{ | |||||
public void doWork() | |||||
{ | |||||
assertSetup(); | |||||
} | |||||
} |
@@ -10,6 +10,7 @@ package org.apache.myrmidon; | |||||
import java.io.File; | import java.io.File; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.avalon.framework.CascadingThrowable; | |||||
import org.apache.avalon.framework.logger.LogKitLogger; | import org.apache.avalon.framework.logger.LogKitLogger; | ||||
import org.apache.avalon.framework.logger.Logger; | import org.apache.avalon.framework.logger.Logger; | ||||
import org.apache.log.Hierarchy; | import org.apache.log.Hierarchy; | ||||
@@ -96,11 +97,31 @@ public abstract class AbstractMyrmidonTest | |||||
return new LogKitLogger( targetLogger ); | 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. | * 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 ) | protected void assertSameMessage( final String message, final Throwable throwable ) | ||||
{ | { | ||||
@@ -26,7 +26,6 @@ import org.apache.myrmidon.components.deployer.DefaultClassLoaderManager; | |||||
import org.apache.myrmidon.components.deployer.DefaultDeployer; | import org.apache.myrmidon.components.deployer.DefaultDeployer; | ||||
import org.apache.myrmidon.components.extensions.DefaultExtensionManager; | import org.apache.myrmidon.components.extensions.DefaultExtensionManager; | ||||
import org.apache.myrmidon.components.role.DefaultRoleManager; | 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.components.type.DefaultTypeManager; | ||||
import org.apache.myrmidon.interfaces.configurer.Configurer; | import org.apache.myrmidon.interfaces.configurer.Configurer; | ||||
import org.apache.myrmidon.interfaces.converter.ConverterRegistry; | 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.deployer.Deployer; | ||||
import org.apache.myrmidon.interfaces.extensions.ExtensionManager; | import org.apache.myrmidon.interfaces.extensions.ExtensionManager; | ||||
import org.apache.myrmidon.interfaces.role.RoleManager; | 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.DefaultTypeFactory; | ||||
import org.apache.myrmidon.interfaces.type.TypeException; | import org.apache.myrmidon.interfaces.type.TypeException; | ||||
import org.apache.myrmidon.interfaces.type.TypeManager; | import org.apache.myrmidon.interfaces.type.TypeManager; | ||||
@@ -117,10 +115,6 @@ public abstract class AbstractComponentTest | |||||
m_serviceManager.put( RoleManager.ROLE, component ); | m_serviceManager.put( RoleManager.ROLE, component ); | ||||
components.add( component ); | components.add( component ); | ||||
component = new DefaultAntServiceManager(); | |||||
m_serviceManager.put( AntServiceManager.ROLE, component ); | |||||
components.add( component ); | |||||
// Log enable the components | // Log enable the components | ||||
for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | ||||
{ | { | ||||
@@ -20,8 +20,8 @@ import org.apache.myrmidon.components.workspace.DefaultTaskContext; | |||||
import org.apache.myrmidon.framework.DataType; | import org.apache.myrmidon.framework.DataType; | ||||
import org.apache.myrmidon.interfaces.configurer.Configurer; | import org.apache.myrmidon.interfaces.configurer.Configurer; | ||||
import org.apache.myrmidon.interfaces.configurer.TaskContextAdapter; | 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.RoleInfo; | ||||
import org.apache.myrmidon.interfaces.role.RoleManager; | |||||
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | ||||
/** | /** | ||||
@@ -339,8 +339,11 @@ public class DefaultConfigurerTest | |||||
} | } | ||||
catch( ConfigurationException e ) | 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 ) | 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 ) | 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 ) | 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 ) | 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 ); | |||||
} | } | ||||
} | } | ||||
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @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 ); | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @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 ); | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @version $Revision$ $Date$ | |||||
*/ | |||||
public interface TestService | |||||
{ | |||||
void doWork(); | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @version $Revision$ $Date$ | |||||
*/ | |||||
public class TestServiceFactory1 | |||||
implements ServiceFactory | |||||
{ | |||||
/** | |||||
* Create a service that coresponds to this factory. | |||||
*/ | |||||
public Object createService() | |||||
throws AntServiceException | |||||
{ | |||||
return new TestServiceImpl1(); | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @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(); | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @version $Revision$ $Date$ | |||||
*/ | |||||
public class TestServiceImpl1 | |||||
implements TestService | |||||
{ | |||||
public void doWork() | |||||
{ | |||||
} | |||||
} |
@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
* @version $Revision$ $Date$ | |||||
*/ | |||||
public class TestServiceImpl2 | |||||
extends LifecycleValidator | |||||
implements TestService | |||||
{ | |||||
public void doWork() | |||||
{ | |||||
assertSetup(); | |||||
} | |||||
} |