View Javadoc
1   package org.codehaus.plexus.interpolation.fixed;
2   /*
3    * Copyright 2001-2008 Codehaus Foundation.
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  import java.io.IOException;
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.Properties;
24  
25  import org.codehaus.plexus.interpolation.FixedInterpolatorValueSource;
26  import org.codehaus.plexus.interpolation.InterpolationException;
27  import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
28  import org.codehaus.plexus.interpolation.StringSearchInterpolator;
29  import org.codehaus.plexus.interpolation.os.OperatingSystemUtils;
30  import org.junit.jupiter.api.BeforeEach;
31  import org.junit.jupiter.api.Test;
32  
33  import static org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator.create;
34  import static org.junit.jupiter.api.Assertions.assertEquals;
35  import static org.junit.jupiter.api.Assertions.assertThrows;
36  
37  public class FixedStringSearchInterpolatorTest {
38  
39      @BeforeEach
40      public void setUp() {
41          EnvarBasedValueSource.resetStatics();
42      }
43  
44      @Test
45      void testLongDelimitersInContext() {
46          String src = "This is a <expression>test.label</expression> for long delimiters in context.";
47          String result = "This is a test for long delimiters in context.";
48  
49          Properties p = new Properties();
50          p.setProperty("test.label", "test");
51  
52          FixedStringSearchInterpolator interpolator =
53                  create(new PropertiesBasedValueSource(p)).withExpressionMarkers("<expression>", "</expression>");
54  
55          assertEquals(result, interpolator.interpolate(src));
56      }
57  
58      @Test
59      void testLongDelimitersWithNoStartContext() {
60          String src = "<expression>test.label</expression> for long delimiters in context.";
61          String result = "test for long delimiters in context.";
62  
63          Properties p = new Properties();
64          p.setProperty("test.label", "test");
65  
66          FixedStringSearchInterpolator interpolator =
67                  create(new PropertiesBasedValueSource(p)).withExpressionMarkers("<expression>", "</expression>");
68  
69          assertEquals(result, interpolator.interpolate(src));
70      }
71  
72      @Test
73      void testLongDelimitersWithNoEndContext() {
74          String src = "This is a <expression>test.label</expression>";
75          String result = "This is a test";
76  
77          Properties p = new Properties();
78          p.setProperty("test.label", "test");
79  
80          FixedStringSearchInterpolator interpolator =
81                  create(new PropertiesBasedValueSource(p)).withExpressionMarkers("<expression>", "</expression>");
82  
83          assertEquals(result, interpolator.interpolate(src));
84      }
85  
86      @Test
87      void testLongDelimitersWithNoContext() {
88          String src = "<expression>test.label</expression>";
89          String result = "test";
90  
91          Properties p = new Properties();
92          p.setProperty("test.label", "test");
93  
94          FixedStringSearchInterpolator interpolator =
95                  create(new PropertiesBasedValueSource(p)).withExpressionMarkers("<expression>", "</expression>");
96  
97          assertEquals(result, interpolator.interpolate(src));
98      }
99  
100     @Test
101     void testSimpleSubstitution() {
102         Properties p = new Properties();
103         p.setProperty("key", "value");
104 
105         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p));
106 
107         assertEquals("This is a test value.", interpolator.interpolate("This is a test ${key}."));
108     }
109 
110     @Test
111     void testSimpleSubstitution_TwoExpressions() {
112         Properties p = new Properties();
113         p.setProperty("key", "value");
114         p.setProperty("key2", "value2");
115 
116         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p));
117 
118         assertEquals("value-value2", interpolator.interpolate("${key}-${key2}"));
119     }
120 
121     @Test
122     void testBrokenExpression_LeaveItAlone() {
123         Properties p = new Properties();
124         p.setProperty("key", "value");
125 
126         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p));
127 
128         assertEquals("This is a test ${key.", interpolator.interpolate("This is a test ${key."));
129     }
130 
131     @Test
132     void testShouldFailOnExpressionCycle() {
133         Properties props = new Properties();
134         props.setProperty("key1", "${key2}");
135         props.setProperty("key2", "${key1}");
136 
137         FixedStringSearchInterpolator rbi = create(new PropertiesBasedValueSource(props));
138 
139         assertThrows(
140                 InterpolationCycleException.class,
141                 () -> rbi.interpolate("${key1}"),
142                 "Should detect expression cycle and fail.");
143     }
144 
145     @Test
146     void testShouldResolveByUsingObject_List_Map() throws InterpolationException {
147         FixedStringSearchInterpolator rbi = create(new ObjectBasedValueSource(this));
148         String result =
149                 rbi.interpolate("this is a ${var} ${list[1].name} ${anArray[2].name} ${map(Key with spaces).name}");
150 
151         assertEquals("this is a testVar testIndexedWithList testIndexedWithArray testMap", result);
152     }
153 
154     @Test
155     void testShouldResolveByContextValue() throws InterpolationException {
156 
157         Map<String, String> context = new HashMap<String, String>();
158         context.put("var", "testVar");
159 
160         FixedStringSearchInterpolator rbi = create(new MapBasedValueSource(context));
161 
162         String result = rbi.interpolate("this is a ${var}");
163 
164         assertEquals("this is a testVar", result);
165     }
166 
167     @Test
168     void testShouldResolveByEnvar() throws IOException, InterpolationException {
169         OperatingSystemUtils.setEnvVarSource(new OperatingSystemUtils.EnvVarSource() {
170             public Map<String, String> getEnvMap() {
171                 HashMap<String, String> map = new HashMap<String, String>();
172                 map.put("SOME_ENV", "variable");
173                 map.put("OTHER_ENV", "other variable");
174                 return map;
175             }
176         });
177 
178         FixedStringSearchInterpolator rbi = create(new EnvarBasedValueSource(false));
179 
180         String result = rbi.interpolate("this is a ${env.SOME_ENV} ${env.OTHER_ENV}");
181 
182         assertEquals("this is a variable other variable", result);
183     }
184 
185     @Test
186     void testUsePostProcessor_DoesNotChangeValue() throws InterpolationException {
187 
188         Map<String, String> context = new HashMap<String, String>();
189         context.put("test.var", "testVar");
190 
191         final InterpolationPostProcessor postProcessor = new InterpolationPostProcessor() {
192             public Object execute(String expression, Object value) {
193                 return null;
194             }
195         };
196         FixedStringSearchInterpolator rbi =
197                 create(new MapBasedValueSource(context)).withPostProcessor(postProcessor);
198 
199         String result = rbi.interpolate("this is a ${test.var}");
200 
201         assertEquals("this is a testVar", result);
202     }
203 
204     @Test
205     void testUsePostProcessor_ChangesValue() throws InterpolationException {
206 
207         Map context = new HashMap();
208         context.put("test.var", "testVar");
209 
210         final InterpolationPostProcessor postProcessor = new InterpolationPostProcessor() {
211             public Object execute(String expression, Object value) {
212                 return value + "2";
213             }
214         };
215 
216         FixedStringSearchInterpolator rbi =
217                 create(new MapBasedValueSource(context)).withPostProcessor(postProcessor);
218 
219         String result = rbi.interpolate("this is a ${test.var}");
220 
221         assertEquals("this is a testVar2", result);
222     }
223 
224     @Test
225     void testSimpleSubstitutionWithDefinedExpr() throws InterpolationException {
226         Properties p = new Properties();
227         p.setProperty("key", "value");
228 
229         FixedStringSearchInterpolator interpolator = create("@{", "}", new PropertiesBasedValueSource(p));
230 
231         assertEquals("This is a test value.", interpolator.interpolate("This is a test @{key}."));
232     }
233 
234     @Test
235     void testEscape() throws InterpolationException {
236         Properties p = new Properties();
237         p.setProperty("key", "value");
238 
239         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p))
240                 .withExpressionMarkers("@{", "}")
241                 .withEscapeString("\\");
242 
243         String result = interpolator.interpolate("This is a test \\@{key}.");
244 
245         assertEquals("This is a test @{key}.", result);
246     }
247 
248     @Test
249     void testEscapeWithLongEscapeStr() throws InterpolationException {
250         Properties p = new Properties();
251         p.setProperty("key", "value");
252 
253         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p))
254                 .withExpressionMarkers("@{", "}")
255                 .withEscapeString("$$");
256 
257         String result = interpolator.interpolate("This is a test $$@{key}.");
258 
259         assertEquals("This is a test @{key}.", result);
260     }
261 
262     @Test
263     void testEscapeWithLongEscapeStrAtStart() throws InterpolationException {
264         Properties p = new Properties();
265         p.setProperty("key", "value");
266 
267         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p))
268                 .withExpressionMarkers("@{", "}")
269                 .withEscapeString("$$");
270 
271         String result = interpolator.interpolate("$$@{key} This is a test.");
272 
273         assertEquals("@{key} This is a test.", result);
274     }
275 
276     @Test
277     void testNotEscapeWithLongEscapeStrAtStart() throws InterpolationException {
278         Properties p = new Properties();
279         p.setProperty("key", "value");
280 
281         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p))
282                 .withExpressionMarkers("@{", "}")
283                 .withEscapeString("$$");
284 
285         String result = interpolator.interpolate("@{key} This is a test.");
286 
287         assertEquals("value This is a test.", result);
288     }
289 
290     @Test
291     void testEscapeNotFailWithNullEscapeStr() throws InterpolationException {
292         Properties p = new Properties();
293         p.setProperty("key", "value");
294 
295         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p))
296                 .withExpressionMarkers("@{", "}")
297                 .withEscapeString(null);
298 
299         String result = interpolator.interpolate("This is a test @{key}.");
300 
301         assertEquals("This is a test value.", result);
302     }
303 
304     @Test
305     void testOnlyEscapeExprAtStart() throws InterpolationException {
306         Properties p = new Properties();
307         p.setProperty("key", "value");
308 
309         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p))
310                 .withExpressionMarkers("@{", "}")
311                 .withEscapeString("\\");
312 
313         String result = interpolator.interpolate("\\@{key} This is a test.");
314 
315         assertEquals("@{key} This is a test.", result);
316     }
317 
318     @Test
319     void testNotEscapeExprAtStart() throws InterpolationException {
320         Properties p = new Properties();
321         p.setProperty("key", "value");
322 
323         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p))
324                 .withExpressionMarkers("@{", "}")
325                 .withEscapeString("\\");
326 
327         String result = interpolator.interpolate("@{key} This is a test.");
328 
329         assertEquals("value This is a test.", result);
330     }
331 
332     @Test
333     void testEscapeExprAtStart() throws InterpolationException {
334         Properties p = new Properties();
335         p.setProperty("key", "value");
336 
337         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p))
338                 .withExpressionMarkers("@", "@")
339                 .withEscapeString("\\");
340 
341         String result = interpolator.interpolate("\\@key@ This is a test @key@.");
342 
343         assertEquals("@key@ This is a test value.", result);
344     }
345 
346     @Test
347     void testNPEFree() throws InterpolationException {
348         Properties p = new Properties();
349         p.setProperty("key", "value");
350 
351         FixedStringSearchInterpolator interpolator = create(new PropertiesBasedValueSource(p))
352                 .withExpressionMarkers("@{", "}")
353                 .withEscapeString("\\");
354 
355         String result = interpolator.interpolate(null);
356 
357         assertEquals("", result);
358     }
359 
360     @Test
361     void testInterruptedInterpolate() throws InterpolationException {
362         final boolean[] error = new boolean[] {false};
363         FixedValueSource valueSource = new FixedValueSource() {
364             public Object getValue(String expression, InterpolationState errorCollector) {
365                 if (expression.equals("key")) {
366                     if (error[0]) {
367                         throw new IllegalStateException("broken");
368                     }
369                     return "val";
370                 } else {
371                     return null;
372                 }
373             }
374         };
375 
376         FixedStringSearchInterpolator interpolator = create(valueSource);
377 
378         assertEquals("-val-", interpolator.interpolate("-${key}-"), "control case");
379         error[0] = true;
380 
381         assertThrows(
382                 IllegalStateException.class,
383                 () -> interpolator.interpolate("-${key}-"),
384                 "should have thrown exception");
385 
386         error[0] = false;
387         assertEquals("-val-", interpolator.interpolate("-${key}-"), "should not believe there is a cycle here");
388     }
389 
390     public String getVar() {
391         return "testVar";
392     }
393 
394     public Person[] getAnArray() {
395         Person[] array = new Person[3];
396         array[0] = new Person("Gabriel");
397         array[1] = new Person("Daniela");
398         array[2] = new Person("testIndexedWithArray");
399         return array;
400     }
401 
402     public List<Person> getList() {
403         List<Person> list = new ArrayList<Person>();
404         list.add(new Person("Gabriel"));
405         list.add(new Person("testIndexedWithList"));
406         list.add(new Person("Daniela"));
407         return list;
408     }
409 
410     public Map<String, Person> getMap() {
411         Map<String, Person> map = new HashMap<String, Person>();
412         map.put("Key with spaces", new Person("testMap"));
413         return map;
414     }
415 
416     public static class Person {
417         private String name;
418 
419         public Person(String name) {
420             this.name = name;
421         }
422 
423         public String getName() {
424             return name;
425         }
426     }
427 
428     @Test
429     void testLinkedInterpolators() {
430         final String EXPR = "${test.label}AND${test2}";
431         final String EXPR2 = "${test.label}${test2.label}AND${test2}";
432 
433         FixedStringSearchInterpolator interWith2Fields =
434                 create(properttyBasedValueSource("test.label", "p", "test2", "x"));
435         assertEquals("pANDx", interWith2Fields.interpolate(EXPR));
436 
437         FixedStringSearchInterpolator joined = create(interWith2Fields, properttyBasedValueSource("test2.label", "zz"));
438         assertEquals("pzzANDx", joined.interpolate(EXPR2));
439     }
440 
441     @Test
442     void testDominance() {
443         final String EXPR = "${test.label}AND${test2}";
444         final String EXPR2 = "${test.label}${test2.label}AND${test2}";
445 
446         FixedStringSearchInterpolator interWith2Fields =
447                 create(properttyBasedValueSource("test.label", "p", "test2", "x", "test2.label", "dominant"));
448         assertEquals("pANDx", interWith2Fields.interpolate(EXPR));
449 
450         FixedStringSearchInterpolator joined = create(interWith2Fields, properttyBasedValueSource("test2.label", "zz"));
451         assertEquals("pdominantANDx", joined.interpolate(EXPR2));
452     }
453 
454     @Test
455     void unresolable_linked() {
456         final String EXPR2 = "${test.label}${test2.label}AND${test2}";
457 
458         FixedStringSearchInterpolator interWith2Fields =
459                 create(properttyBasedValueSource("test.label", "p", "test2", "x", "test2.label", "dominant"));
460 
461         FixedStringSearchInterpolator joined = create(interWith2Fields, properttyBasedValueSource("test2.label", "zz"));
462         assertEquals("pdominantANDx", joined.interpolate(EXPR2));
463     }
464 
465     @Test
466     void testCyclesWithLinked() {
467         assertThrows(InterpolationCycleException.class, () -> {
468             FixedStringSearchInterpolator first = create(properttyBasedValueSource("key1", "${key2}"));
469             FixedStringSearchInterpolator second = create(first, properttyBasedValueSource("key2", "${key1}"));
470             second.interpolate("${key2}");
471         });
472     }
473 
474     @Test
475     void testCyclesWithLinked_betweenRootAndOther() {
476         assertThrows(InterpolationCycleException.class, () -> {
477             FixedStringSearchInterpolator first = create(properttyBasedValueSource("key1", "${key2}"));
478             FixedStringSearchInterpolator second = create(first, properttyBasedValueSource("key2", "${key1}"));
479             second.interpolate("${key1}");
480         });
481     }
482 
483     @Test
484     void fixedInjectedIntoRegular() throws InterpolationException {
485         FixedStringSearchInterpolator first = create(properttyBasedValueSource("key1", "v1"));
486 
487         Properties p = new Properties();
488         p.setProperty("key", "X");
489         StringSearchInterpolator interpolator = new StringSearchInterpolator("${", "}");
490         interpolator.setEscapeString("\\");
491         interpolator.addValueSource(new org.codehaus.plexus.interpolation.PropertiesBasedValueSource(p));
492         interpolator.addValueSource(new FixedInterpolatorValueSource(first));
493         assertEquals("v1X", interpolator.interpolate("${key1}${key}"));
494     }
495 
496     private PropertiesBasedValueSource properttyBasedValueSource(String... values) {
497         Properties p = new Properties();
498         for (int i = 0; i < values.length; i += 2) {
499             p.setProperty(values[i], values[i + 1]);
500         }
501         return new PropertiesBasedValueSource(p);
502     }
503 }