You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2014/10/14 08:52:39 UTC
svn commit: r1631643 - in /maven/shared/trunk/maven-shared-utils/src:
main/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractor.java
test/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractorTest.java
Author: krosenvold
Date: Tue Oct 14 06:52:39 2014
New Revision: 1631643
URL: http://svn.apache.org/r1631643
Log:
[MSHARED-313] Port dotted expression parser fixes.
Patch by Igor Fedorenko, adapted to msu by me
Modified:
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractor.java
maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractorTest.java
Modified: maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractor.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractor.java?rev=1631643&r1=1631642&r2=1631643&view=diff
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractor.java (original)
+++ maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractor.java Tue Oct 14 06:52:39 2014
@@ -19,6 +19,7 @@ package org.apache.maven.shared.utils.in
* under the License.
*/
+import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
@@ -28,6 +29,7 @@ import java.util.StringTokenizer;
import java.util.WeakHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+
import org.apache.maven.shared.utils.StringUtils;
import org.apache.maven.shared.utils.introspection.MethodMap.AmbiguousException;
@@ -46,292 +48,291 @@ import javax.annotation.Nullable;
* @version $Id$
* @see <a href="http://struts.apache.org/1.x/struts-taglib/indexedprops.html">http://struts.apache.org/1.x/struts-taglib/indexedprops.html</a>
*/
-public class ReflectionValueExtractor
-{
- private static final Class<?>[] CLASS_ARGS = new Class[0];
-
- private static final Object[] OBJECT_ARGS = new Object[0];
-
- /**
- * Use a WeakHashMap here, so the keys (Class objects) can be garbage collected.
- * This approach prevents permgen space overflows due to retention of discarded
- * classloaders.
- */
- private static final Map<Class<?>, ClassMap> classMaps = new WeakHashMap<Class<?>, ClassMap>();
-
- /**
- * Indexed properties pattern, ie <code>(\\w+)\\[(\\d+)\\]</code>
- */
- private static final Pattern INDEXED_PROPS = Pattern.compile( "(\\w+)\\[(\\d+)\\]" );
-
- /**
- * Indexed properties pattern, ie <code>(\\w+)\\((.+)\\)</code>
- */
- private static final Pattern MAPPED_PROPS = Pattern.compile( "(\\w+)\\((.+)\\)" );
-
- private ReflectionValueExtractor()
- {
- }
+public class ReflectionValueExtractor {
+ private static final Class<?>[] CLASS_ARGS = new Class[0];
- /**
- * <p>The implementation supports indexed, nested and mapped properties.</p>
- * <p/>
- * <ul>
- * <li>nested properties should be defined by a dot, i.e. "user.address.street"</li>
- * <li>indexed properties (java.util.List or array instance) should be contains <code>(\\w+)\\[(\\d+)\\]</code>
- * pattern, i.e. "user.addresses[1].street"</li>
- * <li>mapped properties should be contains <code>(\\w+)\\((.+)\\)</code> pattern, i.e. "user.addresses(myAddress).street"</li>
- * <ul>
- *
- * @param expression not null expression
- * @param root not null object
- * @return the object defined by the expression
- * @throws IntrospectionException if any
- */
- public static Object evaluate( @Nonnull String expression, @Nullable Object root )
- throws IntrospectionException
- {
- return evaluate( expression, root, true );
- }
+ private static final Object[] OBJECT_ARGS = new Object[0];
- /**
- * <p>The implementation supports indexed, nested and mapped properties.</p>
- * <p/>
- * <ul>
- * <li>nested properties should be defined by a dot, i.e. "user.address.street"</li>
- * <li>indexed properties (java.util.List or array instance) should be contains <code>(\\w+)\\[(\\d+)\\]</code>
- * pattern, i.e. "user.addresses[1].street"</li>
- * <li>mapped properties should be contains <code>(\\w+)\\((.+)\\)</code> pattern, i.e. "user.addresses(myAddress).street"</li>
- * <ul>
- *
- * @param expression not null expression
- * @param root not null object
- * @return the object defined by the expression
- * @throws IntrospectionException if any
- */
- public static Object evaluate( @Nonnull String expression, @Nullable Object root, boolean trimRootToken )
- throws IntrospectionException
- {
- // if the root token refers to the supplied root object parameter, remove it.
- if ( trimRootToken )
- {
- expression = expression.substring( expression.indexOf( '.' ) + 1 );
+ /**
+ * Use a WeakHashMap here, so the keys (Class objects) can be garbage collected.
+ * This approach prevents permgen space overflows due to retention of discarded
+ * classloaders.
+ */
+ private static final Map<Class<?>, ClassMap> classMaps = new WeakHashMap<Class<?>, ClassMap>();
+
+
+ static final int EOF = -1;
+
+ static final char PROPERTY_START = '.';
+
+ static final char INDEXED_START = '[';
+
+ static final char INDEXED_END = ']';
+
+ static final char MAPPED_START = '(';
+
+ static final char MAPPED_END = ')';
+
+ static class Tokenizer {
+ final String expression;
+
+ int idx;
+
+ public Tokenizer(String expression) {
+ this.expression = expression;
+ }
+
+ public int peekChar() {
+ return idx < expression.length() ? expression.charAt(idx) : EOF;
+ }
+
+ public int skipChar() {
+ return idx < expression.length() ? expression.charAt(idx++) : EOF;
+ }
+
+ public String nextToken(char delimiter) {
+ int start = idx;
+
+ while (idx < expression.length() && delimiter != expression.charAt(idx)) {
+ idx++;
+ }
+
+ // delimiter MUST be present
+ if (idx <= start || idx >= expression.length()) {
+ return null;
+ }
+
+ return expression.substring(start, idx++);
+ }
+
+ public String nextPropertyName() {
+ final int start = idx;
+
+ while (idx < expression.length() && Character.isJavaIdentifierPart(expression.charAt(idx))) {
+ idx++;
+ }
+
+ // property name does not require delimiter
+ if (idx <= start || idx > expression.length()) {
+ return null;
+ }
+
+ return expression.substring(start, idx);
+ }
+
+ public int getPosition() {
+ return idx < expression.length() ? idx : EOF;
+ }
+
+ // to make tokenizer look pretty in debugger
+ @Override
+ public String toString() {
+ return idx < expression.length() ? expression.substring(idx) : "<EOF>";
+ }
+ }
+
+ private ReflectionValueExtractor() {
+ }
+
+ /**
+ * <p>The implementation supports indexed, nested and mapped properties.</p>
+ * <p/>
+ * <ul>
+ * <li>nested properties should be defined by a dot, i.e. "user.address.street"</li>
+ * <li>indexed properties (java.util.List or array instance) should be contains <code>(\\w+)\\[(\\d+)\\]</code>
+ * pattern, i.e. "user.addresses[1].street"</li>
+ * <li>mapped properties should be contains <code>(\\w+)\\((.+)\\)</code> pattern, i.e. "user.addresses(myAddress).street"</li>
+ * <ul>
+ *
+ * @param expression not null expression
+ * @param root not null object
+ * @return the object defined by the expression
+ * @throws IntrospectionException if any
+ */
+ public static Object evaluate(@Nonnull String expression, @Nullable Object root)
+ throws IntrospectionException {
+ return evaluate(expression, root, true);
+ }
+
+ /**
+ * <p>The implementation supports indexed, nested and mapped properties.</p>
+ * <p/>
+ * <ul>
+ * <li>nested properties should be defined by a dot, i.e. "user.address.street"</li>
+ * <li>indexed properties (java.util.List or array instance) should be contains <code>(\\w+)\\[(\\d+)\\]</code>
+ * pattern, i.e. "user.addresses[1].street"</li>
+ * <li>mapped properties should be contains <code>(\\w+)\\((.+)\\)</code> pattern, i.e. "user.addresses(myAddress).street"</li>
+ * <ul>
+ *
+ * @param expression not null expression
+ * @param root not null object
+ * @return the object defined by the expression
+ * @throws IntrospectionException if any
+ */
+ public static Object evaluate(@Nonnull String expression, @Nullable Object root, boolean trimRootToken)
+ throws IntrospectionException {
+ Object value = root;
+
+ // ----------------------------------------------------------------------
+ // Walk the dots and retrieve the ultimate value desired from the
+ // MavenProject instance.
+ // ----------------------------------------------------------------------
+
+ if (org.codehaus.plexus.util.StringUtils.isEmpty(expression) || !Character.isJavaIdentifierStart(expression.charAt(0))) {
+ return null;
+ }
+
+ final Tokenizer tokenizer;
+ if (trimRootToken) {
+ tokenizer = new Tokenizer(expression);
+ tokenizer.nextPropertyName();
+ if (tokenizer.getPosition() == EOF) {
+ return null;
+ }
+ } else {
+ tokenizer = new Tokenizer("." + expression);
+ }
+
+ int propertyPosition = tokenizer.getPosition();
+ while (value != null && tokenizer.peekChar() != EOF) {
+ switch (tokenizer.skipChar()) {
+ case INDEXED_START:
+ value =
+ getIndexedValue(expression, propertyPosition, tokenizer.getPosition(), value,
+ tokenizer.nextToken(INDEXED_END));
+ break;
+ case MAPPED_START:
+ value =
+ getMappedValue(expression, propertyPosition, tokenizer.getPosition(), value,
+ tokenizer.nextToken(MAPPED_END));
+ break;
+ case PROPERTY_START:
+ propertyPosition = tokenizer.getPosition();
+ value = getPropertyValue(value, tokenizer.nextPropertyName());
+ break;
+ default:
+ // could not parse expression
+ return null;
+ }
+ }
+
+ return value;
+ }
+
+ private static Object getMappedValue(final String expression, final int from, final int to, final Object value,
+ final String key)
+ throws IntrospectionException {
+ if (value == null || key == null) {
+ return null;
+ }
+
+ if (value instanceof Map) {
+ Object[] localParams = new Object[] { key };
+ ClassMap classMap = getClassMap(value.getClass());
+ try {
+ Method method = classMap.findMethod("get", localParams);
+ return method.invoke(value, localParams);
+ } catch (AmbiguousException e) {
+ throw new IntrospectionException(e);
+ } catch (IllegalAccessException e) {
+ throw new IntrospectionException(e);
+ } catch (InvocationTargetException e) {
+ throw new IntrospectionException(e.getTargetException());
+ }
+
+ }
+
+ final String message =
+ String.format("The token '%s' at position '%d' refers to a java.util.Map, but the value seems is an instance of '%s'",
+ expression.subSequence(from, to), from, value.getClass());
+
+ throw new IntrospectionException(message);
+ }
+
+ private static Object getIndexedValue(final String expression, final int from, final int to, final Object value,
+ final String indexStr)
+ throws IntrospectionException {
+ try {
+ int index = Integer.parseInt(indexStr);
+
+ if (value.getClass().isArray()) {
+ return Array.get(value, index);
+ }
+
+ if (value instanceof List) {
+ ClassMap classMap = getClassMap(value.getClass());
+ // use get method on List interface
+ Object[] localParams = new Object[] { index };
+ Method method = null;
+ try {
+ method = classMap.findMethod("get", localParams);
+ return method.invoke(value, localParams);
+ } catch (AmbiguousException e) {
+ throw new IntrospectionException(e);
+ } catch (IllegalAccessException e) {
+ throw new IntrospectionException(e);
+ }
+ }
+ } catch (NumberFormatException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ // catch array index issues gracefully, otherwise release
+ if (e.getCause() instanceof IndexOutOfBoundsException) {
+ return null;
+ }
+
+ throw new IntrospectionException(e.getTargetException());
+ }
+
+ final String message =
+ String.format("The token '%s' at position '%d' refers to a java.util.List or an array, but the value seems is an instance of '%s'",
+ expression.subSequence(from, to), from, value.getClass());
+
+ throw new IntrospectionException(message);
+ }
+
+ private static Object getPropertyValue(Object value, String property)
+ throws IntrospectionException {
+ if (value == null || property == null) {
+ return null;
+ }
+
+ ClassMap classMap = getClassMap(value.getClass());
+ String methodBase = org.codehaus.plexus.util.StringUtils.capitalizeFirstLetter(property);
+ String methodName = "get" + methodBase;
+ try {
+ Method method = classMap.findMethod(methodName, CLASS_ARGS);
+
+ if (method == null) {
+ // perhaps this is a boolean property??
+ methodName = "is" + methodBase;
+
+ method = classMap.findMethod(methodName, CLASS_ARGS);
+ }
+
+ if (method == null) {
+ return null;
+ }
+
+ return method.invoke(value, OBJECT_ARGS);
+ } catch (InvocationTargetException e) {
+ throw new IntrospectionException(e.getTargetException());
+ } catch (AmbiguousException e) {
+ throw new IntrospectionException(e);
+ } catch (IllegalAccessException e) {
+ throw new IntrospectionException(e);
}
-
- Object value = root;
-
- // ----------------------------------------------------------------------
- // Walk the dots and retrieve the ultimate value desired from the
- // MavenProject instance.
- // ----------------------------------------------------------------------
-
- StringTokenizer parser = new StringTokenizer( expression, "." );
-
- while ( parser.hasMoreTokens() )
- {
- // if we have nothing, stop now
- if ( value == null )
- {
- return null;
- }
-
- String token = parser.nextToken();
-
- ClassMap classMap = getClassMap( value.getClass() );
-
- Method method;
- Object[] localParams = OBJECT_ARGS;
-
- // do we have an indexed property?
- Matcher matcher = INDEXED_PROPS.matcher( token );
- if ( matcher.find() )
- {
- String methodBase = StringUtils.capitalizeFirstLetter( matcher.group( 1 ) );
- String methodName = "get" + methodBase;
- try
- {
- method = classMap.findMethod( methodName, CLASS_ARGS );
- }
- catch ( AmbiguousException e )
- {
- throw new IntrospectionException( e );
- }
-
- try
- {
- value = method.invoke( value, OBJECT_ARGS );
- }
- catch ( IllegalArgumentException e )
- {
- throw new IntrospectionException( e );
- }
- catch ( IllegalAccessException e )
- {
- throw new IntrospectionException( e );
- }
- catch ( InvocationTargetException e )
- {
- throw new IntrospectionException( e );
- }
-
- classMap = getClassMap( value.getClass() );
-
- if ( classMap.getCachedClass().isArray() )
- {
- value = Arrays.asList( (Object[]) value );
- classMap = getClassMap( value.getClass() );
- }
-
- if ( value instanceof List )
- {
- // use get method on List interface
- localParams = new Object[1];
- localParams[0] = Integer.valueOf( matcher.group( 2 ) );
- try
- {
- method = classMap.findMethod( "get", localParams );
- }
- catch ( AmbiguousException e )
- {
- throw new IntrospectionException( e );
- }
- }
- else
- {
- throw new IntrospectionException( "The token '" + token
- + "' refers to a java.util.List or an array, but the value seems is an instance of '"
- + value.getClass() + "'." );
- }
- }
- else
- {
- // do we have a mapped property?
- matcher = MAPPED_PROPS.matcher( token );
- if ( matcher.find() )
- {
- String methodBase = StringUtils.capitalizeFirstLetter( matcher.group( 1 ) );
- String methodName = "get" + methodBase;
- try
- {
- method = classMap.findMethod( methodName, CLASS_ARGS );
- }
- catch ( AmbiguousException e )
- {
- throw new IntrospectionException( e );
- }
-
- try
- {
- value = method.invoke( value, OBJECT_ARGS );
- }
- catch ( IllegalArgumentException e )
- {
- throw new IntrospectionException( e );
- }
- catch ( IllegalAccessException e )
- {
- throw new IntrospectionException( e );
- }
- catch ( InvocationTargetException e )
- {
- throw new IntrospectionException( e );
- }
- classMap = getClassMap( value.getClass() );
-
- if ( value instanceof Map )
- {
- // use get method on List interface
- localParams = new Object[1];
- localParams[0] = matcher.group( 2 );
- try
- {
- method = classMap.findMethod( "get", localParams );
- }
- catch ( AmbiguousException e )
- {
- throw new IntrospectionException( e );
- }
- }
- else
- {
- throw new IntrospectionException( "The token '" + token
- + "' refers to a java.util.Map, but the value seems is an instance of '"
- + value.getClass() + "'." );
- }
- }
- else
- {
- String methodBase = StringUtils.capitalizeFirstLetter( token );
- String methodName = "get" + methodBase;
- try
- {
- method = classMap.findMethod( methodName, CLASS_ARGS );
- }
- catch ( AmbiguousException e )
- {
- throw new IntrospectionException( e );
- }
-
- if ( method == null )
- {
- // perhaps this is a boolean property??
- methodName = "is" + methodBase;
-
- try
- {
- method = classMap.findMethod( methodName, CLASS_ARGS );
- }
- catch ( AmbiguousException e )
- {
- throw new IntrospectionException( e );
- }
- }
- }
- }
-
- if ( method == null )
- {
- return null;
- }
-
- try
- {
- value = method.invoke( value, localParams );
- }
- catch ( InvocationTargetException e )
- {
- // catch array index issues gracefully, otherwise release
- if ( e.getCause() instanceof IndexOutOfBoundsException )
- {
- return null;
- }
-
- throw new IntrospectionException( e );
- }
- catch ( IllegalArgumentException e )
- {
- throw new IntrospectionException( e );
- }
- catch ( IllegalAccessException e )
- {
- throw new IntrospectionException( e );
- }
- }
-
- return value;
}
- private static ClassMap getClassMap( Class<?> clazz )
- {
- ClassMap classMap = classMaps.get( clazz );
-
- if ( classMap == null )
- {
- classMap = new ClassMap( clazz );
+ private static ClassMap getClassMap(Class<?> clazz) {
+ ClassMap classMap = classMaps.get(clazz);
- classMaps.put( clazz, classMap );
- }
+ if (classMap == null) {
+ classMap = new ClassMap(clazz);
- return classMap;
- }
+ classMaps.put(clazz, classMap);
+ }
+
+ return classMap;
+ }
}
Modified: maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractorTest.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractorTest.java?rev=1631643&r1=1631642&r2=1631643&view=diff
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractorTest.java (original)
+++ maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractorTest.java Tue Oct 14 06:52:39 2014
@@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+
import junit.framework.Assert;
import junit.framework.TestCase;
@@ -57,6 +58,11 @@ public class ReflectionValueExtractorTes
project.addDependency( dependency1 );
project.addDependency( dependency2 );
project.setBuild( new Build() );
+
+ // Build up an artifactMap
+ project.addArtifact( new Artifact("g0","a0","v0","e0","c0") );
+ project.addArtifact( new Artifact("g1","a1","v1","e1","c1") );
+ project.addArtifact( new Artifact("g2","a2","v2","e2","c2") );
}
public void testValueExtraction()
@@ -148,6 +154,185 @@ public class ReflectionValueExtractorTes
Assert.assertNull( ReflectionValueExtractor.evaluate( "project.dependencies[0].foo", project ) );
}
+ public void testMappedDottedKey()
+ throws Exception
+ {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put( "a.b", "a.b-value" );
+
+ Assert.assertEquals( "a.b-value", ReflectionValueExtractor.evaluate("h.value(a.b)", new ValueHolder(map)) );
+ }
+
+ public void testIndexedMapped()
+ throws Exception
+ {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+ map.put( "a", "a-value" );
+ List<Object> list = new ArrayList<Object>();
+ list.add( map );
+
+ Assert.assertEquals( "a-value", ReflectionValueExtractor.evaluate("h.value[0](a)", new ValueHolder(list)) );
+ }
+
+ public void testMappedIndexed()
+ throws Exception
+ {
+ List<Object> list = new ArrayList<Object>();
+ list.add( "a-value" );
+ Map<Object, Object> map = new HashMap<Object, Object>();
+ map.put( "a", list );
+ Assert.assertEquals( "a-value", ReflectionValueExtractor.evaluate("h.value(a)[0]", new ValueHolder(map)) );
+ }
+
+ public void testMappedMissingDot()
+ throws Exception
+ {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+ map.put( "a", new ValueHolder( "a-value" ) );
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value(a)value", new ValueHolder(map)) );
+ }
+
+ public void testIndexedMissingDot()
+ throws Exception
+ {
+ List<Object> list = new ArrayList<Object>();
+ list.add( new ValueHolder( "a-value" ) );
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value[0]value", new ValueHolder(list)) );
+ }
+
+ public void testDotDot()
+ throws Exception
+ {
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h..value", new ValueHolder("value")) );
+ }
+
+ public void testBadIndexedSyntax()
+ throws Exception
+ {
+ List<Object> list = new ArrayList<Object>();
+ list.add( "a-value" );
+ Object value = new ValueHolder( list );
+
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value[", value) );
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value[]", value) );
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value[a]", value) );
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value[0", value) );
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value[0)", value) );
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value[-1]", value) );
+ }
+
+ public void testBadMappedSyntax()
+ throws Exception
+ {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+ map.put( "a", "a-value" );
+ Object value = new ValueHolder( map );
+
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value(", value) );
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value()", value) );
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value(a", value) );
+ Assert.assertNull( ReflectionValueExtractor.evaluate("h.value(a]", value) );
+ }
+
+ public void testIllegalIndexedType()
+ throws Exception
+ {
+ try
+ {
+ ReflectionValueExtractor.evaluate("h.value[1]", new ValueHolder("string"));
+ }
+ catch ( Exception e )
+ {
+ // TODO assert exception message
+ }
+ }
+
+ public void testIllegalMappedType()
+ throws Exception
+ {
+ try
+ {
+ ReflectionValueExtractor.evaluate("h.value(key)", new ValueHolder("string"));
+ }
+ catch ( Exception e )
+ {
+ // TODO assert exception message
+ }
+ }
+
+ public void testTrimRootToken()
+ throws Exception
+ {
+ Assert.assertNull( ReflectionValueExtractor.evaluate("project", project, true) );
+ }
+
+ public void testArtifactMap()
+ throws Exception
+ {
+ assertEquals( "g0", ((Artifact) ReflectionValueExtractor.evaluate("project.artifactMap(g0:a0:c0)", project)).getGroupId() );
+ assertEquals( "a1", ((Artifact) ReflectionValueExtractor.evaluate("project.artifactMap(g1:a1:c1)", project)).getArtifactId() );
+ assertEquals( "c2", ((Artifact) ReflectionValueExtractor.evaluate("project.artifactMap(g2:a2:c2)", project)).getClassifier() );
+ }
+
+ public static class Artifact
+ {
+ private String groupId;
+ private String artifactId;
+ private String version;
+ private String extension;
+ private String classifier;
+
+ public Artifact( String groupId, String artifactId, String version, String extension, String classifier )
+ {
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.version = version;
+ this.extension = extension;
+ this.classifier = classifier;
+ }
+
+ public String getGroupId()
+ {
+ return groupId;
+ }
+ public void setGroupId( String groupId )
+ {
+ this.groupId = groupId;
+ }
+ public String getArtifactId()
+ {
+ return artifactId;
+ }
+ public void setArtifactId( String artifactId )
+ {
+ this.artifactId = artifactId;
+ }
+ public String getVersion()
+ {
+ return version;
+ }
+ public void setVersion( String version )
+ {
+ this.version = version;
+ }
+ public String getExtension()
+ {
+ return extension;
+ }
+ public void setExtension( String extension )
+ {
+ this.extension = extension;
+ }
+ public String getClassifier()
+ {
+ return classifier;
+ }
+ public void setClassifier( String classifier )
+ {
+ this.classifier = classifier;
+ }
+ }
+
public static class Project
{
private String modelVersion;
@@ -166,6 +351,8 @@ public class ReflectionValueExtractorTes
private String version;
+ private Map<String,Artifact> artifactMap = new HashMap<String,Artifact>();
+
public void setModelVersion( String modelVersion )
{
this.modelVersion = modelVersion;
@@ -262,8 +449,21 @@ public class ReflectionValueExtractorTes
}
return ret;
}
+
+
+ // ${project.artifactMap(g:a:v)}
+ public void addArtifact(Artifact a)
+ {
+ artifactMap.put( a.getGroupId() + ":" + a.getArtifactId() + ":" + a.getClassifier(), a );
+ }
+
+ public Map<String,Artifact> getArtifactMap()
+ {
+ return artifactMap;
+ }
}
+
public static class Build
{
@@ -298,4 +498,19 @@ public class ReflectionValueExtractorTes
return connection;
}
}
+
+ public static class ValueHolder
+ {
+ private final Object value;
+
+ public ValueHolder( Object value )
+ {
+ this.value = value;
+ }
+
+ public Object getValue()
+ {
+ return value;
+ }
+ }
}