1   package org.apache.maven.model.interpolation;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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  /**
37   * @author jdcasey
38   * @author Benjamin Bentmann
39   * @version $Id: StringSearchModelInterpolatorTest.java 1000601 2010-09-23 20:05:09Z bentmann $
40   */
41  public class StringSearchModelInterpolatorTest
42      extends AbstractModelInterpolatorTest 
43  {
44  
45  
46      protected ModelInterpolator interpolator;
47  
48      @Override
49      protected void setUp()
50          throws Exception
51      {
52          super.setUp();
53          interpolator =  lookup(ModelInterpolator.class);
54      }
55  
56  
57      protected ModelInterpolator createInterpolator( org.apache.maven.model.path.PathTranslator translator )
58          throws Exception
59      {
60          return this.interpolator;
61      }
62  
63      protected ModelInterpolator createInterpolator()
64          throws Exception
65      {
66          return this.interpolator;
67      }
68  
69      public void testInterpolateStringArray()
70          throws Exception
71      {
72          Model model = new Model();
73  
74          Properties p = new Properties();
75          p.setProperty( "key", "value" );
76          p.setProperty( "key2", "value2" );
77  
78          String[] values = { "${key}", "${key2}" };
79  
80          StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
81  
82          ModelBuildingRequest config = createModelBuildingRequest(p);
83  
84          final SimpleProblemCollector collector = new SimpleProblemCollector();
85          interpolator.interpolateObject( values, model, new File( "." ), config, collector );
86          assertProblemFree(  collector );
87          
88  
89          assertEquals( "value", values[0] );
90          assertEquals( "value2", values[1] );
91      }
92  
93      private ModelBuildingRequest createModelBuildingRequest(Properties p) {
94          ModelBuildingRequest config = new DefaultModelBuildingRequest();
95          config.setSystemProperties( p);
96          return config;
97      }
98  
99      public void testInterpolateObjectWithStringArrayField()
100         throws Exception
101     {
102         Model model = new Model();
103 
104         Properties p = new Properties();
105         p.setProperty( "key", "value" );
106         p.setProperty( "key2", "value2" );
107 
108         String[] values = { "${key}", "${key2}" };
109 
110         ObjectWithStringArrayField obj = new ObjectWithStringArrayField( values );
111 
112         StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
113 
114         ModelBuildingRequest config = createModelBuildingRequest(p);
115 
116         final SimpleProblemCollector collector = new SimpleProblemCollector();
117         interpolator.interpolateObject( obj, model, new File( "." ), config, collector );
118         assertProblemFree(  collector );
119         
120 
121         assertEquals( "value", obj.values[0] );
122         assertEquals( "value2", obj.values[1] );
123     }
124 
125     public void testInterpolateObjectWithStringListField()
126         throws Exception
127     {
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<String>();
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 
149         assertEquals( "value", obj.values.get( 0 ) );
150         assertEquals( "value2", obj.values.get( 1 ) );
151     }
152 
153     public void testInterpolateObjectWithStringListFieldAndOneLiteralValue()
154         throws Exception
155     {
156         Model model = new Model();
157 
158         Properties p = new Properties();
159         p.setProperty( "key", "value" );
160         p.setProperty( "key2", "value2" );
161 
162         List<String> values = new ArrayList<String>();
163         values.add( "key" );
164         values.add( "${key2}" );
165 
166         ObjectWithListField obj = new ObjectWithListField( values );
167 
168         StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
169 
170         ModelBuildingRequest config = createModelBuildingRequest(p);
171 
172         final SimpleProblemCollector collector = new SimpleProblemCollector();
173         interpolator.interpolateObject( obj, model, new File( "." ), config, collector );
174         assertProblemFree(  collector );
175         
176 
177         assertEquals( "key", obj.values.get( 0 ) );
178         assertEquals( "value2", obj.values.get( 1 ) );
179     }
180 
181     public void testInterpolateObjectWithUnmodifiableStringListField()
182         throws Exception
183     {
184         Model model = new Model();
185 
186         Properties p = new Properties();
187         p.setProperty( "key", "value" );
188         p.setProperty( "key2", "value2" );
189 
190         List values = Collections.unmodifiableList( Collections.singletonList( "${key}" ) );
191 
192         ObjectWithListField obj = new ObjectWithListField( values );
193 
194         StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
195 
196         ModelBuildingRequest config = createModelBuildingRequest(p);
197 
198         final SimpleProblemCollector collector = new SimpleProblemCollector();
199         interpolator.interpolateObject( obj, model, new File( "." ), config, collector );
200         assertProblemFree(  collector );
201         
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<String[]>();
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 
232         assertEquals( "value", ( (String[]) obj.values.get( 0 ) )[0] );
233         assertEquals( "value2", ( (String[]) obj.values.get( 0 ) )[1] );
234         assertEquals( "value3", ( (String[]) obj.values.get( 1 ) )[0] );
235         assertEquals( "value4", ( (String[]) obj.values.get( 1 ) )[1] );
236     }
237 
238     public void testInterpolateObjectWithStringToStringMapField()
239         throws Exception
240     {
241         Model model = new Model();
242 
243         Properties p = new Properties();
244         p.setProperty( "key", "value" );
245         p.setProperty( "key2", "value2" );
246 
247         Map<String, String> values = new HashMap<String, String>();
248         values.put( "key", "${key}" );
249         values.put( "key2", "${key2}" );
250 
251         ObjectWithMapField obj = new ObjectWithMapField( values );
252 
253         StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
254 
255         ModelBuildingRequest config = createModelBuildingRequest(p);
256 
257         final SimpleProblemCollector collector = new SimpleProblemCollector();
258         interpolator.interpolateObject( obj, model, new File( "." ), config, collector );
259         assertProblemFree(  collector );
260         
261 
262         assertEquals( "value", obj.values.get( "key" ) );
263         assertEquals( "value2", obj.values.get( "key2" ) );
264     }
265 
266     public void testInterpolateObjectWithStringToStringMapFieldAndOneLiteralValue()
267         throws Exception
268     {
269         Model model = new Model();
270 
271         Properties p = new Properties();
272         p.setProperty( "key", "value" );
273         p.setProperty( "key2", "value2" );
274 
275         Map<String, String> values = new HashMap<String, String>();
276         values.put( "key", "val" );
277         values.put( "key2", "${key2}" );
278 
279         ObjectWithMapField obj = new ObjectWithMapField( values );
280 
281         StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
282 
283         ModelBuildingRequest config = createModelBuildingRequest(p);
284 
285         final SimpleProblemCollector collector = new SimpleProblemCollector();
286         interpolator.interpolateObject( obj, model, new File( "." ), config, collector );
287         assertProblemFree(  collector );
288         
289 
290         assertEquals( "val", obj.values.get( "key" ) );
291         assertEquals( "value2", obj.values.get( "key2" ) );
292     }
293 
294     public void testInterpolateObjectWithUnmodifiableStringToStringMapField()
295         throws Exception
296     {
297         Model model = new Model();
298 
299         Properties p = new Properties();
300         p.setProperty( "key", "value" );
301         p.setProperty( "key2", "value2" );
302 
303         Map<String, String> values = Collections.unmodifiableMap( Collections.singletonMap( "key", "${key}" ) );
304 
305         ObjectWithMapField obj = new ObjectWithMapField( values );
306 
307         StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
308 
309         ModelBuildingRequest config = createModelBuildingRequest(p);
310 
311         final SimpleProblemCollector collector = new SimpleProblemCollector();
312         interpolator.interpolateObject( obj, model, new File( "." ), config, collector );
313         assertProblemFree(  collector );
314         
315 
316         assertEquals( "${key}", obj.values.get( "key" ) );
317     }
318 
319     public void testInterpolateObjectWithStringToStringArrayMapField()
320         throws Exception
321     {
322         Model model = new Model();
323 
324         Properties p = new Properties();
325         p.setProperty( "key", "value" );
326         p.setProperty( "key2", "value2" );
327         p.setProperty( "key3", "value3" );
328         p.setProperty( "key4", "value4" );
329 
330         Map<String, String[]> values = new HashMap<String, String[]>();
331         values.put( "key", new String[] { "${key}", "${key2}" } );
332         values.put( "key2", new String[] { "${key3}", "${key4}" } );
333 
334         ObjectWithMapField obj = new ObjectWithMapField( values );
335 
336         StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
337 
338         ModelBuildingRequest config = createModelBuildingRequest(p);
339 
340         final SimpleProblemCollector collector = new SimpleProblemCollector();
341         interpolator.interpolateObject( obj, model, new File( "." ), config, collector );
342         assertProblemFree(  collector );
343         
344 
345         assertEquals( "value", ( (String[]) obj.values.get( "key" ) )[0] );
346         assertEquals( "value2", ( (String[]) obj.values.get( "key" ) )[1] );
347         assertEquals( "value3", ( (String[]) obj.values.get( "key2" ) )[0] );
348         assertEquals( "value4", ( (String[]) obj.values.get( "key2" ) )[1] );
349     }
350 
351 
352     public void testConcurrentInterpolation() throws Exception {
353         final Model model = new Model();
354 
355         final Properties p = new Properties();
356         p.setProperty( "key", "value" );
357         p.setProperty( "key2", "value2" );
358         p.setProperty( "key3", "value3" );
359         p.setProperty( "key4", "value4" );
360         p.setProperty( "key5", "value5" );
361 
362         final StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
363 
364 
365         int numItems = 100;
366         final CountDownLatch countDownLatch = new CountDownLatch(1);
367 
368         List<Future<SimpleProblemCollector>>  futures = new ArrayList<Future<SimpleProblemCollector>>();
369         for (int i = 0; i < numItems; i++){
370             Callable<SimpleProblemCollector> future = new Callable<SimpleProblemCollector>() {
371                 public SimpleProblemCollector call() throws Exception {
372                     final ObjectWithMixedProtection obj = getValueList();
373                     final ModelBuildingRequest config = createModelBuildingRequest(p);
374 
375                     countDownLatch.await();
376                     final SimpleProblemCollector collector = new SimpleProblemCollector();
377                     interpolator.interpolateObject( obj, model, new File( "." ), config, collector);
378                     return collector;
379                 }
380             };
381             FutureTask<SimpleProblemCollector> task = new FutureTask<SimpleProblemCollector>(future);
382             futures.add ( task);
383             new Thread( task).start();
384         }
385         countDownLatch.countDown(); // Start all the threads
386         for(Future<SimpleProblemCollector> result : futures){
387             SimpleProblemCollector problemCollector = result.get(); // ArrayIndexOutOfBoundsException are typical indication of threading issues
388             assertProblemFree(  problemCollector );
389             
390         }
391     }
392 
393     private ObjectWithMixedProtection getValueList()
394     {
395         List<String[]> values = new ArrayList<String[]>();
396 
397         values.add( new String[] { "${key}", "${key2}" } );
398         values.add( new String[] { "${key3}", "${key4}" } );
399         List<String> values2 = new ArrayList<String>();
400         values.add( new String[] { "${key}", "${key2}" } );
401         values.add( new String[] { "${key3}", "${key4}" } );
402         List<String> values3 = new ArrayList<String>();
403         values.add( new String[] { "${key}", "${key2}" } );
404         values.add( new String[] { "${key3}", "${key4}" } );
405 
406         return new ObjectWithMixedProtection( values, values2, values3, "${key5}" );
407     }
408 
409 
410     private static final class ObjectWithStringArrayField
411     {
412         private final String[] values;
413 
414         public ObjectWithStringArrayField( String[] values )
415         {
416             this.values = values;
417         }
418     }
419 
420     private static final class ObjectWithListField
421     {
422         private final List<?> values;
423 
424         public ObjectWithListField( List<?> values )
425         {
426             this.values = values;
427         }
428     }
429 
430     private static final class ObjectWithMapField
431     {
432         private final Map<?, ?> values;
433 
434         public ObjectWithMapField( Map<?, ?> values )
435         {
436             this.values = values;
437         }
438     }
439 
440     @SuppressWarnings({"UnusedDeclaration", "unused"})
441     private static final class ObjectWithMixedProtection
442     {
443         private List<?> values1;
444         protected List<?> values2;
445         List<?> values3;
446         private String fooBar;
447 
448         private ObjectWithMixedProtection(List<?> values1, List<?> values2, List<?> values3) {
449             this.values1 = values1;
450             this.values2 = values2;
451             this.values3 = values3;
452         }
453 
454         private ObjectWithMixedProtection( List<?> values1, List<?> values2, List<?> values3, String fooBar )
455         {
456             this.values1 = values1;
457             this.values2 = values2;
458             this.values3 = values3;
459             this.fooBar = fooBar;
460         }
461 
462         public String getFooBar()
463         {
464             return fooBar;
465         }
466     }
467     
468     public void testFinalFieldsExcludedFromInterpolation()
469     {
470         Properties props = new Properties();
471         props.setProperty( "expression", "value" );
472         DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
473         request.setUserProperties( props );
474 
475         SimpleProblemCollector problems = new SimpleProblemCollector();
476         StringSearchModelInterpolator interpolator = new StringSearchModelInterpolator();
477         interpolator.interpolateObject( new ClassWithFinalField(), new Model(), null, request, problems );
478 
479         assertProblemFree(  problems );
480     }
481 
482     @SuppressWarnings({"UnusedDeclaration"})
483     static class ClassWithFinalField
484     {
485         public static final String CONSTANT = "${expression}";
486     }
487 
488     public void testLocationTrackerShouldBeExcludedFromInterpolation()
489     {
490         Properties props = new Properties();
491         props.setProperty( "expression", "value" );
492         DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
493         request.setUserProperties( props );
494 
495         InputSource source = new InputSource();
496         source.setLocation( "${expression}" );
497         source.setModelId( "${expression}" );
498         Model model = new Model();
499         model.setLocation( "", new InputLocation( 1, 1, source ) );
500 
501         SimpleProblemCollector problems = new SimpleProblemCollector();
502         StringSearchModelInterpolator interpolator = new StringSearchModelInterpolator();
503         interpolator.interpolateObject( model, model, null, request, problems );
504 
505         assertProblemFree( problems );
506         assertEquals( "${expression}", source.getLocation() );
507         assertEquals( "${expression}", source.getModelId() );
508     }
509 
510 }