diff --git a/src/main/java/org/codehaus/plexus/interpolation/AbstractDelegatingValueSource.java b/src/main/java/org/codehaus/plexus/interpolation/AbstractDelegatingValueSource.java index 836c6b3..bd0c7aa 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/AbstractDelegatingValueSource.java +++ b/src/main/java/org/codehaus/plexus/interpolation/AbstractDelegatingValueSource.java @@ -34,14 +34,22 @@ protected ValueSource getDelegate() { return delegate; } + @Override + public Object getValue(String expression, String delimiterStart, String delimiterEnd) { + return getDelegate().getValue(expression, delimiterStart, delimiterEnd); + } + + @Override public Object getValue(String expression) { return getDelegate().getValue(expression); } + @Override public void clearFeedback() { delegate.clearFeedback(); } + @Override public List getFeedback() { return delegate.getFeedback(); } diff --git a/src/main/java/org/codehaus/plexus/interpolation/RegexBasedInterpolator.java b/src/main/java/org/codehaus/plexus/interpolation/RegexBasedInterpolator.java index b286bb8..d940aaa 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/RegexBasedInterpolator.java +++ b/src/main/java/org/codehaus/plexus/interpolation/RegexBasedInterpolator.java @@ -177,6 +177,8 @@ public String interpolate(String input, String thisPrefixPattern, RecursionInter int realExprGroup = 2; Pattern expressionPattern; + final String expressionDelimiterStart; + final String expressionDelimiterEnd; if (startRegex != null || endRegex != null) { if (thisPrefixPattern == null) { expressionPattern = getPattern(startRegex + endRegex); @@ -184,16 +186,27 @@ public String interpolate(String input, String thisPrefixPattern, RecursionInter } else { expressionPattern = getPattern(startRegex + thisPrefixPattern + endRegex); } + expressionDelimiterStart = startRegex; + expressionDelimiterEnd = endRegex; - } else if (thisPrefixPattern != null) { - expressionPattern = getPattern("\\$\\{(" + thisPrefixPattern + ")?(.+?)\\}"); } else { - expressionPattern = getPattern(DEFAULT_REGEXP); - realExprGroup = 1; + expressionDelimiterStart = "${"; + expressionDelimiterEnd = "}"; + if (thisPrefixPattern != null) { + expressionPattern = getPattern("\\$\\{(" + thisPrefixPattern + ")?(.+?)\\}"); + } else { + expressionPattern = getPattern(DEFAULT_REGEXP); + realExprGroup = 1; + } } - try { - return interpolate(input, recursionInterceptor, expressionPattern, realExprGroup); + return interpolate( + input, + recursionInterceptor, + expressionPattern, + expressionDelimiterStart, + expressionDelimiterEnd, + realExprGroup); } finally { if (!cacheAnswers) { clearAnswers(); @@ -228,7 +241,12 @@ private Pattern getPattern(String regExp) { * @todo Ensure unresolvable expressions don't trigger infinite recursion. */ private String interpolate( - String input, RecursionInterceptor recursionInterceptor, Pattern expressionPattern, int realExprGroup) + String input, + RecursionInterceptor recursionInterceptor, + Pattern expressionPattern, + String expressionDelimiterStart, + String expressionDelimiterEnd, + int realExprGroup) throws InterpolationException { if (input == null) { // return empty String to prevent NPE too @@ -256,11 +274,17 @@ private String interpolate( for (ValueSource vs : valueSources) { if (value != null) break; - value = vs.getValue(realExpr); + value = vs.getValue(realExpr, expressionDelimiterStart, expressionDelimiterEnd); } if (value != null) { - value = interpolate(String.valueOf(value), recursionInterceptor, expressionPattern, realExprGroup); + value = interpolate( + String.valueOf(value), + recursionInterceptor, + expressionPattern, + expressionDelimiterStart, + expressionDelimiterEnd, + realExprGroup); if (postProcessors != null && !postProcessors.isEmpty()) { for (InterpolationPostProcessor postProcessor : postProcessors) { diff --git a/src/main/java/org/codehaus/plexus/interpolation/StringSearchInterpolator.java b/src/main/java/org/codehaus/plexus/interpolation/StringSearchInterpolator.java index 04cba3d..28e2189 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/StringSearchInterpolator.java +++ b/src/main/java/org/codehaus/plexus/interpolation/StringSearchInterpolator.java @@ -163,7 +163,7 @@ private String interpolate(String input, RecursionInterceptor recursionIntercept if (value != null) { break; } - value = valueSource.getValue(realExpr); + value = valueSource.getValue(realExpr, startExpr, endExpr); if (value != null && value.toString().contains(wholeExpr)) { bestAnswer = value; diff --git a/src/main/java/org/codehaus/plexus/interpolation/ValueSource.java b/src/main/java/org/codehaus/plexus/interpolation/ValueSource.java index 347b738..005822b 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/ValueSource.java +++ b/src/main/java/org/codehaus/plexus/interpolation/ValueSource.java @@ -25,8 +25,21 @@ public interface ValueSource { /** + * Returns a value resolved from an expression. The return value is recursively resolved via {@link Interpolator#interpolate(String)}, i.e. might contain expressions as well. * @param expression The string expression. - * @return the value related to the expression, or null if not found. + * @param expressionStartDelimiter A valid start delimiter of the expression to be used with the calling {@link Interpolator} (by default ${). + * @param expressionEndDelimiter A valid end delimiter of the expression to be used with the calling {@link Interpolator} (by default }). + * @return the value related to the expression, or {@code null} if not found. This value might contain other expressions separated by {@code expressionStartDelimiter} and {@code expressionEndDelimiter} + * @since 1.28 + */ + default Object getValue(String expression, String expressionStartDelimiter, String expressionEndDelimiter) { + return getValue(expression); + } + + /** + * @param expression The string expression. + * @return the value related to the expression, or {@code null} if not found. + * @see #getValue(String, String, String) */ public Object getValue(String expression); 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 fc472e2..ba658e5 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java +++ b/src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java @@ -201,7 +201,7 @@ private String interpolate(String input, RecursionInterceptor recursionIntercept for (ValueSource vs : valueSources) { if (value != null) break; - value = vs.getValue(realExpr); + value = vs.getValue(realExpr, startExpr, endExpr); if (value != null && value.toString().contains(wholeExpr)) { bestAnswer = value; diff --git a/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java index d3c31f6..61a25c2 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/RegexBasedInterpolatorTest.java @@ -80,6 +80,28 @@ public void testShouldResolveByContextValue() throws InterpolationException { assertEquals("this is a testVar", result); } + @Test + public void testDelimitersPassedToValueSource() throws InterpolationException { + RegexBasedInterpolator interpolator = new RegexBasedInterpolator(); + interpolator.addValueSource(new AbstractValueSource(false) { + + @Override + public Object getValue(String expression, String expressionStartDelimiter, String expressionEndDelimiter) { + assertEquals("${", expressionStartDelimiter); + assertEquals("}", expressionEndDelimiter); + return expression; + } + + @Override + public Object getValue(String expression) { + fail("This method is not supposed to be called"); + return null; + } + }); + + assertEquals("test", interpolator.interpolate("${test}")); + } + @Test public void testShouldResolveByEnvar() throws IOException, InterpolationException { OperatingSystemUtils.setEnvVarSource(new OperatingSystemUtils.EnvVarSource() { diff --git a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java index 41de806..e1fa00a 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java @@ -94,6 +94,30 @@ public void testLongDelimitersWithNoContext() throws InterpolationException { assertEquals(result, interpolator.interpolate(src)); } + @Test + public void testLongDelimitersPassedToValueSource() throws InterpolationException { + String src = "test"; + + StringSearchInterpolator interpolator = new StringSearchInterpolator("", ""); + interpolator.addValueSource(new AbstractValueSource(false) { + + @Override + public Object getValue(String expression, String expressionStartDelimiter, String expressionEndDelimiter) { + assertEquals("", expressionStartDelimiter); + assertEquals("", expressionEndDelimiter); + return expression; + } + + @Override + public Object getValue(String expression) { + fail("This method is not supposed to be called"); + return null; + } + }); + + assertEquals("test", interpolator.interpolate(src)); + } + @Test public void testSimpleSubstitution() throws InterpolationException { Properties p = new Properties(); 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 2c5fe2f..8b3b724 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolatorTest.java @@ -19,12 +19,14 @@ import java.util.HashMap; import java.util.Map; +import org.codehaus.plexus.interpolation.AbstractValueSource; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.MapBasedValueSource; import org.codehaus.plexus.interpolation.ValueSource; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; public class MultiDelimiterStringSearchInterpolatorTest { @@ -119,4 +121,29 @@ public void testInterpolationWithMultipleEscapes3() throws InterpolationExceptio assertEquals("##${first} and #${second} and beer", result); } + + @Test + public void testDelimitersPassedToValueSource() throws InterpolationException { + ValueSource vs = new AbstractValueSource(false) { + + @Override + public Object getValue(String expression, String expressionStartDelimiter, String expressionEndDelimiter) { + assertEquals("#(", expressionStartDelimiter); + assertEquals(")", expressionEndDelimiter); + return expression; + } + + @Override + public Object getValue(String expression) { + fail("This method is not supposed to be called"); + return null; + } + }; + MultiDelimiterStringSearchInterpolator interpolator = new MultiDelimiterStringSearchInterpolator() // + .withValueSource(vs) // + .escapeString("#"); + interpolator.addDelimiterSpec("#(*)"); + + assertEquals("test", interpolator.interpolate("#(test)")); + } }