diff --git a/src/main/java/org/codehaus/plexus/interpolation/StringSearchInterpolator.java b/src/main/java/org/codehaus/plexus/interpolation/StringSearchInterpolator.java index ffdd6bc..04cba3d 100644 --- a/src/main/java/org/codehaus/plexus/interpolation/StringSearchInterpolator.java +++ b/src/main/java/org/codehaus/plexus/interpolation/StringSearchInterpolator.java @@ -156,7 +156,7 @@ private String interpolate(String input, RecursionInterceptor recursionIntercept recursionInterceptor.expressionResolutionStarted(realExpr); try { - Object value = existingAnswers.get(realExpr); + Object value = getExistingAnswer(realExpr); Object bestAnswer = null; for (ValueSource valueSource : valueSources) { @@ -197,6 +197,10 @@ private String interpolate(String input, RecursionInterceptor recursionIntercept // behaviour result.append(String.valueOf(value)); resolved = true; + + if (cacheAnswers) { + existingAnswers.put(realExpr, value); + } } else { unresolvable.add(wholeExpr); } @@ -275,4 +279,13 @@ public String getEscapeString() { public void setEscapeString(String escapeString) { this.escapeString = escapeString; } + + /** + * For testing purposes only. Not part of the public API. + * @param key the key of a possible existing answer. + * @return the associated interpolated object, or null if there is none. + */ + protected Object getExistingAnswer(String key) { + return existingAnswers.get(key); + } } diff --git a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java index 5152670..481f8f0 100644 --- a/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java +++ b/src/test/java/org/codehaus/plexus/interpolation/StringSearchInterpolatorTest.java @@ -406,6 +406,75 @@ public void clearFeedback() {} "should not believe there is a cycle here"); } + public void testCacheAnswersTrue() throws InterpolationException { + Properties p = new Properties(); + p.setProperty("key", "value"); + + class CountingStringSearchInterpolator extends StringSearchInterpolator { + private int existingCallCount; + + @Override + protected Object getExistingAnswer(String key) { + Object value = super.getExistingAnswer(key); + if (value != null) { + ++existingCallCount; + } + return value; + } + + public int getExistingCallCount() { + return existingCallCount; + } + } + + CountingStringSearchInterpolator interpolator = new CountingStringSearchInterpolator(); + interpolator.setCacheAnswers(true); + interpolator.addValueSource(new PropertiesBasedValueSource(p)); + + String result = interpolator.interpolate("${key}-${key}-${key}-${key}"); + + assertEquals("value-value-value-value", result); + // first value is interpolated and saved, then the 3 next answers came from existing answer Map + assertEquals(3, interpolator.getExistingCallCount()); + + // answers are preserved between calls: + result = interpolator.interpolate("${key}-${key}-${key}-${key}"); + assertEquals("value-value-value-value", result); + // 3 from the first call to interpolate(), plus 4 from second call + assertEquals(3 + 4, interpolator.getExistingCallCount()); + } + + public void testCacheAnswersFalse() throws InterpolationException { + Properties p = new Properties(); + p.setProperty("key", "value"); + + class CountingStringSearchInterpolator extends StringSearchInterpolator { + private int existingCallCount; + + @Override + protected Object getExistingAnswer(String key) { + Object value = super.getExistingAnswer(key); + if (value != null) { + ++existingCallCount; + } + return value; + } + + public int getExistingCallCount() { + return existingCallCount; + } + } + + CountingStringSearchInterpolator interpolator = new CountingStringSearchInterpolator(); + interpolator.addValueSource(new PropertiesBasedValueSource(p)); + + String result = interpolator.interpolate("${key}-${key}-${key}-${key}"); + + assertEquals("value-value-value-value", result); + // all values are interpolated each time + assertEquals(0, interpolator.getExistingCallCount()); + } + public String getVar() { return "testVar"; }