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