Skip to content

Commit ecd7a6d

Browse files
Copilotslachiewicz
andcommitted
Add new interpolate methods accepting ValueSource and InterpolationPostProcessor lists
Co-authored-by: slachiewicz <[email protected]>
1 parent e0a2e06 commit ecd7a6d

File tree

5 files changed

+355
-15
lines changed

5 files changed

+355
-15
lines changed

src/main/java/org/codehaus/plexus/interpolation/Interpolator.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,62 @@ public interface Interpolator extends BasicInterpolator {
8888
String interpolate(String input, String thisPrefixPattern, RecursionInterceptor recursionInterceptor)
8989
throws InterpolationException;
9090

91+
/**
92+
* Attempt to resolve all expressions in the given input string, using the
93+
* provided lists of value sources and post processors. This method allows
94+
* for efficient interpolation without the need to repeatedly add and remove
95+
* value sources and post processors from the interpolator instance.
96+
* <p>
97+
* This method triggers the use of a {@link SimpleRecursionInterceptor}
98+
* instance for protection against expression cycles.</p>
99+
* <p>
100+
* <b>return an empty String if input is null</b>
101+
*
102+
* @param input The input string to interpolate
103+
* @param valueSources The list of value sources to use for resolving expressions.
104+
* If null or empty, no value sources will be used.
105+
* @param postProcessors The list of post processors to apply after interpolation.
106+
* If null or empty, no post processors will be used.
107+
* @return interpolated string.
108+
* @throws InterpolationException in case of an error.
109+
* @since 1.29
110+
*/
111+
default String interpolate(
112+
String input, List<ValueSource> valueSources, List<InterpolationPostProcessor> postProcessors)
113+
throws InterpolationException {
114+
return interpolate(input, valueSources, postProcessors, new SimpleRecursionInterceptor());
115+
}
116+
117+
/**
118+
* Attempt to resolve all expressions in the given input string, using the
119+
* provided lists of value sources and post processors. This method allows
120+
* for efficient interpolation without the need to repeatedly add and remove
121+
* value sources and post processors from the interpolator instance.
122+
* <p>
123+
* The supplied recursion interceptor will provide protection from expression
124+
* cycles, ensuring that the input can be resolved or an exception is thrown.
125+
* <p>
126+
* <b>return an empty String if input is null</b>
127+
*
128+
* @param input The input string to interpolate
129+
* @param valueSources The list of value sources to use for resolving expressions.
130+
* If null or empty, no value sources will be used.
131+
* @param postProcessors The list of post processors to apply after interpolation.
132+
* If null or empty, no post processors will be used.
133+
* @param recursionInterceptor Used to protect the interpolation process
134+
* from expression cycles, and throw an
135+
* exception if one is detected.
136+
* @return interpolated string.
137+
* @throws InterpolationException in case of an error.
138+
* @since 1.29
139+
*/
140+
String interpolate(
141+
String input,
142+
List<ValueSource> valueSources,
143+
List<InterpolationPostProcessor> postProcessors,
144+
RecursionInterceptor recursionInterceptor)
145+
throws InterpolationException;
146+
91147
/**
92148
* Return any feedback messages and errors that were generated - but
93149
* suppressed - during the interpolation process. Since unresolvable

src/main/java/org/codehaus/plexus/interpolation/RegexBasedInterpolator.java

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,39 @@ private String interpolate(
248248
String expressionDelimiterEnd,
249249
int realExprGroup)
250250
throws InterpolationException {
251+
return interpolate(
252+
input,
253+
recursionInterceptor,
254+
expressionPattern,
255+
expressionDelimiterStart,
256+
expressionDelimiterEnd,
257+
realExprGroup,
258+
this.valueSources,
259+
this.postProcessors);
260+
}
261+
262+
private String interpolate(
263+
String input,
264+
RecursionInterceptor recursionInterceptor,
265+
Pattern expressionPattern,
266+
String expressionDelimiterStart,
267+
String expressionDelimiterEnd,
268+
int realExprGroup,
269+
List<ValueSource> valueSources,
270+
List<InterpolationPostProcessor> postProcessors)
271+
throws InterpolationException {
251272
if (input == null) {
252273
// return empty String to prevent NPE too
253274
return "";
254275
}
276+
277+
// Use instance value sources if provided list is null or empty
278+
List<ValueSource> effectiveValueSources =
279+
(valueSources != null && !valueSources.isEmpty()) ? valueSources : this.valueSources;
280+
// Use instance post processors if provided list is null or empty
281+
List<InterpolationPostProcessor> effectivePostProcessors =
282+
(postProcessors != null && !postProcessors.isEmpty()) ? postProcessors : this.postProcessors;
283+
255284
String result = input;
256285

257286
Matcher matcher = expressionPattern.matcher(result);
@@ -271,7 +300,7 @@ private String interpolate(
271300
recursionInterceptor.expressionResolutionStarted(realExpr);
272301
try {
273302
Object value = existingAnswers.get(realExpr);
274-
for (ValueSource vs : valueSources) {
303+
for (ValueSource vs : effectiveValueSources) {
275304
if (value != null) break;
276305

277306
value = vs.getValue(realExpr, expressionDelimiterStart, expressionDelimiterEnd);
@@ -284,10 +313,12 @@ private String interpolate(
284313
expressionPattern,
285314
expressionDelimiterStart,
286315
expressionDelimiterEnd,
287-
realExprGroup);
316+
realExprGroup,
317+
effectiveValueSources,
318+
effectivePostProcessors);
288319

289-
if (postProcessors != null && !postProcessors.isEmpty()) {
290-
for (InterpolationPostProcessor postProcessor : postProcessors) {
320+
if (effectivePostProcessors != null && !effectivePostProcessors.isEmpty()) {
321+
for (InterpolationPostProcessor postProcessor : effectivePostProcessors) {
291322
Object newVal = postProcessor.execute(realExpr, value);
292323
if (newVal != null) {
293324
value = newVal;
@@ -373,7 +404,7 @@ public String interpolate(String input, String thisPrefixPattern) throws Interpo
373404
* @param input The input string to interpolate
374405
*/
375406
public String interpolate(String input) throws InterpolationException {
376-
return interpolate(input, null, null);
407+
return interpolate(input, (String) null, (RecursionInterceptor) null);
377408
}
378409

379410
/**
@@ -393,6 +424,65 @@ public String interpolate(String input, RecursionInterceptor recursionIntercepto
393424
return interpolate(input, null, recursionInterceptor);
394425
}
395426

427+
/**
428+
* {@inheritDoc}
429+
*/
430+
public String interpolate(
431+
String input,
432+
List<ValueSource> valueSources,
433+
List<InterpolationPostProcessor> postProcessors,
434+
RecursionInterceptor recursionInterceptor)
435+
throws InterpolationException {
436+
if (input == null) {
437+
// return empty String to prevent NPE too
438+
return "";
439+
}
440+
if (recursionInterceptor == null) {
441+
recursionInterceptor = new SimpleRecursionInterceptor();
442+
}
443+
444+
String thisPrefixPattern = null;
445+
int realExprGroup = 2;
446+
Pattern expressionPattern;
447+
final String expressionDelimiterStart;
448+
final String expressionDelimiterEnd;
449+
if (startRegex != null || endRegex != null) {
450+
if (thisPrefixPattern == null) {
451+
expressionPattern = getPattern(startRegex + endRegex);
452+
realExprGroup = 1;
453+
} else {
454+
expressionPattern = getPattern(startRegex + thisPrefixPattern + endRegex);
455+
}
456+
expressionDelimiterStart = startRegex;
457+
expressionDelimiterEnd = endRegex;
458+
459+
} else {
460+
expressionDelimiterStart = "${";
461+
expressionDelimiterEnd = "}";
462+
if (thisPrefixPattern != null) {
463+
expressionPattern = getPattern("\\$\\{(" + thisPrefixPattern + ")?(.+?)\\}");
464+
} else {
465+
expressionPattern = getPattern(DEFAULT_REGEXP);
466+
realExprGroup = 1;
467+
}
468+
}
469+
try {
470+
return interpolate(
471+
input,
472+
recursionInterceptor,
473+
expressionPattern,
474+
expressionDelimiterStart,
475+
expressionDelimiterEnd,
476+
realExprGroup,
477+
valueSources,
478+
postProcessors);
479+
} finally {
480+
if (!cacheAnswers) {
481+
clearAnswers();
482+
}
483+
}
484+
}
485+
396486
public boolean isReusePatterns() {
397487
return reusePatterns;
398488
}

src/main/java/org/codehaus/plexus/interpolation/StringSearchInterpolator.java

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,48 @@ public String interpolate(String input, RecursionInterceptor recursionIntercepto
110110
}
111111
}
112112

113+
/**
114+
* {@inheritDoc}
115+
*/
116+
public String interpolate(
117+
String input,
118+
List<ValueSource> valueSources,
119+
List<InterpolationPostProcessor> postProcessors,
120+
RecursionInterceptor recursionInterceptor)
121+
throws InterpolationException {
122+
try {
123+
return interpolate(input, recursionInterceptor, new HashSet<String>(), valueSources, postProcessors);
124+
} finally {
125+
if (!cacheAnswers) {
126+
existingAnswers.clear();
127+
}
128+
}
129+
}
130+
113131
private String interpolate(String input, RecursionInterceptor recursionInterceptor, Set<String> unresolvable)
114132
throws InterpolationException {
133+
return interpolate(input, recursionInterceptor, unresolvable, this.valueSources, this.postProcessors);
134+
}
135+
136+
private String interpolate(
137+
String input,
138+
RecursionInterceptor recursionInterceptor,
139+
Set<String> unresolvable,
140+
List<ValueSource> valueSources,
141+
List<InterpolationPostProcessor> postProcessors)
142+
throws InterpolationException {
115143
if (input == null) {
116144
// return empty String to prevent NPE too
117145
return "";
118146
}
119147

148+
// Use instance value sources if provided list is null or empty
149+
List<ValueSource> effectiveValueSources =
150+
(valueSources != null && !valueSources.isEmpty()) ? valueSources : this.valueSources;
151+
// Use instance post processors if provided list is null or empty
152+
List<InterpolationPostProcessor> effectivePostProcessors =
153+
(postProcessors != null && !postProcessors.isEmpty()) ? postProcessors : this.postProcessors;
154+
120155
int startIdx;
121156
int endIdx = -1;
122157
if ((startIdx = input.indexOf(startExpr, endIdx + 1)) > -1) {
@@ -159,7 +194,7 @@ private String interpolate(String input, RecursionInterceptor recursionIntercept
159194
Object value = getExistingAnswer(realExpr);
160195
Object bestAnswer = null;
161196

162-
for (ValueSource valueSource : valueSources) {
197+
for (ValueSource valueSource : effectiveValueSources) {
163198
if (value != null) {
164199
break;
165200
}
@@ -179,10 +214,15 @@ private String interpolate(String input, RecursionInterceptor recursionIntercept
179214
}
180215

181216
if (value != null) {
182-
value = interpolate(String.valueOf(value), recursionInterceptor, unresolvable);
183-
184-
if (postProcessors != null && !postProcessors.isEmpty()) {
185-
for (InterpolationPostProcessor postProcessor : postProcessors) {
217+
value = interpolate(
218+
String.valueOf(value),
219+
recursionInterceptor,
220+
unresolvable,
221+
effectiveValueSources,
222+
effectivePostProcessors);
223+
224+
if (effectivePostProcessors != null && !effectivePostProcessors.isEmpty()) {
225+
for (InterpolationPostProcessor postProcessor : effectivePostProcessors) {
186226
Object newVal = postProcessor.execute(realExpr, value);
187227
if (newVal != null) {
188228
value = newVal;

src/main/java/org/codehaus/plexus/interpolation/multi/MultiDelimiterStringSearchInterpolator.java

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,48 @@ public String interpolate(String input, RecursionInterceptor recursionIntercepto
133133
}
134134
}
135135

136+
/**
137+
* {@inheritDoc}
138+
*/
139+
public String interpolate(
140+
String input,
141+
List<ValueSource> valueSources,
142+
List<InterpolationPostProcessor> postProcessors,
143+
RecursionInterceptor recursionInterceptor)
144+
throws InterpolationException {
145+
try {
146+
return interpolate(input, recursionInterceptor, new HashSet(), valueSources, postProcessors);
147+
} finally {
148+
if (!cacheAnswers) {
149+
existingAnswers.clear();
150+
}
151+
}
152+
}
153+
136154
private String interpolate(String input, RecursionInterceptor recursionInterceptor, Set<String> unresolvable)
137155
throws InterpolationException {
156+
return interpolate(input, recursionInterceptor, unresolvable, this.valueSources, this.postProcessors);
157+
}
158+
159+
private String interpolate(
160+
String input,
161+
RecursionInterceptor recursionInterceptor,
162+
Set<String> unresolvable,
163+
List<ValueSource> valueSources,
164+
List postProcessors)
165+
throws InterpolationException {
138166
if (input == null) {
139167
// return empty String to prevent NPE too
140168
return "";
141169
}
170+
171+
// Use instance value sources if provided list is null or empty
172+
List<ValueSource> effectiveValueSources =
173+
(valueSources != null && !valueSources.isEmpty()) ? valueSources : this.valueSources;
174+
// Use instance post processors if provided list is null or empty
175+
List effectivePostProcessors =
176+
(postProcessors != null && !postProcessors.isEmpty()) ? postProcessors : this.postProcessors;
177+
142178
StringBuilder result = new StringBuilder(input.length() * 2);
143179

144180
String lastResult = input;
@@ -198,7 +234,7 @@ private String interpolate(String input, RecursionInterceptor recursionIntercept
198234

199235
Object value = existingAnswers.get(realExpr);
200236
Object bestAnswer = null;
201-
for (ValueSource vs : valueSources) {
237+
for (ValueSource vs : effectiveValueSources) {
202238
if (value != null) break;
203239

204240
value = vs.getValue(realExpr, startExpr, endExpr);
@@ -217,10 +253,15 @@ private String interpolate(String input, RecursionInterceptor recursionIntercept
217253
}
218254

219255
if (value != null) {
220-
value = interpolate(String.valueOf(value), recursionInterceptor, unresolvable);
221-
222-
if (postProcessors != null && !postProcessors.isEmpty()) {
223-
for (Object postProcessor1 : postProcessors) {
256+
value = interpolate(
257+
String.valueOf(value),
258+
recursionInterceptor,
259+
unresolvable,
260+
effectiveValueSources,
261+
effectivePostProcessors);
262+
263+
if (effectivePostProcessors != null && !effectivePostProcessors.isEmpty()) {
264+
for (Object postProcessor1 : effectivePostProcessors) {
224265
InterpolationPostProcessor postProcessor = (InterpolationPostProcessor) postProcessor1;
225266
Object newVal = postProcessor.execute(realExpr, value);
226267
if (newVal != null) {

0 commit comments

Comments
 (0)