1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.model.interpolation;
20
21 import java.io.File;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.concurrent.Callable;
29 import java.util.concurrent.CountDownLatch;
30 import java.util.concurrent.Future;
31 import java.util.concurrent.FutureTask;
32
33 import org.apache.maven.model.InputLocation;
34 import org.apache.maven.model.InputSource;
35 import org.apache.maven.model.Model;
36 import org.apache.maven.model.building.DefaultModelBuildingRequest;
37 import org.apache.maven.model.building.ModelBuildingRequest;
38 import org.apache.maven.model.building.SimpleProblemCollector;
39 import org.junit.jupiter.api.BeforeEach;
40 import org.junit.jupiter.api.Test;
41
42 import static org.hamcrest.CoreMatchers.anyOf;
43 import static org.hamcrest.CoreMatchers.is;
44 import static org.hamcrest.MatcherAssert.assertThat;
45 import static org.junit.jupiter.api.Assertions.assertEquals;
46 import static org.junit.jupiter.api.Assertions.assertNotNull;
47 import static org.powermock.reflect.Whitebox.getField;
48 import static org.powermock.reflect.Whitebox.getInternalState;
49
50
51
52
53
54 public class StringSearchModelInterpolatorTest extends AbstractModelInterpolatorTest {
55
56 protected ModelInterpolator interpolator;
57
58 @BeforeEach
59 protected void setUp() throws Exception {
60 super.setUp();
61 interpolator =
62 new StringSearchModelInterpolator().setVersionPropertiesProcessor(new DefaultModelVersionProcessor());
63 }
64
65 protected ModelInterpolator createInterpolator(org.apache.maven.model.path.PathTranslator translator)
66 throws Exception {
67 return this.interpolator;
68 }
69
70 protected ModelInterpolator createInterpolator() throws Exception {
71 return this.interpolator;
72 }
73
74 @Test
75 public void testInterpolateStringArray() throws Exception {
76 Model model = new Model();
77
78 Properties p = new Properties();
79 p.setProperty("key", "value");
80 p.setProperty("key2", "value2");
81
82 String[] values = {"${key}", "${key2}"};
83
84 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
85
86 ModelBuildingRequest config = createModelBuildingRequest(p);
87
88 final SimpleProblemCollector collector = new SimpleProblemCollector();
89 interpolator.interpolateObject(values, model, new File("."), config, collector);
90 assertProblemFree(collector);
91
92 assertEquals("value", values[0]);
93 assertEquals("value2", values[1]);
94 }
95
96 private ModelBuildingRequest createModelBuildingRequest(Properties p) {
97 ModelBuildingRequest config = new DefaultModelBuildingRequest();
98 config.setSystemProperties(p);
99 return config;
100 }
101
102 @Test
103 public void testInterpolateObjectWithStringArrayField() throws Exception {
104 Model model = new Model();
105
106 Properties p = new Properties();
107 p.setProperty("key", "value");
108 p.setProperty("key2", "value2");
109
110 String[] values = {"${key}", "${key2}"};
111
112 ObjectWithStringArrayField obj = new ObjectWithStringArrayField(values);
113
114 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
115
116 ModelBuildingRequest config = createModelBuildingRequest(p);
117
118 final SimpleProblemCollector collector = new SimpleProblemCollector();
119 interpolator.interpolateObject(obj, model, new File("."), config, collector);
120 assertProblemFree(collector);
121
122 assertEquals("value", obj.values[0]);
123 assertEquals("value2", obj.values[1]);
124 }
125
126 @Test
127 public void testInterpolateObjectWithStringListField() throws Exception {
128 Model model = new Model();
129
130 Properties p = new Properties();
131 p.setProperty("key", "value");
132 p.setProperty("key2", "value2");
133
134 List<String> values = new ArrayList<>();
135 values.add("${key}");
136 values.add("${key2}");
137
138 ObjectWithListField obj = new ObjectWithListField(values);
139
140 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
141
142 ModelBuildingRequest config = createModelBuildingRequest(p);
143
144 final SimpleProblemCollector collector = new SimpleProblemCollector();
145 interpolator.interpolateObject(obj, model, new File("."), config, collector);
146 assertProblemFree(collector);
147
148 assertEquals("value", obj.values.get(0));
149 assertEquals("value2", obj.values.get(1));
150 }
151
152 @Test
153 public void testInterpolateObjectWithStringListFieldAndOneLiteralValue() throws Exception {
154 Model model = new Model();
155
156 Properties p = new Properties();
157 p.setProperty("key", "value");
158 p.setProperty("key2", "value2");
159
160 List<String> values = new ArrayList<>();
161 values.add("key");
162 values.add("${key2}");
163
164 ObjectWithListField obj = new ObjectWithListField(values);
165
166 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
167
168 ModelBuildingRequest config = createModelBuildingRequest(p);
169
170 final SimpleProblemCollector collector = new SimpleProblemCollector();
171 interpolator.interpolateObject(obj, model, new File("."), config, collector);
172 assertProblemFree(collector);
173
174 assertEquals("key", obj.values.get(0));
175 assertEquals("value2", obj.values.get(1));
176 }
177
178 @Test
179 public void testInterpolateObjectWithUnmodifiableStringListField() throws Exception {
180 Model model = new Model();
181
182 Properties p = new Properties();
183 p.setProperty("key", "value");
184 p.setProperty("key2", "value2");
185
186 List<String> values = Collections.unmodifiableList(Collections.singletonList("${key}"));
187
188 ObjectWithListField obj = new ObjectWithListField(values);
189
190 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
191
192 ModelBuildingRequest config = createModelBuildingRequest(p);
193
194 final SimpleProblemCollector collector = new SimpleProblemCollector();
195 interpolator.interpolateObject(obj, model, new File("."), config, collector);
196 assertProblemFree(collector);
197
198 assertEquals("${key}", obj.values.get(0));
199 }
200
201 @Test
202 public void testInterpolateObjectWithStringArrayListField() throws Exception {
203 Model model = new Model();
204
205 Properties p = new Properties();
206 p.setProperty("key", "value");
207 p.setProperty("key2", "value2");
208 p.setProperty("key3", "value3");
209 p.setProperty("key4", "value4");
210
211 List<String[]> values = new ArrayList<>();
212 values.add(new String[] {"${key}", "${key2}"});
213 values.add(new String[] {"${key3}", "${key4}"});
214
215 ObjectWithListField obj = new ObjectWithListField(values);
216
217 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
218
219 ModelBuildingRequest config = createModelBuildingRequest(p);
220
221 final SimpleProblemCollector collector = new SimpleProblemCollector();
222 interpolator.interpolateObject(obj, model, new File("."), config, collector);
223 assertProblemFree(collector);
224
225 assertEquals("value", ((String[]) obj.values.get(0))[0]);
226 assertEquals("value2", ((String[]) obj.values.get(0))[1]);
227 assertEquals("value3", ((String[]) obj.values.get(1))[0]);
228 assertEquals("value4", ((String[]) obj.values.get(1))[1]);
229 }
230
231 @Test
232 public void testInterpolateObjectWithStringToStringMapField() throws Exception {
233 Model model = new Model();
234
235 Properties p = new Properties();
236 p.setProperty("key", "value");
237 p.setProperty("key2", "value2");
238
239 Map<String, String> values = new HashMap<>();
240 values.put("key", "${key}");
241 values.put("key2", "${key2}");
242
243 ObjectWithMapField obj = new ObjectWithMapField(values);
244
245 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
246
247 ModelBuildingRequest config = createModelBuildingRequest(p);
248
249 final SimpleProblemCollector collector = new SimpleProblemCollector();
250 interpolator.interpolateObject(obj, model, new File("."), config, collector);
251 assertProblemFree(collector);
252
253 assertEquals("value", obj.values.get("key"));
254 assertEquals("value2", obj.values.get("key2"));
255 }
256
257 @Test
258 public void testInterpolateObjectWithStringToStringMapFieldAndOneLiteralValue() throws Exception {
259 Model model = new Model();
260
261 Properties p = new Properties();
262 p.setProperty("key", "value");
263 p.setProperty("key2", "value2");
264
265 Map<String, String> values = new HashMap<>();
266 values.put("key", "val");
267 values.put("key2", "${key2}");
268
269 ObjectWithMapField obj = new ObjectWithMapField(values);
270
271 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
272
273 ModelBuildingRequest config = createModelBuildingRequest(p);
274
275 final SimpleProblemCollector collector = new SimpleProblemCollector();
276 interpolator.interpolateObject(obj, model, new File("."), config, collector);
277 assertProblemFree(collector);
278
279 assertEquals("val", obj.values.get("key"));
280 assertEquals("value2", obj.values.get("key2"));
281 }
282
283 @Test
284 public void testInterpolateObjectWithUnmodifiableStringToStringMapField() throws Exception {
285 Model model = new Model();
286
287 Properties p = new Properties();
288 p.setProperty("key", "value");
289 p.setProperty("key2", "value2");
290
291 Map<String, String> values = Collections.unmodifiableMap(Collections.singletonMap("key", "${key}"));
292
293 ObjectWithMapField obj = new ObjectWithMapField(values);
294
295 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
296
297 ModelBuildingRequest config = createModelBuildingRequest(p);
298
299 final SimpleProblemCollector collector = new SimpleProblemCollector();
300 interpolator.interpolateObject(obj, model, new File("."), config, collector);
301 assertProblemFree(collector);
302
303 assertEquals("${key}", obj.values.get("key"));
304 }
305
306 @Test
307 public void testInterpolateObjectWithStringToStringArrayMapField() throws Exception {
308 Model model = new Model();
309
310 Properties p = new Properties();
311 p.setProperty("key", "value");
312 p.setProperty("key2", "value2");
313 p.setProperty("key3", "value3");
314 p.setProperty("key4", "value4");
315
316 Map<String, String[]> values = new HashMap<>();
317 values.put("key", new String[] {"${key}", "${key2}"});
318 values.put("key2", new String[] {"${key3}", "${key4}"});
319
320 ObjectWithMapField obj = new ObjectWithMapField(values);
321
322 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
323
324 ModelBuildingRequest config = createModelBuildingRequest(p);
325
326 final SimpleProblemCollector collector = new SimpleProblemCollector();
327 interpolator.interpolateObject(obj, model, new File("."), config, collector);
328 assertProblemFree(collector);
329
330 assertEquals("value", ((String[]) obj.values.get("key"))[0]);
331 assertEquals("value2", ((String[]) obj.values.get("key"))[1]);
332 assertEquals("value3", ((String[]) obj.values.get("key2"))[0]);
333 assertEquals("value4", ((String[]) obj.values.get("key2"))[1]);
334 }
335
336 @Test
337 public void testInterpolateObjectWithPomFile() throws Exception {
338 Model model = new Model();
339 model.setPomFile(new File(System.getProperty("user.dir"), "pom.xml"));
340 File baseDir = model.getProjectDirectory();
341
342 Properties p = new Properties();
343
344 Map<String, String> values = new HashMap<>();
345 values.put("key", "${project.basedir}" + File.separator + "target");
346
347 ObjectWithMapField obj = new ObjectWithMapField(values);
348
349 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
350
351 ModelBuildingRequest config = createModelBuildingRequest(p);
352
353 SimpleProblemCollector collector = new SimpleProblemCollector();
354 interpolator.interpolateObject(obj, model, new File("."), config, collector);
355 assertProblemFree(collector);
356
357 assertEquals(System.getProperty("user.dir"), baseDir.getAbsolutePath());
358 assertEquals(1, obj.values.size());
359 assertThat(
360 (String) obj.values.get("key"),
361 is(anyOf(
362 is(System.getProperty("user.dir") + File.separator + "target"),
363
364 is(System.getProperty("user.dir") + File.separator + '.' + File.separator + "target"))));
365 }
366
367 @Test
368 public void testNotInterpolateObjectWithFile() throws Exception {
369 Model model = new Model();
370
371 File baseDir = new File(System.getProperty("user.dir"));
372
373 Properties p = new Properties();
374
375 ObjectWithNotInterpolatedFile obj = new ObjectWithNotInterpolatedFile(baseDir);
376
377 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
378
379 ModelBuildingRequest config = createModelBuildingRequest(p);
380
381 SimpleProblemCollector collector = new SimpleProblemCollector();
382 interpolator.interpolateObject(obj, model, new File("."), config, collector);
383 assertProblemFree(collector);
384
385
386 Map<Class<?>, ?> cache = (Map<Class<?>, ?>)
387 getField(StringSearchModelInterpolator.class, "CACHED_ENTRIES").get(null);
388
389 Object objCacheItem = cache.get(Object.class);
390 Object fileCacheItem = cache.get(File.class);
391
392 assertNotNull(objCacheItem);
393 assertNotNull(fileCacheItem);
394
395 assertEquals(0, ((Object[]) getInternalState(objCacheItem, "fields")).length);
396 assertEquals(0, ((Object[]) getInternalState(fileCacheItem, "fields")).length);
397 }
398
399 @Test
400 public void testNotInterpolateFile() throws Exception {
401 Model model = new Model();
402
403 File baseDir = new File(System.getProperty("user.dir"));
404
405 Properties p = new Properties();
406
407 StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
408
409 ModelBuildingRequest config = createModelBuildingRequest(p);
410
411 SimpleProblemCollector collector = new SimpleProblemCollector();
412 interpolator.interpolateObject(baseDir, model, new File("."), config, collector);
413 assertProblemFree(collector);
414
415
416 Map<Class<?>, ?> cache = (Map<Class<?>, ?>)
417 getField(StringSearchModelInterpolator.class, "CACHED_ENTRIES").get(null);
418
419 Object fileCacheItem = cache.get(File.class);
420
421 assertNotNull(fileCacheItem);
422
423 assertEquals(0, ((Object[]) getInternalState(fileCacheItem, "fields")).length);
424 }
425
426 @Test
427 public void testConcurrentInterpolation() throws Exception {
428 final Model model = new Model();
429
430 final Properties p = new Properties();
431 p.setProperty("key", "value");
432 p.setProperty("key2", "value2");
433 p.setProperty("key3", "value3");
434 p.setProperty("key4", "value4");
435 p.setProperty("key5", "value5");
436
437 final StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
438
439 int numItems = 100;
440 final CountDownLatch countDownLatch = new CountDownLatch(1);
441
442 List<Future<SimpleProblemCollector>> futures = new ArrayList<>();
443 for (int i = 0; i < numItems; i++) {
444 Callable<SimpleProblemCollector> future = new Callable<SimpleProblemCollector>() {
445 public SimpleProblemCollector call() throws Exception {
446 final ObjectWithMixedProtection obj = getValueList();
447 final ModelBuildingRequest config = createModelBuildingRequest(p);
448
449 countDownLatch.await();
450 final SimpleProblemCollector collector = new SimpleProblemCollector();
451 interpolator.interpolateObject(obj, model, new File("."), config, collector);
452 return collector;
453 }
454 };
455 FutureTask<SimpleProblemCollector> task = new FutureTask<>(future);
456 futures.add(task);
457 new Thread(task).start();
458 }
459 countDownLatch.countDown();
460 for (Future<SimpleProblemCollector> result : futures) {
461 SimpleProblemCollector problemCollector =
462 result.get();
463 assertProblemFree(problemCollector);
464 }
465 }
466
467 private ObjectWithMixedProtection getValueList() {
468 List<String[]> values = new ArrayList<>();
469
470 values.add(new String[] {"${key}", "${key2}"});
471 values.add(new String[] {"${key3}", "${key4}"});
472 List<String> values2 = new ArrayList<>();
473 values.add(new String[] {"${key}", "${key2}"});
474 values.add(new String[] {"${key3}", "${key4}"});
475 List<String> values3 = new ArrayList<>();
476 values.add(new String[] {"${key}", "${key2}"});
477 values.add(new String[] {"${key3}", "${key4}"});
478
479 return new ObjectWithMixedProtection(values, values2, values3, "${key5}");
480 }
481
482 private static final class ObjectWithStringArrayField {
483 private final String[] values;
484
485 ObjectWithStringArrayField(String[] values) {
486 this.values = values;
487 }
488 }
489
490 private static final class ObjectWithListField {
491 private final List<?> values;
492
493 ObjectWithListField(List<?> values) {
494 this.values = values;
495 }
496 }
497
498 private static final class ObjectWithMapField {
499 private final Map<?, ?> values;
500
501 ObjectWithMapField(Map<?, ?> values) {
502 this.values = values;
503 }
504 }
505
506 private static final class ObjectWithNotInterpolatedFile {
507 private final File f;
508
509 ObjectWithNotInterpolatedFile(File f) {
510 this.f = f;
511 }
512 }
513
514 @SuppressWarnings("unused")
515 private static final class ObjectWithMixedProtection {
516 private List<?> values1;
517 protected List<?> values2;
518 List<?> values3;
519 private String fooBar;
520
521 private ObjectWithMixedProtection(List<?> values1, List<?> values2, List<?> values3) {
522 this.values1 = values1;
523 this.values2 = values2;
524 this.values3 = values3;
525 }
526
527 private ObjectWithMixedProtection(List<?> values1, List<?> values2, List<?> values3, String fooBar) {
528 this.values1 = values1;
529 this.values2 = values2;
530 this.values3 = values3;
531 this.fooBar = fooBar;
532 }
533
534 public String getFooBar() {
535 return fooBar;
536 }
537 }
538
539 @Test
540 public void testFinalFieldsExcludedFromInterpolation() {
541 Properties props = new Properties();
542 props.setProperty("expression", "value");
543 DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
544 request.setUserProperties(props);
545
546 SimpleProblemCollector problems = new SimpleProblemCollector();
547 StringSearchModelInterpolator interpolator = new StringSearchModelInterpolator();
548 interpolator.setVersionPropertiesProcessor(new DefaultModelVersionProcessor());
549 interpolator.interpolateObject(new ClassWithFinalField(), new Model(), null, request, problems);
550
551 assertProblemFree(problems);
552 }
553
554 static class ClassWithFinalField {
555 public static final String CONSTANT = "${expression}";
556 }
557
558 @Test
559 public void testLocationTrackerShouldBeExcludedFromInterpolation() {
560 Properties props = new Properties();
561 props.setProperty("expression", "value");
562 DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
563 request.setUserProperties(props);
564
565 InputSource source = new InputSource();
566 source.setLocation("${expression}");
567 source.setModelId("${expression}");
568 Model model = new Model();
569 model.setLocation("", new InputLocation(1, 1, source));
570
571 SimpleProblemCollector problems = new SimpleProblemCollector();
572 StringSearchModelInterpolator interpolator = new StringSearchModelInterpolator();
573 interpolator.setVersionPropertiesProcessor(new DefaultModelVersionProcessor());
574 interpolator.interpolateObject(model, model, null, request, problems);
575
576 assertProblemFree(problems);
577 assertEquals("${expression}", source.getLocation());
578 assertEquals("${expression}", source.getModelId());
579 }
580 }