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