View Javadoc
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.nio.file.Path;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.List;
27  import java.util.Properties;
28  import java.util.concurrent.atomic.AtomicInteger;
29  
30  import org.apache.commons.io.FileUtils;
31  import org.apache.maven.AbstractCoreMavenComponentTestCase;
32  import org.apache.maven.execution.MavenSession;
33  import org.apache.maven.model.Plugin;
34  import org.apache.maven.model.building.FileModelSource;
35  import org.apache.maven.model.building.ModelBuildingRequest;
36  import org.apache.maven.model.building.ModelProblem;
37  import org.apache.maven.model.building.ModelSource;
38  import org.junit.jupiter.api.Test;
39  import org.junit.jupiter.api.io.TempDir;
40  
41  import static org.apache.maven.project.ProjectBuildingResultWithLocationMatcher.projectBuildingResultWithLocation;
42  import static org.apache.maven.project.ProjectBuildingResultWithProblemMessageMatcher.projectBuildingResultWithProblemMessage;
43  import static org.hamcrest.MatcherAssert.assertThat;
44  import static org.hamcrest.Matchers.contains;
45  import static org.hamcrest.Matchers.containsString;
46  import static org.hamcrest.Matchers.empty;
47  import static org.hamcrest.Matchers.greaterThan;
48  import static org.hamcrest.Matchers.hasKey;
49  import static org.hamcrest.Matchers.is;
50  import static org.junit.jupiter.api.Assertions.assertEquals;
51  import static org.junit.jupiter.api.Assertions.assertNotNull;
52  import static org.junit.jupiter.api.Assertions.assertThrows;
53  import static org.junit.jupiter.api.Assertions.assertTrue;
54  
55  
56  public class ProjectBuilderTest
57      extends AbstractCoreMavenComponentTestCase
58  {
59      @Override
60      protected String getProjectsDirectory()
61      {
62          return "src/test/projects/project-builder";
63      }
64  
65      @Test
66      public void testSystemScopeDependencyIsPresentInTheCompileClasspathElements()
67          throws Exception
68      {
69          File pom = getProject( "it0063" );
70  
71          Properties eps = new Properties();
72          eps.setProperty( "jre.home", new File( pom.getParentFile(), "jdk/jre" ).getPath() );
73  
74          MavenSession session = createMavenSession( pom, eps );
75          MavenProject project = session.getCurrentProject();
76  
77          // Here we will actually not have any artifacts because the ProjectDependenciesResolver is not involved here. So
78          // right now it's not valid to ask for artifacts unless plugins require the artifacts.
79  
80          project.getCompileClasspathElements();
81      }
82  
83      @Test
84      public void testBuildFromModelSource()
85          throws Exception
86      {
87          File pomFile = new File( "src/test/resources/projects/modelsource/module01/pom.xml" );
88          MavenSession mavenSession = createMavenSession( pomFile );
89          ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
90          configuration.setRepositorySession( mavenSession.getRepositorySession() );
91          ModelSource modelSource = new FileModelSource( pomFile );
92          ProjectBuildingResult result =
93              getContainer().lookup( org.apache.maven.project.ProjectBuilder.class ).build( modelSource, configuration );
94  
95          assertNotNull( result.getProject().getParentFile() );
96      }
97  
98      @Test
99      public void testVersionlessManagedDependency()
100         throws Exception
101     {
102         File pomFile = new File( "src/test/resources/projects/versionless-managed-dependency.xml" );
103         MavenSession mavenSession = createMavenSession( null );
104         ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
105         configuration.setRepositorySession( mavenSession.getRepositorySession() );
106 
107         ProjectBuildingException e = assertThrows( ProjectBuildingException.class,
108                       () -> getContainer().lookup( org.apache.maven.project.ProjectBuilder.class ).build( pomFile, configuration ) );
109         assertThat( e.getResults(), contains( projectBuildingResultWithProblemMessage(
110                 "'dependencies.dependency.version' for org.apache.maven.its:a:jar is missing" ) ) );
111         assertThat( e.getResults(), contains( projectBuildingResultWithLocation( 17, 9 ) ) );
112     }
113 
114     @Test
115     public void testResolveDependencies()
116         throws Exception
117     {
118         File pomFile = new File( "src/test/resources/projects/basic-resolveDependencies.xml" );
119         MavenSession mavenSession = createMavenSession( null );
120         ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
121         configuration.setRepositorySession( mavenSession.getRepositorySession() );
122         configuration.setResolveDependencies( true );
123 
124         // single project build entry point
125         ProjectBuildingResult result = getContainer().lookup( org.apache.maven.project.ProjectBuilder.class ).build( pomFile, configuration );
126         assertEquals( 1, result.getProject().getArtifacts().size() );
127         // multi projects build entry point
128         List<ProjectBuildingResult> results =
129                 getContainer().lookup( org.apache.maven.project.ProjectBuilder.class ).build( Collections.singletonList( pomFile ), false,
130                                                                            configuration );
131         assertEquals( 1, results.size() );
132         MavenProject mavenProject = results.get( 0 ).getProject();
133         assertEquals( 1, mavenProject.getArtifacts().size() );
134 
135         final MavenProject project = mavenProject;
136         final AtomicInteger artifactsResultInAnotherThread = new AtomicInteger();
137         Thread t = new Thread(new Runnable() {
138             @Override
139             public void run() {
140                 artifactsResultInAnotherThread.set(project.getArtifacts().size());
141             }
142         });
143         t.start();
144         t.join();
145         assertEquals( project.getArtifacts().size(), artifactsResultInAnotherThread.get() );
146     }
147 
148     @Test
149     public void testDontResolveDependencies()
150         throws Exception
151     {
152         File pomFile = new File( "src/test/resources/projects/basic-resolveDependencies.xml" );
153         MavenSession mavenSession = createMavenSession( null );
154         ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
155         configuration.setRepositorySession( mavenSession.getRepositorySession() );
156         configuration.setResolveDependencies( false );
157 
158         // single project build entry point
159         ProjectBuildingResult result = getContainer().lookup( org.apache.maven.project.ProjectBuilder.class ).build( pomFile, configuration );
160         assertEquals( 0, result.getProject().getArtifacts().size() );
161         // multi projects build entry point
162         List<ProjectBuildingResult> results = getContainer().lookup( org.apache.maven.project.ProjectBuilder.class ).build( Collections.singletonList( pomFile ), false, configuration );
163         assertEquals( 1, results.size() );
164         MavenProject mavenProject = results.get( 0 ).getProject();
165         assertEquals( 0, mavenProject.getArtifacts().size() );
166     }
167 
168     @Test
169     public void testReadModifiedPoms( @TempDir Path tempDir ) throws Exception {
170         // TODO a similar test should be created to test the dependency management (basically all usages
171         // of DefaultModelBuilder.getCache() are affected by MNG-6530
172 
173         FileUtils.copyDirectory( new File( "src/test/resources/projects/grandchild-check" ), tempDir.toFile() );
174         MavenSession mavenSession = createMavenSession( null );
175         ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
176         configuration.setRepositorySession( mavenSession.getRepositorySession() );
177         org.apache.maven.project.ProjectBuilder projectBuilder = getContainer().lookup( org.apache.maven.project.ProjectBuilder.class );
178         File child = new File( tempDir.toFile(), "child/pom.xml" );
179         // build project once
180         projectBuilder.build( child, configuration );
181         // modify parent
182         File parent = new File( tempDir.toFile(), "pom.xml" );
183         String parentContent = FileUtils.readFileToString( parent, "UTF-8" );
184         parentContent = parentContent.replaceAll( "<packaging>pom</packaging>",
185                  "<packaging>pom</packaging><properties><addedProperty>addedValue</addedProperty></properties>" );
186         FileUtils.write( parent, parentContent, "UTF-8" );
187         // re-build pom with modified parent
188         ProjectBuildingResult result = projectBuilder.build( child, configuration );
189         assertThat( result.getProject().getProperties(), hasKey( (Object) "addedProperty" ) );
190     }
191 
192     @Test
193     public void testReadErroneousMavenProjectContainsReference()
194         throws Exception
195     {
196         File pomFile = new File( "src/test/resources/projects/artifactMissingVersion.xml" ).getAbsoluteFile();
197         MavenSession mavenSession = createMavenSession( null );
198         ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
199         configuration.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
200         configuration.setRepositorySession( mavenSession.getRepositorySession() );
201         org.apache.maven.project.ProjectBuilder projectBuilder =
202                 getContainer().lookup( org.apache.maven.project.ProjectBuilder.class );
203 
204         // single project build entry point
205         ProjectBuildingException ex1 =
206             assertThrows( ProjectBuildingException.class, () -> projectBuilder.build( pomFile, configuration ) );
207 
208         assertEquals( 1, ex1.getResults().size() );
209         MavenProject project1 = ex1.getResults().get( 0 ).getProject();
210         assertNotNull( project1 );
211         assertEquals( "testArtifactMissingVersion", project1.getArtifactId() );
212         assertEquals( pomFile, project1.getFile() );
213 
214         // multi projects build entry point
215         ProjectBuildingException ex2 =
216             assertThrows( ProjectBuildingException.class,
217                           () -> projectBuilder.build( Collections.singletonList( pomFile ), false, configuration ) );
218 
219         assertEquals( 1, ex2.getResults().size() );
220         MavenProject project2 = ex2.getResults().get( 0 ).getProject();
221         assertNotNull( project2 );
222         assertEquals( "testArtifactMissingVersion", project2.getArtifactId() );
223         assertEquals( pomFile, project2.getFile() );
224     }
225 
226     @Test
227     public void testReadInvalidPom()
228         throws Exception
229     {
230         File pomFile = new File( "src/test/resources/projects/badPom.xml" ).getAbsoluteFile();
231         MavenSession mavenSession = createMavenSession( null );
232         ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
233         configuration.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
234         configuration.setRepositorySession( mavenSession.getRepositorySession() );
235         org.apache.maven.project.ProjectBuilder projectBuilder =
236                 getContainer().lookup( org.apache.maven.project.ProjectBuilder.class );
237 
238         // single project build entry point
239         Exception ex = assertThrows( Exception.class, () -> projectBuilder.build( pomFile, configuration ) );
240         assertThat( ex.getMessage(), containsString( "expected START_TAG or END_TAG not TEXT" ) );
241 
242         // multi projects build entry point
243         ProjectBuildingException pex =
244             assertThrows( ProjectBuildingException.class,
245                           () -> projectBuilder.build( Collections.singletonList( pomFile ), false, configuration ) );
246         assertEquals( 1, pex.getResults().size() );
247         assertNotNull( pex.getResults().get( 0 ).getPomFile() );
248         assertThat( pex.getResults().get( 0 ).getProblems().size(), greaterThan( 0 ) );
249         assertThat( pex.getResults(), contains( projectBuildingResultWithProblemMessage( "expected START_TAG or END_TAG not TEXT" ) ) );
250     }
251 
252     @Test
253     public void testReadParentAndChildWithRegularVersionSetParentFile()
254         throws Exception
255     {
256         List<File> toRead = new ArrayList<>( 2 );
257         File parentPom = getProject( "MNG-6723" );
258         toRead.add( parentPom );
259         toRead.add( new File( parentPom.getParentFile(), "child/pom.xml" ) );
260         MavenSession mavenSession = createMavenSession( null );
261         ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
262         configuration.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
263         configuration.setRepositorySession( mavenSession.getRepositorySession() );
264         org.apache.maven.project.ProjectBuilder projectBuilder =
265                 getContainer().lookup( org.apache.maven.project.ProjectBuilder.class );
266 
267         // read poms separately
268         boolean parentFileWasFoundOnChild = false;
269         for ( File file : toRead )
270         {
271             List<ProjectBuildingResult> results = projectBuilder.build( Collections.singletonList( file ), false, configuration );
272             assertResultShowNoError( results );
273             MavenProject project = findChildProject( results );
274             if ( project != null )
275             {
276                 assertEquals( parentPom, project.getParentFile() );
277                 parentFileWasFoundOnChild = true;
278             }
279         }
280         assertTrue( parentFileWasFoundOnChild );
281 
282         // read projects together
283         List<ProjectBuildingResult> results = projectBuilder.build( toRead, false, configuration );
284         assertResultShowNoError( results );
285         assertEquals( parentPom, findChildProject( results ).getParentFile() );
286         Collections.reverse( toRead );
287         results = projectBuilder.build( toRead, false, configuration );
288         assertResultShowNoError( results );
289         assertEquals( parentPom, findChildProject( results ).getParentFile() );
290     }
291 
292     private MavenProject findChildProject( List<ProjectBuildingResult> results )
293     {
294         for ( ProjectBuildingResult result : results )
295         {
296             if ( result.getPomFile().getParentFile().getName().equals( "child" ) )
297             {
298                 return result.getProject();
299             }
300         }
301         return null;
302     }
303 
304     private void assertResultShowNoError( List<ProjectBuildingResult> results )
305     {
306         for ( ProjectBuildingResult result : results )
307         {
308             assertThat( result.getProblems(), is( empty() ) );
309             assertNotNull( result.getProject() );
310         }
311     }
312 
313     @Test
314     public void testBuildProperties()
315             throws Exception
316     {
317         File file = new File( getProject( "MNG-6716" ).getParentFile(), "project/pom.xml" );
318         MavenSession mavenSession = createMavenSession( null );
319         ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
320         configuration.setRepositorySession( mavenSession.getRepositorySession() );
321         configuration.setResolveDependencies( true );
322         List<ProjectBuildingResult> result = projectBuilder.build( Collections.singletonList( file ), true, configuration );
323         MavenProject project = result.get( 0 ).getProject();
324         // verify a few typical parameters are not duplicated
325         assertEquals( 1, project.getTestCompileSourceRoots().size() );
326         assertEquals( 1, project.getCompileSourceRoots().size() );
327         assertEquals( 1, project.getMailingLists().size() );
328         assertEquals( 1, project.getResources().size() );
329     }
330 
331     @Test
332     public void testPropertyInPluginManagementGroupId()
333             throws Exception
334     {
335         File pom = getProject( "MNG-6983" );
336 
337         MavenSession session = createMavenSession( pom );
338         MavenProject project = session.getCurrentProject();
339 
340         for (Plugin buildPlugin : project.getBuildPlugins()) {
341             assertNotNull( "Missing version for build plugin " + buildPlugin.getKey(), buildPlugin.getVersion() );
342         }
343     }
344 
345     @Test
346     public void testBuildFromModelSourceResolvesBasedir()
347         throws Exception
348     {
349         File pomFile = new File( "src/test/resources/projects/modelsourcebasedir/pom.xml" );
350         MavenSession mavenSession = createMavenSession( null );
351         ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
352         configuration.setRepositorySession( mavenSession.getRepositorySession() );
353         ModelSource modelSource = new FileModelSource( pomFile );
354         ProjectBuildingResult result =
355             getContainer().lookup( org.apache.maven.project.ProjectBuilder.class ).build( modelSource, configuration );
356 
357         assertEquals( pomFile.getAbsoluteFile(), result.getProject().getModel().getPomFile().getAbsoluteFile() );
358         int errors = 0;
359         for ( ModelProblem p : result.getProblems() )
360         {
361             if ( p.getSeverity() == ModelProblem.Severity.ERROR )
362             {
363                 errors++;
364             }
365         }
366         assertEquals( 0, errors );
367     }
368 
369 }