From 7eb8a34e54e5c7ff3241f4414e04cf3b623c3e07 Mon Sep 17 00:00:00 2001 From: adammurdoch Date: Tue, 9 Apr 2002 02:26:35 +0000 Subject: [PATCH] * Rolled back change to PropertyResolver.resolveProperties(), so that it uses a TaskContext again. Added some regression tests. * Changed Embeddor.createWorkspace() to use a Map, rather than a Parameters, to supply initial workspace properties. Initial properties can be Objects, rather than only Strings. Got rid of the Object -> String convertion from and . * Generalised ExecutionFrame, so that it can represent any execution scope (root, workspace, project, task, inherited, etc), rather than just task scope: - Replaced getTaskContext() with getPropertyStore(). - Replaced getTypeManager() with getServiceManager(). * Executor is now responsible for creating TaskContext. * Changed DefaultExecutor to use the configurer provided by the execution frame. * Added ExecutionContainer, a lifecycle interface which is used to supply the root execution frame to a service which executes tasks (directly or indirectly). * Changed interaction between DefaultEmbeddor and workspaces. Embeddor is now responsible for creating the base property store for workspaces. ExecutionContainer is used to pass this to workspaces. Parameterizable is now used to pass container params to workspaces (which matches how it is used with all the other services). git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272302 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/antlib/core/AbstractAntTask.java | 49 ++------ .../org/apache/antlib/core/AntCallTask.java | 3 +- .../components/embeddor/DefaultEmbeddor.java | 62 +++++++-- .../executor/AspectAwareExecutor.java | 10 +- .../components/executor/DefaultExecutor.java | 58 ++++----- .../property/ClassicPropertyResolver.java | 13 +- .../property/DefaultPropertyResolver.java | 40 +++--- .../components/property/Resources.properties | 2 +- .../workspace/DefaultExecutionFrame.java | 40 +++--- .../workspace/DefaultTaskContext.java | 2 +- .../workspace/DefaultWorkspace.java | 97 +++----------- .../myrmidon/frontends/EmbeddedAnt.java | 9 +- .../interfaces/embeddor/Embeddor.java | 7 +- .../executor/ExecutionContainer.java | 23 ++++ .../interfaces/executor/ExecutionFrame.java | 23 ++-- .../interfaces/property/MapPropertyStore.java | 119 ++++++++++++++++++ .../interfaces/property/PropertyResolver.java | 5 +- .../interfaces/property/Resources.properties | 1 + .../embeddor/test/DefaultEmbeddorTest.java | 3 +- .../AbstractPropertyResolverTestCase.java | 48 +++---- .../test/ClassicPropertyResolverTestCase.java | 2 +- .../test/DefaultPropertyResolverTestCase.java | 4 +- .../framework/file/test/PathTestCase.java | 37 ++++-- .../framework/file/test/TestFileList.java | 29 ++++- .../myrmidon/framework/file/test/path.ant | 17 ++- 25 files changed, 455 insertions(+), 248 deletions(-) create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionContainer.java create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/MapPropertyStore.java create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/Resources.properties diff --git a/proposal/myrmidon/src/java/org/apache/antlib/core/AbstractAntTask.java b/proposal/myrmidon/src/java/org/apache/antlib/core/AbstractAntTask.java index 1a7c1d820..f97c15cdb 100644 --- a/proposal/myrmidon/src/java/org/apache/antlib/core/AbstractAntTask.java +++ b/proposal/myrmidon/src/java/org/apache/antlib/core/AbstractAntTask.java @@ -7,15 +7,14 @@ */ package org.apache.antlib.core; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import org.apache.myrmidon.api.AbstractTask; import org.apache.myrmidon.api.TaskException; +import org.apache.myrmidon.interfaces.embeddor.Embeddor; import org.apache.myrmidon.interfaces.model.Project; import org.apache.myrmidon.interfaces.workspace.Workspace; -import org.apache.myrmidon.interfaces.embeddor.Embeddor; -import org.apache.avalon.framework.parameters.Parameters; -import java.util.Map; -import java.util.Iterator; -import java.util.ArrayList; /** * Abstract base class for Tasks which execute targets. @@ -24,7 +23,8 @@ import java.util.ArrayList; * @author Darrell DeBoer * @version $Revision$ $Date$ */ -public abstract class AbstractAntTask extends AbstractTask +public abstract class AbstractAntTask + extends AbstractTask { /** * If true, inherit all properties from parent Project @@ -32,6 +32,7 @@ public abstract class AbstractAntTask extends AbstractTask * inside the ant call itself */ private boolean m_inheritAll; + /** * The target to process in build file. If not specified * will use default in specified build file. @@ -90,6 +91,7 @@ public abstract class AbstractAntTask extends AbstractTask final Workspace workspace = embeddor.createWorkspace( buildParameters() ); + // TODO - inherit listeners, and services (TypeManager specifically) workspace.addProjectListener( embeddor.createListener("default")); if( null == m_target ) @@ -134,21 +136,14 @@ public abstract class AbstractAntTask extends AbstractTask * * @return the created parameters */ - private Parameters buildParameters() + private Map buildParameters() throws TaskException { - final Parameters parameters = new Parameters(); + final Map parameters = new HashMap(); if( m_inheritAll ) { - final Map properties = getContext().getProperties(); - final Iterator keys = properties.keySet().iterator(); - while( keys.hasNext() ) - { - final String key = (String)keys.next(); - final Object value = properties.get( key ); - setProperty( parameters, key, value ); - } + parameters.putAll( getContext().getProperties() ); } final int size = m_parameters.size(); @@ -157,28 +152,10 @@ public abstract class AbstractAntTask extends AbstractTask final AntParam param = (AntParam)m_parameters.get( i ); param.validate(); final String name = param.getName(); - final String value = param.getValue().toString(); - setProperty( parameters, name, value ); + final Object value = param.getValue(); + parameters.put( name, value ); } return parameters; } - - /** - * Utility method to add the property into parameters object. - * - * @param parameters where to put property - * @param name the property - * @param value the value of property - * @todo allow non-string params to be passed down - */ - private void setProperty( final Parameters parameters, - final String name, - final Object value ) - { - if( !name.startsWith( "myrmidon." ) ) - { - parameters.setParameter( name, value.toString() ); - } - } } diff --git a/proposal/myrmidon/src/java/org/apache/antlib/core/AntCallTask.java b/proposal/myrmidon/src/java/org/apache/antlib/core/AntCallTask.java index 26da9011b..1bbe78ef4 100644 --- a/proposal/myrmidon/src/java/org/apache/antlib/core/AntCallTask.java +++ b/proposal/myrmidon/src/java/org/apache/antlib/core/AntCallTask.java @@ -20,7 +20,8 @@ import org.apache.myrmidon.interfaces.model.Project; * @version $Revision$ $Date$ * @ant.task name="ant-call" */ -public class AntCallTask extends AbstractAntTask +public class AntCallTask + extends AbstractAntTask { private static final Resources REZ = ResourceManager.getPackageResources( AntCallTask.class ); diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java index ca14b760e..400e6e7f7 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java @@ -12,6 +12,7 @@ import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Map; import org.apache.aut.converter.Converter; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; @@ -37,15 +38,20 @@ import org.apache.myrmidon.interfaces.deployer.DeploymentException; import org.apache.myrmidon.interfaces.deployer.TypeDeployer; import org.apache.myrmidon.interfaces.embeddor.Embeddor; import org.apache.myrmidon.interfaces.executor.Executor; +import org.apache.myrmidon.interfaces.executor.ExecutionFrame; +import org.apache.myrmidon.interfaces.executor.ExecutionContainer; import org.apache.myrmidon.interfaces.extensions.ExtensionManager; import org.apache.myrmidon.interfaces.model.Project; import org.apache.myrmidon.interfaces.property.PropertyResolver; +import org.apache.myrmidon.interfaces.property.PropertyStore; import org.apache.myrmidon.interfaces.role.RoleManager; 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; import org.apache.myrmidon.listeners.ProjectListener; +import org.apache.myrmidon.components.workspace.DefaultExecutionFrame; +import org.apache.myrmidon.components.store.DefaultPropertyStore; /** * Default implementation of Embeddor. @@ -72,8 +78,6 @@ public class DefaultEmbeddor private DefaultServiceManager m_serviceManager = new DefaultServiceManager(); private Parameters m_parameters; - private static final String MYRMIDON_HOME = "myrmidon.home"; - /** * Setup basic properties of engine. * Called before init() and can be used to specify alternate components in system. @@ -121,22 +125,29 @@ public class DefaultEmbeddor { final TypeFactory factory = m_typeManager.getFactory( ProjectBuilder.ROLE ); final ProjectBuilder builder = (ProjectBuilder)factory.create( type ); - setupObject( builder, m_workspaceServiceManager, parameters ); + setupObject( builder, m_serviceManager, parameters ); return builder; } /** * Creates a workspace. */ - public Workspace createWorkspace( final Parameters parameters ) + public Workspace createWorkspace( final Map properties ) throws Exception { final Workspace workspace = (Workspace)createService( Workspace.class, PREFIX + "workspace.DefaultWorkspace" ); - // TODO - don't do this; need some way to pass separate sets of defines and config - // to the workspace - parameters.setParameter( MYRMIDON_HOME, m_parameters.getParameter( MYRMIDON_HOME ) ); - setupObject( workspace, m_workspaceServiceManager, parameters ); + setupObject( workspace, m_workspaceServiceManager, m_parameters ); + + // Create the property store + final PropertyStore propStore = createBaseStore( properties ); + + // Create an execution frame, and attach it to the workspace + final ExecutionFrame frame = + new DefaultExecutionFrame( getLogger(), + propStore, + m_workspaceServiceManager); + ( (ExecutionContainer)workspace ).setRootExecutionFrame( frame ); // TODO - should keep track of workspaces, to dispose them later return workspace; @@ -395,4 +406,39 @@ public class DefaultEmbeddor } } } + + /** + * Creates the root property store for a workspace + */ + private PropertyStore createBaseStore( final Map properties ) + throws Exception + { + final DefaultPropertyStore store = new DefaultPropertyStore(); + + addToStore( store, properties ); + + //Add system properties so that they overide user-defined properties + addToStore( store, System.getProperties() ); + + return store; + } + + /** + * Helper method to add values to a store. + * + * @param store the store + * @param map the map of names->values + */ + private void addToStore( final PropertyStore store, final Map map ) + throws Exception + { + final Iterator keys = map.keySet().iterator(); + + while( keys.hasNext() ) + { + final String key = (String)keys.next(); + final Object value = map.get( key ); + store.setProperty( key, value ); + } + } } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/AspectAwareExecutor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/AspectAwareExecutor.java index 9eb093e41..233c2d8ba 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/AspectAwareExecutor.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/AspectAwareExecutor.java @@ -18,8 +18,10 @@ import org.apache.avalon.framework.logger.Logger; 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.api.Task; import org.apache.myrmidon.api.TaskException; +import org.apache.myrmidon.api.TaskContext; import org.apache.myrmidon.interfaces.aspect.AspectManager; import org.apache.myrmidon.interfaces.executor.ExecutionFrame; @@ -32,6 +34,7 @@ import org.apache.myrmidon.interfaces.executor.ExecutionFrame; */ public class AspectAwareExecutor extends DefaultExecutor + implements Serviceable { private static final Resources REZ = ResourceManager.getPackageResources( AspectAwareExecutor.class ); @@ -49,8 +52,6 @@ public class AspectAwareExecutor public void service( final ServiceManager serviceManager ) throws ServiceException { - super.service( serviceManager ); - m_aspectManager = (AspectManager)serviceManager.lookup( AspectManager.ROLE ); } @@ -90,11 +91,12 @@ public class AspectAwareExecutor getAspectManager().preLogEnabled( logger ); debug( "contextualizing.notice", taskName ); - doContextualize( task, taskModel, frame.getContext() ); + final TaskContext context = doCreateContext( frame ); + doContextualize( task, taskModel, context, frame ); debug( "configuring.notice", taskName ); getAspectManager().preConfigure( taskModel ); - doConfigure( task, taskModel, frame.getContext() ); + doConfigure( task, taskModel, context, frame ); debug( "executing.notice", taskName ); getAspectManager().preExecute(); diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/DefaultExecutor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/DefaultExecutor.java index 36fe51750..47c7bc46c 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/DefaultExecutor.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/DefaultExecutor.java @@ -10,19 +10,16 @@ package org.apache.myrmidon.components.executor; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; import org.apache.avalon.framework.configuration.Configuration; -import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.logger.AbstractLogEnabled; -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.api.Task; import org.apache.myrmidon.api.TaskContext; import org.apache.myrmidon.api.TaskException; +import org.apache.myrmidon.components.workspace.DefaultTaskContext; import org.apache.myrmidon.interfaces.configurer.Configurer; import org.apache.myrmidon.interfaces.executor.ExecutionFrame; import org.apache.myrmidon.interfaces.executor.Executor; -import org.apache.myrmidon.interfaces.type.TypeException; import org.apache.myrmidon.interfaces.type.TypeFactory; +import org.apache.myrmidon.interfaces.type.TypeManager; /** * The basic executor that just executes the tasks. @@ -32,25 +29,11 @@ import org.apache.myrmidon.interfaces.type.TypeFactory; */ public class DefaultExecutor extends AbstractLogEnabled - implements Executor, Serviceable + implements Executor { private static final Resources REZ = ResourceManager.getPackageResources( DefaultExecutor.class ); - private Configurer m_configurer; - - /** - * Retrieve relevent services needed to deploy. - * - * @param serviceManager the ServiceManager - * @exception ServiceException if an error occurs - */ - public void service( final ServiceManager serviceManager ) - throws ServiceException - { - m_configurer = (Configurer)serviceManager.lookup( Configurer.ROLE ); - } - /** * Executes a task. */ @@ -64,10 +47,11 @@ public class DefaultExecutor final Task task = doCreateTask( taskName, frame ); debug( "contextualizing.notice", taskName ); - doContextualize( task, taskModel, frame.getContext() ); + final TaskContext context = doCreateContext( frame ); + doContextualize( task, taskModel, context, frame ); debug( "configuring.notice", taskName ); - doConfigure( task, taskModel, frame.getContext() ); + doConfigure( task, taskModel, context, frame ); debug( "executing.notice", taskName ); task.execute(); @@ -90,6 +74,18 @@ public class DefaultExecutor } } + /** + * Creates a context for the task. + */ + protected TaskContext doCreateContext( final ExecutionFrame frame ) + { + // TODO - need to deactivate the context once the task has finished + // executing + return new DefaultTaskContext( frame.getServiceManager(), + frame.getLogger(), + frame.getProperties() ); + } + /** * Creates a task instance. */ @@ -98,10 +94,11 @@ public class DefaultExecutor { try { - final TypeFactory factory = frame.getTypeManager().getFactory( Task.ROLE ); + final TypeManager typeManager = (TypeManager)frame.getServiceManager().lookup( TypeManager.ROLE ); + final TypeFactory factory = typeManager.getFactory( Task.ROLE ); return (Task)factory.create( name ); } - catch( final TypeException te ) + catch( final Exception te ) { final String message = REZ.getString( "create.error", name ); throw new TaskException( message, te ); @@ -113,10 +110,12 @@ public class DefaultExecutor */ protected final void doConfigure( final Task task, final Configuration taskModel, - final TaskContext taskContext ) - throws ConfigurationException + final TaskContext taskContext, + final ExecutionFrame frame ) + throws Exception { - m_configurer.configureElement( task, taskModel, taskContext ); + final Configurer configurer = (Configurer)frame.getServiceManager().lookup( Configurer.ROLE ); + configurer.configureElement( task, taskModel, taskContext ); } /** @@ -124,12 +123,13 @@ public class DefaultExecutor */ protected final void doContextualize( final Task task, final Configuration taskModel, - final TaskContext context ) + final TaskContext taskContext, + final ExecutionFrame frame ) throws TaskException { try { - task.contextualize( context ); + task.contextualize( taskContext ); } catch( final Throwable throwable ) { diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/ClassicPropertyResolver.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/ClassicPropertyResolver.java index 0bf4592f6..79ef47471 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/ClassicPropertyResolver.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/ClassicPropertyResolver.java @@ -10,6 +10,7 @@ package org.apache.myrmidon.components.property; import org.apache.myrmidon.interfaces.property.PropertyResolver; import org.apache.myrmidon.interfaces.property.PropertyStore; import org.apache.myrmidon.api.TaskException; +import org.apache.myrmidon.api.TaskContext; /** * A {@link PropertyResolver} implementation which resolves properties @@ -29,16 +30,20 @@ public class ClassicPropertyResolver * If there is no such value, returns the original property reference. * * @param propertyName the name of the property to retrieve - * @param properties the set of known properties + * @param context the set of known properties */ protected Object getPropertyValue( final String propertyName, - final PropertyStore properties ) + final TaskContext context ) throws TaskException { - if( ! properties.isPropertySet( propertyName ) ) + final Object value = context.getProperty( propertyName ); + if( value != null ) + { + return value; + } + else { return "${" + propertyName + "}"; } - return properties.getProperty( propertyName ); } } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/DefaultPropertyResolver.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/DefaultPropertyResolver.java index 74a7a6ad9..035d6c1e9 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/DefaultPropertyResolver.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/DefaultPropertyResolver.java @@ -15,6 +15,7 @@ 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.api.TaskException; +import org.apache.myrmidon.api.TaskContext; import org.apache.myrmidon.interfaces.property.PropertyResolver; import org.apache.myrmidon.interfaces.property.PropertyStore; @@ -51,12 +52,12 @@ public class DefaultPropertyResolver * toString() called on the property value. * * @param content the property to resolve - * @param properties the context in which to resolve property + * @param context the context in which to resolve property * @return the reolved property * @exception TaskException if an error occurs */ public Object resolveProperties( final String content, - final PropertyStore properties ) + final TaskContext context ) throws TaskException { int start = findNextProperty( content, 0 ); @@ -72,7 +73,7 @@ public class DefaultPropertyResolver if( 0 == start && end == ( length - 1 ) ) { return getPropertyValue( content.substring( start + 2, end ), - properties ); + context ); } final StringBuffer sb = new StringBuffer( length * 2 ); @@ -82,7 +83,7 @@ public class DefaultPropertyResolver { final String propertyValue = getPropertyStringValue( content.substring( start + 2, end ), - properties ); + context ); sb.append( content.substring( lastPlace, start ) ); sb.append( propertyValue ); @@ -108,12 +109,12 @@ public class DefaultPropertyResolver * substitutions based on specified context. * * @param content the property to resolve - * @param properties the context in which to resolve property + * @param context the context in which to resolve property * @return the reolved property * @exception TaskException if an error occurs */ private Object recursiveResolveProperty( final String content, - final PropertyStore properties ) + final TaskContext context ) throws TaskException { int start = findNextProperty( content, 0 ); @@ -129,8 +130,8 @@ public class DefaultPropertyResolver if( 0 == start && end == ( length - 1 ) ) { final String propertyName = content.substring( start + 2, end ); - final Object key = recursiveResolveProperty( propertyName, properties ); - return getPropertyValue( key.toString(), properties ); + final Object key = recursiveResolveProperty( propertyName, context ); + return getPropertyValue( key.toString(), context ); } final StringBuffer sb = new StringBuffer( length * 2 ); @@ -140,8 +141,8 @@ public class DefaultPropertyResolver while( true ) { final String propertyName = content.substring( start + 2, end ); - final Object key = recursiveResolveProperty( propertyName, properties ); - final String value = getPropertyStringValue( key.toString(), properties ); + final Object key = recursiveResolveProperty( propertyName, context ); + final String value = getPropertyStringValue( key.toString(), context ); sb.append( content.substring( lastPlace, start ) ); sb.append( value ); @@ -246,17 +247,17 @@ public class DefaultPropertyResolver * Returns a property's value, converted to a String. */ private String getPropertyStringValue( final String propertyName, - final PropertyStore properties ) + final TaskContext context ) throws TaskException { - final Object value = getPropertyValue( propertyName, properties ); + final Object value = getPropertyValue( propertyName, context ); if( value instanceof String ) { return (String)value; } try { - return (String)m_converter.convert( String.class, value, properties ); + return (String)m_converter.convert( String.class, value, context ); } catch( final ConverterException e ) { @@ -268,15 +269,22 @@ public class DefaultPropertyResolver * Retrieve a value from the specified context using the specified key. * * @param propertyName the key of value in context - * @param properties the set of known properties + * @param context the set of known properties * @return the object retrieved from context * @exception TaskException if the property is undefined */ protected Object getPropertyValue( final String propertyName, - final PropertyStore properties ) + final TaskContext context ) throws TaskException { - return properties.getProperty( propertyName ); + final Object value = context.getProperty( propertyName ); + if( value != null ) + { + return value; + } + + final String message = REZ.getString( "prop.missing-value.error", propertyName ); + throw new TaskException( message ); } } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/Resources.properties b/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/Resources.properties index cabd0d25b..ed5ea183e 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/Resources.properties +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/property/Resources.properties @@ -1,3 +1,3 @@ #AbstractPropertyResolver 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=Unknown property "{0}". diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultExecutionFrame.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultExecutionFrame.java index 500f4c96a..39f03e39c 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultExecutionFrame.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultExecutionFrame.java @@ -8,9 +8,9 @@ package org.apache.myrmidon.components.workspace; import org.apache.avalon.framework.logger.Logger; -import org.apache.myrmidon.api.TaskContext; +import org.apache.avalon.framework.service.ServiceManager; import org.apache.myrmidon.interfaces.executor.ExecutionFrame; -import org.apache.myrmidon.interfaces.type.TypeManager; +import org.apache.myrmidon.interfaces.property.PropertyStore; /** * Frames in which tasks are executed. @@ -18,34 +18,44 @@ import org.apache.myrmidon.interfaces.type.TypeManager; * @author Peter Donald * @version $Revision$ $Date$ */ -class DefaultExecutionFrame +public class DefaultExecutionFrame implements ExecutionFrame { private final Logger m_logger; - private final TaskContext m_context; - private final TypeManager m_typeManager; + private final PropertyStore m_propertyStore; + private final ServiceManager m_serviceManager; public DefaultExecutionFrame( final Logger logger, - final TaskContext context, - final TypeManager typeManager ) + final PropertyStore propertyStore, + final ServiceManager serviceManager ) { m_logger = logger; - m_context = context; - m_typeManager = typeManager; + m_propertyStore = propertyStore; + m_serviceManager = serviceManager; } - public TypeManager getTypeManager() + /** + * Returns the logger which is to be supplied to tasks. + */ + public Logger getLogger() { - return m_typeManager; + return m_logger; } - public Logger getLogger() + /** + * Returns the set of services to use to create, configure, and execute + * tasks. + */ + public ServiceManager getServiceManager() { - return m_logger; + return m_serviceManager; } - public TaskContext getContext() + /** + * Returns the set of properties to be supplied to tasks. + */ + public PropertyStore getProperties() { - return m_context; + return m_propertyStore; } } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java index 3858e8f0a..9da9039cb 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java @@ -149,7 +149,7 @@ public class DefaultTaskContext m_propertyResolver = (PropertyResolver)getService( PropertyResolver.class ); } final Object object = - m_propertyResolver.resolveProperties( value, m_store ); + m_propertyResolver.resolveProperties( value, this ); if( null == object ) { final String message = REZ.getString( "null-resolved-value.error", value ); diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java index 0b95c4696..9c252f551 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java @@ -9,11 +9,8 @@ package org.apache.myrmidon.components.workspace; import java.io.File; 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.Initializable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.logger.Logger; @@ -21,25 +18,23 @@ 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.myrmidon.api.TaskContext; import org.apache.myrmidon.api.TaskException; import org.apache.myrmidon.interfaces.deployer.Deployer; import org.apache.myrmidon.interfaces.deployer.DeploymentException; import org.apache.myrmidon.interfaces.deployer.TypeDeployer; +import org.apache.myrmidon.interfaces.executor.ExecutionContainer; import org.apache.myrmidon.interfaces.executor.ExecutionFrame; import org.apache.myrmidon.interfaces.executor.Executor; import org.apache.myrmidon.interfaces.model.Dependency; 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.property.PropertyStore; import org.apache.myrmidon.interfaces.type.TypeManager; import org.apache.myrmidon.interfaces.workspace.Workspace; -import org.apache.myrmidon.interfaces.property.PropertyStore; import org.apache.myrmidon.listeners.ProjectListener; -import org.apache.myrmidon.components.store.DefaultPropertyStore; /** * This is the default implementation of Workspace. @@ -49,7 +44,7 @@ import org.apache.myrmidon.components.store.DefaultPropertyStore; */ public class DefaultWorkspace extends AbstractLogEnabled - implements Workspace, Serviceable, Parameterizable, Initializable + implements Workspace, ExecutionContainer, Parameterizable { private static final Resources REZ = ResourceManager.getPackageResources( DefaultWorkspace.class ); @@ -59,10 +54,12 @@ public class DefaultWorkspace private ServiceManager m_serviceManager; private Parameters m_parameters; private PropertyStore m_baseStore; - private HashMap m_entries = new HashMap(); private TypeManager m_typeManager; private Deployer m_deployer; + /** A map from Project object -> ProjectEntry for that project. */ + private HashMap m_entries = new HashMap(); + /** * Add a listener to project events. * @@ -84,18 +81,15 @@ public class DefaultWorkspace } /** - * Retrieve relevent services needed for engine. - * - * @param serviceManager the ServiceManager - * @exception ServiceException if an error occurs + * Sets the root execution frame. */ - public void service( final ServiceManager serviceManager ) - throws ServiceException + public void setRootExecutionFrame( final ExecutionFrame frame ) throws Exception { - m_serviceManager = serviceManager; - m_typeManager = (TypeManager)serviceManager.lookup( TypeManager.ROLE ); - m_executor = (Executor)serviceManager.lookup( Executor.ROLE ); - m_deployer = (Deployer)serviceManager.lookup( Deployer.ROLE ); + m_baseStore = frame.getProperties(); + m_serviceManager = frame.getServiceManager(); + m_typeManager = (TypeManager)m_serviceManager.lookup( TypeManager.ROLE ); + m_executor = (Executor)m_serviceManager.lookup( Executor.ROLE ); + m_deployer = (Deployer)m_serviceManager.lookup( Deployer.ROLE ); } public void parameterize( final Parameters parameters ) @@ -104,12 +98,6 @@ public class DefaultWorkspace m_parameters = parameters; } - public void initialize() - throws Exception - { - m_baseStore = createBaseStore(); - } - /** * Execute a target in a particular project. * Execute in the project context. @@ -130,24 +118,6 @@ public class DefaultWorkspace m_listenerSupport.projectFinished( project.getProjectName() ); } - private PropertyStore createBaseStore() - throws Exception - { - final DefaultPropertyStore store = new DefaultPropertyStore(); - - final String[] names = m_parameters.getNames(); - for( int i = 0; i < names.length; i++ ) - { - final String value = m_parameters.getParameter( names[ i ], null ); - store.setProperty( names[ i ], value ); - } - - //Add system properties so that they overide user-defined properties - addToStore( store, System.getProperties() ); - - return store; - } - private File findTypeLib( final String libraryName ) throws Exception { @@ -227,7 +197,7 @@ public class DefaultWorkspace final TypeManager typeManager = m_typeManager.createChildTypeManager(); serviceManager.put( TypeManager.ROLE, typeManager ); - // TODO - Add child role manager + // TODO - Add child role manager and configurer //We need to create a new deployer so that it deploys //to project specific TypeManager @@ -239,31 +209,20 @@ public class DefaultWorkspace //We need to place projects and ProjectManager //in ComponentManager so as to support project-local call() + // TODO - add project to properties, not services serviceManager.put( Workspace.ROLE, this ); serviceManager.put( Project.ROLE, project ); - final String[] names = project.getProjectNames(); - for( int i = 0; i < names.length; i++ ) - { - final String name = names[ i ]; - final Project other = project.getProject( name ); - serviceManager.put( Project.ROLE + "/" + name, other ); - } - // Create a logger final Logger logger = new RoutingLogger( getLogger(), m_listenerSupport ); - //TODO: Put this in Execution Frame + // Properties final PropertyStore store = m_baseStore.createChildStore(""); - - // Create and configure the context - final DefaultTaskContext context = - new DefaultTaskContext( serviceManager, logger, store ); - context.setProperty( TaskContext.BASE_DIRECTORY, project.getBaseDirectory() ); + store.setProperty( TaskContext.BASE_DIRECTORY, project.getBaseDirectory() ); final DefaultExecutionFrame frame = - new DefaultExecutionFrame( logger, context, typeManager ); + new DefaultExecutionFrame( logger, store, serviceManager ); /** * @todo Should no occur but done for the time being to simplify evolution. @@ -462,7 +421,7 @@ public class DefaultWorkspace } //is setting name even necessary ??? - frame.getContext().setProperty( TaskContext.NAME, name ); + frame.getProperties().setProperty( TaskContext.NAME, name ); //notify listeners m_listenerSupport.taskStarted( name ); @@ -474,22 +433,4 @@ public class DefaultWorkspace m_listenerSupport.taskFinished(); } - /** - * Helper method to add values to a store. - * - * @param store the store - * @param map the map of names->values - */ - private void addToStore( final PropertyStore store, final Map map ) - throws Exception - { - final Iterator keys = map.keySet().iterator(); - - while( keys.hasNext() ) - { - final String key = (String)keys.next(); - final Object value = map.get( key ); - store.setProperty( key, value ); - } - } } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/frontends/EmbeddedAnt.java b/proposal/myrmidon/src/java/org/apache/myrmidon/frontends/EmbeddedAnt.java index 1be3e5316..ab4036e91 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/frontends/EmbeddedAnt.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/frontends/EmbeddedAnt.java @@ -9,6 +9,8 @@ package org.apache.myrmidon.frontends; import java.io.File; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; import org.apache.avalon.excalibur.io.FileUtil; @@ -50,9 +52,9 @@ public class EmbeddedAnt private Project m_project; private String m_listenerName = "default"; private ArrayList m_listeners = new ArrayList(); - private Parameters m_workspaceProps = new Parameters(); private Parameters m_builderProps = new Parameters(); private Parameters m_embeddorParameters = new Parameters(); + private Map m_workspaceProperties = new HashMap(); private ClassLoader m_sharedClassLoader; private Embeddor m_embeddor; private File m_homeDir; @@ -122,8 +124,7 @@ public class EmbeddedAnt */ public void setWorkspaceProperty( final String name, final Object value ) { - // TODO - Make properties Objects, not Strings - m_workspaceProps.setParameter( name, value.toString() ); + m_workspaceProperties.put( name, value ); } /** @@ -174,7 +175,7 @@ public class EmbeddedAnt final Project project = prepareProjectModel( embeddor ); // Create a new workspace - final Workspace workspace = embeddor.createWorkspace( m_workspaceProps ); + final Workspace workspace = embeddor.createWorkspace( m_workspaceProperties ); prepareListeners( embeddor, workspace ); //execute the project diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/embeddor/Embeddor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/embeddor/Embeddor.java index eb53831b4..2c3da907c 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/embeddor/Embeddor.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/embeddor/Embeddor.java @@ -11,6 +11,7 @@ import org.apache.avalon.framework.parameters.Parameters; import org.apache.myrmidon.interfaces.model.Project; import org.apache.myrmidon.interfaces.workspace.Workspace; import org.apache.myrmidon.listeners.ProjectListener; +import java.util.Map; /** * Interface through which you embed Myrmidon into applications. @@ -53,10 +54,12 @@ public interface Embeddor /** * Creates a {@link Workspace} that can be used to execute projects. * - * @param parameters The properties to define in the workspace + * @param properties The properties to define in the workspace. These + * are added to the properties in the embeddor's + * root execution frame. * @return the Workspace * @throws Exception If the workspace could not be created. */ - Workspace createWorkspace( Parameters parameters ) + Workspace createWorkspace( Map properties ) throws Exception; } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionContainer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionContainer.java new file mode 100644 index 000000000..a3c6b2569 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionContainer.java @@ -0,0 +1,23 @@ +/* + * 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.executor; + +/** + * This interface is used to supply a root execution frame to a container + * that executes tasks. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public interface ExecutionContainer +{ + /** + * Sets the root execution frame for the container. + */ + void setRootExecutionFrame( ExecutionFrame frame ) throws Exception; +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionFrame.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionFrame.java index 156e39dbe..f737ef2c1 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionFrame.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionFrame.java @@ -8,11 +8,17 @@ package org.apache.myrmidon.interfaces.executor; import org.apache.avalon.framework.logger.Logger; -import org.apache.myrmidon.api.TaskContext; -import org.apache.myrmidon.interfaces.type.TypeManager; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.myrmidon.interfaces.property.PropertyStore; /** - * Frames in which tasks are executed. + * An Execution Frame represents the scope in which tasks are executed. + * The scope may include an entire workspace, a project, target, or + * individual task. + * + *

An Execution Frame bundles together all of the context required to + * execute tasks - that is, a set of properties, a set of services, and + * a logger. * * @author Peter Donald * @version $Revision$ $Date$ @@ -23,17 +29,18 @@ public interface ExecutionFrame String ROLE = ExecutionFrame.class.getName(); /** - * @return The TypeManager to use for creating Tasks. + * Returns the set of services to use to create, configure, and execute + * tasks. */ - TypeManager getTypeManager(); + ServiceManager getServiceManager(); /** - * @return The logger which is used for execution messages. + * Returns the logger which is to be supplied to tasks. */ Logger getLogger(); /** - * @return The TaskContext in which the task is executed. + * Returns the set of properties to be supplied to tasks. */ - TaskContext getContext(); + PropertyStore getProperties(); } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/MapPropertyStore.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/MapPropertyStore.java new file mode 100644 index 000000000..4d0f2712d --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/MapPropertyStore.java @@ -0,0 +1,119 @@ +/* + * 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.property; + +import java.util.Map; +import java.util.HashMap; +import org.apache.myrmidon.api.TaskException; +import org.apache.avalon.excalibur.i18n.ResourceManager; +import org.apache.avalon.excalibur.i18n.Resources; + +/** + * A simple unscoped, unsynchronized property store which is backed by a Map. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public class MapPropertyStore + implements PropertyStore +{ + private static final Resources REZ = + ResourceManager.getPackageResources( MapPropertyStore.class ); + + private final Map m_properties = new HashMap(); + + /** + * Creates an empty store. + */ + public MapPropertyStore() + { + } + + /** + * Creates a store containing the given properties. + */ + public MapPropertyStore( final Map properties ) + { + m_properties.putAll( properties ); + } + + /** + * Return true if the specified property is set. + * + * @param name the name of property + */ + public boolean isPropertySet( final String name ) + { + return m_properties.containsKey( name ); + } + + /** + * Retrieve the value of specified property. + * + * @param name the name of the property + * @return the value of the property. Never returns null. + * @throws TaskException if there is no such property, or on error + * retrieving property, such as an invalid property name. + */ + public Object getProperty( final String name ) + throws TaskException + { + final Object value = m_properties.get( name ); + if( value == null ) + { + final String message = REZ.getString( "unknown-property.error", name ); + throw new TaskException( message ); + } + return value; + } + + /** + * Retrieve a copy of all the properties that are "in-scope" + * for store. + * + * @return a copy of all the properties that are "in-scope" + * for store. + * @throws TaskException if theres an error retrieving propertys + */ + public Map getProperties() + throws TaskException + { + return new HashMap( m_properties ); + } + + /** + * Set the property with specified name to specified value. + * The specific implementation will apply various rules + * before setting the property. + * + * @param name the name of property + * @param value the value of property + * @throws TaskException if property can not be set + */ + public void setProperty( String name, Object value ) + throws TaskException + { + m_properties.put( name, value ); + } + + /** + * Return a child PropertyStore with specified name. + * This is to allow support for scoped stores. However a + * store may choose to be unscoped and just return a + * reference to itself. + * + * @param name the name of child store + * @return the child store + * @throws TaskException if theres an error creating child store + */ + public PropertyStore createChildStore( String name ) + throws TaskException + { + return this; + } +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/PropertyResolver.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/PropertyResolver.java index a97fbe754..66d09dd22 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/PropertyResolver.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/PropertyResolver.java @@ -8,6 +8,7 @@ package org.apache.myrmidon.interfaces.property; import org.apache.myrmidon.api.TaskException; +import org.apache.myrmidon.api.TaskContext; /** * @@ -30,11 +31,11 @@ public interface PropertyResolver * Rules used for property resolution are implementation dependent. * * @param value the value to resolve, which may contain property identifiers - * @param properties the set of properties to resolve against. + * @param context the set of properties to resolve against. * @return the resolved content * @exception TaskException if an error occurs */ Object resolveProperties( final String value, - final PropertyStore properties ) + final TaskContext context ) throws TaskException; } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/Resources.properties b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/Resources.properties new file mode 100644 index 000000000..368a4fd47 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/Resources.properties @@ -0,0 +1 @@ +unknown-property.error=Unknown property "{0}". \ No newline at end of file diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/embeddor/test/DefaultEmbeddorTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/embeddor/test/DefaultEmbeddorTest.java index d96fad6d0..480429154 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/embeddor/test/DefaultEmbeddorTest.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/embeddor/test/DefaultEmbeddorTest.java @@ -8,6 +8,7 @@ package org.apache.myrmidon.components.embeddor.test; import java.io.File; +import java.util.HashMap; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.logger.Logger; import org.apache.myrmidon.AbstractProjectTest; @@ -118,7 +119,7 @@ public class DefaultEmbeddorTest final Project project = embeddor.createProject( projectFile.getAbsolutePath(), null, null ); // Build the workspace - final Workspace workspace = embeddor.createWorkspace( new Parameters() ); + final Workspace workspace = embeddor.createWorkspace( new HashMap() ); // Install a listener final LogMessageTracker listener = new LogMessageTracker(); diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/AbstractPropertyResolverTestCase.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/AbstractPropertyResolverTestCase.java index b2925afa8..da422a1b7 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/AbstractPropertyResolverTestCase.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/AbstractPropertyResolverTestCase.java @@ -11,8 +11,11 @@ import java.io.File; import java.util.Date; import org.apache.aut.converter.lib.ObjectToStringConverter; import org.apache.avalon.excalibur.i18n.Resources; +import org.apache.avalon.framework.service.DefaultServiceManager; import org.apache.myrmidon.api.TaskException; +import org.apache.myrmidon.api.TaskContext; import org.apache.myrmidon.components.AbstractComponentTest; +import org.apache.myrmidon.components.workspace.DefaultTaskContext; import org.apache.myrmidon.components.property.DefaultPropertyResolver; import org.apache.myrmidon.components.store.DefaultPropertyStore; import org.apache.myrmidon.interfaces.property.PropertyResolver; @@ -28,7 +31,7 @@ public abstract class AbstractPropertyResolverTestCase extends AbstractComponentTest { protected PropertyResolver m_resolver; - protected PropertyStore m_store; + protected TaskContext m_context; public AbstractPropertyResolverTestCase( final String name ) { @@ -39,9 +42,12 @@ public abstract class AbstractPropertyResolverTestCase { m_resolver = (PropertyResolver)getServiceManager().lookup( PropertyResolver.ROLE ); - m_store = new DefaultPropertyStore(); - m_store.setProperty( "intProp", new Integer( 333 ) ); - m_store.setProperty( "stringProp", "String property" ); + final PropertyStore store = new DefaultPropertyStore(); + m_context = + new DefaultTaskContext( new DefaultServiceManager(), getLogger(), store ); + + m_context.setProperty( "intProp", new Integer( 333 ) ); + m_context.setProperty( "stringProp", "String property" ); registerConverter( ObjectToStringConverter.class, Object.class, String.class ); } @@ -87,14 +93,14 @@ public abstract class AbstractPropertyResolverTestCase private void testPropertyValue( final Object propObject ) throws Exception { - m_store.setProperty( "typedProp", propObject ); + m_context.setProperty( "typedProp", propObject ); final String propString = propObject.toString(); - doTestResolution( "${typedProp}", propObject, m_store ); + doTestResolution( "${typedProp}", propObject, m_context ); doTestResolution( "${typedProp} with following text", - propString + " with following text", m_store ); + propString + " with following text", m_context ); doTestResolution( "Preceding text with ${typedProp}", - "Preceding text with " + propString, m_store ); + "Preceding text with " + propString, m_context ); } /** @@ -102,15 +108,15 @@ public abstract class AbstractPropertyResolverTestCase */ public void testMultipleProperties() throws Exception { - m_store.setProperty( "prop1", "value1" ); - m_store.setProperty( "prop2", "value2" ); - m_store.setProperty( "int1", new Integer( 123 ) ); + m_context.setProperty( "prop1", "value1" ); + m_context.setProperty( "prop2", "value2" ); + m_context.setProperty( "int1", new Integer( 123 ) ); - doTestResolution( "${prop1}${prop2}", "value1value2", m_store ); - doTestResolution( "${prop1}${prop1}${prop1}", "value1value1value1", m_store ); + doTestResolution( "${prop1}${prop2}", "value1value2", m_context ); + doTestResolution( "${prop1}${prop1}${prop1}", "value1value1value1", m_context ); doTestResolution( "before ${prop2} between ${prop1} after", - "before value2 between value1 after", m_store ); - doTestResolution( "${prop1}-${int1}-${prop2}", "value1-123-value2", m_store ); + "before value2 between value1 after", m_context ); + doTestResolution( "${prop1}-${int1}-${prop2}", "value1-123-value2", m_context ); } /** @@ -121,10 +127,10 @@ public abstract class AbstractPropertyResolverTestCase final Resources rez = getResourcesForTested( DefaultPropertyResolver.class ); doTestFailure( "${unclosed", rez.getString( "prop.mismatched-braces.error" ), - m_store ); + m_context ); doTestFailure( "${", rez.getString( "prop.mismatched-braces.error" ), - m_store ); + m_context ); /* TODO - need to handle these cases. */ // testFailure( "${bad${}", "", m_context ); @@ -136,10 +142,10 @@ public abstract class AbstractPropertyResolverTestCase */ protected void doTestResolution( final String value, final Object expected, - final PropertyStore properties ) + final TaskContext context ) throws Exception { - final Object resolved = m_resolver.resolveProperties( value, properties ); + final Object resolved = m_resolver.resolveProperties( value, context ); assertEquals( expected, resolved ); } @@ -150,11 +156,11 @@ public abstract class AbstractPropertyResolverTestCase */ protected void doTestFailure( final String value, final String expectedErrorMessage, - final PropertyStore properties ) + final TaskContext context ) { try { - m_resolver.resolveProperties( value, properties ); + m_resolver.resolveProperties( value, context ); fail( "Unexpected sucess - test should have failed." ); } catch( TaskException e ) diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/ClassicPropertyResolverTestCase.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/ClassicPropertyResolverTestCase.java index 742e2478d..12eef075a 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/ClassicPropertyResolverTestCase.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/ClassicPropertyResolverTestCase.java @@ -37,6 +37,6 @@ public class ClassicPropertyResolverTestCase { final String undefinedProp = "undefinedProperty"; final String propRef = "${" + undefinedProp + "}"; - doTestResolution( propRef, propRef, m_store ); + doTestResolution( propRef, propRef, m_context ); } } diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/DefaultPropertyResolverTestCase.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/DefaultPropertyResolverTestCase.java index cc358f07f..985a5a493 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/DefaultPropertyResolverTestCase.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/DefaultPropertyResolverTestCase.java @@ -41,11 +41,11 @@ public class DefaultPropertyResolverTestCase final String undefinedProp = "undefinedProperty"; doTestFailure( "${" + undefinedProp + "}", rez.getString( "unknown-prop.error", undefinedProp ), - m_store ); + m_context ); //TODO - "" should be disallowed as a property name doTestFailure( "${}", rez.getString( "unknown-prop.error", "" ), - m_store ); + m_context ); } } diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/PathTestCase.java b/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/PathTestCase.java index 36b391051..e23055298 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/PathTestCase.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/PathTestCase.java @@ -8,6 +8,7 @@ package org.apache.myrmidon.framework.file.test; import java.io.File; +import org.apache.aut.nativelib.PathUtil; import org.apache.avalon.excalibur.io.FileUtil; import org.apache.myrmidon.AbstractProjectTest; import org.apache.myrmidon.LogMessageTracker; @@ -31,7 +32,7 @@ public class PathTestCase */ public void testLocationAttribute() throws Exception { - testPathContent( "set-location", new String[] { "location" } ); + testPathContent( "set-location", new String[]{"location"} ); } /** @@ -40,13 +41,13 @@ public class PathTestCase public void testPathAttribute() throws Exception { // Test a path with a single file - testPathContent( "set-path", new String[] { "single-file" } ); + testPathContent( "set-path", new String[]{"single-file"} ); // Test a path with several files, using ; separator - testPathContent( "set-multi-path", new String[] { "file1", "file2", ".." } ); + testPathContent( "set-multi-path", new String[]{"file1", "file2", ".."} ); // Test a path with several files, using : separator - testPathContent( "set-multi-path2", new String[] { "file1", "file2", ".." } ); + testPathContent( "set-multi-path2", new String[]{"file1", "file2", ".."} ); } /** @@ -54,8 +55,8 @@ public class PathTestCase */ public void testPathElement() throws Exception { - testPathContent( "nested-path", new String[] { "some-file" } ); - testPathContent( "mixed-path", new String[] { "file1", "file2", "file3", "file4", "file5" } ); + testPathContent( "nested-path", new String[]{"some-file"} ); + testPathContent( "mixed-path", new String[]{"file1", "file2", "file3", "file4", "file5"} ); } /** @@ -63,7 +64,7 @@ public class PathTestCase */ public void testFilesetElement() throws Exception { - testPathContent( "set-fileset", new String[] { "path.ant" } ); + testPathContent( "set-fileset", new String[]{"path.ant"} ); } /** @@ -71,7 +72,27 @@ public class PathTestCase */ public void testCustomFileList() throws Exception { - testPathContent( "test-custom-file-list", new String[] { "file1" } ); + testPathContent( "test-custom-file-list", new String[]{"file1"} ); + } + + /** + * Test converting between string and path. + */ + public void testConvert() throws Exception + { + testPathContent( "convert-string-to-path", new String[]{"file1", "file2"} ); + + // Test conversion from path -> string + final File[] files = { + getTestResource( "file1", false ), + getTestResource( "file2", false ) + }; + final String path = PathUtil.formatPath( files ); + final LogMessageTracker listener = new LogMessageTracker(); + listener.addExpectedMessage( "convert-path-to-string", "test-path = " + path ); + + final File projectFile = getTestResource( "path.ant" ); + executeTarget( projectFile, "convert-path-to-string", listener ); } /** diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/TestFileList.java b/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/TestFileList.java index d134a0c48..8ca76f0e7 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/TestFileList.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/TestFileList.java @@ -7,10 +7,12 @@ */ package org.apache.myrmidon.framework.file.test; -import org.apache.myrmidon.framework.file.FileList; +import java.io.File; +import java.util.ArrayList; import org.apache.myrmidon.api.TaskContext; import org.apache.myrmidon.api.TaskException; -import java.io.File; +import org.apache.myrmidon.framework.file.FileList; +import org.apache.myrmidon.framework.file.Path; /** * A test FileList implementation. @@ -24,19 +26,38 @@ public class TestFileList implements FileList { private String m_name; + private Path m_path; public void setName( final String name ) { m_name = name; } + public void setPath( final Path path ) + { + m_path = path; + } + /** * Returns the files in this list. */ public String[] listFiles( final TaskContext context ) throws TaskException { - final File file = context.resolveFile( m_name ); - return new String[] { file.getAbsolutePath() }; + final ArrayList files = new ArrayList(); + if( m_name != null ) + { + final File file = context.resolveFile( m_name ); + files.add( file.getAbsolutePath() ); + } + if( m_path != null ) + { + final String[] fileNames = m_path.listFiles( context ); + for( int i = 0; i < fileNames.length; i++ ) + { + files.add( fileNames[ i ] ); + } + } + return (String[])files.toArray( new String[ files.size() ] ); } } diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/path.ant b/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/path.ant index 319f92336..006c3f441 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/path.ant +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/framework/file/test/path.ant @@ -13,14 +13,14 @@ - + - + @@ -64,4 +64,17 @@ + + + + + + + + + + + test-path = ${test-path} + + \ No newline at end of file