Browse Source

Removed AntServiceManager:

* 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-ffa450edef68
master
adammurdoch 23 years ago
parent
commit
f42a96f304
38 changed files with 1248 additions and 531 deletions
  1. +76
    -71
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java
  2. +3
    -32
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java
  3. +3
    -10
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/NoSuchPropertyException.java
  4. +10
    -15
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java
  5. +2
    -3
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/PropertyConfigurer.java
  6. +39
    -0
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ReportableConfigurationException.java
  7. +4
    -8
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties
  8. +6
    -9
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java
  9. +45
    -44
      proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java
  10. +0
    -151
      proposal/myrmidon/src/java/org/apache/myrmidon/components/service/DefaultAntServiceManager.java
  11. +222
    -0
      proposal/myrmidon/src/java/org/apache/myrmidon/components/service/InstantiatingServiceManager.java
  12. +3
    -3
      proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties
  13. +9
    -9
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java
  14. +3
    -11
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java
  15. +0
    -54
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ServiceManagerAdaptor.java
  16. +0
    -37
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/AntServiceManager.java
  17. +24
    -17
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/MultiSourceServiceManager.java
  18. +1
    -1
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceFactory.java
  19. +24
    -3
      proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java
  20. +0
    -6
      proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java
  21. +33
    -19
      proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
  22. +147
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/service/InstantiatingServiceManagerTest.java
  23. +67
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/service/LifecycleValidator.java
  24. +19
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestService.java
  25. +30
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceFactory1.java
  26. +33
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceFactory2.java
  27. +22
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceImpl1.java
  28. +24
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceImpl2.java
  29. +24
    -3
      proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java
  30. +0
    -6
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java
  31. +33
    -19
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
  32. +147
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/InstantiatingServiceManagerTest.java
  33. +67
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/LifecycleValidator.java
  34. +19
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestService.java
  35. +30
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceFactory1.java
  36. +33
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceFactory2.java
  37. +22
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceImpl1.java
  38. +24
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceImpl2.java

+ 76
- 71
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java View File

@@ -27,7 +27,6 @@ import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.converter.MasterConverter;
import org.apache.myrmidon.interfaces.role.RoleInfo;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;

@@ -83,16 +82,36 @@ public class DefaultConfigurer
final Context context )
throws ConfigurationException
{
configureObject( object, configuration, context );
try
{
// Configure the object
configureObject( object, configuration, context );
}
catch( final ReportableConfigurationException e )
{
// Already have a reasonable error message - so rethrow
throw e.getCause();
}
catch( final Exception e )
{
// Wrap all other errors with general purpose error message
final String message = REZ.getString( "bad-configure-element.error", configuration.getName() );
throw new ConfigurationException( message, e );
}
}

/**
* Does the work of configuring an object.
*
* @throws ReportableConfigurationException On error. This exception
* indicates that the error has been wrapped with an appropriate
* error message.
* @throws Exception On error
*/
private void configureObject( final Object object,
final Configuration configuration,
final Context context )
throws ConfigurationException
throws Exception
{
if( object instanceof Configurable )
{
@@ -101,12 +120,9 @@ public class DefaultConfigurer
}
else
{
// Start configuration of the object
final String elemName = configuration.getName();

// Locate the configurer for this object
final ObjectConfigurer configurer = getConfigurer( object.getClass() );

// Start configuring this object
final ConfigurationState state = configurer.startConfiguration( object );

// Set each of the attributes
@@ -124,17 +140,13 @@ public class DefaultConfigurer
{
final String message =
REZ.getString( "no-such-attribute.error", elemName, name );
throw new ConfigurationException( message, nspe );
}
catch( final ConfigurationException ce )
{
throw ce;
throw new ReportableConfigurationException( message, nspe );
}
catch( final Exception ce )
{
final String message =
REZ.getString( "bad-set-attribute.error", elemName, name );
throw new ConfigurationException( message, ce );
throw new ReportableConfigurationException( message, ce );
}
}

@@ -145,24 +157,19 @@ public class DefaultConfigurer
try
{
// Set the content
final PropertyConfigurer contentConfigurer = state.getConfigurer().getContentConfigurer();
setValue( contentConfigurer, state, content, context );
setContent( state, content, context );
}
catch( final NoSuchPropertyException nspe )
{
final String message =
REZ.getString( "no-content.error", elemName );
throw new ConfigurationException( message, nspe );
}
catch( final ConfigurationException ce )
{
throw ce;
throw new ReportableConfigurationException( message );
}
catch( final Exception ce )
{
final String message =
REZ.getString( "bad-set-content.error", elemName );
throw new ConfigurationException( message, ce );
throw new ReportableConfigurationException( message, ce );
}
}

@@ -180,17 +187,17 @@ public class DefaultConfigurer
{
final String message =
REZ.getString( "no-such-element.error", elemName, name );
throw new ConfigurationException( message, nspe );
throw new ReportableConfigurationException( message, nspe );
}
catch( final ConfigurationException ce )
catch( final ReportableConfigurationException ce )
{
throw ce;
}
catch( final Exception ce )
{
final String message =
REZ.getString( "bad-set-element.error", elemName, name );
throw new ConfigurationException( message, ce );
REZ.getString( "bad-configure-element.error", name );
throw new ReportableConfigurationException( message, ce );
}
}

@@ -240,6 +247,25 @@ public class DefaultConfigurer
configurer.finishConfiguration( state );
}

/**
* Sets the text content for the element.
*/
private void setContent( final ConfigurationState state,
final String content,
final Context context )
throws Exception
{
// Locate the content configurer
final PropertyConfigurer contentConfigurer = state.getConfigurer().getContentConfigurer();
if( contentConfigurer == null )
{
throw new NoSuchPropertyException();
}

// Set the content
setValue( contentConfigurer, state, content, context );
}

/**
* Configures a property from a nested element.
*/
@@ -323,7 +349,7 @@ public class DefaultConfigurer
= getConfigurerFromName( state.getConfigurer(), name, false );

// Resolve any props in the id
Object id = resolveProperty( unresolvedId, context );
Object id = PropertyUtil.resolveProperty( unresolvedId, context, false );

// Locate the referenced object
Object ref = null;
@@ -331,10 +357,10 @@ public class DefaultConfigurer
{
ref = context.get( id );
}
catch( final ContextException exc )
catch( final ContextException e )
{
final String message = REZ.getString( "get-ref.error", id );
throw new ConfigurationException( message, exc );
throw new ConfigurationException( message, e );
}

// Check the types
@@ -349,13 +375,6 @@ public class DefaultConfigurer
childConfigurer.addValue( state, ref );
}

private Object resolveProperty( final String unresolvedId,
final Context context )
throws Exception
{
return PropertyUtil.resolveProperty( unresolvedId, context, false );
}

/**
* Sets an attribute value.
*/
@@ -428,7 +447,7 @@ public class DefaultConfigurer
final Configuration element,
final Context context,
final PropertyConfigurer childConfigurer )
throws ConfigurationException
throws Exception
{
final String name = element.getName();
final Class type = childConfigurer.getType();
@@ -472,30 +491,33 @@ public class DefaultConfigurer
throws Exception
{
// Try a named property
final NoSuchPropertyException exc;
try
PropertyConfigurer propertyConfigurer = configurer.getProperty( name );
if( propertyConfigurer != null )
{
return configurer.getProperty( name );
}
catch( NoSuchPropertyException e )
{
// Keep for later
exc = e;
return propertyConfigurer;
}

// Try a typed property
final PropertyConfigurer propertyConfigurer = configurer.getTypedProperty();
if( !ignoreRoleName )
propertyConfigurer = configurer.getTypedProperty();
if( propertyConfigurer != null )
{
final RoleInfo roleInfo = m_roleManager.getRoleByType( propertyConfigurer.getType() );
if( roleInfo == null || !name.equalsIgnoreCase( roleInfo.getShorthand() ) )
if( ignoreRoleName )
{
// Rethrow the original exception
throw exc;
return propertyConfigurer;
}
else
{
// Check the role name
final RoleInfo roleInfo = m_roleManager.getRoleByType( propertyConfigurer.getType() );
if( roleInfo != null && name.equalsIgnoreCase( roleInfo.getShorthand() ) )
{
return propertyConfigurer;
}
}
}

return propertyConfigurer;
// Unknown prop
throw new NoSuchPropertyException();
}

/**
@@ -504,13 +526,13 @@ public class DefaultConfigurer
*/
private Object createdTypedObject( final String name,
final Class type )
throws ConfigurationException
throws Exception
{
// Attempt to create the object
final Object obj;
try
{
final TypeFactory factory = getTypeFactory( DataType.class );
final TypeFactory factory = m_typeManager.getFactory( DataType.class );
obj = factory.create( name );
}
catch( final Exception e )
@@ -537,7 +559,7 @@ public class DefaultConfigurer
* Utility method to instantiate an instance of the specified class.
*/
private Object createObject( final Class type )
throws ConfigurationException
throws Exception
{
try
{
@@ -551,21 +573,4 @@ public class DefaultConfigurer
throw new ConfigurationException( message, e );
}
}

/**
* Locates a type factory.
*/
protected final TypeFactory getTypeFactory( final Class role )
throws ConfigurationException
{
try
{
return m_typeManager.getFactory( role );
}
catch( final TypeException te )
{
final String message = REZ.getString( "no-factory-for-role.error", role.getName() );
throw new ConfigurationException( message, te );
}
}
}

+ 3
- 32
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java View File

@@ -353,53 +353,24 @@ class DefaultObjectConfigurer
* Returns a configurer for an element of this class.
*/
public PropertyConfigurer getProperty( final String name )
throws NoSuchPropertyException
{
PropertyConfigurer configurer = (PropertyConfigurer)m_props.get( name );
if( null != configurer )
{
return configurer;
}

// Unknown property
final String message = REZ.getString( "unknown-property.error", m_class.getName(), name );
throw new NoSuchPropertyException( message );
return (PropertyConfigurer)m_props.get( name );
}

/**
* Returns a configurer for the typed property of this class.
*/
public PropertyConfigurer getTypedProperty()
throws NoSuchPropertyException
{
if( null != m_typedPropConfigurer )
{
return m_typedPropConfigurer;
}
else
{
// No typed property
final String message = REZ.getString( "no-typed-property.error", m_class.getName() );
throw new NoSuchPropertyException( message );
}
return m_typedPropConfigurer;
}

/**
* Returns a configurer for the content of this class.
*/
public PropertyConfigurer getContentConfigurer()
throws NoSuchPropertyException
{
if( null != m_contentConfigurer )
{
return m_contentConfigurer;
}
else
{
// Does not handle content
final String message = REZ.getString( "content-unsupported.error", m_class.getName() );
throw new NoSuchPropertyException( message );
}
return m_contentConfigurer;
}

/**


+ 3
- 10
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/NoSuchPropertyException.java View File

@@ -7,22 +7,15 @@
*/
package org.apache.myrmidon.components.configurer;

import org.apache.avalon.framework.CascadingException;

/**
* An exception thrown when an unknown property is encountered.
*
* TODO - this should extend ConfigurationException, however
* ConfigurationException is final.
* A marker exception that is thrown when an unknown property is encountered.
*
* @author Adam Murdoch
* @version $Revision$ $Date$
*/
class NoSuchPropertyException
extends CascadingException
extends Exception
{
public NoSuchPropertyException( String message )
{
super( message );
}
}

+ 10
- 15
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java View File

@@ -43,29 +43,24 @@ interface ObjectConfigurer
* Returns a configurer for a property of this class.
*
* @param name The element name. Property names are case-insensitive.
* @return A configurer for the property.
* @throws NoSuchPropertyException If the property is not valid for this
* class
* @return A configurer for the property, or null if the property is not
* valid for this class.
*/
PropertyConfigurer getProperty( String name )
throws NoSuchPropertyException;
PropertyConfigurer getProperty( String name );

/**
* Returns a configurer for the content of this class.
* Returns a configurer for the text content of this class.
*
* @return A configurer for the content.
* @throws NoSuchPropertyException If the class does not handle content.
* @return A configurer for the text content, or null if the class does not
* support text content.
*/
PropertyConfigurer getContentConfigurer()
throws NoSuchPropertyException;
PropertyConfigurer getContentConfigurer();

/**
* Returns a configurer for the typed property of this class.
*
* @return A configurer for the typed property.
* @throws NoSuchPropertyException If the class does not have a typed
* property.
* @return A configurer for the typed property, or null if the class
* does not have a typed property.
*/
PropertyConfigurer getTypedProperty()
throws NoSuchPropertyException;
PropertyConfigurer getTypedProperty();
}

+ 2
- 3
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/PropertyConfigurer.java View File

@@ -11,7 +11,7 @@ import org.apache.avalon.framework.configuration.ConfigurationException;

/**
* Configures a property of an object.
* TODO - axe useCreator() and createValue().
* TODO - axe createValue().
*
* @author <a href="mailto:adammurdoch_ml@yahoo.com">Adam Murdoch</a>
* @version $Revision$ $Date$
@@ -25,8 +25,7 @@ interface PropertyConfigurer

/**
* Creates a default value for this property. This value must be configured,
* and then attached to the object using {@link #setValue}. This
* method must be called if {@link #useCreator} returns true.
* and then attached to the object using {@link #addValue}.
*
* @param state The state object, representing the object being configured.
* @return An object which is assignable to the type returned by


+ 39
- 0
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ReportableConfigurationException.java View File

@@ -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;
}
}

+ 4
- 8
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties View File

@@ -1,14 +1,11 @@
create-object.error=Could not create an object of class {0}.
extra-config-for-ref.error=A reference element can only include an "id" attribute.
get-ref.error=Could not locate reference "{0}".
mismatch-ref-types.error=Mismatched type for reference "{0}". Was expecting an object of type {1}, instead found an object of type {2}.
incompatible-element-types.error=Incompatible creator and adder/setter methods found in class {0} for property "{1}".
multiple-adder-methods-for-element.error=Multiple add{1}() or set{1}() methods found in class {0}.
multiple-creator-methods-for-element.error=Multiple {1}() methods found in class {0}.
multiple-content-setter-methods.error=Multiple content setter methods found in class {0}.
pending-property-value.error=An object created using the creator method has not been set using the adder/setter method.
unknown-property.error=Class {0} does not have a "{1}" property.
content-not-supported.error=Class {0} does not support text content.
must-be-element.error=This property must be configured using a nested element.
too-many-values.error=Too many values for this property.
no-complex-type.error=Can not get complex type for non-primitive type {0}.
@@ -16,13 +13,12 @@ no-such-attribute.error=Attribute "{1}" is not allowed for element <{0}>.
bad-set-attribute.error=Could not set attribute "{1}" for element <{0}>.
bad-set-class-attribute.error=Could not set attribute "{0}" for object of class {1}.
no-such-element.error=Nested <{1}> elements are not allowed for element <{0}>.
bad-set-element.error=Could not handle element <{1}>, nested in element <{0}>.
no-content.error=Text content is not allowed for element <{0}>.
no-content.error=Text content is not allowed in element <{0}>.
bad-set-content.error=Could not set text content for element <{0}>.
typed-adder-non-interface.error=The typed adder for class "{0}" must have a single parameter that is an interface rather than {1} which defines a class.
no-factory-for-role.error=Unable to locate type factory for role "{0}"
create-typed-object.error=Could not create an object of type "{0}" of class {1}.
no-typed-property.error=Class {0} does not have a typed property.
unknown-reference.error=Could not find referenced object "{0}".
bad-configure-element.error=Could not configure element <{0}>.

prop.mismatched-braces.error=Malformed property with mismatched }'s.
prop.missing-value.error=Unable to find "{0}" to expand during property resolution.
prop.missing-value.error=Unable to find "{0}" to expand during property resolution.

+ 6
- 9
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java View File

@@ -26,7 +26,6 @@ import org.apache.myrmidon.interfaces.deployer.TypeDefinition;
import org.apache.myrmidon.interfaces.deployer.TypeDeployer;
import org.apache.myrmidon.interfaces.role.RoleInfo;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.service.AntServiceManager;
import org.apache.myrmidon.interfaces.service.ServiceFactory;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;
@@ -53,7 +52,6 @@ public class DefaultDeployer

/** Map from ClassLoader to the deployer for that class loader. */
private final Map m_classLoaderDeployers = new HashMap();
private AntServiceManager m_serviceManager;

/**
* Retrieve relevent services needed to deploy.
@@ -68,7 +66,6 @@ public class DefaultDeployer
m_typeManager = (TypeManager)serviceManager.lookup( TypeManager.ROLE );
m_roleManager = (RoleManager)serviceManager.lookup( RoleManager.ROLE );
m_classLoaderManager = (ClassLoaderManager)serviceManager.lookup( ClassLoaderManager.ROLE );
m_serviceManager = (AntServiceManager)serviceManager.lookup( AntServiceManager.ROLE );
}

/**
@@ -148,9 +145,9 @@ public class DefaultDeployer
throws Exception
{
final String roleShorthand = definition.getRoleShorthand();
final Class serviceType = getRoleType( roleShorthand );
final String roleName = getRole( roleShorthand ).getName();
final String factoryClassName = definition.getFactoryClass();
handleType( deployment, ServiceFactory.class, serviceType.getName(), factoryClassName );
handleType( deployment, ServiceFactory.class, roleName, factoryClassName );
}

/**
@@ -205,7 +202,7 @@ public class DefaultDeployer
}

// Deploy general-purpose type
final Class roleType = getRoleType( roleShorthand );
final Class roleType = getRole( roleShorthand ).getType();
handleType( deployment, roleType, typeName, className );

if( getLogger().isDebugEnabled() )
@@ -275,9 +272,9 @@ public class DefaultDeployer
}

/**
* Determines the type for a role, from its shorthand.
* Locates a role, from its shorthand.
*/
private Class getRoleType( final String roleShorthand )
private RoleInfo getRole( final String roleShorthand )
throws DeploymentException
{
final RoleInfo roleInfo = m_roleManager.getRoleByShorthandName( roleShorthand );
@@ -286,6 +283,6 @@ public class DefaultDeployer
final String message = REZ.getString( "unknown-role4name.error", roleShorthand );
throw new DeploymentException( message );
}
return roleInfo.getType();
return roleInfo;
}
}

+ 45
- 44
proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java View File

@@ -22,6 +22,7 @@ import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.myrmidon.components.deployer.ClassLoaderManager;
import org.apache.myrmidon.interfaces.aspect.AspectManager;
@@ -37,7 +38,7 @@ import org.apache.myrmidon.interfaces.executor.Executor;
import org.apache.myrmidon.interfaces.extensions.ExtensionManager;
import org.apache.myrmidon.interfaces.model.Project;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.service.AntServiceManager;
import org.apache.myrmidon.interfaces.service.MultiSourceServiceManager;
import org.apache.myrmidon.interfaces.type.TypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;
import org.apache.myrmidon.interfaces.workspace.Workspace;
@@ -62,6 +63,7 @@ public class DefaultEmbeddor

private Deployer m_deployer;
private TypeManager m_typeManager;
private MultiSourceServiceManager m_workspaceServiceManager;

private List m_components = new ArrayList();
private DefaultServiceManager m_serviceManager = new DefaultServiceManager();
@@ -110,7 +112,7 @@ public class DefaultEmbeddor

final TypeFactory factory = m_typeManager.getFactory( ProjectBuilder.class );
final ProjectBuilder builder = (ProjectBuilder)factory.create( type );
setupObject( builder, parameters );
setupObject( builder, m_workspaceServiceManager, parameters );
return builder;
}

@@ -120,10 +122,9 @@ public class DefaultEmbeddor
public Workspace createWorkspace( final Parameters parameters )
throws Exception
{
final String component = getParameter( Workspace.ROLE );
final Workspace workspace =
(Workspace)createService( component, Workspace.class );
setupObject( workspace, parameters );
(Workspace)createService( Workspace.class, PREFIX + "workspace.DefaultWorkspace" );
setupObject( workspace, m_workspaceServiceManager, parameters );
return workspace;
}

@@ -148,18 +149,27 @@ public class DefaultEmbeddor
public void initialize()
throws Exception
{
//setup default properties
// setup default properties
m_defaults = createDefaultParameters();

//create all the components
createComponents();

//setup the components
// setup the root components
setupComponents();

// locate the components we need
m_deployer = (Deployer)m_serviceManager.lookup( Deployer.ROLE );
m_typeManager = (TypeManager)m_serviceManager.lookup( TypeManager.ROLE );

// setup a service manager that creates the project services
final ServiceManager projServiceManager
= (ServiceManager)createService( ServiceManager.class, PREFIX + "service.InstantiatingServiceManager" );
setupObject( projServiceManager, m_serviceManager, m_parameters );

// setup a service manager to be used by workspaces
m_workspaceServiceManager = new MultiSourceServiceManager();
m_workspaceServiceManager.add( projServiceManager );
m_workspaceServiceManager.add( m_serviceManager );

// setup
setupFiles();
}

@@ -224,18 +234,16 @@ public class DefaultEmbeddor
defaults.setParameter( "myrmidon.bin.path", "bin" );
defaults.setParameter( "myrmidon.lib.path", "lib" );

// Default workspace implementation
defaults.setParameter( Workspace.ROLE, PREFIX + "workspace.DefaultWorkspace" );

return defaults;
}

/**
* Create all required components.
*/
private void createComponents()
private void setupComponents()
throws Exception
{
// Create the components
createComponent( ConverterRegistry.class, PREFIX + "converter.DefaultConverterRegistry" );
createComponent( ExtensionManager.class, PREFIX + "extensions.DefaultExtensionManager" );
createComponent( MasterConverter.class, PREFIX + "converter.DefaultMasterConverter" );
@@ -246,7 +254,13 @@ public class DefaultEmbeddor
createComponent( Deployer.class, PREFIX + "deployer.DefaultDeployer" );
createComponent( ClassLoaderManager.class, PREFIX + "deployer.DefaultClassLoaderManager" );
createComponent( Executor.class, PREFIX + "executor.AspectAwareExecutor" );
createComponent( AntServiceManager.class, PREFIX + "service.DefaultAntServiceManager" );

// Setup the components
for( Iterator iterator = m_components.iterator(); iterator.hasNext(); )
{
final Object component = iterator.next();
setupObject( component, m_serviceManager, m_parameters );
}
}

/**
@@ -255,28 +269,11 @@ public class DefaultEmbeddor
private void createComponent( Class roleType, String defaultImpl )
throws Exception
{
final String role = roleType.getName();
final String className = m_parameters.getParameter( role, defaultImpl );
final Object component = createService( className, roleType );
m_serviceManager.put( role, component );
final Object component = createService( roleType, defaultImpl );
m_serviceManager.put( roleType.getName(), component );
m_components.add( component );
}

/**
* Setup all the components. (ir run all required lifecycle methods).
*
* @exception Exception if an error occurs
*/
private void setupComponents()
throws Exception
{
for( Iterator iterator = m_components.iterator(); iterator.hasNext(); )
{
final Object component = iterator.next();
setupObject( component, m_parameters );
}
}

/**
* Setup all the files attributes.
*/
@@ -354,21 +351,24 @@ public class DefaultEmbeddor
/**
* Create a component that implements an interface.
*
* @param component the name of the component
* @param clazz the name of interface/type
* @param roleType the name of interface/type
* @param defaultImpl the classname of the default implementation
* @return the created object
* @exception Exception if an error occurs
*/
private Object createService( final String component, final Class clazz )
private Object createService( final Class roleType, final String defaultImpl )
throws Exception
{
final String role = roleType.getName();
final String className = m_parameters.getParameter( role, defaultImpl );

try
{
final Object object = Class.forName( component ).newInstance();
final Object object = Class.forName( className ).newInstance();

if( !clazz.isInstance( object ) )
if( !roleType.isInstance( object ) )
{
final String message = REZ.getString( "bad-type.error", component, clazz.getName() );
final String message = REZ.getString( "bad-type.error", className, roleType.getName() );
throw new Exception( message );
}

@@ -376,19 +376,19 @@ public class DefaultEmbeddor
}
catch( final IllegalAccessException iae )
{
final String message = REZ.getString( "bad-ctor.error", clazz.getName(), component );
final String message = REZ.getString( "bad-ctor.error", roleType.getName(), className );
throw new Exception( message );
}
catch( final InstantiationException ie )
{
final String message =
REZ.getString( "no-instantiate.error", clazz.getName(), component );
REZ.getString( "no-instantiate.error", roleType.getName(), className );
throw new Exception( message );
}
catch( final ClassNotFoundException cnfe )
{
final String message =
REZ.getString( "no-class.error", clazz.getName(), component );
REZ.getString( "no-class.error", roleType.getName(), className );
throw new Exception( message );
}
}
@@ -398,6 +398,7 @@ public class DefaultEmbeddor
* parameterise and initialise lifecycle stages.
*/
private void setupObject( final Object object,
final ServiceManager serviceManager,
final Parameters parameters )
throws Exception
{
@@ -405,7 +406,7 @@ public class DefaultEmbeddor

if( object instanceof Serviceable )
{
( (Serviceable)object ).service( m_serviceManager );
( (Serviceable)object ).service( serviceManager );
}

if( object instanceof Parameterizable )


+ 0
- 151
proposal/myrmidon/src/java/org/apache/myrmidon/components/service/DefaultAntServiceManager.java View File

@@ -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 );
}
}
}

+ 222
- 0
proposal/myrmidon/src/java/org/apache/myrmidon/components/service/InstantiatingServiceManager.java View File

@@ -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 );
}
}

+ 3
- 3
proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties View File

@@ -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}".

+ 9
- 9
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java View File

@@ -14,13 +14,13 @@ import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.excalibur.io.FileUtil;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.components.configurer.PropertyUtil;
import org.apache.myrmidon.components.configurer.PropertyException;
import org.apache.myrmidon.components.configurer.PropertyUtil;
import org.apache.myrmidon.interfaces.configurer.TaskContextAdapter;
import org.apache.myrmidon.interfaces.service.AntServiceException;
import org.apache.myrmidon.interfaces.service.AntServiceManager;

/**
* Default implementation of TaskContext.
@@ -36,7 +36,7 @@ public class DefaultTaskContext

private final Map m_contextData = new Hashtable();
private final TaskContext m_parent;
private AntServiceManager m_serviceManager;
private ServiceManager m_serviceManager;

/**
* Constructor for Context with no parent contexts.
@@ -57,7 +57,7 @@ public class DefaultTaskContext
/**
* Constructor that specifies the service directory for context.
*/
public DefaultTaskContext( final AntServiceManager serviceManager )
public DefaultTaskContext( final ServiceManager serviceManager )
{
this( null, serviceManager );
}
@@ -66,7 +66,7 @@ public class DefaultTaskContext
* Constructor that takes both parent context and a service directory.
*/
public DefaultTaskContext( final TaskContext parent,
final AntServiceManager serviceManager )
final ServiceManager serviceManager )
{
m_parent = parent;
m_serviceManager = serviceManager;
@@ -153,13 +153,13 @@ public class DefaultTaskContext
{
// Try this context first
final String name = serviceClass.getName();
if( m_serviceManager != null && m_serviceManager.hasService( serviceClass ) )
if( m_serviceManager != null && m_serviceManager.hasService( name ) )
{
try
{
return m_serviceManager.getService( serviceClass );
return m_serviceManager.lookup( name );
}
catch( final AntServiceException se )
catch( final ServiceException se )
{
throw new TaskException( se.getMessage(), se );
}


+ 3
- 11
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java View File

@@ -21,10 +21,10 @@ import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.log.Hierarchy;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
@@ -37,8 +37,6 @@ import org.apache.myrmidon.interfaces.executor.Executor;
import org.apache.myrmidon.interfaces.model.Project;
import org.apache.myrmidon.interfaces.model.Target;
import org.apache.myrmidon.interfaces.model.TypeLib;
import org.apache.myrmidon.interfaces.service.MultiSourceServiceManager;
import org.apache.myrmidon.interfaces.service.AntServiceManager;
import org.apache.myrmidon.interfaces.type.TypeManager;
import org.apache.myrmidon.interfaces.workspace.Workspace;
import org.apache.myrmidon.listeners.ProjectListener;
@@ -258,15 +256,9 @@ public class DefaultWorkspace
serviceManager.put( Project.ROLE + "/" + name, other );
}

// Create a service manager that aggregates the contents of the context's
// component manager, and service manager
final MultiSourceServiceManager msServiceManager = new MultiSourceServiceManager();
msServiceManager.add( (AntServiceManager)serviceManager.lookup( AntServiceManager.ROLE ) );
msServiceManager.add( new ServiceManagerAdaptor( serviceManager ) );

// Create and configure the context
final DefaultTaskContext context =
new DefaultTaskContext( m_baseContext, msServiceManager );
new DefaultTaskContext( m_baseContext, serviceManager );
context.setProperty( TaskContext.BASE_DIRECTORY, project.getBaseDirectory() );

// Create a logger


+ 0
- 54
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ServiceManagerAdaptor.java View File

@@ -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 );
}
}
}

+ 0
- 37
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/AntServiceManager.java View File

@@ -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;
}

+ 24
- 17
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/MultiSourceServiceManager.java View File

@@ -10,16 +10,18 @@ package org.apache.myrmidon.interfaces.service;
import java.util.ArrayList;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;

/**
* A service manager that aggregates services from several
* {@link AntServiceManager} objects.
* {@link ServiceManager} objects.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public class MultiSourceServiceManager
implements AntServiceManager
implements ServiceManager
{
private final static Resources REZ
= ResourceManager.getPackageResources( MultiSourceServiceManager.class );
@@ -30,23 +32,21 @@ public class MultiSourceServiceManager
/**
* Adds a service manager to the end of the source list.
*/
public void add( final AntServiceManager mgr )
public void add( final ServiceManager mgr )
{
m_sources.add( mgr );
}

/**
* Determines if this service manager contains a particular service.
*
* @param serviceType The service interface.
*/
public boolean hasService( final Class serviceType )
public boolean hasService( final String serviceRole )
{
final int size = m_sources.size();
for( int i = 0; i < size; i++ )
{
final AntServiceManager serviceManager = (AntServiceManager)m_sources.get( i );
if( serviceManager.hasService( serviceType ) )
final ServiceManager serviceManager = (ServiceManager)m_sources.get( i );
if( serviceManager.hasService( serviceRole ) )
{
return true;
}
@@ -57,25 +57,32 @@ public class MultiSourceServiceManager
/**
* Locates a service instance.
*
* @param serviceType The service interface.
* @param serviceRole The service interface.
* @return The service instance. The returned object is guaranteed to
* implement the service interface.
* @throws AntServiceException If the service does not exist.
* @throws ServiceException If the service does not exist.
*/
public Object getService( final Class serviceType )
throws AntServiceException
public Object lookup( final String serviceRole )
throws ServiceException
{
final int size = m_sources.size();
for( int i = 0; i < size; i++ )
{
final AntServiceManager serviceManager = (AntServiceManager)m_sources.get( i );
if( serviceManager.hasService( serviceType ) )
final ServiceManager serviceManager = (ServiceManager)m_sources.get( i );
if( serviceManager.hasService( serviceRole ) )
{
return serviceManager.getService( serviceType );
return serviceManager.lookup( serviceRole );
}
}

final String message = REZ.getString( "unknown-service.error", serviceType.getName() );
throw new AntServiceException( message );
final String message = REZ.getString( "unknown-service.error", serviceRole );
throw new ServiceException( message );
}

/**
* Releases a service.
*/
public void release( final Object service )
{
}
}

+ 1
- 1
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceFactory.java View File

@@ -20,7 +20,7 @@ public interface ServiceFactory
String ROLE = ServiceFactory.class.getName();

/**
* Create a service that coresponds to this factory.
* Create a service that corresponds to this factory.
* This method is usually called after the factory has been
* prepared and configured as appropriate.
*/


+ 24
- 3
proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java View File

@@ -10,6 +10,7 @@ package org.apache.myrmidon;
import java.io.File;
import java.io.IOException;
import junit.framework.TestCase;
import org.apache.avalon.framework.CascadingThrowable;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.log.Hierarchy;
@@ -96,11 +97,31 @@ public abstract class AbstractMyrmidonTest
return new LogKitLogger( targetLogger );
}

/**
* Asserts that an exception chain contains the expected messages.
*/
protected void assertSameMessage( final String[] messages, final Throwable throwable )
{
Throwable current = throwable;
for( int i = 0; i < messages.length; i++ )
{
String message = messages[ i ];
assertNotNull( current );
assertEquals( message, current.getMessage() );

if( current instanceof CascadingThrowable )
{
current = ( (CascadingThrowable)current ).getCause();
}
else
{
current = null;
}
}
}

/**
* Asserts that an exception contains the expected message.
*
* TODO - should take the expected exception, rather than the message,
* to check the entire cause chain.
*/
protected void assertSameMessage( final String message, final Throwable throwable )
{


+ 0
- 6
proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java View File

@@ -26,7 +26,6 @@ import org.apache.myrmidon.components.deployer.DefaultClassLoaderManager;
import org.apache.myrmidon.components.deployer.DefaultDeployer;
import org.apache.myrmidon.components.extensions.DefaultExtensionManager;
import org.apache.myrmidon.components.role.DefaultRoleManager;
import org.apache.myrmidon.components.service.DefaultAntServiceManager;
import org.apache.myrmidon.components.type.DefaultTypeManager;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
@@ -34,7 +33,6 @@ import org.apache.myrmidon.interfaces.converter.MasterConverter;
import org.apache.myrmidon.interfaces.deployer.Deployer;
import org.apache.myrmidon.interfaces.extensions.ExtensionManager;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.service.AntServiceManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeManager;
@@ -117,10 +115,6 @@ public abstract class AbstractComponentTest
m_serviceManager.put( RoleManager.ROLE, component );
components.add( component );

component = new DefaultAntServiceManager();
m_serviceManager.put( AntServiceManager.ROLE, component );
components.add( component );

// Log enable the components
for( Iterator iterator = components.iterator(); iterator.hasNext(); )
{


+ 33
- 19
proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java View File

@@ -20,8 +20,8 @@ import org.apache.myrmidon.components.workspace.DefaultTaskContext;
import org.apache.myrmidon.framework.DataType;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.configurer.TaskContextAdapter;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.role.RoleInfo;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;

/**
@@ -339,8 +339,11 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
final String message = REZ.getString( "extra-config-for-ref.error" );
assertSameMessage( message, e );
final String[] messages = {
REZ.getString( "bad-configure-element.error", "some-prop-ref" ),
REZ.getString( "extra-config-for-ref.error" )
};
assertSameMessage( messages, e );
}
}

@@ -364,10 +367,13 @@ public class DefaultConfigurerTest
}
catch( final ConfigurationException ce )
{
final String message = REZ.getString( "typed-adder-non-interface.error",
ConfigTest4.class.getName(),
Integer.class.getName() );
assertSameMessage( message, ce );
final String[] messages = {
REZ.getString( "bad-configure-element.error", "test" ),
REZ.getString( "typed-adder-non-interface.error",
ConfigTest4.class.getName(),
Integer.class.getName() )
};
assertSameMessage( messages, ce );
}
}

@@ -390,10 +396,13 @@ public class DefaultConfigurerTest
}
catch( final ConfigurationException ce )
{
final String message = REZ.getString( "multiple-adder-methods-for-element.error",
ConfigTest5.class.getName(),
"");
assertSameMessage( message, ce );
final String[] messages = {
REZ.getString( "bad-configure-element.error", "test" ),
REZ.getString( "multiple-adder-methods-for-element.error",
ConfigTest5.class.getName(),
"")
};
assertSameMessage( messages, ce );
}
}

@@ -566,9 +575,11 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
final String message = REZ.getString( "get-ref.error",
"unknown-prop" );
assertSameMessage( message, e );
final String[] messages = {
REZ.getString( "bad-set-attribute.error", "test", "some-prop-ref" ),
REZ.getString( "unknown-reference.error", "unknown-prop" )
};
assertSameMessage( messages, e );
}
}

@@ -594,11 +605,14 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
final String message = REZ.getString( "mismatch-ref-types.error",
"prop-a",
String.class.getName(),
ConfigTest2.class.getName() );
assertSameMessage( message, e );
final String[] messages = {
REZ.getString( "bad-set-attribute.error", "test", "some-prop-ref" ),
REZ.getString( "mismatch-ref-types.error",
"prop-a",
String.class.getName(),
ConfigTest2.class.getName() )
};
assertSameMessage( messages, e );
}
}



+ 147
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/components/service/InstantiatingServiceManagerTest.java View File

@@ -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 );
}
}

+ 67
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/components/service/LifecycleValidator.java View File

@@ -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 );
}
}

+ 19
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestService.java View File

@@ -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();
}

+ 30
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceFactory1.java View File

@@ -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();
}
}

+ 33
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceFactory2.java View File

@@ -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();
}
}

+ 22
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceImpl1.java View File

@@ -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()
{
}
}

+ 24
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/components/service/TestServiceImpl2.java View File

@@ -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();
}
}

+ 24
- 3
proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java View File

@@ -10,6 +10,7 @@ package org.apache.myrmidon;
import java.io.File;
import java.io.IOException;
import junit.framework.TestCase;
import org.apache.avalon.framework.CascadingThrowable;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.log.Hierarchy;
@@ -96,11 +97,31 @@ public abstract class AbstractMyrmidonTest
return new LogKitLogger( targetLogger );
}

/**
* Asserts that an exception chain contains the expected messages.
*/
protected void assertSameMessage( final String[] messages, final Throwable throwable )
{
Throwable current = throwable;
for( int i = 0; i < messages.length; i++ )
{
String message = messages[ i ];
assertNotNull( current );
assertEquals( message, current.getMessage() );

if( current instanceof CascadingThrowable )
{
current = ( (CascadingThrowable)current ).getCause();
}
else
{
current = null;
}
}
}

/**
* Asserts that an exception contains the expected message.
*
* TODO - should take the expected exception, rather than the message,
* to check the entire cause chain.
*/
protected void assertSameMessage( final String message, final Throwable throwable )
{


+ 0
- 6
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java View File

@@ -26,7 +26,6 @@ import org.apache.myrmidon.components.deployer.DefaultClassLoaderManager;
import org.apache.myrmidon.components.deployer.DefaultDeployer;
import org.apache.myrmidon.components.extensions.DefaultExtensionManager;
import org.apache.myrmidon.components.role.DefaultRoleManager;
import org.apache.myrmidon.components.service.DefaultAntServiceManager;
import org.apache.myrmidon.components.type.DefaultTypeManager;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
@@ -34,7 +33,6 @@ import org.apache.myrmidon.interfaces.converter.MasterConverter;
import org.apache.myrmidon.interfaces.deployer.Deployer;
import org.apache.myrmidon.interfaces.extensions.ExtensionManager;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.service.AntServiceManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeManager;
@@ -117,10 +115,6 @@ public abstract class AbstractComponentTest
m_serviceManager.put( RoleManager.ROLE, component );
components.add( component );

component = new DefaultAntServiceManager();
m_serviceManager.put( AntServiceManager.ROLE, component );
components.add( component );

// Log enable the components
for( Iterator iterator = components.iterator(); iterator.hasNext(); )
{


+ 33
- 19
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java View File

@@ -20,8 +20,8 @@ import org.apache.myrmidon.components.workspace.DefaultTaskContext;
import org.apache.myrmidon.framework.DataType;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.configurer.TaskContextAdapter;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.role.RoleInfo;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;

/**
@@ -339,8 +339,11 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
final String message = REZ.getString( "extra-config-for-ref.error" );
assertSameMessage( message, e );
final String[] messages = {
REZ.getString( "bad-configure-element.error", "some-prop-ref" ),
REZ.getString( "extra-config-for-ref.error" )
};
assertSameMessage( messages, e );
}
}

@@ -364,10 +367,13 @@ public class DefaultConfigurerTest
}
catch( final ConfigurationException ce )
{
final String message = REZ.getString( "typed-adder-non-interface.error",
ConfigTest4.class.getName(),
Integer.class.getName() );
assertSameMessage( message, ce );
final String[] messages = {
REZ.getString( "bad-configure-element.error", "test" ),
REZ.getString( "typed-adder-non-interface.error",
ConfigTest4.class.getName(),
Integer.class.getName() )
};
assertSameMessage( messages, ce );
}
}

@@ -390,10 +396,13 @@ public class DefaultConfigurerTest
}
catch( final ConfigurationException ce )
{
final String message = REZ.getString( "multiple-adder-methods-for-element.error",
ConfigTest5.class.getName(),
"");
assertSameMessage( message, ce );
final String[] messages = {
REZ.getString( "bad-configure-element.error", "test" ),
REZ.getString( "multiple-adder-methods-for-element.error",
ConfigTest5.class.getName(),
"")
};
assertSameMessage( messages, ce );
}
}

@@ -566,9 +575,11 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
final String message = REZ.getString( "get-ref.error",
"unknown-prop" );
assertSameMessage( message, e );
final String[] messages = {
REZ.getString( "bad-set-attribute.error", "test", "some-prop-ref" ),
REZ.getString( "unknown-reference.error", "unknown-prop" )
};
assertSameMessage( messages, e );
}
}

@@ -594,11 +605,14 @@ public class DefaultConfigurerTest
}
catch( ConfigurationException e )
{
final String message = REZ.getString( "mismatch-ref-types.error",
"prop-a",
String.class.getName(),
ConfigTest2.class.getName() );
assertSameMessage( message, e );
final String[] messages = {
REZ.getString( "bad-set-attribute.error", "test", "some-prop-ref" ),
REZ.getString( "mismatch-ref-types.error",
"prop-a",
String.class.getName(),
ConfigTest2.class.getName() )
};
assertSameMessage( messages, e );
}
}



+ 147
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/InstantiatingServiceManagerTest.java View File

@@ -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 );
}
}

+ 67
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/LifecycleValidator.java View File

@@ -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 );
}
}

+ 19
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestService.java View File

@@ -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();
}

+ 30
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceFactory1.java View File

@@ -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();
}
}

+ 33
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceFactory2.java View File

@@ -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();
}
}

+ 22
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceImpl1.java View File

@@ -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()
{
}
}

+ 24
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/service/TestServiceImpl2.java View File

@@ -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();
}
}

Loading…
Cancel
Save