1   package org.apache.maven.project;
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 java.io.File;
23  import java.io.IOException;
24  import java.net.URI;
25  import java.net.URISyntaxException;
26  import java.net.URL;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.Map;
30  
31  import org.apache.maven.model.Build;
32  import org.apache.maven.model.Dependency;
33  import org.apache.maven.model.Plugin;
34  import org.apache.maven.model.Resource;
35  import org.apache.maven.project.interpolation.ModelInterpolationException;
36  import org.codehaus.plexus.PlexusTestCase;
37  import org.codehaus.plexus.util.StringUtils;
38  import org.codehaus.plexus.util.xml.Xpp3Dom;
39  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
40  
41  public class MavenProjectDynamismTest
42      extends PlexusTestCase
43  {
44  
45      private DefaultMavenProjectBuilder projectBuilder;
46  
47      public void setUp()
48          throws Exception
49      {
50          super.setUp();
51  
52          projectBuilder = (DefaultMavenProjectBuilder) lookup( MavenProjectBuilder.class.getName() );
53      }
54  
55      public void testBuildSectionGroupIdInterpolation()
56          throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException,
57          ModelInterpolationException
58      {
59          MavenProject project = buildProject( "pom-interp.xml" );
60  
61          projectBuilder.calculateConcreteState( project, new DefaultProjectBuilderConfiguration() );
62  
63          String basepath = new File( project.getBasedir(), project.getGroupId() ).getAbsolutePath();
64  
65          Build build = project.getBuild();
66  
67          assertTrue( build.getSourceDirectory() + " doesn't start with base-path: " + basepath,
68                      build.getSourceDirectory().startsWith( basepath ) );
69          assertTrue( build.getTestSourceDirectory() + " doesn't start with base-path: " + basepath,
70                      build.getTestSourceDirectory().startsWith( basepath ) );
71          
72          // TODO: MNG-3731
73  //        assertTrue( build.getScriptSourceDirectory() + " doesn't start with base-path: " + basepath,
74  //                    build.getScriptSourceDirectory().startsWith( basepath ) );
75  
76          List plugins = build.getPlugins();
77          assertNotNull( plugins );
78          assertEquals( 1, plugins.size() );
79  
80          Plugin plugin = (Plugin) plugins.get( 0 );
81          assertEquals( "my-plugin", plugin.getArtifactId() );
82  
83          Xpp3Dom conf = (Xpp3Dom) plugin.getConfiguration();
84          assertNotNull( conf );
85  
86          Xpp3Dom[] children = conf.getChildren();
87          assertEquals( 3, children.length );
88  
89          for ( int i = 0; i < children.length; i++ )
90          {
91              assertEquals( "Configuration parameter: " + children[i].getName()
92                  + " should have a an interpolated POM groupId as its value.", children[i].getValue(),
93                            project.getGroupId() );
94          }
95  
96          project.getProperties().setProperty( "foo", "bar" );
97  
98          projectBuilder.restoreDynamicState( project, new DefaultProjectBuilderConfiguration() );
99  
100         String projectGidExpr = "${project.groupId}";
101         String pomGidExpr = "${pom.groupId}";
102         String nakedGidExpr = "${groupId}";
103 
104         build = project.getBuild();
105 
106         assertTrue( build.getSourceDirectory() + " didn't start with: " + projectGidExpr,
107                     build.getSourceDirectory().startsWith( projectGidExpr ) );
108         assertTrue( build.getTestSourceDirectory() + " didn't start with: " + pomGidExpr,
109                     build.getTestSourceDirectory().startsWith( pomGidExpr ) );
110         assertTrue( build.getScriptSourceDirectory() + " didn't start with: " + nakedGidExpr,
111                     build.getScriptSourceDirectory().startsWith( nakedGidExpr ) );
112 
113         plugins = build.getPlugins();
114         assertNotNull( plugins );
115         assertEquals( 1, plugins.size() );
116 
117         plugin = (Plugin) plugins.get( 0 );
118         assertEquals( "my-plugin", plugin.getArtifactId() );
119 
120         conf = (Xpp3Dom) plugin.getConfiguration();
121         assertNotNull( conf );
122 
123         children = conf.getChildren();
124         assertEquals( 3, children.length );
125 
126         assertEquals( "Configuration parameter: " + children[0].getName() + " should have " + projectGidExpr
127             + " as its value.", children[0].getValue(), projectGidExpr );
128 
129         assertEquals( "Configuration parameter: " + children[1].getName() + " should have " + pomGidExpr
130             + " as its value.", children[1].getValue(), pomGidExpr );
131 
132         assertEquals( "Configuration parameter: " + children[2].getName() + " should have " + nakedGidExpr
133             + " as its value.", children[2].getValue(), nakedGidExpr );
134     }
135 
136     public void testRoundTrip()
137         throws IOException, XmlPullParserException, URISyntaxException, ModelInterpolationException,
138         ProjectBuildingException
139     {
140         MavenProject project = buildProject( "pom.xml" );
141         ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration();
142         projectBuilder.calculateConcreteState( project, config );
143 
144         File baseDir = project.getBasedir();
145         File buildDir = new File( baseDir, "target" );
146 
147         String basedirExpr = "${pom.basedir}";
148         String buildDirExpr = "${pom.build.directory}";
149 
150         assertTrue( project.isConcrete() );
151 
152         Build build = project.getBuild();
153 
154         assertEquals( "Concrete source directory should be absolute.",
155                       new File( baseDir, "/src/main/java" ).getAbsolutePath(),
156                       new File( build.getSourceDirectory() ).getAbsolutePath() );
157 
158         assertEquals( "Concrete test-source directory should be absolute.",
159                       new File( baseDir, "/src/test/java" ).getAbsolutePath(),
160                       new File( build.getTestSourceDirectory() ).getAbsolutePath() );
161 
162         assertEquals( "Concrete script-source directory should be absolute.",
163                       new File( baseDir, "/src/main/scripts" ).getAbsolutePath(),
164                       new File( build.getScriptSourceDirectory() ).getAbsolutePath() );
165 
166         List compileSourceRoots = project.getCompileSourceRoots();
167 
168         assertNotNull( "Concrete compile-source roots should not be null.", compileSourceRoots );
169 
170         assertEquals( "Concrete compile-source roots should contain one entry.", 1, compileSourceRoots.size() );
171 
172         assertEquals( "Concrete compile-source roots should contain interpolated source-directory value.",
173                       new File( baseDir, "/src/main/java" ).getAbsolutePath(),
174                       new File( (String) compileSourceRoots.get( 0 ) ).getAbsolutePath() );
175 
176         List testCompileSourceRoots = project.getTestCompileSourceRoots();
177 
178         assertNotNull( "Concrete test-compile-source roots should not be null.", testCompileSourceRoots );
179 
180         assertEquals( "Concrete test-compile-source roots should contain one entry.", 1, testCompileSourceRoots.size() );
181 
182         assertEquals( "Concrete test-compile-source roots should contain interpolated test-source-directory value.",
183                       new File( baseDir, "/src/test/java" ).getAbsolutePath(),
184                       new File( (String) testCompileSourceRoots.get( 0 ) ).getAbsolutePath() );
185 
186         List scriptSourceRoots = project.getScriptSourceRoots();
187 
188         assertNotNull( "Concrete script-source roots should not be null.", scriptSourceRoots );
189 
190         assertEquals( "Concrete script-source roots should contain one entry.", 1, scriptSourceRoots.size() );
191 
192         assertEquals( "Concrete script-source roots should contain interpolated script-source-directory value.",
193                       new File( baseDir, "/src/main/scripts" ).getAbsolutePath(),
194                       new File( (String) scriptSourceRoots.get( 0 ) ).getAbsolutePath() );
195 
196         List resources = build.getResources();
197 
198         assertNotNull( "Concrete resources should not be null.", resources );
199 
200         assertEquals( "Concrete resources should contain one entry.", 1, resources.size() );
201 
202         assertEquals( "Concrete resource should contain absolute path.",
203                       new File( buildDir, "generated-resources/plexus" ).getAbsolutePath(),
204                       new File( ( (Resource) resources.get( 0 ) ).getDirectory() ).getAbsolutePath() );
205 
206         List filters = build.getFilters();
207 
208         assertNotNull( "Concrete filters should not be null.", filters );
209 
210         assertEquals( "Concrete filters should contain one entry.", 1, filters.size() );
211 
212         assertEquals( "Concrete filter entry should contain absolute path.",
213                       new File( buildDir, "/generated-filters.properties" ).getAbsolutePath(),
214                       new File( (String) filters.get( 0 ) ).getAbsolutePath() );
215 
216         assertEquals( "Concrete output-directory should be absolute.",
217                       new File( buildDir, "/classes" ).getAbsolutePath(),
218                       new File( build.getOutputDirectory() ).getAbsolutePath() );
219 
220         assertEquals( "Concrete test-output-directory should be absolute.",
221                       new File( buildDir, "/test-classes" ).getAbsolutePath(),
222                       new File( build.getTestOutputDirectory() ).getAbsolutePath() );
223 
224         assertEquals( "Concrete build directory should be absolute.", new File( baseDir, "target" ).getAbsolutePath(),
225                       new File( build.getDirectory() ).getAbsolutePath() );
226 
227         // Next, we have to change something to ensure the project is restored to its dynamic state.
228         project.getProperties().setProperty( "restoreTrigger", "true" );
229 
230         // --------------------------------------------------------------------
231         // NOW, RESTORE THE DYNAMIC STATE FOR THE BUILD SECTION AND
232         // ASSOCIATED DIRECTORIES ATTACHED TO THE PROJECT INSTANCE.
233         // --------------------------------------------------------------------
234 
235         projectBuilder.restoreDynamicState( project, config );
236 
237         assertFalse( project.isConcrete() );
238 
239         build = project.getBuild();
240 
241         assertEquals( "Restored source directory should be expressed in terms of the basedir.\nWas: "
242             + build.getSourceDirectory() + "\nShould be: " + basedirExpr + "/src/main/java\n", basedirExpr
243             + "/src/main/java", build.getSourceDirectory() );
244 
245         assertEquals( "Restored test-source directory should be expressed in terms of the basedir.", basedirExpr
246             + "/src/test/java", build.getTestSourceDirectory() );
247 
248         assertEquals( "Restored script-source directory should be expressed in terms of the basedir.", basedirExpr
249             + "/src/main/scripts", build.getScriptSourceDirectory() );
250 
251         compileSourceRoots = project.getCompileSourceRoots();
252 
253         assertNotNull( "Restored compile-source roots should not be null.", compileSourceRoots );
254 
255         assertEquals( "Restored compile-source roots should contain one entry.", 1, compileSourceRoots.size() );
256 
257         assertEquals( "Restored compile-source roots should contain uninterpolated source-directory value.",
258                       "${pom.basedir}/src/main/java", compileSourceRoots.get( 0 ) );
259 
260         testCompileSourceRoots = project.getTestCompileSourceRoots();
261 
262         assertNotNull( "Restored test-compile-source roots should not be null.", testCompileSourceRoots );
263 
264         assertEquals( "Restored test-compile-source roots should contain one entry.", 1, testCompileSourceRoots.size() );
265 
266         assertEquals( "Restored test-compile-source roots should contain uninterpolated test-source-directory value.",
267                       "${pom.basedir}/src/test/java", testCompileSourceRoots.get( 0 ) );
268 
269         scriptSourceRoots = project.getScriptSourceRoots();
270 
271         assertNotNull( "Restored script-source roots should not be null.", scriptSourceRoots );
272 
273         assertEquals( "Restored script-source roots should contain one entry.", 1, scriptSourceRoots.size() );
274 
275         assertEquals( "Restored script-source roots should contain uninterpolated script-source-directory value.",
276                       "${pom.basedir}/src/main/scripts", scriptSourceRoots.get( 0 ) );
277 
278         resources = build.getResources();
279 
280         assertNotNull( "Restored resources should not be null.", resources );
281 
282         assertEquals( "Restored resources should contain one entry.", 1, resources.size() );
283 
284         assertEquals( "Restored resource should contain uninterpolated reference to build directory.", buildDirExpr
285             + "/generated-resources/plexus", ( (Resource) resources.get( 0 ) ).getDirectory() );
286 
287         filters = build.getFilters();
288 
289         assertNotNull( "Restored filters should not be null.", filters );
290 
291         assertEquals( "Restored filters should contain one entry.", 1, filters.size() );
292 
293         assertEquals( "Restored filter entry should contain uninterpolated reference to build directory.", buildDirExpr
294             + "/generated-filters.properties", filters.get( 0 ) );
295 
296         assertEquals( "Restored output-directory should be expressed in terms of the build-directory.", buildDirExpr
297             + "/classes", build.getOutputDirectory() );
298 
299         assertEquals( "Restored test-output-directory should be expressed in terms of the build-directory.",
300                       buildDirExpr + "/test-classes", build.getTestOutputDirectory() );
301 
302         assertEquals( "Restored build directory should be relative.", "target", build.getDirectory() );
303     }
304 
305     public void testShouldPreserveAddedResourceInRestoredState()
306         throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException,
307         ModelInterpolationException
308     {
309         MavenProject project = buildProject( "pom.xml" );
310 
311         ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration();
312 
313         projectBuilder.calculateConcreteState( project, config );
314 
315         Build build = project.getBuild();
316 
317         Resource r = new Resource();
318         r.setDirectory( "myDir" );
319 
320         build.addResource( r );
321 
322         List resources = build.getResources();
323         assertNotNull( "Concrete resources should not be null.", resources );
324         assertEquals( "Concrete resources should contain two entries.", 2, resources.size() );
325         assertResourcePresent( "concrete resources",
326                                new File( build.getDirectory(), "generated-resources/plexus" ).getAbsolutePath(),
327                                resources );
328         assertResourcePresent( "concrete resources", "myDir", resources );
329 
330         // Next, we have to change something to ensure the project is restored to its dynamic state.
331         project.getProperties().setProperty( "restoreTrigger", "true" );
332 
333         projectBuilder.restoreDynamicState( project, config );
334 
335         build = project.getBuild();
336 
337         resources = build.getResources();
338         assertNotNull( "Restored resources should not be null.", resources );
339         assertEquals( "Restored resources should contain two entries.", 2, resources.size() );
340         assertResourcePresent( "restored resources", "${pom.build.directory}/generated-resources/plexus", resources );
341         assertResourcePresent( "restored resources", "myDir", resources );
342     }
343 
344     public void testShouldPreserveAddedFilterInRestoredState()
345         throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException,
346         ModelInterpolationException
347     {
348         MavenProject project = buildProject( "pom.xml" );
349 
350         ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration();
351         projectBuilder.calculateConcreteState( project, config );
352 
353         Build build = project.getBuild();
354 
355         build.addFilter( "myDir/filters.properties" );
356 
357         List filters = build.getFilters();
358         assertNotNull( "Concrete filters should not be null.", filters );
359         assertEquals( "Concrete filters should contain two entries.", 2, filters.size() );
360         assertFilterPresent( "concrete filters",
361                              new File( build.getDirectory(), "generated-filters.properties" ).getAbsolutePath(),
362                              filters );
363 
364         assertFilterPresent( "concrete filters", "myDir/filters.properties", filters );
365 
366         // Next, we have to change something to ensure the project is restored to its dynamic state.
367         project.getProperties().setProperty( "restoreTrigger", "true" );
368 
369         projectBuilder.restoreDynamicState( project, config );
370 
371         build = project.getBuild();
372 
373         filters = build.getFilters();
374         assertNotNull( "Restored filters should not be null.", filters );
375         assertEquals( "Restored filters should contain two entries.", 2, filters.size() );
376         assertFilterPresent( "restored filters", "${pom.build.directory}/generated-filters.properties", filters );
377         assertFilterPresent( "restored filters", "myDir/filters.properties", filters );
378     }
379 
380     public void testShouldIncorporateChangedBuildDirectoryViaExpressionsOnNextConcreteCalculation()
381         throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException,
382         ModelInterpolationException
383     {
384         MavenProject project = buildProject( "pom.xml" );
385 
386         ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration();
387         projectBuilder.calculateConcreteState( project, config );
388 
389         Build build = project.getBuild();
390 
391         assertEquals( "First concrete build directory should be absolute and point to target dir.",
392                       new File( project.getBasedir(), "target" ).getAbsolutePath(), build.getDirectory() );
393         assertEquals( "First concrete build output-directory should be absolute and point to target/classes dir.",
394                       new File( project.getBasedir(), "target/classes" ).getAbsolutePath(),
395                       new File( build.getOutputDirectory() ).getAbsolutePath() );
396 
397         build.setDirectory( "target2" );
398 
399         assertEquals( "AFTER CHANGING BUILD DIRECTORY, build directory should be relative and point to target2 dir.",
400                       "target2", build.getDirectory() );
401         assertEquals(
402                       "AFTER CHANGING BUILD DIRECTORY, build output-directory should be absolute and still point to target/classes dir.",
403                       new File( project.getBasedir(), "target/classes" ).getAbsolutePath(),
404                       new File( build.getOutputDirectory() ).getAbsolutePath() );
405 
406         projectBuilder.restoreDynamicState( project, config );
407         projectBuilder.calculateConcreteState( project, config );
408 
409         build = project.getBuild();
410 
411         assertEquals( "Second concrete build directory should be absolute and point to target2 dir.",
412                       new File( project.getBasedir(), "target2" ).getAbsolutePath(),
413                       new File( build.getDirectory() ).getAbsolutePath() );
414         assertEquals( "Second concrete build output-directory should be absolute and point to target2/classes dir.",
415                       new File( project.getBasedir(), "target2/classes" ).getAbsolutePath(),
416                       new File( build.getOutputDirectory() ).getAbsolutePath() );
417     }
418 
419     public void testShouldPreserveInitialValuesForPropertiesReferencingBuildPaths()
420         throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException,
421         ModelInterpolationException
422     {
423         MavenProject project = buildProject( "pom.xml" );
424 
425         ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration();
426         projectBuilder.calculateConcreteState( project, config );
427 
428         project.getBuild().setDirectory( "target2" );
429 
430         String originalValue = project.getProperties().getProperty( "myProperty" );
431 
432         projectBuilder.restoreDynamicState( project, config );
433         projectBuilder.calculateConcreteState( project, config );
434 
435         assertEquals( "After resetting build-directory and going through a recalculation phase for the project, "
436             + "property value for 'myProperty' should STILL be the absolute initial build directory.", originalValue,
437                       project.getProperties().getProperty( "myProperty" ) );
438     }
439 
440     public void testShouldAlignCompileSourceRootsInConcreteState()
441         throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException,
442         ModelInterpolationException
443     {
444         MavenProject project = buildProject( "pom-relative.xml" );
445 
446         ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration();
447         projectBuilder.calculateConcreteState( project, config );
448 
449         List compileSourceRoots = project.getCompileSourceRoots();
450         assertNotNull( "First concrete state compile-source roots should not be null.", compileSourceRoots );
451         assertEquals( "First concrete state should contain one compile-source root.", 1, compileSourceRoots.size() );
452         assertEquals( "First concrete state should have an absolute path for compile-source root.",
453                       new File( project.getBasedir(), "src/main/java" ).getAbsolutePath(), compileSourceRoots.get( 0 ) );
454 
455         String newSourceRoot =
456             new File( project.getBuild().getDirectory(), "generated-sources/modello" ).getAbsolutePath();
457 
458         project.addCompileSourceRoot( newSourceRoot );
459 
460         // Next, we have to change something to ensure the project is restored to its dynamic state.
461         project.getProperties().setProperty( "restoreTrigger", "true" );
462 
463         projectBuilder.restoreDynamicState( project, config );
464 
465         compileSourceRoots = project.getCompileSourceRoots();
466         assertNotNull( "Restored dynamic state compile-source roots should not be null.", compileSourceRoots );
467         assertEquals( "Restored dynamic state should contain two compile-source roots.", 2, compileSourceRoots.size() );
468         assertEquals( "Restored dynamic state should have a relative path for original compile-source root.",
469                       "src/main/java", compileSourceRoots.get( 0 ) );
470         assertEquals( "Restored dynamic state should have a relative path for new compile-source root.",
471                       "target/generated-sources/modello", compileSourceRoots.get( 1 ) );
472 
473         projectBuilder.calculateConcreteState( project, config );
474 
475         compileSourceRoots = project.getCompileSourceRoots();
476         assertNotNull( "Second concrete state compile-source roots should not be null.", compileSourceRoots );
477         assertEquals( "Second concrete state should contain two compile-source roots.", 2, compileSourceRoots.size() );
478         assertEquals( "Second concrete state should have an absolute path for original compile-source root.",
479                       new File( project.getBasedir(), "src/main/java" ).getAbsolutePath(), compileSourceRoots.get( 0 ) );
480         assertEquals( "Second concrete state should have an absolute path for new compile-source root.", newSourceRoot,
481                       compileSourceRoots.get( 1 ) );
482     }
483 
484     public void testShouldMaintainAddedAndExistingPluginEntriesInRoundTrip()
485         throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException,
486         ModelInterpolationException
487     {
488         MavenProject project = buildProject( "pom-plugins.xml" );
489 
490         String firstPlugin = "one:first-maven-plugin";
491         String secondPlugin = "two:second-maven-plugin";
492         String thirdPlugin = "three:third-maven-plugin";
493 
494         project.getBuild().flushPluginMap();
495         Map pluginMap = project.getBuild().getPluginsAsMap();
496 
497         assertNotNull( "Before calculating concrete state, project should contain plugin: " + firstPlugin,
498                        pluginMap.get( firstPlugin ) );
499         assertNotNull( "Before calculating concrete state, project should contain plugin: " + secondPlugin,
500                        pluginMap.get( secondPlugin ) );
501         assertNull( "Before calculating concrete state, project should NOT contain plugin: " + thirdPlugin,
502                     pluginMap.get( thirdPlugin ) );
503 
504         ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration();
505         projectBuilder.calculateConcreteState( project, config );
506 
507         project.getBuild().flushPluginMap();
508         pluginMap = project.getBuild().getPluginsAsMap();
509 
510         assertNotNull( "After calculating concrete state, project should contain plugin: " + firstPlugin,
511                        pluginMap.get( firstPlugin ) );
512         assertNotNull( "After calculating concrete state, project should contain plugin: " + secondPlugin,
513                        pluginMap.get( secondPlugin ) );
514         assertNull( "After calculating concrete state, project should NOT contain plugin: " + thirdPlugin,
515                     pluginMap.get( thirdPlugin ) );
516 
517         Plugin third = new Plugin();
518         third.setGroupId( "three" );
519         third.setArtifactId( "third-maven-plugin" );
520         third.setVersion( "3" );
521 
522         project.addPlugin( third );
523 
524         project.getBuild().flushPluginMap();
525         pluginMap = project.getBuild().getPluginsAsMap();
526 
527         assertNotNull( "After adding third plugin, project should contain plugin: " + firstPlugin,
528                        pluginMap.get( firstPlugin ) );
529         assertNotNull( "After adding third plugin, project should contain plugin: " + secondPlugin,
530                        pluginMap.get( secondPlugin ) );
531         assertNotNull( "After adding third plugin, project should contain plugin: " + thirdPlugin,
532                        pluginMap.get( thirdPlugin ) );
533 
534         projectBuilder.restoreDynamicState( project, config );
535 
536         project.getBuild().flushPluginMap();
537         pluginMap = project.getBuild().getPluginsAsMap();
538 
539         assertNotNull( "After restoring project dynamism, project should contain plugin: " + firstPlugin,
540                        pluginMap.get( firstPlugin ) );
541         assertNotNull( "After restoring project dynamism, project should contain plugin: " + secondPlugin,
542                        pluginMap.get( secondPlugin ) );
543         assertNotNull( "After restoring project dynamism, project should contain plugin: " + thirdPlugin,
544                        pluginMap.get( thirdPlugin ) );
545     }
546 
547     public void testShouldMaintainAddedAndExistingSourceRootsInRoundTrip()
548         throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException,
549         ModelInterpolationException
550     {
551         MavenProject project = buildProject( "pom-source-roots.xml" );
552         
553         File basedir = project.getBasedir();
554 
555         ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration();
556         projectBuilder.calculateConcreteState( project, config );
557 
558         assertTrue( "Before adding source roots, project should be concrete", project.isConcrete() );
559         assertEquals( "Before adding source roots, project should contain one compile source root", 1, project.getCompileSourceRoots().size() );
560         assertEquals( "First compile source root should be absolute ref to src/main/java", new File( basedir, "src/main/java" ).getAbsolutePath(), project.getCompileSourceRoots().get( 0 ) );
561         
562         assertEquals( "Before adding source roots, project should contain one test source root", 1, project.getTestCompileSourceRoots().size() );
563         assertEquals( "First test source root should be absolute ref to src/test/java", new File( basedir, "src/test/java" ).getAbsolutePath(), project.getTestCompileSourceRoots().get( 0 ) );
564         
565         assertEquals( "Before adding source roots, project should contain one script source root", 1, project.getScriptSourceRoots().size() );
566         assertEquals( "First script source root should be relative ref to src/main/scripts", "src/main/scripts", project.getScriptSourceRoots().get( 0 ) );
567 
568         project.addCompileSourceRoot( new File( basedir, "target/generated/src/main/java" ).getAbsolutePath() );
569         project.addTestCompileSourceRoot( new File( basedir, "target/generated/src/test/java" ).getAbsolutePath() );
570         project.addScriptSourceRoot( new File( basedir, "target/generated/src/main/scripts" ).getAbsolutePath() );
571         
572         project.getProperties().setProperty( "trigger-transition", "true" );
573         
574         projectBuilder.restoreDynamicState( project, config );
575         
576         projectBuilder.calculateConcreteState( project, config );
577         
578         assertTrue( "After adding source roots and transitioning, project should be concrete", project.isConcrete() );
579         assertEquals( "After adding source roots and transitioning, project should contain two compile source roots", 2, project.getCompileSourceRoots().size() );
580         assertEquals( "First compile source root should be absolute ref to src/main/java", new File( basedir, "src/main/java" ).getAbsolutePath(), project.getCompileSourceRoots().get( 0 ) );
581         assertEquals( "Second compile source root should be absolute ref to target/generated/src/main/java", new File( basedir, "target/generated/src/main/java" ).getAbsolutePath(), project.getCompileSourceRoots().get( 1 ) );
582         
583         assertEquals( "After adding source roots and transitioning, project should contain two test source roots", 2, project.getTestCompileSourceRoots().size() );
584         assertEquals( "First test source root should be absolute ref to src/test/java", new File( basedir, "src/test/java" ).getAbsolutePath(), project.getTestCompileSourceRoots().get( 0 ) );
585         assertEquals( "Second test source root should be absolute ref to target/generated/src/test/java", new File( basedir, "target/generated/src/test/java" ).getAbsolutePath(), project.getTestCompileSourceRoots().get( 1 ) );
586         
587         assertEquals( "After adding source roots and transitioning, project should contain two script source roots", 2, project.getScriptSourceRoots().size() );
588         assertEquals( "First script source root should be relative ref to src/main/scripts", "src/main/scripts", project.getScriptSourceRoots().get( 0 ) );
589         assertEquals( "Second script source root should be relative ref to target/generated/src/main/scripts", "target/generated/src/main/scripts", project.getScriptSourceRoots().get( 1 ) );
590     }
591 
592     public void testShouldInterpolatePluginLevelDependency()
593         throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException,
594         ModelInterpolationException
595     {
596         MavenProject project = buildProject( "plugin-level-dep.pom.xml" );
597 
598         Plugin plugin =
599             (Plugin) project.getBuild().getPluginsAsMap().get( "org.apache.maven.plugins:maven-compiler-plugin" );
600 
601         assertNotNull( "ERROR - compiler plugin config not found!", plugin );
602         assertTrue( "ERROR - compiler plugin custom dependencies not found!",
603                     ( plugin.getDependencies() != null && !plugin.getDependencies().isEmpty() ) );
604 
605         Dependency dep = (Dependency) plugin.getDependencies().get( 0 );
606 
607         assertEquals( "custom dependency version should be an INTERPOLATED reference to this project's version.",
608                       project.getVersion(), dep.getVersion() );
609     }
610 
611     // Useful for diagnostics.
612     // private void displayPOM( Model model )
613     // throws IOException
614     // {
615     // StringWriter writer = new StringWriter();
616     // new MavenXpp3Writer().write( writer, model );
617     //
618     // System.out.println( writer.toString() );
619     // }
620 
621     private void assertResourcePresent( String testLabel, String directory, List resources )
622     {
623         boolean found = false;
624 
625         if ( resources != null )
626         {
627             for ( Iterator it = resources.iterator(); it.hasNext(); )
628             {
629                 Resource resource = (Resource) it.next();
630                 if ( new File( directory ).getAbsolutePath().equals(
631                                                                      new File( resource.getDirectory() ).getAbsolutePath() ) )
632                 {
633                     found = true;
634                     break;
635                 }
636             }
637         }
638 
639         if ( !found )
640         {
641             fail( "Missing resource with directory: " + directory + " in " + testLabel );
642         }
643     }
644 
645     private void assertFilterPresent( String testLabel, String path, List filters )
646     {
647         boolean found = false;
648 
649         if ( filters != null )
650         {
651             for ( Iterator it = filters.iterator(); it.hasNext(); )
652             {
653                 String filterPath = (String) it.next();
654                 if ( new File( path ).getAbsolutePath().equals( new File( filterPath ).getAbsolutePath() ) )
655                 {
656                     found = true;
657                     break;
658                 }
659             }
660         }
661 
662         if ( !found )
663         {
664             fail( "Missing filter with path: " + path + " in " + testLabel );
665         }
666     }
667 
668     private MavenProject buildProject( String path )
669         throws IOException, XmlPullParserException, URISyntaxException, ProjectBuildingException
670     {
671         ClassLoader cloader = Thread.currentThread().getContextClassLoader();
672         URL resource = cloader.getResource( "project-dynamism/" + path );
673 
674         if ( resource == null )
675         {
676             fail( "Cannot find classpath resource for POM: " + path );
677         }
678 
679         String resourcePath = StringUtils.replace( resource.getPath(), "%20", " " );
680         URI uri = new File( resourcePath ).toURI().normalize();
681 
682         File pomFile = new File( uri );
683         pomFile = pomFile.getAbsoluteFile();
684 
685         MavenProject project = projectBuilder.build( pomFile, new DefaultProjectBuilderConfiguration() );
686 
687         return project;
688     }
689 
690 }