1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.project;
20
21 import java.io.File;
22 import java.io.InputStream;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25 import java.nio.file.StandardCopyOption;
26 import java.util.List;
27
28 import org.apache.maven.api.model.InputLocation;
29 import org.apache.maven.api.model.InputSource;
30 import org.apache.maven.artifact.Artifact;
31 import org.apache.maven.artifact.repository.ArtifactRepository;
32 import org.apache.maven.impl.InternalSession;
33 import org.apache.maven.internal.impl.DefaultProject;
34 import org.apache.maven.internal.impl.InternalMavenSession;
35 import org.apache.maven.model.Profile;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.Disabled;
38 import org.junit.jupiter.api.Test;
39 import org.junit.jupiter.api.io.TempDir;
40 import org.mockito.Mockito;
41
42 import static org.apache.maven.project.ProjectBuildingResultWithProblemMessageMatcher.projectBuildingResultWithProblemMessage;
43 import static org.codehaus.plexus.testing.PlexusExtension.getTestFile;
44 import static org.hamcrest.MatcherAssert.assertThat;
45 import static org.hamcrest.Matchers.contains;
46 import static org.hamcrest.Matchers.containsString;
47 import static org.hamcrest.Matchers.greaterThan;
48 import static org.hamcrest.Matchers.is;
49 import static org.junit.jupiter.api.Assertions.assertEquals;
50 import static org.junit.jupiter.api.Assertions.assertFalse;
51 import static org.junit.jupiter.api.Assertions.assertNotNull;
52 import static org.junit.jupiter.api.Assertions.assertNull;
53 import static org.junit.jupiter.api.Assertions.assertThrows;
54 import static org.junit.jupiter.api.Assertions.assertTrue;
55 import static org.junit.jupiter.api.Assertions.fail;
56
57 class DefaultMavenProjectBuilderTest extends AbstractMavenProjectTestCase {
58 @TempDir
59 File localRepoDir;
60
61
62 @TempDir
63 Path projectRoot;
64
65 @Override
66 @BeforeEach
67 public void setUp() throws Exception {
68 projectBuilder = getContainer().lookup(ProjectBuilder.class);
69 }
70
71 protected MavenProject getProject(Artifact pom, boolean allowStub) throws Exception {
72 ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
73 configuration.setLocalRepository(getLocalRepository());
74 initRepoSession(configuration);
75
76 return projectBuilder.build(pom, allowStub, configuration).getProject();
77 }
78
79
80
81
82
83
84 @Test
85 void testBuildFromMiddlePom() throws Exception {
86 File f1 = getTestFile("src/test/resources/projects/grandchild-check/child/pom.xml");
87 File f2 = getTestFile("src/test/resources/projects/grandchild-check/child/grandchild/pom.xml");
88
89 getProject(f1);
90
91
92
93 getProject(f2);
94 }
95
96 @Disabled("Maven 4 does not allow duplicate plugin declarations")
97 @Test
98 void testDuplicatePluginDefinitionsMerged() throws Exception {
99 File f1 = getTestFile("src/test/resources/projects/duplicate-plugins-merged-pom.xml");
100
101 MavenProject project = getProject(f1);
102 assertEquals(2, project.getBuildPlugins().get(0).getDependencies().size());
103 assertEquals(2, project.getBuildPlugins().get(0).getExecutions().size());
104 assertEquals(
105 "first", project.getBuildPlugins().get(0).getExecutions().get(0).getId());
106 }
107
108 @Test
109 void testFutureModelVersion() throws Exception {
110 File f1 = getTestFile("src/test/resources/projects/future-model-version-pom.xml");
111
112 ProjectBuildingException e = assertThrows(
113 ProjectBuildingException.class, () -> getProject(f1), "Expected to fail for future versions");
114 assertThat(e.getMessage(), containsString("Building this project requires a newer version of Maven"));
115 }
116
117 @Test
118 void testPastModelVersion() throws Exception {
119
120
121 File f1 = getTestFile("src/test/resources/projects/past-model-version-pom.xml");
122
123 ProjectBuildingException e = assertThrows(
124 ProjectBuildingException.class, () -> getProject(f1), "Expected to fail for past versions");
125 assertThat(e.getMessage(), containsString("Building this project requires an older version of Maven"));
126 }
127
128 @Test
129 void testFutureSchemaModelVersion() throws Exception {
130 File f1 = getTestFile("src/test/resources/projects/future-schema-model-version-pom.xml");
131
132 ProjectBuildingException e = assertThrows(
133 ProjectBuildingException.class, () -> getProject(f1), "Expected to fail for future versions");
134 assertThat(e.getMessage(), containsString("Building this project requires a newer version of Maven"));
135 }
136
137 @Test
138 void testBuildStubModelForMissingRemotePom() throws Exception {
139 Artifact pom = repositorySystem.createProjectArtifact("org.apache.maven.its", "missing", "0.1");
140 MavenProject project = getProject(pom, true);
141
142 assertNotNull(project.getArtifactId());
143
144 assertNotNull(project.getRemoteArtifactRepositories());
145 assertTrue(project.getRemoteArtifactRepositories().isEmpty());
146
147 assertNotNull(project.getPluginArtifactRepositories());
148 assertTrue(project.getPluginArtifactRepositories().isEmpty());
149
150 assertNull(project.getParent());
151 assertNull(project.getParentArtifact());
152
153 assertFalse(project.isExecutionRoot());
154 }
155
156 @Override
157 protected ArtifactRepository getLocalRepository() throws Exception {
158 return repositorySystem.createLocalRepository(getLocalRepositoryPath());
159 }
160
161 @Test
162 void testPartialResultUponBadDependencyDeclaration() throws Exception {
163 File pomFile = getTestFile("src/test/resources/projects/bad-dependency.xml");
164
165 ProjectBuildingRequest request = newBuildingRequest();
166 request.setProcessPlugins(false);
167 request.setResolveDependencies(true);
168 ProjectBuildingException e = assertThrows(
169 ProjectBuildingException.class,
170 () -> projectBuilder.build(pomFile, request),
171 "Project building did not fail despite invalid POM");
172 List<ProjectBuildingResult> results = e.getResults();
173 assertNotNull(results);
174 assertEquals(1, results.size());
175 ProjectBuildingResult result = results.get(0);
176 assertNotNull(result);
177 assertNotNull(result.getProject());
178 assertEquals(1, result.getProblems().size());
179 assertEquals(1, result.getProject().getArtifacts().size());
180 assertNotNull(result.getDependencyResolutionResult());
181 }
182
183
184
185
186
187
188 @Test
189 void testBuildValidParentVersionRangeLocally() throws Exception {
190 File f1 = getTestFile("src/test/resources/projects/parent-version-range-local-valid/child/pom.xml");
191
192 final MavenProject childProject = getProject(f1);
193
194 assertNotNull(childProject.getParentArtifact());
195 assertEquals(childProject.getParentArtifact().getVersion(), "1");
196 assertNotNull(childProject.getParent());
197 assertEquals(childProject.getParent().getVersion(), "1");
198 assertNotNull(childProject.getModel().getParent());
199 assertEquals(childProject.getModel().getParent().getVersion(), "[1,10]");
200 }
201
202
203
204
205
206
207 @Test
208 void testBuildParentVersionRangeLocallyWithoutChildVersion() throws Exception {
209 File f1 = getTestFile(
210 "src/test/resources/projects/parent-version-range-local-child-without-version/child/pom.xml");
211
212 ProjectBuildingException e = assertThrows(
213 ProjectBuildingException.class,
214 () -> getProject(f1),
215 "Expected 'ProjectBuildingException' not thrown.");
216 assertThat(e.getResults(), contains(projectBuildingResultWithProblemMessage("Version must be a constant")));
217 }
218
219
220
221
222
223
224 @Test
225 void testBuildParentVersionRangeLocallyWithChildProjectVersionExpression() throws Exception {
226 File f1 = getTestFile(
227 "src/test/resources/projects/parent-version-range-local-child-project-version-expression/child/pom.xml");
228
229 ProjectBuildingException e = assertThrows(
230 ProjectBuildingException.class,
231 () -> getProject(f1),
232 "Expected 'ProjectBuildingException' not thrown.");
233 assertThat(e.getResults(), contains(projectBuildingResultWithProblemMessage("Version must be a constant")));
234 }
235
236
237
238
239
240
241 public void testBuildParentVersionRangeLocallyWithChildProjectParentVersionExpression() throws Exception {
242 File f1 = getTestFile(
243 "src/test/resources/projects/parent-version-range-local-child-project-parent-version-expression/child/pom.xml");
244
245 try {
246 getProject(f1);
247 fail("Expected 'ProjectBuildingException' not thrown.");
248 } catch (final ProjectBuildingException e) {
249 assertNotNull(e.getMessage());
250 assertThat(e.getMessage(), containsString("Version must be a constant"));
251 }
252 }
253
254
255
256
257
258
259 public void testBuildParentVersionRangeLocallyWithChildRevisionExpression() throws Exception {
260 File f1 = getTestFile(
261 "src/test/resources/projects/parent-version-range-local-child-revision-expression/child/pom.xml");
262
263 MavenProject mp = this.getProjectFromRemoteRepository(f1);
264
265 assertEquals("1.0-SNAPSHOT", mp.getVersion());
266 }
267
268
269
270
271
272
273 @Test
274 void testBuildParentVersionRangeExternally() throws Exception {
275 File f1 = getTestFile("src/test/resources/projects/parent-version-range-external-valid/pom.xml");
276
277 final MavenProject childProject = this.getProjectFromRemoteRepository(f1);
278
279 assertNotNull(childProject.getParentArtifact());
280 assertEquals(childProject.getParentArtifact().getVersion(), "1");
281 assertNotNull(childProject.getParent());
282 assertEquals(childProject.getParent().getVersion(), "1");
283 assertNotNull(childProject.getModel().getParent());
284 assertEquals(childProject.getModel().getParent().getVersion(), "[1,1]");
285 }
286
287
288
289
290
291
292 @Test
293 void testBuildParentVersionRangeExternallyWithoutChildVersion() throws Exception {
294 File f1 =
295 getTestFile("src/test/resources/projects/parent-version-range-external-child-without-version/pom.xml");
296
297 ProjectBuildingException e = assertThrows(
298 ProjectBuildingException.class,
299 () -> getProjectFromRemoteRepository(f1),
300 "Expected 'ProjectBuildingException' not thrown.");
301 assertThat(e.getResults(), contains(projectBuildingResultWithProblemMessage("Version must be a constant")));
302 }
303
304
305
306
307
308
309 @Test
310 void testBuildParentVersionRangeExternallyWithChildProjectVersionExpression() throws Exception {
311 File f1 = getTestFile(
312 "src/test/resources/projects/parent-version-range-external-child-project-version-expression/pom.xml");
313
314 ProjectBuildingException e = assertThrows(
315 ProjectBuildingException.class,
316 () -> getProjectFromRemoteRepository(f1),
317 "Expected 'ProjectBuildingException' not thrown.");
318 assertThat(e.getResults(), contains(projectBuildingResultWithProblemMessage("Version must be a constant")));
319 }
320
321
322
323
324
325
326 @Test
327 void rereadPom_mng7063() throws Exception {
328 final Path pom = projectRoot.resolve("pom.xml");
329 final ProjectBuildingRequest buildingRequest = newBuildingRequest();
330
331 InternalMavenSession.from(InternalSession.from(buildingRequest.getRepositorySession()))
332 .getMavenSession()
333 .getRequest()
334 .setRootDirectory(projectRoot);
335
336 try (InputStream pomResource =
337 DefaultMavenProjectBuilderTest.class.getResourceAsStream("/projects/reread/pom1.xml")) {
338 Files.copy(pomResource, pom, StandardCopyOption.REPLACE_EXISTING);
339 }
340
341 MavenProject project =
342 projectBuilder.build(pom.toFile(), buildingRequest).getProject();
343 assertThat(project.getName(), is("aid"));
344
345 try (InputStream pomResource =
346 DefaultMavenProjectBuilderTest.class.getResourceAsStream("/projects/reread/pom2.xml")) {
347 Files.copy(pomResource, pom, StandardCopyOption.REPLACE_EXISTING);
348 }
349
350 project = projectBuilder.build(pom.toFile(), buildingRequest).getProject();
351 assertThat(project.getName(), is("PROJECT NAME"));
352 }
353
354 @Test
355 void testActivatedProfileBySource() throws Exception {
356 File testPom = getTestFile("src/test/resources/projects/pom-with-profiles/pom.xml");
357
358 ProjectBuildingRequest request = newBuildingRequest();
359 request.setLocalRepository(getLocalRepository());
360 request.setActiveProfileIds(List.of("profile1"));
361
362 MavenProject project = projectBuilder.build(testPom, request).getProject();
363
364 assertTrue(project.getInjectedProfileIds().keySet().containsAll(List.of("external", project.getId())));
365 assertTrue(project.getInjectedProfileIds().get("external").isEmpty());
366 assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().anyMatch("profile1"::equals));
367 assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("profile2"::equals));
368 assertTrue(
369 project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("active-by-default"::equals));
370 }
371
372 @Test
373 void testActivatedDefaultProfileBySource() throws Exception {
374 File testPom = getTestFile("src/test/resources/projects/pom-with-profiles/pom.xml");
375
376 ProjectBuildingRequest request = newBuildingRequest();
377 request.setLocalRepository(getLocalRepository());
378
379 MavenProject project = projectBuilder.build(testPom, request).getProject();
380
381 assertTrue(project.getInjectedProfileIds().keySet().containsAll(List.of("external", project.getId())));
382 assertTrue(project.getInjectedProfileIds().get("external").isEmpty());
383 assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("profile1"::equals));
384 assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("profile2"::equals));
385 assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().anyMatch("active-by-default"::equals));
386
387 InternalMavenSession session = Mockito.mock(InternalMavenSession.class);
388 List<org.apache.maven.api.model.Profile> activeProfiles =
389 new DefaultProject(session, project).getDeclaredActiveProfiles();
390 assertEquals(1, activeProfiles.size());
391 org.apache.maven.api.model.Profile profile = activeProfiles.get(0);
392 assertEquals("active-by-default", profile.getId());
393 InputLocation location = profile.getLocation("");
394 assertNotNull(location);
395 assertThat(location.getLineNumber(), greaterThan(0));
396 assertThat(location.getColumnNumber(), greaterThan(0));
397 assertNotNull(location.getSource());
398 assertThat(location.getSource().getLocation(), containsString("pom-with-profiles/pom.xml"));
399 }
400
401 @Test
402 void testActivatedExternalProfileBySource() throws Exception {
403 File testPom = getTestFile("src/test/resources/projects/pom-with-profiles/pom.xml");
404
405 ProjectBuildingRequest request = newBuildingRequest();
406 request.setLocalRepository(getLocalRepository());
407
408 final Profile externalProfile = new Profile();
409 externalProfile.setLocation(
410 "",
411 new org.apache.maven.model.InputLocation(
412 1, 1, new org.apache.maven.model.InputSource(new InputSource(null, "settings.xml", null))));
413 externalProfile.setId("external-profile");
414 request.addProfile(externalProfile);
415 request.setActiveProfileIds(List.of(externalProfile.getId()));
416
417 MavenProject project = projectBuilder.build(testPom, request).getProject();
418
419 assertTrue(project.getInjectedProfileIds().keySet().containsAll(List.of("external", project.getId())));
420 assertTrue(project.getInjectedProfileIds().get("external").stream().anyMatch("external-profile"::equals));
421 assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("profile1"::equals));
422 assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("profile2"::equals));
423 assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().anyMatch("active-by-default"::equals));
424
425 InternalMavenSession session = Mockito.mock(InternalMavenSession.class);
426 List<org.apache.maven.api.model.Profile> activeProfiles =
427 new DefaultProject(session, project).getDeclaredActiveProfiles();
428 assertEquals(2, activeProfiles.size());
429 org.apache.maven.api.model.Profile profile = activeProfiles.get(0);
430 assertEquals("active-by-default", profile.getId());
431 InputLocation location = profile.getLocation("");
432 assertNotNull(location);
433 assertThat(location.getLineNumber(), greaterThan(0));
434 assertThat(location.getColumnNumber(), greaterThan(0));
435 assertNotNull(location.getSource());
436 assertThat(location.getSource().getLocation(), containsString("pom-with-profiles/pom.xml"));
437 profile = activeProfiles.get(1);
438 assertEquals("external-profile", profile.getId());
439 location = profile.getLocation("");
440 assertNotNull(location);
441 assertThat(location.getLineNumber(), greaterThan(0));
442 assertThat(location.getColumnNumber(), greaterThan(0));
443 assertNotNull(location.getSource());
444 assertThat(location.getSource().getLocation(), containsString("settings.xml"));
445 }
446
447 @Test
448 void testActivatedProfileIsResolved() throws Exception {
449 File testPom = getTestFile("src/test/resources/projects/pom-with-profiles/pom.xml");
450
451 ProjectBuildingRequest request = newBuildingRequest();
452 request.setLocalRepository(getLocalRepository());
453 request.setActiveProfileIds(List.of("profile1"));
454
455 MavenProject project = projectBuilder.build(testPom, request).getProject();
456
457 assertEquals(1, project.getActiveProfiles().size());
458 assertTrue(project.getActiveProfiles().stream().anyMatch(p -> "profile1".equals(p.getId())));
459 assertTrue(project.getActiveProfiles().stream().noneMatch(p -> "profile2".equals(p.getId())));
460 assertTrue(project.getActiveProfiles().stream().noneMatch(p -> "active-by-default".equals(p.getId())));
461 }
462
463 @Test
464 void testActivatedProfileByDefaultIsResolved() throws Exception {
465 File testPom = getTestFile("src/test/resources/projects/pom-with-profiles/pom.xml");
466
467 ProjectBuildingRequest request = newBuildingRequest();
468 request.setLocalRepository(getLocalRepository());
469
470 MavenProject project = projectBuilder.build(testPom, request).getProject();
471
472 assertEquals(1, project.getActiveProfiles().size());
473 assertTrue(project.getActiveProfiles().stream().noneMatch(p -> "profile1".equals(p.getId())));
474 assertTrue(project.getActiveProfiles().stream().noneMatch(p -> "profile2".equals(p.getId())));
475 assertTrue(project.getActiveProfiles().stream().anyMatch(p -> "active-by-default".equals(p.getId())));
476 }
477
478
479
480
481
482
483 public void testBuildParentVersionRangeExternallyWithChildPomVersionExpression() throws Exception {
484 File f1 = getTestFile(
485 "src/test/resources/projects/parent-version-range-external-child-pom-version-expression/pom.xml");
486
487 try {
488 this.getProjectFromRemoteRepository(f1);
489 fail("Expected 'ProjectBuildingException' not thrown.");
490 } catch (final ProjectBuildingException e) {
491 assertNotNull(e.getMessage());
492 assertThat(e.getMessage(), containsString("Version must be a constant"));
493 }
494 }
495
496
497
498
499
500
501 public void testBuildParentVersionRangeExternallyWithChildPomParentVersionExpression() throws Exception {
502 File f1 = getTestFile(
503 "src/test/resources/projects/parent-version-range-external-child-pom-parent-version-expression/pom.xml");
504
505 try {
506 this.getProjectFromRemoteRepository(f1);
507 fail("Expected 'ProjectBuildingException' not thrown.");
508 } catch (final ProjectBuildingException e) {
509 assertNotNull(e.getMessage());
510 assertThat(e.getMessage(), containsString("Version must be a constant"));
511 }
512 }
513
514
515
516
517
518
519 public void testBuildParentVersionRangeExternallyWithChildProjectParentVersionExpression() throws Exception {
520 File f1 = getTestFile(
521 "src/test/resources/projects/parent-version-range-external-child-project-parent-version-expression/pom.xml");
522
523 try {
524 this.getProjectFromRemoteRepository(f1);
525 fail("Expected 'ProjectBuildingException' not thrown.");
526 } catch (final ProjectBuildingException e) {
527 assertNotNull(e.getMessage());
528 assertThat(e.getMessage(), containsString("Version must be a constant"));
529 }
530 }
531
532
533
534
535
536
537 public void testBuildParentVersionRangeExternallyWithChildRevisionExpression() throws Exception {
538 File f1 = getTestFile(
539 "src/test/resources/projects/parent-version-range-external-child-revision-expression/pom.xml");
540
541 MavenProject mp = this.getProjectFromRemoteRepository(f1);
542
543 assertEquals("1.0-SNAPSHOT", mp.getVersion());
544 }
545
546 @Test
547 public void testSubprojectDiscovery() throws Exception {
548 File pom = getTestFile("src/test/resources/projects/subprojects-discover/pom.xml");
549 ProjectBuildingRequest configuration = newBuildingRequest();
550 InternalSession internalSession = InternalSession.from(configuration.getRepositorySession());
551 InternalMavenSession mavenSession = InternalMavenSession.from(internalSession);
552 mavenSession
553 .getMavenSession()
554 .getRequest()
555 .setRootDirectory(pom.toPath().getParent());
556
557 List<ProjectBuildingResult> results = projectBuilder.build(List.of(pom), true, configuration);
558 assertEquals(2, results.size());
559 MavenProject p1 = results.get(0).getProject();
560 MavenProject p2 = results.get(1).getProject();
561 MavenProject parent = p1.getArtifactId().equals("parent") ? p1 : p2;
562 MavenProject child = p1.getArtifactId().equals("parent") ? p2 : p1;
563 assertEquals(List.of("child"), parent.getModel().getDelegate().getSubprojects());
564 }
565 }