From 2976eff4932fafe67e76414a32119f84aab64f79 Mon Sep 17 00:00:00 2001 From: Gabriel Belingueres Date: Sat, 9 Jul 2016 17:58:19 -0300 Subject: [PATCH 1/6] Fixed MultiDelimiterStringSearchInterpolator escape String code --- ...MultiDelimiterStringSearchInterpolator.java | 5 ++++- ...iDelimiterStringSearchInterpolatorTest.java | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java b/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java index 69d979d..3351fb1 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java +++ b/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java @@ -201,13 +201,16 @@ private String interpolate( String input, RecursionInterceptor recursionIntercep if ( startIdx >= 0 && escapeString != null && escapeString.length() > 0 ) { - int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length(); + int startEscapeIdx = (startIdx == 0) ? 0 : startIdx - escapeString.length(); if ( startEscapeIdx >= 0 ) { String escape = input.substring( startEscapeIdx, startIdx ); if ( escape != null && escapeString.equals( escape ) ) { result.append( wholeExpr ); + if (startEscapeIdx > 0) { + --startEscapeIdx; + } result.replace( startEscapeIdx, startEscapeIdx + escapeString.length(), "" ); continue; } diff --git a/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java index d645785..d3994cc 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java @@ -85,4 +85,22 @@ public void testInterpolationWithMultipleEscapes() assertEquals( "#${first} and ${last}", result ); } + public void testInterpolationWithMultipleEscapes2() + throws InterpolationException + { + Map ctx = new HashMap(); + ctx.put( "name", "User" ); + ctx.put( "otherName", "#${first} and ##${last}" ); + + String input = "${otherName}"; + + ValueSource vs = new MapBasedValueSource( ctx ); + MultiDelimiterStringSearchInterpolator interpolator = new MultiDelimiterStringSearchInterpolator() + .withValueSource( vs ); + interpolator.setEscapeString("#"); + + String result = interpolator.interpolate( input ); + + assertEquals( "${first} and #${last}", result ); + } } From a3937b2e0c283ec9747ee78eeabe6af5e8bb81e0 Mon Sep 17 00:00:00 2001 From: Gabriel Belingueres Date: Sat, 9 Jul 2016 18:32:35 -0300 Subject: [PATCH 2/6] Modified ReflectionValueExtractor to a more up to date version ReflectionValueExtractor version with capacity to parse expressions with arrays, lists and maps. --- .../reflection/ReflectionValueExtractor.java | 304 +++++++++++++++--- .../StringSearchInterpolatorTest.java | 49 ++- .../FixedStringSearchInterpolatorTest.java | 50 ++- 3 files changed, 349 insertions(+), 54 deletions(-) diff --git a/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java b/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java index bca759d..dd3e2b5 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java +++ b/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java @@ -1,5 +1,13 @@ package org.codehaus.plexus.interpolation.reflection; +import java.lang.ref.WeakReference; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + /* * Copyright 2001-2006 Codehaus Foundation. * @@ -18,13 +26,6 @@ import org.codehaus.plexus.interpolation.util.StringUtils; -import java.lang.ref.SoftReference; -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.StringTokenizer; -import java.util.WeakHashMap; - /** * NOTE: This class was copied from plexus-utils, to allow this library * to stand completely self-contained. @@ -43,32 +44,142 @@ public class ReflectionValueExtractor 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. + * 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, WeakReference> classMaps = new WeakHashMap, WeakReference>(); + private static final Map, WeakReference> classMaps = + new WeakHashMap, WeakReference>(); + + 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 ) : ""; + } + } private ReflectionValueExtractor() { } + /** + *

+ * The implementation supports indexed, nested and mapped properties. + *

+ *
    + *
  • nested properties should be defined by a dot, i.e. "user.address.street"
  • + *
  • indexed properties (java.util.List or array instance) should be contains (\\w+)\\[(\\d+)\\] + * pattern, i.e. "user.addresses[1].street"
  • + *
  • mapped properties should be contains (\\w+)\\((.+)\\) pattern, i.e. + * "user.addresses(myAddress).street"
  • + *
      + * + * @param expression not null expression + * @param root not null object + * @return the object defined by the expression + * @throws Exception if any + */ public static Object evaluate( String expression, Object root ) throws Exception { return evaluate( expression, root, true ); } + /** + *

      + * The implementation supports indexed, nested and mapped properties. + *

      + *
        + *
      • nested properties should be defined by a dot, i.e. "user.address.street"
      • + *
      • indexed properties (java.util.List or array instance) should be contains (\\w+)\\[(\\d+)\\] + * pattern, i.e. "user.addresses[1].street"
      • + *
      • mapped properties should be contains (\\w+)\\((.+)\\) pattern, i.e. + * "user.addresses(myAddress).street"
      • + *
          + * + * @param expression not null expression + * @param root not null object + * @return the object defined by the expression + * @throws Exception if any + */ // TODO: don't throw Exception - public static Object evaluate( String expression, Object root, boolean trimRootToken ) + public static Object evaluate( String expression, final Object root, final boolean trimRootToken ) throws Exception { - // if the root token refers to the supplied root object parameter, remove it. - if ( trimRootToken ) - { - expression = expression.substring( expression.indexOf( '.' ) + 1 ); - } - Object value = root; // ---------------------------------------------------------------------- @@ -76,57 +187,174 @@ public static Object evaluate( String expression, Object root, boolean trimRootT // MavenProject instance. // ---------------------------------------------------------------------- - StringTokenizer parser = new StringTokenizer( expression, "." ); - - while ( parser.hasMoreTokens() ) + if ( expression == null || "".equals(expression.trim()) || !Character.isJavaIdentifierStart( expression.charAt( 0 ) ) ) { - String token = parser.nextToken(); + return null; + } - if ( value == null ) + boolean hasDots = expression.indexOf( PROPERTY_START ) >= 0; + + final Tokenizer tokenizer; + if ( trimRootToken && hasDots ) + { + 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 Exception + { + if ( value == null || key == null ) + { + return null; + } + + if ( value instanceof Map ) + { + Object[] localParams = new Object[] { key }; ClassMap classMap = getClassMap( value.getClass() ); + Method method = classMap.findMethod( "get", localParams ); + return method.invoke( value, localParams ); + } - String methodBase = StringUtils.capitalizeFirstLetter( token ); + 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() ); - String methodName = "get" + methodBase; + throw new Exception( message ); + } - Method method = classMap.findMethod( methodName, CLASS_ARGS ); + private static Object getIndexedValue( final String expression, final int from, final int to, final Object value, + final String indexStr ) + throws Exception + { + try + { + int index = Integer.parseInt( indexStr ); - if ( method == null ) + if ( value.getClass().isArray() ) { - // perhaps this is a boolean property?? - methodName = "is" + methodBase; - - method = classMap.findMethod( methodName, CLASS_ARGS ); + return Array.get( value, index ); } - if ( method == null ) + if ( value instanceof List ) + { + ClassMap classMap = getClassMap( value.getClass() ); + // use get method on List interface + Object[] localParams = new Object[] { index }; + Method method = classMap.findMethod( "get", localParams ); + return method.invoke( value, localParams ); + } + } + catch ( NumberFormatException e ) + { + return null; + } + catch ( InvocationTargetException e ) + { + // catch array index issues gracefully, otherwise release + if ( e.getCause() instanceof IndexOutOfBoundsException ) { return null; } - value = method.invoke( value, OBJECT_ARGS ); + throw e; } - return value; + 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 Exception( message ); + } + + private static Object getPropertyValue( Object value, String property ) + throws Exception + { + if ( value == null || property == null ) + { + return null; + } + + ClassMap classMap = getClassMap( value.getClass() ); + String methodBase = StringUtils.capitalizeFirstLetter( property ); + String methodName = "get" + methodBase; + 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; + } + + try + { + return method.invoke( value, OBJECT_ARGS ); + } + catch ( InvocationTargetException e ) + { + throw e; + } } private static ClassMap getClassMap( Class clazz ) { - WeakReference ref = classMaps.get( clazz); + + WeakReference softRef = classMaps.get( clazz ); ClassMap classMap; - if ( ref == null || (classMap = ref.get()) == null ) + if ( softRef == null || ( classMap = softRef.get() ) == null ) { classMap = new ClassMap( clazz ); - classMaps.put( clazz, new WeakReference(classMap) ); + classMaps.put( clazz, new WeakReference( classMap ) ); } return classMap; } -} +} \ No newline at end of file diff --git a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java index 79312cf..c4b84a0 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java @@ -17,6 +17,7 @@ */ import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -147,15 +148,15 @@ public void testShouldFailOnExpressionCycle() } } - public void testShouldResolveByMy_getVar_Method() - throws InterpolationException - { - StringSearchInterpolator rbi = new StringSearchInterpolator(); - rbi.addValueSource( new ObjectBasedValueSource( this ) ); - String result = rbi.interpolate( "this is a ${var}" ); + public void testShouldResolveByUsingObject_List_Map() + throws InterpolationException + { + StringSearchInterpolator rbi = new StringSearchInterpolator(); + rbi.addValueSource( new ObjectBasedValueSource( this ) ); + String result = rbi.interpolate( "this is a ${var} ${list[1].name} ${anArray[2].name} ${map(Key with spaces).name}" ); - assertEquals( "this is a testVar", result ); - } + assertEquals( "this is a testVar testIndexedWithList testIndexedWithArray testMap", result ); + } public void testShouldResolveByContextValue() throws InterpolationException @@ -429,4 +430,36 @@ public String getVar() return "testVar"; } + public Person[] getAnArray() { + Person[] array = new Person[3]; + array[0] = new Person("Gabriel"); + array[1] = new Person("Daniela"); + array[2] = new Person("testIndexedWithArray"); + return array; + } + + public List getList() { + List list = new ArrayList(); + list.add(new Person("Gabriel")); + list.add(new Person("testIndexedWithList")); + list.add(new Person("Daniela")); + return list; + } + + public Map getMap() { + Map map = new HashMap(); + map.put("Key with spaces", new Person("testMap")); + return map; + } + + public static class Person { + private String name; + public Person(String name) { + this.name = name; + } + public String getName() { + return name; + } + } + } diff --git a/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java index 074faaf..8bff5d7 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java @@ -22,7 +22,9 @@ import org.junit.Test; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Properties; @@ -148,15 +150,15 @@ public void testShouldFailOnExpressionCycle() } @Test - public void testShouldResolveByMy_getVar_Method() - throws InterpolationException - { - FixedStringSearchInterpolator rbi = create( new ObjectBasedValueSource( this ) ); - String result = rbi.interpolate( "this is a ${var}" ); - - assertEquals( "this is a testVar", result ); - } + public void testShouldResolveByUsingObject_List_Map() + throws InterpolationException + { + FixedStringSearchInterpolator rbi = create( new ObjectBasedValueSource( this ) ); + String result = rbi.interpolate( "this is a ${var} ${list[1].name} ${anArray[2].name} ${map(Key with spaces).name}" ); + assertEquals( "this is a testVar testIndexedWithList testIndexedWithArray testMap", result ); + } + @Test public void testShouldResolveByContextValue() throws InterpolationException @@ -424,6 +426,38 @@ public String getVar() return "testVar"; } + public Person[] getAnArray() { + Person[] array = new Person[3]; + array[0] = new Person("Gabriel"); + array[1] = new Person("Daniela"); + array[2] = new Person("testIndexedWithArray"); + return array; + } + + public List getList() { + List list = new ArrayList(); + list.add(new Person("Gabriel")); + list.add(new Person("testIndexedWithList")); + list.add(new Person("Daniela")); + return list; + } + + public Map getMap() { + Map map = new HashMap(); + map.put("Key with spaces", new Person("testMap")); + return map; + } + + public static class Person { + private String name; + public Person(String name) { + this.name = name; + } + public String getName() { + return name; + } + } + @Test public void testLinkedInterpolators() { From 4d088ded0160cfed01558f3616c16d7b26f33dbc Mon Sep 17 00:00:00 2001 From: belingueres Date: Fri, 12 Aug 2016 19:45:11 -0300 Subject: [PATCH 3/6] Commit to undo the changes I've made since forked the original project. The reason is that I've made a mistake and created a unique PR to solve several issues, which is a bad practice. --- ...ultiDelimiterStringSearchInterpolator.java | 5 +- .../reflection/ReflectionValueExtractor.java | 304 +++--------------- .../StringSearchInterpolatorTest.java | 49 +-- .../FixedStringSearchInterpolatorTest.java | 50 +-- ...DelimiterStringSearchInterpolatorTest.java | 18 -- 5 files changed, 55 insertions(+), 371 deletions(-) diff --git a/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java b/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java index 3351fb1..69d979d 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java +++ b/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java @@ -201,16 +201,13 @@ private String interpolate( String input, RecursionInterceptor recursionIntercep if ( startIdx >= 0 && escapeString != null && escapeString.length() > 0 ) { - int startEscapeIdx = (startIdx == 0) ? 0 : startIdx - escapeString.length(); + int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length(); if ( startEscapeIdx >= 0 ) { String escape = input.substring( startEscapeIdx, startIdx ); if ( escape != null && escapeString.equals( escape ) ) { result.append( wholeExpr ); - if (startEscapeIdx > 0) { - --startEscapeIdx; - } result.replace( startEscapeIdx, startEscapeIdx + escapeString.length(), "" ); continue; } diff --git a/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java b/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java index dd3e2b5..bca759d 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java +++ b/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java @@ -1,13 +1,5 @@ package org.codehaus.plexus.interpolation.reflection; -import java.lang.ref.WeakReference; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; - /* * Copyright 2001-2006 Codehaus Foundation. * @@ -26,6 +18,13 @@ import org.codehaus.plexus.interpolation.util.StringUtils; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.WeakHashMap; + /** * NOTE: This class was copied from plexus-utils, to allow this library * to stand completely self-contained. @@ -44,142 +43,32 @@ public class ReflectionValueExtractor 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. + * 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, WeakReference> classMaps = - new WeakHashMap, WeakReference>(); - - 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 ) : ""; - } - } + private static final Map, WeakReference> classMaps = new WeakHashMap, WeakReference>(); private ReflectionValueExtractor() { } - /** - *

          - * The implementation supports indexed, nested and mapped properties. - *

          - *
            - *
          • nested properties should be defined by a dot, i.e. "user.address.street"
          • - *
          • indexed properties (java.util.List or array instance) should be contains (\\w+)\\[(\\d+)\\] - * pattern, i.e. "user.addresses[1].street"
          • - *
          • mapped properties should be contains (\\w+)\\((.+)\\) pattern, i.e. - * "user.addresses(myAddress).street"
          • - *
              - * - * @param expression not null expression - * @param root not null object - * @return the object defined by the expression - * @throws Exception if any - */ public static Object evaluate( String expression, Object root ) throws Exception { return evaluate( expression, root, true ); } - /** - *

              - * The implementation supports indexed, nested and mapped properties. - *

              - *
                - *
              • nested properties should be defined by a dot, i.e. "user.address.street"
              • - *
              • indexed properties (java.util.List or array instance) should be contains (\\w+)\\[(\\d+)\\] - * pattern, i.e. "user.addresses[1].street"
              • - *
              • mapped properties should be contains (\\w+)\\((.+)\\) pattern, i.e. - * "user.addresses(myAddress).street"
              • - *
                  - * - * @param expression not null expression - * @param root not null object - * @return the object defined by the expression - * @throws Exception if any - */ // TODO: don't throw Exception - public static Object evaluate( String expression, final Object root, final boolean trimRootToken ) + public static Object evaluate( String expression, Object root, boolean trimRootToken ) throws Exception { + // if the root token refers to the supplied root object parameter, remove it. + if ( trimRootToken ) + { + expression = expression.substring( expression.indexOf( '.' ) + 1 ); + } + Object value = root; // ---------------------------------------------------------------------- @@ -187,174 +76,57 @@ public static Object evaluate( String expression, final Object root, final bool // MavenProject instance. // ---------------------------------------------------------------------- - if ( expression == null || "".equals(expression.trim()) || !Character.isJavaIdentifierStart( expression.charAt( 0 ) ) ) - { - return null; - } + StringTokenizer parser = new StringTokenizer( expression, "." ); - boolean hasDots = expression.indexOf( PROPERTY_START ) >= 0; - - final Tokenizer tokenizer; - if ( trimRootToken && hasDots ) + while ( parser.hasMoreTokens() ) { - tokenizer = new Tokenizer( expression ); - tokenizer.nextPropertyName(); - if ( tokenizer.getPosition() == EOF ) - { - return null; - } - } - else - { - tokenizer = new Tokenizer( "." + expression ); - } + String token = parser.nextToken(); - int propertyPosition = tokenizer.getPosition(); - while ( value != null && tokenizer.peekChar() != EOF ) - { - switch ( tokenizer.skipChar() ) + if ( value == null ) { - 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 null; } - } - - return value; - } - private static Object getMappedValue( final String expression, final int from, final int to, final Object value, - final String key ) - throws Exception - { - if ( value == null || key == null ) - { - return null; - } - - if ( value instanceof Map ) - { - Object[] localParams = new Object[] { key }; ClassMap classMap = getClassMap( value.getClass() ); - Method method = classMap.findMethod( "get", localParams ); - return method.invoke( value, localParams ); - } - 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() ); + String methodBase = StringUtils.capitalizeFirstLetter( token ); - throw new Exception( message ); - } + String methodName = "get" + methodBase; - private static Object getIndexedValue( final String expression, final int from, final int to, final Object value, - final String indexStr ) - throws Exception - { - try - { - int index = Integer.parseInt( indexStr ); + Method method = classMap.findMethod( methodName, CLASS_ARGS ); - if ( value.getClass().isArray() ) + if ( method == null ) { - return Array.get( value, index ); - } + // perhaps this is a boolean property?? + methodName = "is" + methodBase; - if ( value instanceof List ) - { - ClassMap classMap = getClassMap( value.getClass() ); - // use get method on List interface - Object[] localParams = new Object[] { index }; - Method method = classMap.findMethod( "get", localParams ); - return method.invoke( value, localParams ); + method = classMap.findMethod( methodName, CLASS_ARGS ); } - } - catch ( NumberFormatException e ) - { - return null; - } - catch ( InvocationTargetException e ) - { - // catch array index issues gracefully, otherwise release - if ( e.getCause() instanceof IndexOutOfBoundsException ) + + if ( method == null ) { return null; } - throw e; - } - - 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 Exception( message ); - } - - private static Object getPropertyValue( Object value, String property ) - throws Exception - { - if ( value == null || property == null ) - { - return null; + value = method.invoke( value, OBJECT_ARGS ); } - ClassMap classMap = getClassMap( value.getClass() ); - String methodBase = StringUtils.capitalizeFirstLetter( property ); - String methodName = "get" + methodBase; - 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; - } - - try - { - return method.invoke( value, OBJECT_ARGS ); - } - catch ( InvocationTargetException e ) - { - throw e; - } + return value; } private static ClassMap getClassMap( Class clazz ) { - - WeakReference softRef = classMaps.get( clazz ); + WeakReference ref = classMaps.get( clazz); ClassMap classMap; - if ( softRef == null || ( classMap = softRef.get() ) == null ) + if ( ref == null || (classMap = ref.get()) == null ) { classMap = new ClassMap( clazz ); - classMaps.put( clazz, new WeakReference( classMap ) ); + classMaps.put( clazz, new WeakReference(classMap) ); } return classMap; } -} \ No newline at end of file +} diff --git a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java index c4b84a0..79312cf 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java @@ -17,7 +17,6 @@ */ import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -148,15 +147,15 @@ public void testShouldFailOnExpressionCycle() } } - public void testShouldResolveByUsingObject_List_Map() - throws InterpolationException - { - StringSearchInterpolator rbi = new StringSearchInterpolator(); - rbi.addValueSource( new ObjectBasedValueSource( this ) ); - String result = rbi.interpolate( "this is a ${var} ${list[1].name} ${anArray[2].name} ${map(Key with spaces).name}" ); + public void testShouldResolveByMy_getVar_Method() + throws InterpolationException + { + StringSearchInterpolator rbi = new StringSearchInterpolator(); + rbi.addValueSource( new ObjectBasedValueSource( this ) ); + String result = rbi.interpolate( "this is a ${var}" ); - assertEquals( "this is a testVar testIndexedWithList testIndexedWithArray testMap", result ); - } + assertEquals( "this is a testVar", result ); + } public void testShouldResolveByContextValue() throws InterpolationException @@ -430,36 +429,4 @@ public String getVar() return "testVar"; } - public Person[] getAnArray() { - Person[] array = new Person[3]; - array[0] = new Person("Gabriel"); - array[1] = new Person("Daniela"); - array[2] = new Person("testIndexedWithArray"); - return array; - } - - public List getList() { - List list = new ArrayList(); - list.add(new Person("Gabriel")); - list.add(new Person("testIndexedWithList")); - list.add(new Person("Daniela")); - return list; - } - - public Map getMap() { - Map map = new HashMap(); - map.put("Key with spaces", new Person("testMap")); - return map; - } - - public static class Person { - private String name; - public Person(String name) { - this.name = name; - } - public String getName() { - return name; - } - } - } diff --git a/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java index 8bff5d7..074faaf 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java @@ -22,9 +22,7 @@ import org.junit.Test; import java.io.IOException; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Properties; @@ -150,15 +148,15 @@ public void testShouldFailOnExpressionCycle() } @Test - public void testShouldResolveByUsingObject_List_Map() - throws InterpolationException - { - FixedStringSearchInterpolator rbi = create( new ObjectBasedValueSource( this ) ); - String result = rbi.interpolate( "this is a ${var} ${list[1].name} ${anArray[2].name} ${map(Key with spaces).name}" ); + public void testShouldResolveByMy_getVar_Method() + throws InterpolationException + { + FixedStringSearchInterpolator rbi = create( new ObjectBasedValueSource( this ) ); + String result = rbi.interpolate( "this is a ${var}" ); + + assertEquals( "this is a testVar", result ); + } - assertEquals( "this is a testVar testIndexedWithList testIndexedWithArray testMap", result ); - } - @Test public void testShouldResolveByContextValue() throws InterpolationException @@ -426,38 +424,6 @@ public String getVar() return "testVar"; } - public Person[] getAnArray() { - Person[] array = new Person[3]; - array[0] = new Person("Gabriel"); - array[1] = new Person("Daniela"); - array[2] = new Person("testIndexedWithArray"); - return array; - } - - public List getList() { - List list = new ArrayList(); - list.add(new Person("Gabriel")); - list.add(new Person("testIndexedWithList")); - list.add(new Person("Daniela")); - return list; - } - - public Map getMap() { - Map map = new HashMap(); - map.put("Key with spaces", new Person("testMap")); - return map; - } - - public static class Person { - private String name; - public Person(String name) { - this.name = name; - } - public String getName() { - return name; - } - } - @Test public void testLinkedInterpolators() { diff --git a/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java index d3994cc..d645785 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java @@ -85,22 +85,4 @@ public void testInterpolationWithMultipleEscapes() assertEquals( "#${first} and ${last}", result ); } - public void testInterpolationWithMultipleEscapes2() - throws InterpolationException - { - Map ctx = new HashMap(); - ctx.put( "name", "User" ); - ctx.put( "otherName", "#${first} and ##${last}" ); - - String input = "${otherName}"; - - ValueSource vs = new MapBasedValueSource( ctx ); - MultiDelimiterStringSearchInterpolator interpolator = new MultiDelimiterStringSearchInterpolator() - .withValueSource( vs ); - interpolator.setEscapeString("#"); - - String result = interpolator.interpolate( input ); - - assertEquals( "${first} and #${last}", result ); - } } From 0af4e032c1ff3b03341a62dd8d5009f7f34401c6 Mon Sep 17 00:00:00 2001 From: belingueres Date: Sat, 20 Aug 2016 23:36:07 -0300 Subject: [PATCH 4/6] Fix #10 - RegexBasedInterpolatorTest fails when building with maven 3.4.0-SNAPSHOT Tests fails because the $HOME env var is no longer defined inside mvn.cmd and is not found (some tests pass even if the env var is not found!). - Changed the OperatingSystemUtils to allow mocking the Map of env vars. - Fixed tests to use mocking whenever the env vars are not the focus of the unit test. - When testing with a REAL env var, it is chosen to be $JAVA_HOME since it is required to be present to run mvn script. - Added tests to EnvarBasedValueSource and fixed.EnvarBasedValueSource. --- .../interpolation/EnvarBasedValueSource.java | 9 ++ .../fixed/EnvarBasedValueSource.java | 9 ++ .../os/OperatingSystemUtils.java | 44 ++++++++- .../EnvarBasedValueSourceTest.java | 97 ++++++++++++++++++ .../RegexBasedInterpolatorTest.java | 24 ++++- .../StringSearchInterpolatorTest.java | 25 ++++- .../fixed/EnvarBasedValueSourceTest.java | 98 +++++++++++++++++++ .../FixedStringSearchInterpolatorTest.java | 24 ++++- 8 files changed, 319 insertions(+), 11 deletions(-) create mode 100644 src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java create mode 100644 src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java diff --git a/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java b/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java index 3e10856..6f7df79 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java +++ b/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java @@ -110,5 +110,14 @@ public Object getValue( String expression ) return envars.getProperty( expr ); } + + /** + * reset static variables acting as a cache for testing purposes only + */ + static void resetStatics() + { + envarsCaseSensitive = null; + envarsCaseInsensitive = null; + } } diff --git a/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java b/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java index 3e1f4ef..067ac31 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java +++ b/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java @@ -110,4 +110,13 @@ public Object getValue( String expression, InterpolationState interpolationState return envars.getProperty( expr ); } + /** + * reset static variables acting as a cache for testing purposes only + */ + static void resetStatics() + { + envarsCaseSensitive = null; + envarsCaseInsensitive = null; + } + } diff --git a/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java b/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java index 28756e0..d18a914 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java +++ b/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java @@ -39,6 +39,8 @@ public final class OperatingSystemUtils { + private static EnvVarSource envVarSource = new DefaultEnvVarSource(); + private OperatingSystemUtils() { } @@ -62,11 +64,11 @@ public static Properties getSystemEnvVars( boolean caseSensitive ) throws IOException { Properties envVars = new Properties(); - Map envs = System.getenv(); + Map envs = envVarSource.getEnvMap(); for ( String key : envs.keySet() ) { String value = envs.get( key ); - if ( !caseSensitive) + if ( !caseSensitive ) { key = key.toUpperCase( Locale.ENGLISH ); } @@ -74,4 +76,42 @@ public static Properties getSystemEnvVars( boolean caseSensitive ) } return envVars; } + + /** + * Set the source object to load the environment variables from. + * Default implementation should suffice. This is mostly for testing. + * @param source the EnvVarSource instance that loads the environment variables. + * + * @since 3.1.2 + */ + public static void setEnvVarSource( EnvVarSource source ) + { + envVarSource = source; + } + + /** + * Defines the functionality to load a Map of environment variables. + * + * @since 3.1.2 + */ + public interface EnvVarSource + { + public Map getEnvMap(); + } + + /** + * Default implementation to load environment variables. + * + * @since 3.1.2 + */ + public static class DefaultEnvVarSource + implements EnvVarSource + { + + public Map getEnvMap() + { + return System.getenv(); + } + + } } diff --git a/src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java b/src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java new file mode 100644 index 0000000..32bd18a --- /dev/null +++ b/src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java @@ -0,0 +1,97 @@ +package org.codehaus.plexus.interpolation; + +/* + * Copyright 2007 The Codehaus Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; +import org.junit.Test; + +public class EnvarBasedValueSourceTest +{ + + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + + @Test + public void testNoArgConstructorIsCaseSensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + assertEquals( "variable", source.getValue( "aVariable" ) ); + assertEquals( "variable", source.getValue( "env.aVariable" ) ); + assertNull( source.getValue( "AVARIABLE" ) ); + assertNull( source.getValue( "env.AVARIABLE" ) ); + } + + @Test + public void testCaseInsensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource( false ); + + assertEquals( "variable", source.getValue( "aVariable" ) ); + assertEquals( "variable", source.getValue( "env.aVariable" ) ); + assertEquals( "variable", source.getValue( "AVARIABLE" ) ); + assertEquals( "variable", source.getValue( "env.AVARIABLE" ) ); + } + + @Test + public void testGetRealEnvironmentVariable() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.DefaultEnvVarSource() ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + String realEnvVar = "JAVA_HOME"; + + String realValue = System.getenv().get( realEnvVar ); + assertNotNull( "Can't run this test until " + realEnvVar + " env variable is set", realValue ); + + assertEquals( realValue, source.getValue( realEnvVar ) ); + } +} diff --git a/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java index 0597564..dcd97d0 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java @@ -21,12 +21,21 @@ import java.util.Map; import java.util.Properties; +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; + import junit.framework.TestCase; public class RegexBasedInterpolatorTest extends TestCase { + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + public String getVar() { return "testVar"; @@ -81,14 +90,23 @@ public void testShouldResolveByContextValue() public void testShouldResolveByEnvar() throws IOException, InterpolationException { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "SOME_ENV", "variable" ); + return map; + } + } ); + RegexBasedInterpolator rbi = new RegexBasedInterpolator(); rbi.addValueSource( new EnvarBasedValueSource() ); - String result = rbi.interpolate( "this is a ${env.HOME}", "this" ); + String result = rbi.interpolate( "this is a ${env.SOME_ENV}", "this" ); - assertFalse( "this is a ${HOME}".equals( result ) ); - assertFalse( "this is a ${env.HOME}".equals( result ) ); + assertEquals( "this is a variable", result ); } public void testUseAlternateRegex() diff --git a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java index 79312cf..aa88dc6 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java @@ -23,12 +23,21 @@ import java.util.Map; import java.util.Properties; +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; + import junit.framework.TestCase; public class StringSearchInterpolatorTest extends TestCase { + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + public void testLongDelimitersInContext() throws InterpolationException { @@ -175,14 +184,24 @@ public void testShouldResolveByContextValue() public void testShouldResolveByEnvar() throws IOException, InterpolationException { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "SOME_ENV", "variable" ); + map.put( "OTHER_ENV", "other variable" ); + return map; + } + } ); + StringSearchInterpolator rbi = new StringSearchInterpolator(); rbi.addValueSource( new EnvarBasedValueSource( false ) ); - String result = rbi.interpolate( "this is a ${env.HOME} ${env.PATH}" ); + String result = rbi.interpolate( "this is a ${env.SOME_ENV} ${env.OTHER_ENV}" ); - assertFalse( "this is a ${HOME} ${PATH}".equals( result ) ); - assertFalse( "this is a ${env.HOME} ${env.PATH}".equals( result ) ); + assertEquals( "this is a variable other variable", result ); } public void testUsePostProcessor_DoesNotChangeValue() diff --git a/src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java b/src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java new file mode 100644 index 0000000..624c07e --- /dev/null +++ b/src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java @@ -0,0 +1,98 @@ +package org.codehaus.plexus.interpolation.fixed; + +/* + * Copyright 2007 The Codehaus Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; +import org.junit.Test; + +public class EnvarBasedValueSourceTest +{ + + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + + @Test + public void testNoArgConstructorIsCaseSensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + assertEquals( "variable", source.getValue( "aVariable", null ) ); + assertEquals( "variable", source.getValue( "env.aVariable", null ) ); + assertNull( source.getValue( "AVARIABLE", null ) ); + assertNull( source.getValue( "env.AVARIABLE", null ) ); + } + + @Test + public void testCaseInsensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource( false ); + + assertEquals( "variable", source.getValue( "aVariable", null ) ); + assertEquals( "variable", source.getValue( "env.aVariable", null ) ); + assertEquals( "variable", source.getValue( "AVARIABLE", null ) ); + assertEquals( "variable", source.getValue( "env.AVARIABLE", null ) ); + } + + @Test + public void testGetRealEnvironmentVariable() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.DefaultEnvVarSource() ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + String realEnvVar = "JAVA_HOME"; + + String realValue = System.getenv().get( realEnvVar ); + assertNotNull( "Can't run this test until " + realEnvVar + " env variable is set", realValue ); + + assertEquals( realValue, source.getValue( realEnvVar, null ) ); + } + +} diff --git a/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java index 074faaf..1bbc7ec 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java @@ -19,6 +19,8 @@ import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.InterpolationPostProcessor; import org.codehaus.plexus.interpolation.StringSearchInterpolator; +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; import org.junit.Test; import java.io.IOException; @@ -32,6 +34,12 @@ public class FixedStringSearchInterpolatorTest { + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + @Test public void testLongDelimitersInContext() { @@ -176,12 +184,22 @@ public void testShouldResolveByContextValue() public void testShouldResolveByEnvar() throws IOException, InterpolationException { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "SOME_ENV", "variable" ); + map.put( "OTHER_ENV", "other variable" ); + return map; + } + } ); + FixedStringSearchInterpolator rbi = create( new EnvarBasedValueSource( false ) ); - String result = rbi.interpolate( "this is a ${env.HOME} ${env.PATH}" ); + String result = rbi.interpolate( "this is a ${env.SOME_ENV} ${env.OTHER_ENV}" ); - assertFalse( "this is a ${HOME} ${PATH}".equals( result ) ); - assertFalse( "this is a ${env.HOME} ${env.PATH}".equals( result ) ); + assertEquals( "this is a variable other variable", result ); } @Test From 2307195685c0ab1ff53627391466e28de0c89f8f Mon Sep 17 00:00:00 2001 From: belingueres Date: Sat, 20 Aug 2016 23:36:07 -0300 Subject: [PATCH 5/6] Fix #10 - RegexBasedInterpolatorTest fails when building with maven 3.4.0-SNAPSHOT Tests fails because the $HOME env var is no longer defined inside mvn.cmd and is not found (some tests pass even if the env var is not found!). - Changed the OperatingSystemUtils to allow mocking the Map of env vars. - Fixed tests to use mocking whenever the env vars are not the focus of the unit test. - When testing with a REAL env var, it is chosen to be $JAVA_HOME since it is required to be present to run mvn script. - Added tests to EnvarBasedValueSource and fixed.EnvarBasedValueSource. --- .../interpolation/EnvarBasedValueSource.java | 9 ++ .../fixed/EnvarBasedValueSource.java | 9 ++ .../os/OperatingSystemUtils.java | 44 ++++++++- .../EnvarBasedValueSourceTest.java | 97 ++++++++++++++++++ .../RegexBasedInterpolatorTest.java | 24 ++++- .../StringSearchInterpolatorTest.java | 25 ++++- .../fixed/EnvarBasedValueSourceTest.java | 98 +++++++++++++++++++ .../FixedStringSearchInterpolatorTest.java | 24 ++++- 8 files changed, 319 insertions(+), 11 deletions(-) create mode 100644 src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java create mode 100644 src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java diff --git a/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java b/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java index 3e10856..6f7df79 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java +++ b/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java @@ -110,5 +110,14 @@ public Object getValue( String expression ) return envars.getProperty( expr ); } + + /** + * reset static variables acting as a cache for testing purposes only + */ + static void resetStatics() + { + envarsCaseSensitive = null; + envarsCaseInsensitive = null; + } } diff --git a/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java b/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java index 3e1f4ef..067ac31 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java +++ b/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java @@ -110,4 +110,13 @@ public Object getValue( String expression, InterpolationState interpolationState return envars.getProperty( expr ); } + /** + * reset static variables acting as a cache for testing purposes only + */ + static void resetStatics() + { + envarsCaseSensitive = null; + envarsCaseInsensitive = null; + } + } diff --git a/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java b/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java index 28756e0..d18a914 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java +++ b/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java @@ -39,6 +39,8 @@ public final class OperatingSystemUtils { + private static EnvVarSource envVarSource = new DefaultEnvVarSource(); + private OperatingSystemUtils() { } @@ -62,11 +64,11 @@ public static Properties getSystemEnvVars( boolean caseSensitive ) throws IOException { Properties envVars = new Properties(); - Map envs = System.getenv(); + Map envs = envVarSource.getEnvMap(); for ( String key : envs.keySet() ) { String value = envs.get( key ); - if ( !caseSensitive) + if ( !caseSensitive ) { key = key.toUpperCase( Locale.ENGLISH ); } @@ -74,4 +76,42 @@ public static Properties getSystemEnvVars( boolean caseSensitive ) } return envVars; } + + /** + * Set the source object to load the environment variables from. + * Default implementation should suffice. This is mostly for testing. + * @param source the EnvVarSource instance that loads the environment variables. + * + * @since 3.1.2 + */ + public static void setEnvVarSource( EnvVarSource source ) + { + envVarSource = source; + } + + /** + * Defines the functionality to load a Map of environment variables. + * + * @since 3.1.2 + */ + public interface EnvVarSource + { + public Map getEnvMap(); + } + + /** + * Default implementation to load environment variables. + * + * @since 3.1.2 + */ + public static class DefaultEnvVarSource + implements EnvVarSource + { + + public Map getEnvMap() + { + return System.getenv(); + } + + } } diff --git a/src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java b/src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java new file mode 100644 index 0000000..32bd18a --- /dev/null +++ b/src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java @@ -0,0 +1,97 @@ +package org.codehaus.plexus.interpolation; + +/* + * Copyright 2007 The Codehaus Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; +import org.junit.Test; + +public class EnvarBasedValueSourceTest +{ + + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + + @Test + public void testNoArgConstructorIsCaseSensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + assertEquals( "variable", source.getValue( "aVariable" ) ); + assertEquals( "variable", source.getValue( "env.aVariable" ) ); + assertNull( source.getValue( "AVARIABLE" ) ); + assertNull( source.getValue( "env.AVARIABLE" ) ); + } + + @Test + public void testCaseInsensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource( false ); + + assertEquals( "variable", source.getValue( "aVariable" ) ); + assertEquals( "variable", source.getValue( "env.aVariable" ) ); + assertEquals( "variable", source.getValue( "AVARIABLE" ) ); + assertEquals( "variable", source.getValue( "env.AVARIABLE" ) ); + } + + @Test + public void testGetRealEnvironmentVariable() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.DefaultEnvVarSource() ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + String realEnvVar = "JAVA_HOME"; + + String realValue = System.getenv().get( realEnvVar ); + assertNotNull( "Can't run this test until " + realEnvVar + " env variable is set", realValue ); + + assertEquals( realValue, source.getValue( realEnvVar ) ); + } +} diff --git a/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java index 0597564..dcd97d0 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java @@ -21,12 +21,21 @@ import java.util.Map; import java.util.Properties; +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; + import junit.framework.TestCase; public class RegexBasedInterpolatorTest extends TestCase { + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + public String getVar() { return "testVar"; @@ -81,14 +90,23 @@ public void testShouldResolveByContextValue() public void testShouldResolveByEnvar() throws IOException, InterpolationException { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "SOME_ENV", "variable" ); + return map; + } + } ); + RegexBasedInterpolator rbi = new RegexBasedInterpolator(); rbi.addValueSource( new EnvarBasedValueSource() ); - String result = rbi.interpolate( "this is a ${env.HOME}", "this" ); + String result = rbi.interpolate( "this is a ${env.SOME_ENV}", "this" ); - assertFalse( "this is a ${HOME}".equals( result ) ); - assertFalse( "this is a ${env.HOME}".equals( result ) ); + assertEquals( "this is a variable", result ); } public void testUseAlternateRegex() diff --git a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java index 79312cf..aa88dc6 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java @@ -23,12 +23,21 @@ import java.util.Map; import java.util.Properties; +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; + import junit.framework.TestCase; public class StringSearchInterpolatorTest extends TestCase { + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + public void testLongDelimitersInContext() throws InterpolationException { @@ -175,14 +184,24 @@ public void testShouldResolveByContextValue() public void testShouldResolveByEnvar() throws IOException, InterpolationException { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "SOME_ENV", "variable" ); + map.put( "OTHER_ENV", "other variable" ); + return map; + } + } ); + StringSearchInterpolator rbi = new StringSearchInterpolator(); rbi.addValueSource( new EnvarBasedValueSource( false ) ); - String result = rbi.interpolate( "this is a ${env.HOME} ${env.PATH}" ); + String result = rbi.interpolate( "this is a ${env.SOME_ENV} ${env.OTHER_ENV}" ); - assertFalse( "this is a ${HOME} ${PATH}".equals( result ) ); - assertFalse( "this is a ${env.HOME} ${env.PATH}".equals( result ) ); + assertEquals( "this is a variable other variable", result ); } public void testUsePostProcessor_DoesNotChangeValue() diff --git a/src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java b/src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java new file mode 100644 index 0000000..624c07e --- /dev/null +++ b/src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java @@ -0,0 +1,98 @@ +package org.codehaus.plexus.interpolation.fixed; + +/* + * Copyright 2007 The Codehaus Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; +import org.junit.Test; + +public class EnvarBasedValueSourceTest +{ + + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + + @Test + public void testNoArgConstructorIsCaseSensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + assertEquals( "variable", source.getValue( "aVariable", null ) ); + assertEquals( "variable", source.getValue( "env.aVariable", null ) ); + assertNull( source.getValue( "AVARIABLE", null ) ); + assertNull( source.getValue( "env.AVARIABLE", null ) ); + } + + @Test + public void testCaseInsensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource( false ); + + assertEquals( "variable", source.getValue( "aVariable", null ) ); + assertEquals( "variable", source.getValue( "env.aVariable", null ) ); + assertEquals( "variable", source.getValue( "AVARIABLE", null ) ); + assertEquals( "variable", source.getValue( "env.AVARIABLE", null ) ); + } + + @Test + public void testGetRealEnvironmentVariable() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.DefaultEnvVarSource() ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + String realEnvVar = "JAVA_HOME"; + + String realValue = System.getenv().get( realEnvVar ); + assertNotNull( "Can't run this test until " + realEnvVar + " env variable is set", realValue ); + + assertEquals( realValue, source.getValue( realEnvVar, null ) ); + } + +} diff --git a/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java index 074faaf..1bbc7ec 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java @@ -19,6 +19,8 @@ import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.InterpolationPostProcessor; import org.codehaus.plexus.interpolation.StringSearchInterpolator; +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; import org.junit.Test; import java.io.IOException; @@ -32,6 +34,12 @@ public class FixedStringSearchInterpolatorTest { + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + @Test public void testLongDelimitersInContext() { @@ -176,12 +184,22 @@ public void testShouldResolveByContextValue() public void testShouldResolveByEnvar() throws IOException, InterpolationException { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "SOME_ENV", "variable" ); + map.put( "OTHER_ENV", "other variable" ); + return map; + } + } ); + FixedStringSearchInterpolator rbi = create( new EnvarBasedValueSource( false ) ); - String result = rbi.interpolate( "this is a ${env.HOME} ${env.PATH}" ); + String result = rbi.interpolate( "this is a ${env.SOME_ENV} ${env.OTHER_ENV}" ); - assertFalse( "this is a ${HOME} ${PATH}".equals( result ) ); - assertFalse( "this is a ${env.HOME} ${env.PATH}".equals( result ) ); + assertEquals( "this is a variable other variable", result ); } @Test From acbce69504291995022e8caa55004c1ec2825852 Mon Sep 17 00:00:00 2001 From: Gabriel Belingueres Date: Tue, 16 May 2017 15:09:06 -0300 Subject: [PATCH 6/6] Reseted branch commit --- README.md | 2 + pom.xml | 4 +- .../interpolation/EnvarBasedValueSource.java | 9 + .../InterpolatorFilterReader.java | 2 +- .../fixed/EnvarBasedValueSource.java | 9 + ...ultiDelimiterStringSearchInterpolator.java | 12 +- .../os/OperatingSystemUtils.java | 44 ++- .../reflection/ReflectionValueExtractor.java | 303 +++++++++++++++--- .../EnvarBasedValueSourceTest.java | 97 ++++++ .../RegexBasedInterpolatorTest.java | 24 +- .../StringSearchInterpolatorTest.java | 73 ++++- .../fixed/EnvarBasedValueSourceTest.java | 98 ++++++ .../FixedStringSearchInterpolatorTest.java | 88 ++++- ...DelimiterStringSearchInterpolatorTest.java | 38 +++ 14 files changed, 735 insertions(+), 68 deletions(-) create mode 100644 src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java create mode 100644 src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java diff --git a/README.md b/README.md index 424ca5e..2943806 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ Plexus-Interpolation =============== +[![Build Status](https://travis-ci.org/codehaus-plexus/plexus-interpolation.svg?branch=master)](https://travis-ci.org/codehaus-plexus/plexus-interpolation) + Components for interpolating `${}` strings and the like. diff --git a/pom.xml b/pom.xml index 7baa8bd..67d8ebe 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ plexus-interpolation - 1.24-SNAPSHOT + 1.25-SNAPSHOT bundle Plexus Interpolation API @@ -17,7 +17,7 @@ scm:git:git@github.com:codehaus-plexus/plexus-interpolation.git scm:git:git@github.com:codehaus-plexus/plexus-interpolation.git http://github.com/codehaus-plexus/plexus-interpolation - HEAD + plexus-interpolation-1.24 diff --git a/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java b/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java index 3e10856..6f7df79 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java +++ b/src/main/java/org/codehaus/plexus/interpolation/EnvarBasedValueSource.java @@ -110,5 +110,14 @@ public Object getValue( String expression ) return envars.getProperty( expr ); } + + /** + * reset static variables acting as a cache for testing purposes only + */ + static void resetStatics() + { + envarsCaseSensitive = null; + envarsCaseInsensitive = null; + } } diff --git a/src/main/java/org/codehaus/plexus/interpolation/InterpolatorFilterReader.java b/src/main/java/org/codehaus/plexus/interpolation/InterpolatorFilterReader.java index 9b90cbd..486878f 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/InterpolatorFilterReader.java +++ b/src/main/java/org/codehaus/plexus/interpolation/InterpolatorFilterReader.java @@ -138,7 +138,7 @@ public InterpolatorFilterReader( Reader in, Interpolator interpolator, String be */ public InterpolatorFilterReader( Reader in, Interpolator interpolator, RecursionInterceptor ri ) { - this( in, interpolator, DEFAULT_BEGIN_TOKEN, DEFAULT_END_TOKEN, new SimpleRecursionInterceptor() ); + this( in, interpolator, DEFAULT_BEGIN_TOKEN, DEFAULT_END_TOKEN, ri ); } /** diff --git a/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java b/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java index 3e1f4ef..067ac31 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java +++ b/src/main/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSource.java @@ -110,4 +110,13 @@ public Object getValue( String expression, InterpolationState interpolationState return envars.getProperty( expr ); } + /** + * reset static variables acting as a cache for testing purposes only + */ + static void resetStatics() + { + envarsCaseSensitive = null; + envarsCaseInsensitive = null; + } + } diff --git a/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java b/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java index 69d979d..766cafb 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java +++ b/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java @@ -201,13 +201,17 @@ private String interpolate( String input, RecursionInterceptor recursionIntercep if ( startIdx >= 0 && escapeString != null && escapeString.length() > 0 ) { - int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length(); + int startEscapeIdx = ( startIdx == 0 ) ? 0 : startIdx - escapeString.length(); if ( startEscapeIdx >= 0 ) { String escape = input.substring( startEscapeIdx, startIdx ); if ( escape != null && escapeString.equals( escape ) ) { result.append( wholeExpr ); + if ( startEscapeIdx > 0 ) + { + --startEscapeIdx; + } result.replace( startEscapeIdx, startEscapeIdx + escapeString.length(), "" ); continue; } @@ -388,6 +392,12 @@ public void setEscapeString( String escapeString ) { this.escapeString = escapeString; } + + public MultiDelimiterStringSearchInterpolator escapeString( String escapeString ) + { + this.escapeString = escapeString; + return this; + } public MultiDelimiterStringSearchInterpolator setDelimiterSpecs( LinkedHashSet specs ) { diff --git a/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java b/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java index 28756e0..d18a914 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java +++ b/src/main/java/org/codehaus/plexus/interpolation/os/OperatingSystemUtils.java @@ -39,6 +39,8 @@ public final class OperatingSystemUtils { + private static EnvVarSource envVarSource = new DefaultEnvVarSource(); + private OperatingSystemUtils() { } @@ -62,11 +64,11 @@ public static Properties getSystemEnvVars( boolean caseSensitive ) throws IOException { Properties envVars = new Properties(); - Map envs = System.getenv(); + Map envs = envVarSource.getEnvMap(); for ( String key : envs.keySet() ) { String value = envs.get( key ); - if ( !caseSensitive) + if ( !caseSensitive ) { key = key.toUpperCase( Locale.ENGLISH ); } @@ -74,4 +76,42 @@ public static Properties getSystemEnvVars( boolean caseSensitive ) } return envVars; } + + /** + * Set the source object to load the environment variables from. + * Default implementation should suffice. This is mostly for testing. + * @param source the EnvVarSource instance that loads the environment variables. + * + * @since 3.1.2 + */ + public static void setEnvVarSource( EnvVarSource source ) + { + envVarSource = source; + } + + /** + * Defines the functionality to load a Map of environment variables. + * + * @since 3.1.2 + */ + public interface EnvVarSource + { + public Map getEnvMap(); + } + + /** + * Default implementation to load environment variables. + * + * @since 3.1.2 + */ + public static class DefaultEnvVarSource + implements EnvVarSource + { + + public Map getEnvMap() + { + return System.getenv(); + } + + } } diff --git a/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java b/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java index bca759d..4c80b7d 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java +++ b/src/main/java/org/codehaus/plexus/interpolation/reflection/ReflectionValueExtractor.java @@ -15,23 +15,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import org.codehaus.plexus.interpolation.util.StringUtils; -import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.List; import java.util.Map; -import java.util.StringTokenizer; import java.util.WeakHashMap; /** - * NOTE: This class was copied from plexus-utils, to allow this library - * to stand completely self-contained. - *
                  - * Using simple dotted expressions extract the values from a MavenProject - * instance, For example we might want to extract a value like: - * project.build.sourceDirectory + * NOTE: This class was copied from plexus-utils, to allow this library to stand completely self-contained.
                  + * Using simple dotted expressions extract the values from a MavenProject instance, For example we might want to extract + * a value like: project.build.sourceDirectory * * @author Jason van Zyl * @version $Id$ @@ -43,32 +40,142 @@ public class ReflectionValueExtractor 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. + * 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, WeakReference> classMaps = new WeakHashMap, WeakReference>(); + private static final Map, WeakReference> classMaps = + new WeakHashMap, WeakReference>(); + + 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 ) : ""; + } + } private ReflectionValueExtractor() { } + /** + *

                  + * The implementation supports indexed, nested and mapped properties. + *

                  + *
                    + *
                  • nested properties should be defined by a dot, i.e. "user.address.street"
                  • + *
                  • indexed properties (java.util.List or array instance) should be contains (\\w+)\\[(\\d+)\\] + * pattern, i.e. "user.addresses[1].street"
                  • + *
                  • mapped properties should be contains (\\w+)\\((.+)\\) pattern, i.e. + * "user.addresses(myAddress).street"
                  • + *
                      + * + * @param expression not null expression + * @param root not null object + * @return the object defined by the expression + * @throws Exception if any + */ public static Object evaluate( String expression, Object root ) throws Exception { return evaluate( expression, root, true ); } + /** + *

                      + * The implementation supports indexed, nested and mapped properties. + *

                      + *
                        + *
                      • nested properties should be defined by a dot, i.e. "user.address.street"
                      • + *
                      • indexed properties (java.util.List or array instance) should be contains (\\w+)\\[(\\d+)\\] + * pattern, i.e. "user.addresses[1].street"
                      • + *
                      • mapped properties should be contains (\\w+)\\((.+)\\) pattern, i.e. + * "user.addresses(myAddress).street"
                      • + *
                          + * + * @param expression not null expression + * @param root not null object + * @return the object defined by the expression + * @throws Exception if any + */ // TODO: don't throw Exception - public static Object evaluate( String expression, Object root, boolean trimRootToken ) + public static Object evaluate( String expression, final Object root, final boolean trimRootToken ) throws Exception { - // if the root token refers to the supplied root object parameter, remove it. - if ( trimRootToken ) - { - expression = expression.substring( expression.indexOf( '.' ) + 1 ); - } - Object value = root; // ---------------------------------------------------------------------- @@ -76,57 +183,173 @@ public static Object evaluate( String expression, Object root, boolean trimRootT // MavenProject instance. // ---------------------------------------------------------------------- - StringTokenizer parser = new StringTokenizer( expression, "." ); - - while ( parser.hasMoreTokens() ) + if ( expression == null || "".equals( expression.trim() ) + || !Character.isJavaIdentifierStart( expression.charAt( 0 ) ) ) { - String token = parser.nextToken(); + return null; + } - if ( value == null ) + boolean hasDots = expression.indexOf( PROPERTY_START ) >= 0; + + final Tokenizer tokenizer; + if ( trimRootToken && hasDots ) + { + 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 Exception + { + if ( value == null || key == null ) + { + return null; + } + + if ( value instanceof Map ) + { + Object[] localParams = new Object[] { key }; ClassMap classMap = getClassMap( value.getClass() ); + Method method = classMap.findMethod( "get", localParams ); + return method.invoke( value, localParams ); + } - String methodBase = StringUtils.capitalizeFirstLetter( token ); + 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() ); - String methodName = "get" + methodBase; + throw new Exception( message ); + } - Method method = classMap.findMethod( methodName, CLASS_ARGS ); + private static Object getIndexedValue( final String expression, final int from, final int to, final Object value, + final String indexStr ) + throws Exception + { + try + { + int index = Integer.parseInt( indexStr ); - if ( method == null ) + if ( value.getClass().isArray() ) { - // perhaps this is a boolean property?? - methodName = "is" + methodBase; - - method = classMap.findMethod( methodName, CLASS_ARGS ); + return Array.get( value, index ); } - if ( method == null ) + if ( value instanceof List ) + { + ClassMap classMap = getClassMap( value.getClass() ); + // use get method on List interface + Object[] localParams = new Object[] { index }; + Method method = classMap.findMethod( "get", localParams ); + return method.invoke( value, localParams ); + } + } + catch ( NumberFormatException e ) + { + return null; + } + catch ( InvocationTargetException e ) + { + // catch array index issues gracefully, otherwise release + if ( e.getCause() instanceof IndexOutOfBoundsException ) { return null; } - value = method.invoke( value, OBJECT_ARGS ); + throw e; } - return value; + 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 Exception( message ); + } + + private static Object getPropertyValue( Object value, String property ) + throws Exception + { + if ( value == null || property == null ) + { + return null; + } + + ClassMap classMap = getClassMap( value.getClass() ); + String methodBase = StringUtils.capitalizeFirstLetter( property ); + String methodName = "get" + methodBase; + 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; + } + + try + { + return method.invoke( value, OBJECT_ARGS ); + } + catch ( InvocationTargetException e ) + { + throw e; + } } private static ClassMap getClassMap( Class clazz ) { - WeakReference ref = classMaps.get( clazz); + + WeakReference softRef = classMaps.get( clazz ); ClassMap classMap; - if ( ref == null || (classMap = ref.get()) == null ) + if ( softRef == null || ( classMap = softRef.get() ) == null ) { classMap = new ClassMap( clazz ); - classMaps.put( clazz, new WeakReference(classMap) ); + classMaps.put( clazz, new WeakReference( classMap ) ); } return classMap; } -} +} \ No newline at end of file diff --git a/src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java b/src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java new file mode 100644 index 0000000..c6896ab --- /dev/null +++ b/src/test/java/org/codehaus/plexus/interpolation/EnvarBasedValueSourceTest.java @@ -0,0 +1,97 @@ +package org.codehaus.plexus.interpolation; + +/* + * Copyright 2007 The Codehaus Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; +import org.junit.Test; + +public class EnvarBasedValueSourceTest +{ + + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + + @Test + public void testNoArgConstructorIsCaseSensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + assertEquals( "variable", source.getValue( "aVariable" ) ); + assertEquals( "variable", source.getValue( "env.aVariable" ) ); + assertNull( source.getValue( "AVARIABLE" ) ); + assertNull( source.getValue( "env.AVARIABLE" ) ); + } + + @Test + public void testCaseInsensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource( false ); + + assertEquals( "variable", source.getValue( "aVariable" ) ); + assertEquals( "variable", source.getValue( "env.aVariable" ) ); + assertEquals( "variable", source.getValue( "AVARIABLE" ) ); + assertEquals( "variable", source.getValue( "env.AVARIABLE" ) ); + } + + @Test + public void testGetRealEnvironmentVariable() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.DefaultEnvVarSource() ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + String realEnvVar = "JAVA_HOME"; + + String realValue = System.getenv().get( realEnvVar ); + assertNotNull( "Can't run this test until " + realEnvVar + " env variable is set", realValue ); + + assertEquals( realValue, source.getValue( realEnvVar ) ); + } +} diff --git a/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java index 0597564..dcd97d0 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java @@ -21,12 +21,21 @@ import java.util.Map; import java.util.Properties; +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; + import junit.framework.TestCase; public class RegexBasedInterpolatorTest extends TestCase { + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + public String getVar() { return "testVar"; @@ -81,14 +90,23 @@ public void testShouldResolveByContextValue() public void testShouldResolveByEnvar() throws IOException, InterpolationException { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "SOME_ENV", "variable" ); + return map; + } + } ); + RegexBasedInterpolator rbi = new RegexBasedInterpolator(); rbi.addValueSource( new EnvarBasedValueSource() ); - String result = rbi.interpolate( "this is a ${env.HOME}", "this" ); + String result = rbi.interpolate( "this is a ${env.SOME_ENV}", "this" ); - assertFalse( "this is a ${HOME}".equals( result ) ); - assertFalse( "this is a ${env.HOME}".equals( result ) ); + assertEquals( "this is a variable", result ); } public void testUseAlternateRegex() diff --git a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java index 79312cf..9065b38 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java @@ -17,18 +17,28 @@ */ import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; + import junit.framework.TestCase; public class StringSearchInterpolatorTest extends TestCase { + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + public void testLongDelimitersInContext() throws InterpolationException { @@ -147,14 +157,15 @@ public void testShouldFailOnExpressionCycle() } } - public void testShouldResolveByMy_getVar_Method() + public void testShouldResolveByUsingObject_List_Map() throws InterpolationException { StringSearchInterpolator rbi = new StringSearchInterpolator(); rbi.addValueSource( new ObjectBasedValueSource( this ) ); - String result = rbi.interpolate( "this is a ${var}" ); + String result = + rbi.interpolate( "this is a ${var} ${list[1].name} ${anArray[2].name} ${map(Key with spaces).name}" ); - assertEquals( "this is a testVar", result ); + assertEquals( "this is a testVar testIndexedWithList testIndexedWithArray testMap", result ); } public void testShouldResolveByContextValue() @@ -175,14 +186,24 @@ public void testShouldResolveByContextValue() public void testShouldResolveByEnvar() throws IOException, InterpolationException { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "SOME_ENV", "variable" ); + map.put( "OTHER_ENV", "other variable" ); + return map; + } + } ); + StringSearchInterpolator rbi = new StringSearchInterpolator(); rbi.addValueSource( new EnvarBasedValueSource( false ) ); - String result = rbi.interpolate( "this is a ${env.HOME} ${env.PATH}" ); + String result = rbi.interpolate( "this is a ${env.SOME_ENV} ${env.OTHER_ENV}" ); - assertFalse( "this is a ${HOME} ${PATH}".equals( result ) ); - assertFalse( "this is a ${env.HOME} ${env.PATH}".equals( result ) ); + assertEquals( "this is a variable other variable", result ); } public void testUsePostProcessor_DoesNotChangeValue() @@ -429,4 +450,44 @@ public String getVar() return "testVar"; } + public Person[] getAnArray() + { + Person[] array = new Person[3]; + array[0] = new Person( "Gabriel" ); + array[1] = new Person( "Daniela" ); + array[2] = new Person( "testIndexedWithArray" ); + return array; + } + + public List getList() + { + List list = new ArrayList(); + list.add( new Person( "Gabriel" ) ); + list.add( new Person( "testIndexedWithList" ) ); + list.add( new Person( "Daniela" ) ); + return list; + } + + public Map getMap() + { + Map map = new HashMap(); + map.put( "Key with spaces", new Person( "testMap" ) ); + return map; + } + + public static class Person + { + private String name; + + public Person( String name ) + { + this.name = name; + } + + public String getName() + { + return name; + } + } + } diff --git a/src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java b/src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java new file mode 100644 index 0000000..beaf014 --- /dev/null +++ b/src/test/java/org/codehaus/plexus/interpolation/fixed/EnvarBasedValueSourceTest.java @@ -0,0 +1,98 @@ +package org.codehaus.plexus.interpolation.fixed; + +/* + * Copyright 2007 The Codehaus Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; +import org.junit.Test; + +public class EnvarBasedValueSourceTest +{ + + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + + @Test + public void testNoArgConstructorIsCaseSensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + assertEquals( "variable", source.getValue( "aVariable", null ) ); + assertEquals( "variable", source.getValue( "env.aVariable", null ) ); + assertNull( source.getValue( "AVARIABLE", null ) ); + assertNull( source.getValue( "env.AVARIABLE", null ) ); + } + + @Test + public void testCaseInsensitive() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "aVariable", "variable" ); + return map; + } + } ); + + EnvarBasedValueSource source = new EnvarBasedValueSource( false ); + + assertEquals( "variable", source.getValue( "aVariable", null ) ); + assertEquals( "variable", source.getValue( "env.aVariable", null ) ); + assertEquals( "variable", source.getValue( "AVARIABLE", null ) ); + assertEquals( "variable", source.getValue( "env.AVARIABLE", null ) ); + } + + @Test + public void testGetRealEnvironmentVariable() + throws IOException + { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.DefaultEnvVarSource() ); + + EnvarBasedValueSource source = new EnvarBasedValueSource(); + + String realEnvVar = "JAVA_HOME"; + + String realValue = System.getenv().get( realEnvVar ); + assertNotNull( "Can't run this test until " + realEnvVar + " env variable is set", realValue ); + + assertEquals( realValue, source.getValue( realEnvVar, null ) ); + } + +} diff --git a/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java index 074faaf..d2c519c 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/fixed/FixedStringSearchInterpolatorTest.java @@ -15,23 +15,34 @@ * limitations under the License. */ -import org.codehaus.plexus.interpolation.FixedInterpolatorValueSource; -import org.codehaus.plexus.interpolation.InterpolationException; -import org.codehaus.plexus.interpolation.InterpolationPostProcessor; -import org.codehaus.plexus.interpolation.StringSearchInterpolator; -import org.junit.Test; +import static org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator.create; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Properties; -import static org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator.create; -import static org.junit.Assert.*; +import org.codehaus.plexus.interpolation.FixedInterpolatorValueSource; +import org.codehaus.plexus.interpolation.InterpolationException; +import org.codehaus.plexus.interpolation.InterpolationPostProcessor; +import org.codehaus.plexus.interpolation.StringSearchInterpolator; +import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.junit.Before; +import org.junit.Test; public class FixedStringSearchInterpolatorTest { + @Before + public void setUp() + { + EnvarBasedValueSource.resetStatics(); + } + @Test public void testLongDelimitersInContext() { @@ -148,13 +159,14 @@ public void testShouldFailOnExpressionCycle() } @Test - public void testShouldResolveByMy_getVar_Method() + public void testShouldResolveByUsingObject_List_Map() throws InterpolationException { FixedStringSearchInterpolator rbi = create( new ObjectBasedValueSource( this ) ); - String result = rbi.interpolate( "this is a ${var}" ); + String result = + rbi.interpolate( "this is a ${var} ${list[1].name} ${anArray[2].name} ${map(Key with spaces).name}" ); - assertEquals( "this is a testVar", result ); + assertEquals( "this is a testVar testIndexedWithList testIndexedWithArray testMap", result ); } @Test @@ -176,12 +188,22 @@ public void testShouldResolveByContextValue() public void testShouldResolveByEnvar() throws IOException, InterpolationException { + OperatingSystemUtils.setEnvVarSource( new OperatingSystemUtils.EnvVarSource() + { + public Map getEnvMap() + { + HashMap map = new HashMap(); + map.put( "SOME_ENV", "variable" ); + map.put( "OTHER_ENV", "other variable" ); + return map; + } + } ); + FixedStringSearchInterpolator rbi = create( new EnvarBasedValueSource( false ) ); - String result = rbi.interpolate( "this is a ${env.HOME} ${env.PATH}" ); + String result = rbi.interpolate( "this is a ${env.SOME_ENV} ${env.OTHER_ENV}" ); - assertFalse( "this is a ${HOME} ${PATH}".equals( result ) ); - assertFalse( "this is a ${env.HOME} ${env.PATH}".equals( result ) ); + assertEquals( "this is a variable other variable", result ); } @Test @@ -424,6 +446,46 @@ public String getVar() return "testVar"; } + public Person[] getAnArray() + { + Person[] array = new Person[3]; + array[0] = new Person( "Gabriel" ); + array[1] = new Person( "Daniela" ); + array[2] = new Person( "testIndexedWithArray" ); + return array; + } + + public List getList() + { + List list = new ArrayList(); + list.add( new Person( "Gabriel" ) ); + list.add( new Person( "testIndexedWithList" ) ); + list.add( new Person( "Daniela" ) ); + return list; + } + + public Map getMap() + { + Map map = new HashMap(); + map.put( "Key with spaces", new Person( "testMap" ) ); + return map; + } + + public static class Person + { + private String name; + + public Person( String name ) + { + this.name = name; + } + + public String getName() + { + return name; + } + } + @Test public void testLinkedInterpolators() { diff --git a/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java index d645785..91b6434 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java @@ -85,4 +85,42 @@ public void testInterpolationWithMultipleEscapes() assertEquals( "#${first} and ${last}", result ); } + public void testInterpolationWithMultipleEscapes2() + throws InterpolationException + { + Map ctx = new HashMap(); + ctx.put( "name", "User" ); + ctx.put( "otherName", "#${first} and ##${last}" ); + + String input = "${otherName}"; + + ValueSource vs = new MapBasedValueSource( ctx ); + MultiDelimiterStringSearchInterpolator interpolator = + new MultiDelimiterStringSearchInterpolator().withValueSource( vs ); + interpolator.setEscapeString( "#" ); + + String result = interpolator.interpolate( input ); + + assertEquals( "${first} and #${last}", result ); + } + + public void testInterpolationWithMultipleEscapes3() + throws InterpolationException + { + Map ctx = new HashMap(); + ctx.put( "name", "User" ); + ctx.put( "last", "beer" ); + ctx.put( "otherName", "###${first} and ##${second} and ${last}" ); + + String input = "${otherName}"; + + ValueSource vs = new MapBasedValueSource( ctx ); + MultiDelimiterStringSearchInterpolator interpolator = new MultiDelimiterStringSearchInterpolator() // + .withValueSource( vs ) // + .escapeString( "#" ); + + String result = interpolator.interpolate( input ); + + assertEquals( "##${first} and #${second} and beer", result ); + } }