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