Browse Source

* Added PropertyResolver service interface, together with 2 implementations.

(One implementation mimics Ant1 behaviour). These are added in the
  "workspace" packages, since that's where PropertyUtil was. Not sure if this
  is the right place.
* DefaultTaskContext now implements Context interface, used by
  PropertyResolver. This avoids having the PropertyResolver dependent on
  TaskContext, avoiding a potential circularity problem. (since TaskContext has
  a "resolve" method of it's own).
* Removed PropertyUtil.
* Tests for PropertyResolver implementations.

Submitted by Darrell DeBoer [darrell@apache.org]


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271801 13f79535-47bb-0310-9956-ffa450edef68
master
adammurdoch 23 years ago
parent
commit
c8ae289ddd
16 changed files with 807 additions and 253 deletions
  1. +1
    -1
      proposal/myrmidon/src/java/org/apache/antlib/file/Delete.java
  2. +1
    -1
      proposal/myrmidon/src/java/org/apache/aut/bzip2/CBZip2InputStream.java
  3. +1
    -1
      proposal/myrmidon/src/java/org/apache/aut/tar/TarOutputStream.java
  4. +2
    -0
      proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java
  5. +44
    -0
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ClassicPropertyResolver.java
  6. +255
    -0
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultPropertyResolver.java
  7. +35
    -5
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java
  8. +0
    -239
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/PropertyUtil.java
  9. +2
    -6
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/Resources.properties
  10. +38
    -0
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/workspace/PropertyResolver.java
  11. +6
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java
  12. +41
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/workspace/ClassicPropertyResolverTest.java
  13. +167
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/workspace/DefaultPropertyResolverTest.java
  14. +6
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java
  15. +41
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/workspace/ClassicPropertyResolverTest.java
  16. +167
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/workspace/DefaultPropertyResolverTest.java

+ 1
- 1
proposal/myrmidon/src/java/org/apache/antlib/file/Delete.java View File

@@ -237,4 +237,4 @@ public class Delete
}
}
}
}
}

+ 1
- 1
proposal/myrmidon/src/java/org/apache/aut/bzip2/CBZip2InputStream.java View File

@@ -958,4 +958,4 @@ public class CBZip2InputStream
}
}
}
}
}

+ 1
- 1
proposal/myrmidon/src/java/org/apache/aut/tar/TarOutputStream.java View File

@@ -338,4 +338,4 @@ public class TarOutputStream

m_buffer.writeRecord( m_recordBuf );
}
}
}

+ 2
- 0
proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java View File

@@ -41,6 +41,7 @@ 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.PropertyResolver;
import org.apache.myrmidon.interfaces.workspace.Workspace;
import org.apache.myrmidon.listeners.ProjectListener;

@@ -254,6 +255,7 @@ public class DefaultEmbeddor
createComponent( Deployer.class, PREFIX + "deployer.DefaultDeployer" );
createComponent( ClassLoaderManager.class, PREFIX + "deployer.DefaultClassLoaderManager" );
createComponent( Executor.class, PREFIX + "executor.AspectAwareExecutor" );
createComponent( PropertyResolver.class, PREFIX + "workspace.DefaultPropertyResolver" );

// Setup the components
for( Iterator iterator = m_components.iterator(); iterator.hasNext(); )


+ 44
- 0
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ClassicPropertyResolver.java View File

@@ -0,0 +1,44 @@
/*
* 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.workspace.PropertyResolver;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;

/**
* A {@link PropertyResolver} implementation which resolves properties
* as per Ant1, ignoring undefined properties.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*/
public class ClassicPropertyResolver
extends DefaultPropertyResolver
implements PropertyResolver
{
/**
* Retrieve a value from the specified context using the specified key.
* If there is no such value, returns the original property reference.
*
* @param propertyName the name of the property to retrieve
* @param context the set of known properties
*/
protected Object getPropertyValue( final String propertyName,
final Context context )
{
try
{
return context.get( propertyName );
}
catch( ContextException e )
{
return "${" + propertyName + "}";
}
}
}

+ 255
- 0
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultPropertyResolver.java View File

@@ -0,0 +1,255 @@
/*
* 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.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.interfaces.workspace.PropertyResolver;

/**
* Base class for PropertyResolver implementations.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*/
public class DefaultPropertyResolver
implements PropertyResolver
{
private final static Resources REZ =
ResourceManager.getPackageResources( DefaultPropertyResolver.class );

/**
* Resolve a string property. This evaluates all property
* substitutions based on specified context.
*
* If the content contains a single property reference, then the property value
* <code>Object</code> itself is returned.
* Otherwise, a <code>String</code> is returned, comprising the supplied
* content, with all property references replaced with the result of
* <code>toString()</code> called on the property value.
*
* @param content the property to resolve
* @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 Context context )
throws TaskException
{
int start = findNextProperty( content, 0 );
if( -1 == start )
{
return content;
}

int end = findEnding( content, start );

final int length = content.length();

if( 0 == start && end == ( length - 1 ) )
{
return getPropertyValue( content.substring( start + 2, end ),
context );
}

final StringBuffer sb = new StringBuffer( length * 2 );
int lastPlace = 0;

while( true )
{
final Object propertyValue =
getPropertyValue( content.substring( start + 2, end ),
context );

sb.append( content.substring( lastPlace, start ) );
sb.append( propertyValue );

lastPlace = end + 1;

start = findNextProperty( content, lastPlace );
if( -1 == start )
{
break;
}

end = findEnding( content, start );
}

sb.append( content.substring( lastPlace, length ) );

return sb.toString();
}

/**
* Resolve a string property. This recursively evaluates all property
* substitutions based on specified context.
*
* @param content the property to resolve
* @param context the context in which to resolve property
* @return the reolved property
* @exception TaskException if an error occurs
*/
protected Object recursiveResolveProperty( final String content,
final Context context )
throws TaskException
{
int start = findNextProperty( content, 0 );
if( -1 == start )
{
return content;
}

int end = findNestedEnding( content, start );

final int length = content.length();

if( 0 == start && end == ( length - 1 ) )
{
final String propertyName = content.substring( start + 2, end );
final Object key = recursiveResolveProperty( propertyName, context );
return getPropertyValue( key.toString(), context );
}

final StringBuffer sb = new StringBuffer( length * 2 );

int lastPlace = 0;

while( true )
{
final String propertyName = content.substring( start + 2, end );
final Object key = recursiveResolveProperty( propertyName, context );
final Object value = getPropertyValue( key.toString(), context );

sb.append( content.substring( lastPlace, start ) );
sb.append( value );

lastPlace = end + 1;

start = findNextProperty( content, lastPlace );
if( -1 == start )
{
break;
}

end = findNestedEnding( content, start );
}

sb.append( content.substring( lastPlace, length ) );

return sb.toString();
}

/**
* Finds the next occurrance of the start of a Property identifier.
* @param content the String to search
* @param currentPosition start location of the search
* @return the position of the next occurrence, or <code>-1</code> if none
* was found.
*/
private int findNextProperty( final String content, final int currentPosition )
{
//TODO: Check if it is commented out
return content.indexOf( "${", currentPosition );
}

/**
* Finds the next occurrence of the end of a Property identifier.
* @param property the String to search
* @param currentPosition start location of the search
* @return the position of the next occurrence
* @throws TaskException if no end was found
*/
private int findEnding( final String property, final int currentPosition )
throws TaskException
{
//TODO: Check if it is commented out
final int index = property.indexOf( '}', currentPosition );
if( -1 == index )
{
final String message = REZ.getString( "prop.mismatched-braces.error" );
throw new TaskException( message );
}

return index;
}

/**
* Finds the end of the property identifier at the currentPosition,
* taking into account nested property identifiers.
* @param property the String to search
* @param currentPosition location of the property
* @return the position of the propery ending.
* @throws TaskException if the property is not properly ended.
*/
private int findNestedEnding( final String property, final int currentPosition )
throws TaskException
{
final int length = property.length();
final int start = currentPosition + 2;

int weight = 1;
for( int i = start; ( weight > 0 ) && ( i < length ); i++ )
{
final char ch = property.charAt( i );
switch( ch )
{
case '}':
//TODO: Check if it is commented out
weight--;
if( weight == 0 )
{
return i;
}
break;

case '$':
{
//TODO: Check if it is commented out
final int next = i + 1;
if( next < length && '{' == property.charAt( next ) )
{
weight++;
}
}
break;
}
}

final String message = REZ.getString( "prop.mismatched-braces.error" );
throw new TaskException( message );
}

/**
* Retrieve a value from the specified context using the specified key.
*
* @param propertyName the key of value in context
* @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 Context context )
throws TaskException
{
try
{
return context.get( propertyName );
}
catch( ContextException e )
{
final String message = REZ.getString( "prop.missing-value.error", propertyName );
throw new TaskException( message );
}
}
}


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

@@ -13,11 +13,14 @@ 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;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.logger.Logger;
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.interfaces.workspace.PropertyResolver;

/**
* Default implementation of TaskContext.
@@ -26,7 +29,7 @@ import org.apache.myrmidon.api.TaskException;
* @version $Revision$ $Date$
*/
public class DefaultTaskContext
implements TaskContext
implements TaskContext, Context
{
private final static Resources REZ =
ResourceManager.getPackageResources( DefaultTaskContext.class );
@@ -35,6 +38,7 @@ public class DefaultTaskContext
private final TaskContext m_parent;
private ServiceManager m_serviceManager;
private Logger m_logger;
private PropertyResolver m_propertyResolver;

/**
* Constructor that takes both parent context and a service directory.
@@ -55,7 +59,7 @@ public class DefaultTaskContext
*/
public String getName()
{
return (String)m_contextData.get( NAME );
return (String)getProperty( NAME );
}

/**
@@ -65,7 +69,7 @@ public class DefaultTaskContext
*/
public File getBaseDirectory()
{
return (File)m_contextData.get( BASE_DIRECTORY );
return (File)getProperty( BASE_DIRECTORY );
}

/**
@@ -133,10 +137,17 @@ public class DefaultTaskContext
public Object resolveValue( final String value )
throws TaskException
{

try
{
// Lazy lookup of the PropertyResolver
if( m_propertyResolver == null )
{
m_propertyResolver = (PropertyResolver)getService( PropertyResolver.class );
}

final Object object =
PropertyUtil.resolveProperty( value, this, false );
m_propertyResolver.resolveProperties( value, this );

if( null == object )
{
@@ -161,7 +172,12 @@ public class DefaultTaskContext
*/
public Object getProperty( final String name )
{
return m_contextData.get( name );
Object value = m_contextData.get( name );
if( value == null && m_parent != null )
{
value = m_parent.getProperty( name );
}
return value;
}

/**
@@ -332,6 +348,20 @@ public class DefaultTaskContext
return context;
}

/**
* Returns a property.
*/
public Object get( final Object key ) throws ContextException
{
final Object value = getProperty( (String)key );
if( value == null )
{
final String message = REZ.getString( "unknown-property.error", key );
throw new ContextException( message );
}
return value;
}

/**
* Make sure property is valid if it is one of the "magic" properties.
*


+ 0
- 239
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/PropertyUtil.java View File

@@ -1,239 +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.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;

/**
* Utility class to evaluate properties.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public final class PropertyUtil
{
private final static Resources REZ =
ResourceManager.getPackageResources( PropertyUtil.class );

private PropertyUtil()
{
}

/**
* Resolve a string property. This evaluates all property
* substitutions based on specified context.
*
* @param property the property to resolve
* @param context the context in which to resolve property
* @param ignoreUndefined if false will throw an TaskException if property is not found
* @return the reolved property
* @exception TaskException if an error occurs
*/
public static Object resolveProperty( final String property,
final TaskContext context,
final boolean ignoreUndefined )
throws TaskException
{
int start = findBeginning( property, 0 );
if( -1 == start )
{
return property;
}

int end = findEnding( property, start );

final int length = property.length();

if( 0 == start && end == ( length - 1 ) )
{
return resolveValue( property.substring( start + 2, end ),
context,
ignoreUndefined );
}

final StringBuffer sb = new StringBuffer( length * 2 );
int lastPlace = 0;

while( true )
{
final Object value =
resolveValue( property.substring( start + 2, end ),
context,
ignoreUndefined );

sb.append( property.substring( lastPlace, start ) );
sb.append( value );

lastPlace = end + 1;

start = findBeginning( property, lastPlace );
if( -1 == start )
{
break;
}

end = findEnding( property, start );
}

sb.append( property.substring( lastPlace, length ) );

return sb.toString();
}

/**
* Resolve a string property. This recursively evaluates all property
* substitutions based on specified context.
*
* @param property the property to resolve
* @param context the context in which to resolve property
* @param ignoreUndefined if false will throw an TaskException if property is not found
* @return the reolved property
* @exception TaskException if an error occurs
*/
public static Object recursiveResolveProperty( final String property,
final TaskContext context,
final boolean ignoreUndefined )
throws TaskException
{
int start = findBeginning( property, 0 );
if( -1 == start )
{
return property;
}

int end = findNestedEnding( property, start );

final int length = property.length();

if( 0 == start && end == ( length - 1 ) )
{
final String propertyName = property.substring( start + 2, end );
final Object key = recursiveResolveProperty( propertyName, context, ignoreUndefined );
return resolveValue( key.toString(), context, ignoreUndefined );
}

final StringBuffer sb = new StringBuffer( length * 2 );

int lastPlace = 0;

while( true )
{
final String propertyName = property.substring( start + 2, end );
final Object key = recursiveResolveProperty( propertyName, context, ignoreUndefined );
final Object value = resolveValue( key.toString(), context, ignoreUndefined );

sb.append( property.substring( lastPlace, start ) );
sb.append( value );

lastPlace = end + 1;

start = findBeginning( property, lastPlace );
if( -1 == start )
{
break;
}

end = findNestedEnding( property, start );
}

sb.append( property.substring( lastPlace, length ) );

return sb.toString();
}

private static int findBeginning( final String property, final int currentPosition )
{
//TODO: Check if it is commented out
return property.indexOf( "${", currentPosition );
}

private static int findEnding( final String property, final int currentPosition )
throws TaskException
{
//TODO: Check if it is commented out
final int index = property.indexOf( '}', currentPosition );
if( -1 == index )
{
final String message = REZ.getString( "prop.mismatched-braces.error" );
throw new TaskException( message );
}

return index;
}

private static int findNestedEnding( final String property, final int currentPosition )
throws TaskException
{
final int length = property.length();
final int start = currentPosition + 2;

int weight = 1;
for( int i = start; ( weight > 0 ) && ( i < length ); i++ )
{
final char ch = property.charAt( i );
switch( ch )
{
case '}':
//TODO: Check if it is commented out
weight--;
if( weight == 0 )
{
return i;
}
break;

case '$':
{
//TODO: Check if it is commented out
final int next = i + 1;
if( next < length && '{' == property.charAt( next ) )
{
weight++;
}
}
break;
}
}

final String message = REZ.getString( "prop.mismatched-braces.error" );
throw new TaskException( message );
}

/**
* Retrieve a value from the specified context using the specified key.
* If there is no such value and ignoreUndefined is not false then a
* TaskException is generated.
*
* @param key the key of value in context
* @param context the Context
* @param ignoreUndefined true if undefined variables are ignored
* @return the object retrieved from context
* @exception TaskException if an error occurs
*/
private static Object resolveValue( final String key,
final TaskContext context,
final boolean ignoreUndefined )
throws TaskException
{
final Object value = context.getProperty( key );
if( value != null )
{
return value;
}
if( ignoreUndefined )
{
return "";
}
final String message = REZ.getString( "prop.missing-value.error", key );
throw new TaskException( message );
}
}


+ 2
- 6
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/Resources.properties View File

@@ -11,17 +11,13 @@ exec-target.notice=Executing target {0}.
exec-task.notice=Executing task {0}.

#DefaultTaskContext
no-version.error=No JavaVersion in Context.
no-name.error=No Name in Context.
no-dir.error=No Base Directory in Context.
no-parent.error=Can't set a property with parent scope when context has no parent.
bad-scope.error=Unknown property scope! ({0}).
unknown-prop.error=Unknown property {0}.
bad-property.error=Property {0} must have a value of type {1}.
null-resolved-value.error=Value "{0}" resolved to null.
bad-resolve.error=Unable to resolve value "{0}".
bad-find-service.error=Could not find service "{0}".
bad-service-class.error=Find service "{0}" but it was of type {1} where it was expected to be of type {2}.

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

+ 38
- 0
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/workspace/PropertyResolver.java View File

@@ -0,0 +1,38 @@
/*
* 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.workspace;

import org.apache.myrmidon.api.TaskException;
import org.apache.avalon.framework.context.Context;

/**
*
* Provides a service for the resolution of property identifiers within
* String content.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*/
public interface PropertyResolver
{
String ROLE = PropertyResolver.class.getName();

/**
* Resolve a string property. This evaluates all property
* substitutions based on specified contex.
* Rules used for property resolution are implementation dependent.
*
* @param value the value to resolve, which may contain property identifiers
* @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 Context context )
throws TaskException;
}

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

@@ -27,6 +27,7 @@ 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.type.DefaultTypeManager;
import org.apache.myrmidon.components.workspace.DefaultPropertyResolver;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
import org.apache.myrmidon.interfaces.deployer.Deployer;
@@ -36,6 +37,7 @@ import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeManager;
import org.apache.myrmidon.interfaces.workspace.PropertyResolver;

/**
* A base class for tests for the default components.
@@ -120,6 +122,10 @@ public abstract class AbstractComponentTest
m_serviceManager.put( RoleManager.ROLE, component );
components.add( component );

component = new DefaultPropertyResolver();
m_serviceManager.put( PropertyResolver.ROLE, component );
components.add( component );

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


+ 41
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/components/workspace/ClassicPropertyResolverTest.java View File

@@ -0,0 +1,41 @@
/*
* 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.workspace.PropertyResolver;

/**
* A test for {@link ClassicPropertyResolver}
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*/
public class ClassicPropertyResolverTest
extends DefaultPropertyResolverTest
{
public ClassicPropertyResolverTest( String name )
{
super( name );
}

protected PropertyResolver createResolver()
{
return new ClassicPropertyResolver();
}

/**
* Tests handing undefined property.
*/
public void testUndefinedProp() throws Exception
{
String undefinedProp = "undefinedProperty";

final String propRef = "${" + undefinedProp + "}";
doTestResolution( propRef, propRef, m_context );
}
}

+ 167
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/components/workspace/DefaultPropertyResolverTest.java View File

@@ -0,0 +1,167 @@
/*
* 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 java.io.File;
import java.util.Date;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.context.Context;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.components.AbstractComponentTest;
import org.apache.myrmidon.interfaces.workspace.PropertyResolver;

/**
* Functional tests for {@link DefaultPropertyResolver}.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*/
public class DefaultPropertyResolverTest
extends AbstractComponentTest
{
protected final static Resources REZ
= ResourceManager.getPackageResources( DefaultPropertyResolver.class );

protected PropertyResolver m_resolver;
protected DefaultTaskContext m_context;

public DefaultPropertyResolverTest( String name )
{
super( name );
}

protected void setUp() throws Exception
{
super.setUp();

m_resolver = createResolver();

m_context = new DefaultTaskContext( null, getServiceManager(), getLogger() );
m_context.setProperty( "intProp", new Integer( 333 ) );
m_context.setProperty( "stringProp", "String property" );
}

protected PropertyResolver createResolver()
{
return new DefaultPropertyResolver();
}

/**
* Test property resolution with various different typed properties.
*/
public void testPropertyTypes() throws Exception
{
testPropertyValue( new String( "String value" ) );
testPropertyValue( new Date() );
testPropertyValue( new Integer( Integer.MIN_VALUE ) );
testPropertyValue( new Double( 24234.98453 ) );
testPropertyValue( this.getClass() );
testPropertyValue( File.createTempFile( "PropertyResolverTest", null ) );
}

/**
* Simple tests with property on it's own, and accompanied by text.
*/
private void testPropertyValue( Object propObject )
throws Exception
{
m_context.setProperty( "typedProp", propObject );
String propString = propObject.toString();

doTestResolution( "${typedProp}", propObject, m_context );
doTestResolution( "${typedProp} with following text",
propString + " with following text", m_context );
doTestResolution( "Preceding text with ${typedProp}",
"Preceding text with " + propString, m_context );
}

/**
* Tests multiple property declarations in a single value.
*/
public void testMultipleProperties() throws Exception
{
m_context.setProperty( "prop1", "value1" );
m_context.setProperty( "prop2", "value2" );
m_context.setProperty( "int1", new Integer( 123 ) );

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_context );
doTestResolution( "${prop1}-${int1}-${prop2}", "value1-123-value2", m_context );

}

/**
* Tests handing undefined property.
*/
public void testUndefinedProp() throws Exception
{
String undefinedProp = "undefinedProperty";
doTestFailure( "${" + undefinedProp + "}",
REZ.getString( "prop.missing-value.error", undefinedProp ),
m_context );

//TODO - "" should be disallowed as a property name
doTestFailure( "${}",
REZ.getString( "prop.missing-value.error", "" ),
m_context );
}

/**
* Tests illegal property syntax.
*/
public void testInvalidTypeDeclarations() throws Exception
{

doTestFailure( "${unclosed",
REZ.getString( "prop.mismatched-braces.error" ),
m_context );
doTestFailure( "${",
REZ.getString( "prop.mismatched-braces.error" ),
m_context );

/* TODO - need to handle these cases. */
// testFailure( "${bad${}", "", m_context );
// testFailure( "${ }", "", m_context );

}

/**
* Resolves the property using the supplied context, and checks the result.
*/
protected void doTestResolution( String value,
Object expected,
Context context )
throws Exception
{
Object resolved = m_resolver.resolveProperties( value, context );

assertEquals( expected, resolved );
}

/**
* Attempts to resolve the value using the supplied context, expecting to
* fail with the supplied error message.
*/
protected void doTestFailure( String value,
String expectedErrorMessage,
Context context )
{
try
{
m_resolver.resolveProperties( value, context );
fail( "Unexpected sucess - test should have failed." );
}
catch( TaskException e )
{
assertSameMessage( expectedErrorMessage, e );
}
}
}

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

@@ -27,6 +27,7 @@ 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.type.DefaultTypeManager;
import org.apache.myrmidon.components.workspace.DefaultPropertyResolver;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
import org.apache.myrmidon.interfaces.deployer.Deployer;
@@ -36,6 +37,7 @@ import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeManager;
import org.apache.myrmidon.interfaces.workspace.PropertyResolver;

/**
* A base class for tests for the default components.
@@ -120,6 +122,10 @@ public abstract class AbstractComponentTest
m_serviceManager.put( RoleManager.ROLE, component );
components.add( component );

component = new DefaultPropertyResolver();
m_serviceManager.put( PropertyResolver.ROLE, component );
components.add( component );

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


+ 41
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/workspace/ClassicPropertyResolverTest.java View File

@@ -0,0 +1,41 @@
/*
* 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.workspace.PropertyResolver;

/**
* A test for {@link ClassicPropertyResolver}
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*/
public class ClassicPropertyResolverTest
extends DefaultPropertyResolverTest
{
public ClassicPropertyResolverTest( String name )
{
super( name );
}

protected PropertyResolver createResolver()
{
return new ClassicPropertyResolver();
}

/**
* Tests handing undefined property.
*/
public void testUndefinedProp() throws Exception
{
String undefinedProp = "undefinedProperty";

final String propRef = "${" + undefinedProp + "}";
doTestResolution( propRef, propRef, m_context );
}
}

+ 167
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/workspace/DefaultPropertyResolverTest.java View File

@@ -0,0 +1,167 @@
/*
* 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 java.io.File;
import java.util.Date;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.context.Context;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.components.AbstractComponentTest;
import org.apache.myrmidon.interfaces.workspace.PropertyResolver;

/**
* Functional tests for {@link DefaultPropertyResolver}.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*/
public class DefaultPropertyResolverTest
extends AbstractComponentTest
{
protected final static Resources REZ
= ResourceManager.getPackageResources( DefaultPropertyResolver.class );

protected PropertyResolver m_resolver;
protected DefaultTaskContext m_context;

public DefaultPropertyResolverTest( String name )
{
super( name );
}

protected void setUp() throws Exception
{
super.setUp();

m_resolver = createResolver();

m_context = new DefaultTaskContext( null, getServiceManager(), getLogger() );
m_context.setProperty( "intProp", new Integer( 333 ) );
m_context.setProperty( "stringProp", "String property" );
}

protected PropertyResolver createResolver()
{
return new DefaultPropertyResolver();
}

/**
* Test property resolution with various different typed properties.
*/
public void testPropertyTypes() throws Exception
{
testPropertyValue( new String( "String value" ) );
testPropertyValue( new Date() );
testPropertyValue( new Integer( Integer.MIN_VALUE ) );
testPropertyValue( new Double( 24234.98453 ) );
testPropertyValue( this.getClass() );
testPropertyValue( File.createTempFile( "PropertyResolverTest", null ) );
}

/**
* Simple tests with property on it's own, and accompanied by text.
*/
private void testPropertyValue( Object propObject )
throws Exception
{
m_context.setProperty( "typedProp", propObject );
String propString = propObject.toString();

doTestResolution( "${typedProp}", propObject, m_context );
doTestResolution( "${typedProp} with following text",
propString + " with following text", m_context );
doTestResolution( "Preceding text with ${typedProp}",
"Preceding text with " + propString, m_context );
}

/**
* Tests multiple property declarations in a single value.
*/
public void testMultipleProperties() throws Exception
{
m_context.setProperty( "prop1", "value1" );
m_context.setProperty( "prop2", "value2" );
m_context.setProperty( "int1", new Integer( 123 ) );

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_context );
doTestResolution( "${prop1}-${int1}-${prop2}", "value1-123-value2", m_context );

}

/**
* Tests handing undefined property.
*/
public void testUndefinedProp() throws Exception
{
String undefinedProp = "undefinedProperty";
doTestFailure( "${" + undefinedProp + "}",
REZ.getString( "prop.missing-value.error", undefinedProp ),
m_context );

//TODO - "" should be disallowed as a property name
doTestFailure( "${}",
REZ.getString( "prop.missing-value.error", "" ),
m_context );
}

/**
* Tests illegal property syntax.
*/
public void testInvalidTypeDeclarations() throws Exception
{

doTestFailure( "${unclosed",
REZ.getString( "prop.mismatched-braces.error" ),
m_context );
doTestFailure( "${",
REZ.getString( "prop.mismatched-braces.error" ),
m_context );

/* TODO - need to handle these cases. */
// testFailure( "${bad${}", "", m_context );
// testFailure( "${ }", "", m_context );

}

/**
* Resolves the property using the supplied context, and checks the result.
*/
protected void doTestResolution( String value,
Object expected,
Context context )
throws Exception
{
Object resolved = m_resolver.resolveProperties( value, context );

assertEquals( expected, resolved );
}

/**
* Attempts to resolve the value using the supplied context, expecting to
* fail with the supplied error message.
*/
protected void doTestFailure( String value,
String expectedErrorMessage,
Context context )
{
try
{
m_resolver.resolveProperties( value, context );
fail( "Unexpected sucess - test should have failed." );
}
catch( TaskException e )
{
assertSameMessage( expectedErrorMessage, e );
}
}
}

Loading…
Cancel
Save