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 javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.io.ByteArrayInputStream;
26 import java.io.File;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.nio.charset.StandardCharsets;
30 import java.nio.file.Path;
31 import java.util.AbstractMap;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.LinkedHashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Objects;
40 import java.util.Properties;
41 import java.util.Set;
42 import java.util.concurrent.ConcurrentHashMap;
43 import java.util.function.Supplier;
44 import java.util.stream.Collectors;
45 import java.util.stream.Stream;
46
47 import org.apache.maven.ProjectCycleException;
48 import org.apache.maven.RepositoryUtils;
49 import org.apache.maven.api.ArtifactCoordinates;
50 import org.apache.maven.api.Language;
51 import org.apache.maven.api.LocalRepository;
52 import org.apache.maven.api.ProjectScope;
53 import org.apache.maven.api.SessionData;
54 import org.apache.maven.api.annotations.Nonnull;
55 import org.apache.maven.api.annotations.Nullable;
56 import org.apache.maven.api.model.Build;
57 import org.apache.maven.api.model.Dependency;
58 import org.apache.maven.api.model.DependencyManagement;
59 import org.apache.maven.api.model.DeploymentRepository;
60 import org.apache.maven.api.model.Extension;
61 import org.apache.maven.api.model.Model;
62 import org.apache.maven.api.model.Plugin;
63 import org.apache.maven.api.model.Profile;
64 import org.apache.maven.api.model.ReportPlugin;
65 import org.apache.maven.api.model.Resource;
66 import org.apache.maven.api.services.ArtifactResolver;
67 import org.apache.maven.api.services.ArtifactResolverException;
68 import org.apache.maven.api.services.ArtifactResolverRequest;
69 import org.apache.maven.api.services.ArtifactResolverResult;
70 import org.apache.maven.api.services.BuilderProblem.Severity;
71 import org.apache.maven.api.services.ModelBuilder;
72 import org.apache.maven.api.services.ModelBuilderException;
73 import org.apache.maven.api.services.ModelBuilderRequest;
74 import org.apache.maven.api.services.ModelBuilderResult;
75 import org.apache.maven.api.services.ModelProblem;
76 import org.apache.maven.api.services.ModelProblem.Version;
77 import org.apache.maven.api.services.ModelProblemCollector;
78 import org.apache.maven.api.services.ModelSource;
79 import org.apache.maven.api.services.ModelTransformer;
80 import org.apache.maven.api.services.ProblemCollector;
81 import org.apache.maven.api.services.Source;
82 import org.apache.maven.api.services.Sources;
83 import org.apache.maven.api.services.model.LifecycleBindingsInjector;
84 import org.apache.maven.artifact.Artifact;
85 import org.apache.maven.artifact.InvalidRepositoryException;
86 import org.apache.maven.artifact.repository.ArtifactRepository;
87 import org.apache.maven.bridge.MavenRepositorySystem;
88 import org.apache.maven.impl.DefaultSourceRoot;
89 import org.apache.maven.impl.InternalSession;
90 import org.apache.maven.impl.resolver.ArtifactDescriptorUtils;
91 import org.apache.maven.internal.impl.InternalMavenSession;
92 import org.apache.maven.model.building.DefaultModelProblem;
93 import org.apache.maven.model.building.FileModelSource;
94 import org.apache.maven.model.building.ModelBuildingRequest;
95 import org.apache.maven.model.building.ModelSource2;
96 import org.apache.maven.model.root.RootLocator;
97 import org.apache.maven.plugin.PluginManagerException;
98 import org.apache.maven.plugin.PluginResolutionException;
99 import org.apache.maven.plugin.version.PluginVersionResolutionException;
100 import org.eclipse.aether.RepositorySystem;
101 import org.eclipse.aether.RepositorySystemSession;
102 import org.eclipse.aether.repository.LocalRepositoryManager;
103 import org.slf4j.Logger;
104 import org.slf4j.LoggerFactory;
105
106
107
108
109 @Named
110 @Singleton
111 public class DefaultProjectBuilder implements ProjectBuilder {
112
113 private final Logger logger = LoggerFactory.getLogger(getClass());
114 private final ModelBuilder modelBuilder;
115 private final ProjectBuildingHelper projectBuildingHelper;
116 private final MavenRepositorySystem repositorySystem;
117 private final org.eclipse.aether.RepositorySystem repoSystem;
118 private final ProjectDependenciesResolver dependencyResolver;
119 private final RootLocator rootLocator;
120 private final LifecycleBindingsInjector lifecycleBindingsInjector;
121
122 @SuppressWarnings("checkstyle:ParameterNumber")
123 @Inject
124 public DefaultProjectBuilder(
125 ModelBuilder modelBuilder,
126 ProjectBuildingHelper projectBuildingHelper,
127 MavenRepositorySystem repositorySystem,
128 RepositorySystem repoSystem,
129 ProjectDependenciesResolver dependencyResolver,
130 RootLocator rootLocator,
131 LifecycleBindingsInjector lifecycleBindingsInjector) {
132 this.modelBuilder = modelBuilder;
133 this.projectBuildingHelper = projectBuildingHelper;
134 this.repositorySystem = repositorySystem;
135 this.repoSystem = repoSystem;
136 this.dependencyResolver = dependencyResolver;
137 this.rootLocator = rootLocator;
138 this.lifecycleBindingsInjector = lifecycleBindingsInjector;
139 }
140
141
142
143
144 @Override
145 public ProjectBuildingResult build(File pomFile, ProjectBuildingRequest request) throws ProjectBuildingException {
146 try (BuildSession bs = new BuildSession(request)) {
147 Path path = pomFile.toPath();
148 return bs.build(path, Sources.buildSource(path));
149 }
150 }
151
152 @Deprecated
153 @Override
154 public ProjectBuildingResult build(
155 org.apache.maven.model.building.ModelSource modelSource, ProjectBuildingRequest request)
156 throws ProjectBuildingException {
157 return build(toSource(modelSource), request);
158 }
159
160 @Deprecated
161 static ModelSource toSource(org.apache.maven.model.building.ModelSource modelSource) {
162 if (modelSource instanceof FileModelSource fms) {
163 return Sources.buildSource(fms.getPath());
164 } else {
165 return new WrapModelSource(modelSource);
166 }
167 }
168
169 @Override
170 public ProjectBuildingResult build(ModelSource modelSource, ProjectBuildingRequest request)
171 throws ProjectBuildingException {
172 try (BuildSession bs = new BuildSession(request)) {
173 return bs.build(null, modelSource);
174 }
175 }
176
177 @Override
178 public ProjectBuildingResult build(Artifact artifact, ProjectBuildingRequest request)
179 throws ProjectBuildingException {
180 return build(artifact, false, request);
181 }
182
183 @Override
184 public ProjectBuildingResult build(Artifact artifact, boolean allowStubModel, ProjectBuildingRequest request)
185 throws ProjectBuildingException {
186 try (BuildSession bs = new BuildSession(request)) {
187 return bs.build(artifact, allowStubModel);
188 }
189 }
190
191 @Override
192 public List<ProjectBuildingResult> build(List<File> pomFiles, boolean recursive, ProjectBuildingRequest request)
193 throws ProjectBuildingException {
194 try (BuildSession bs = new BuildSession(request)) {
195 return bs.build(pomFiles, recursive);
196 }
197 }
198
199 private static class StubModelSource implements ModelSource {
200 private final String xml;
201 private final Artifact artifact;
202
203 StubModelSource(String xml, Artifact artifact) {
204 this.xml = xml;
205 this.artifact = artifact;
206 }
207
208 @Override
209 @Nullable
210 public ModelSource resolve(@Nonnull ModelLocator modelLocator, @Nonnull String relative) {
211 return null;
212 }
213
214 @Override
215 @Nullable
216 public Path getPath() {
217 return null;
218 }
219
220 @Override
221 @Nonnull
222 public InputStream openStream() throws IOException {
223 return new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
224 }
225
226 @Override
227 @Nonnull
228 public String getLocation() {
229 return artifact.getId();
230 }
231
232 @Override
233 @Nullable
234 public Source resolve(@Nonnull String relative) {
235 return null;
236 }
237
238 @Override
239 public boolean equals(Object o) {
240 if (this == o) {
241 return true;
242 }
243 if (o == null || getClass() != o.getClass()) {
244 return false;
245 }
246 StubModelSource that = (StubModelSource) o;
247 return Objects.equals(xml, that.xml) && Objects.equals(artifact, that.artifact);
248 }
249
250 @Override
251 public int hashCode() {
252 return Objects.hash(xml, artifact);
253 }
254 }
255
256 private static class WrapModelSource implements ModelSource {
257 private final org.apache.maven.model.building.ModelSource modelSource;
258
259 WrapModelSource(org.apache.maven.model.building.ModelSource modelSource) {
260 this.modelSource = modelSource;
261 }
262
263 @Override
264 @Nullable
265 public ModelSource resolve(@Nonnull ModelLocator modelLocator, @Nonnull String relative) {
266 return null;
267 }
268
269 @Override
270 @Nullable
271 public Path getPath() {
272 return null;
273 }
274
275 @Override
276 @Nonnull
277 public InputStream openStream() throws IOException {
278 return modelSource.getInputStream();
279 }
280
281 @Override
282 @Nonnull
283 public String getLocation() {
284 return modelSource.getLocation();
285 }
286
287 @Override
288 @Nullable
289 public Source resolve(@Nonnull String relative) {
290 if (modelSource instanceof ModelSource2 ms) {
291 return toSource(ms.getRelatedSource(relative));
292 } else {
293 return null;
294 }
295 }
296
297 @Override
298 public boolean equals(Object o) {
299 if (this == o) {
300 return true;
301 }
302 if (o == null || getClass() != o.getClass()) {
303 return false;
304 }
305 WrapModelSource that = (WrapModelSource) o;
306 return Objects.equals(modelSource, that.modelSource);
307 }
308
309 @Override
310 public int hashCode() {
311 return Objects.hashCode(modelSource);
312 }
313 }
314
315 class BuildSession implements AutoCloseable {
316 private final ProjectBuildingRequest request;
317 private final InternalSession session;
318 private final ModelBuilder.ModelBuilderSession modelBuilderSession;
319 private final Map<String, MavenProject> projectIndex = new ConcurrentHashMap<>(256);
320
321 BuildSession(ProjectBuildingRequest request) {
322 this.request = request;
323 InternalSession session = InternalSession.from(request.getRepositorySession());
324 Path basedir = request.getLocalRepository() != null
325 ? request.getLocalRepository().getBasedirPath()
326 : null;
327 if (basedir != null) {
328 LocalRepository localRepository = session.createLocalRepository(basedir);
329 session = InternalSession.from(session.withLocalRepository(localRepository));
330 }
331 this.session = session;
332 this.modelBuilderSession = modelBuilder.newSession();
333
334
335
336
337 this.session
338 .getData()
339 .replace(SessionData.key(ModelBuilder.ModelBuilderSession.class), null, modelBuilderSession);
340 }
341
342 @Override
343 public void close() {}
344
345 ProjectBuildingResult build(Path pomFile, ModelSource modelSource) throws ProjectBuildingException {
346 ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
347
348 try {
349 MavenProject project = request.getProject();
350
351 ProblemCollector<ModelProblem> problemCollector = null;
352 Throwable error = null;
353
354 if (project == null) {
355 project = new MavenProject();
356 project.setFile(pomFile != null ? pomFile.toFile() : null);
357
358 ModelBuilderRequest.ModelBuilderRequestBuilder builder = getModelBuildingRequest();
359 ModelBuilderRequest.RequestType type = pomFile != null
360 && this.request.isProcessPlugins()
361 && this.request.getValidationLevel() == ModelBuildingRequest.VALIDATION_LEVEL_STRICT
362 ? ModelBuilderRequest.RequestType.BUILD_EFFECTIVE
363 : ModelBuilderRequest.RequestType.CONSUMER_PARENT;
364 MavenProject theProject = project;
365 ModelBuilderRequest request = builder.source(modelSource)
366 .requestType(type)
367 .locationTracking(true)
368 .lifecycleBindingsInjector(
369 (m, r, p) -> injectLifecycleBindings(m, r, p, theProject, this.request))
370 .build();
371
372 if (pomFile != null) {
373 project.setRootDirectory(rootLocator.findRoot(pomFile.getParent()));
374 }
375
376 ModelBuilderResult result;
377 try {
378 result = modelBuilderSession.build(request);
379 } catch (ModelBuilderException e) {
380 result = e.getResult();
381 if (result == null || result.getEffectiveModel() == null) {
382 throw new ProjectBuildingException(
383 e.getModelId(), e.getMessage(), pomFile != null ? pomFile.toFile() : null, e);
384 }
385
386 error = e;
387 }
388
389 problemCollector = result.getProblemCollector();
390
391 initProject(project, result);
392 }
393
394 DependencyResolutionResult resolutionResult = null;
395
396 if (request.isResolveDependencies()) {
397 projectBuildingHelper.selectProjectRealm(project);
398 resolutionResult = resolveDependencies(project);
399 }
400
401 ProjectBuildingResult result =
402 new DefaultProjectBuildingResult(project, convert(problemCollector), resolutionResult);
403
404 if (error != null) {
405 ProjectBuildingException e = new ProjectBuildingException(List.of(result));
406 e.initCause(error);
407 throw e;
408 }
409
410 return result;
411 } finally {
412 Thread.currentThread().setContextClassLoader(oldContextClassLoader);
413 }
414 }
415
416 ProjectBuildingResult build(Artifact artifact, boolean allowStubModel) throws ProjectBuildingException {
417 org.eclipse.aether.artifact.Artifact pomArtifact = RepositoryUtils.toArtifact(artifact);
418 pomArtifact = ArtifactDescriptorUtils.toPomArtifact(pomArtifact);
419
420 boolean localProject;
421
422 try {
423 ArtifactCoordinates coordinates = session.createArtifactCoordinates(session.getArtifact(pomArtifact));
424 ArtifactResolverRequest req = ArtifactResolverRequest.builder()
425 .session(session)
426 .repositories(request.getRemoteRepositories().stream()
427 .map(RepositoryUtils::toRepo)
428 .map(session::getRemoteRepository)
429 .toList())
430 .coordinates(List.of(coordinates))
431 .build();
432 ArtifactResolverResult res =
433 session.getService(ArtifactResolver.class).resolve(req);
434 ArtifactResolverResult.ResultItem resItem = res.getResult(coordinates);
435
436 pomArtifact = InternalMavenSession.from(session).toArtifact(resItem.getArtifact());
437 localProject = resItem.getRepository() instanceof org.apache.maven.api.WorkspaceRepository;
438 } catch (ArtifactResolverException e) {
439 if (e.getResult().getResults().values().iterator().next().isMissing() && allowStubModel) {
440 return build(null, createStubModelSource(artifact));
441 }
442 throw new ProjectBuildingException(
443 artifact.getId(), "Error resolving project artifact: " + e.getMessage(), e);
444 }
445
446 Path pomFile = pomArtifact.getPath();
447
448 if (!artifact.isResolved() && "pom".equals(artifact.getType())) {
449 artifact.selectVersion(pomArtifact.getVersion());
450 artifact.setFile(pomFile.toFile());
451 artifact.setResolved(true);
452 }
453
454 if (localProject) {
455 return build(pomFile, Sources.buildSource(pomFile));
456 } else {
457 return build(
458 null,
459 Sources.resolvedSource(
460 pomFile,
461 artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion()));
462 }
463 }
464
465 List<ProjectBuildingResult> build(List<File> pomFiles, boolean recursive) throws ProjectBuildingException {
466 List<ProjectBuildingResult> results = doBuild(pomFiles, recursive);
467 if (results.stream()
468 .flatMap(r -> r.getProblems().stream())
469 .anyMatch(p -> p.getSeverity() != org.apache.maven.model.building.ModelProblem.Severity.WARNING)) {
470 org.apache.maven.model.building.ModelProblem cycle = results.stream()
471 .flatMap(r -> r.getProblems().stream())
472 .filter(p -> p.getException() instanceof CycleDetectedException)
473 .findAny()
474 .orElse(null);
475 if (cycle != null) {
476 throw new RuntimeException(new ProjectCycleException(
477 "The projects in the reactor contain a cyclic reference: " + cycle.getMessage(),
478 (CycleDetectedException) cycle.getException()));
479 }
480 throw new ProjectBuildingException(results);
481 }
482
483 return results;
484 }
485
486 List<ProjectBuildingResult> doBuild(List<File> pomFiles, boolean recursive) {
487 ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
488 try {
489 return pomFiles.stream()
490 .map(pomFile -> build(pomFile, recursive))
491 .flatMap(List::stream)
492 .collect(Collectors.toList());
493 } finally {
494 Thread.currentThread().setContextClassLoader(oldContextClassLoader);
495 }
496 }
497
498 @SuppressWarnings("checkstyle:parameternumber")
499 private List<ProjectBuildingResult> build(File pomFile, boolean recursive) {
500 ModelBuilderResult result;
501 try {
502 ModelTransformer injector = (m, r, p) -> {
503 MavenProject project = projectIndex.computeIfAbsent(m.getId(), f -> new MavenProject());
504 return injectLifecycleBindings(m, r, p, project, request);
505 };
506 ModelBuilderRequest modelBuildingRequest = getModelBuildingRequest()
507 .source(Sources.buildSource(pomFile.toPath()))
508 .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
509 .locationTracking(true)
510 .recursive(recursive)
511 .lifecycleBindingsInjector(injector)
512 .build();
513 result = modelBuilderSession.build(modelBuildingRequest);
514 } catch (ModelBuilderException e) {
515 result = e.getResult();
516 if (result == null || result.getEffectiveModel() == null) {
517 return List.of(new DefaultProjectBuildingResult(
518 e.getModelId(), pomFile, convert(e.getProblemCollector())));
519 }
520 }
521
522 List<ProjectBuildingResult> results = new ArrayList<>();
523 List<ModelBuilderResult> allModels = results(result).toList();
524 for (ModelBuilderResult r : allModels) {
525 if (r.getEffectiveModel() != null) {
526 File pom = r.getSource().getPath().toFile();
527 MavenProject project =
528 projectIndex.get(r.getEffectiveModel().getId());
529 Path rootDirectory =
530 rootLocator.findRoot(pom.getParentFile().toPath());
531 project.setRootDirectory(rootDirectory);
532 project.setFile(pom);
533 project.setExecutionRoot(pom.equals(pomFile));
534 initProject(project, r);
535 project.setCollectedProjects(results(r)
536 .filter(cr -> cr != r && cr.getEffectiveModel() != null)
537 .map(cr -> projectIndex.get(cr.getEffectiveModel().getId()))
538 .collect(Collectors.toList()));
539
540 DependencyResolutionResult resolutionResult = null;
541 if (request.isResolveDependencies()) {
542 resolutionResult = resolveDependencies(project);
543 }
544 results.add(new DefaultProjectBuildingResult(
545 project, convert(r.getProblemCollector()), resolutionResult));
546 } else {
547 results.add(new DefaultProjectBuildingResult(null, convert(r.getProblemCollector()), null));
548 }
549 }
550 return results;
551 }
552
553 private Stream<ModelBuilderResult> results(ModelBuilderResult result) {
554 return Stream.concat(result.getChildren().stream().flatMap(this::results), Stream.of(result));
555 }
556
557 private List<org.apache.maven.model.building.ModelProblem> convert(
558 ProblemCollector<ModelProblem> problemCollector) {
559 if (problemCollector == null) {
560 return null;
561 }
562 ArrayList<org.apache.maven.model.building.ModelProblem> problems = new ArrayList<>();
563 problemCollector.problems().map(BuildSession::convert).forEach(problems::add);
564 if (problemCollector.problemsOverflow()) {
565 problems.add(
566 0,
567 new DefaultModelProblem(
568 "Too many model problems reported (listed problems are just a subset of reported problems)",
569 org.apache.maven.model.building.ModelProblem.Severity.WARNING,
570 null,
571 null,
572 -1,
573 -1,
574 null,
575 null));
576 return new ArrayList<>(problems) {
577 @Override
578 public int size() {
579 return problemCollector.totalProblemsReported();
580 }
581 };
582 } else {
583 return problems;
584 }
585 }
586
587 private static org.apache.maven.model.building.ModelProblem convert(ModelProblem p) {
588 return new DefaultModelProblem(
589 p.getMessage(),
590 org.apache.maven.model.building.ModelProblem.Severity.valueOf(
591 p.getSeverity().name()),
592 org.apache.maven.model.building.ModelProblem.Version.valueOf(
593 p.getVersion().name()),
594 p.getSource(),
595 p.getLineNumber(),
596 p.getColumnNumber(),
597 p.getModelId(),
598 p.getException());
599 }
600
601 @SuppressWarnings({"checkstyle:methodlength", "deprecation"})
602 private void initProject(MavenProject project, ModelBuilderResult result) {
603 project.setModel(new org.apache.maven.model.Model(result.getEffectiveModel()));
604 project.setOriginalModel(new org.apache.maven.model.Model(result.getFileModel()));
605
606 initParent(project, result);
607
608 Artifact projectArtifact = repositorySystem.createArtifact(
609 project.getGroupId(), project.getArtifactId(), project.getVersion(), null, project.getPackaging());
610 project.setArtifact(projectArtifact);
611
612
613 if (project.getFile() != null) {
614 Build build = project.getBuild().getDelegate();
615 List<org.apache.maven.api.model.Source> sources = build.getSources();
616 Path baseDir = project.getBaseDirectory();
617 boolean hasScript = false;
618 boolean hasMain = false;
619 boolean hasTest = false;
620 for (var source : sources) {
621 var src = new DefaultSourceRoot(session, baseDir, source);
622 project.addSourceRoot(src);
623 Language language = src.language();
624 if (Language.JAVA_FAMILY.equals(language)) {
625 ProjectScope scope = src.scope();
626 if (ProjectScope.MAIN.equals(scope)) {
627 hasMain = true;
628 } else {
629 hasTest |= ProjectScope.TEST.equals(scope);
630 }
631 } else {
632 hasScript |= Language.SCRIPT.equals(language);
633 }
634 }
635
636
637
638
639
640
641
642 if (!hasScript) {
643 project.addScriptSourceRoot(build.getScriptSourceDirectory());
644 }
645 if (!hasMain) {
646 project.addCompileSourceRoot(build.getSourceDirectory());
647 }
648 if (!hasTest) {
649 project.addTestCompileSourceRoot(build.getTestSourceDirectory());
650 }
651 for (Resource resource : project.getBuild().getDelegate().getResources()) {
652 project.addSourceRoot(new DefaultSourceRoot(baseDir, ProjectScope.MAIN, resource));
653 }
654 for (Resource resource : project.getBuild().getDelegate().getTestResources()) {
655 project.addSourceRoot(new DefaultSourceRoot(baseDir, ProjectScope.TEST, resource));
656 }
657 }
658
659 project.setActiveProfiles(
660 Stream.concat(result.getActivePomProfiles().stream(), result.getActiveExternalProfiles().stream())
661 .map(org.apache.maven.model.Profile::new)
662 .toList());
663
664 project.setInjectedProfileIds("external", getProfileIds(result.getActiveExternalProfiles()));
665 project.setInjectedProfileIds(
666 result.getEffectiveModel().getId(), getProfileIds(result.getActivePomProfiles()));
667
668
669
670
671
672 project.setProjectBuildingRequest(request);
673
674
675 Set<Artifact> pluginArtifacts = new HashSet<>();
676 for (Plugin plugin : project.getModel().getDelegate().getBuild().getPlugins()) {
677 Artifact artifact = repositorySystem.createPluginArtifact(new org.apache.maven.model.Plugin(plugin));
678
679 if (artifact != null) {
680 pluginArtifacts.add(artifact);
681 }
682 }
683 project.setPluginArtifacts(pluginArtifacts);
684
685
686 Set<Artifact> reportArtifacts = new HashSet<>();
687 for (ReportPlugin report :
688 project.getModel().getDelegate().getReporting().getPlugins()) {
689 Plugin pp = Plugin.newBuilder()
690 .groupId(report.getGroupId())
691 .artifactId(report.getArtifactId())
692 .version(report.getVersion())
693 .build();
694
695 Artifact artifact = repositorySystem.createPluginArtifact(new org.apache.maven.model.Plugin(pp));
696
697 if (artifact != null) {
698 reportArtifacts.add(artifact);
699 }
700 }
701 project.setReportArtifacts(reportArtifacts);
702
703
704 Set<Artifact> extensionArtifacts = new HashSet<>();
705 List<Extension> extensions =
706 project.getModel().getDelegate().getBuild().getExtensions();
707 if (extensions != null) {
708 for (Extension ext : extensions) {
709 String version;
710 if (ext.getVersion() == null || ext.getVersion().isEmpty()) {
711 version = "RELEASE";
712 } else {
713 version = ext.getVersion();
714 }
715
716 Artifact artifact = repositorySystem.createArtifact(
717 ext.getGroupId(), ext.getArtifactId(), version, null, "jar");
718
719 if (artifact != null) {
720 extensionArtifacts.add(artifact);
721 }
722 }
723 }
724 project.setExtensionArtifacts(extensionArtifacts);
725
726
727 Map<String, Artifact> map = Collections.emptyMap();
728 final DependencyManagement dependencyManagement =
729 project.getModel().getDelegate().getDependencyManagement();
730 if (dependencyManagement != null
731 && dependencyManagement.getDependencies() != null
732 && !dependencyManagement.getDependencies().isEmpty()) {
733 map = new LazyMap<>(() -> {
734 Map<String, Artifact> tmp = new HashMap<>();
735 for (Dependency d : dependencyManagement.getDependencies()) {
736 Artifact artifact =
737 repositorySystem.createDependencyArtifact(new org.apache.maven.model.Dependency(d));
738 if (artifact != null) {
739 tmp.put(d.getManagementKey(), artifact);
740 }
741 }
742 return Collections.unmodifiableMap(tmp);
743 });
744 }
745 project.setManagedVersionMap(map);
746
747
748 if (project.getDistributionManagement() != null
749 && project.getDistributionManagement().getRepository() != null) {
750 try {
751 DeploymentRepository r = project.getModel()
752 .getDelegate()
753 .getDistributionManagement()
754 .getRepository();
755 if (r.getId() != null
756 && !r.getId().isEmpty()
757 && r.getUrl() != null
758 && !r.getUrl().isEmpty()) {
759 ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository(
760 new org.apache.maven.model.DeploymentRepository(r));
761 repositorySystem.injectProxy(request.getRepositorySession(), List.of(repo));
762 repositorySystem.injectAuthentication(request.getRepositorySession(), List.of(repo));
763 project.setReleaseArtifactRepository(repo);
764 }
765 } catch (InvalidRepositoryException e) {
766 throw new IllegalStateException(
767 "Failed to create release distribution repository for " + project.getId(), e);
768 }
769 }
770
771
772 if (project.getDistributionManagement() != null
773 && project.getDistributionManagement().getSnapshotRepository() != null) {
774 try {
775 DeploymentRepository r = project.getModel()
776 .getDelegate()
777 .getDistributionManagement()
778 .getSnapshotRepository();
779 if (r.getId() != null
780 && !r.getId().isEmpty()
781 && r.getUrl() != null
782 && !r.getUrl().isEmpty()) {
783 ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository(
784 new org.apache.maven.model.DeploymentRepository(r));
785 repositorySystem.injectProxy(request.getRepositorySession(), List.of(repo));
786 repositorySystem.injectAuthentication(request.getRepositorySession(), List.of(repo));
787 project.setSnapshotArtifactRepository(repo);
788 }
789 } catch (InvalidRepositoryException e) {
790 throw new IllegalStateException(
791 "Failed to create snapshot distribution repository for " + project.getId(), e);
792 }
793 }
794 }
795
796 private void initParent(MavenProject project, ModelBuilderResult result) {
797 Model parentModel = result.getParentModel();
798
799 if (parentModel != null) {
800 final String parentGroupId = getGroupId(parentModel);
801 final String parentVersion = getVersion(parentModel);
802
803 project.setParentArtifact(repositorySystem.createProjectArtifact(
804 parentGroupId, parentModel.getArtifactId(), parentVersion));
805
806 MavenProject parent = projectIndex.get(parentModel.getId());
807 if (parent == null) {
808
809
810
811
812
813 request.setRemoteRepositories(project.getRemoteArtifactRepositories());
814 Path parentPomFile = parentModel.getPomFile();
815 if (parentPomFile != null) {
816 project.setParentFile(parentPomFile.toFile());
817 try {
818 parent = build(parentPomFile, Sources.buildSource(parentPomFile))
819 .getProject();
820 } catch (ProjectBuildingException e) {
821
822 if (logger.isDebugEnabled()) {
823
824 logger.warn("Failed to build parent project for " + project.getId(), e);
825 } else {
826
827 logger.warn("Failed to build parent project for " + project.getId());
828 }
829 }
830 } else {
831 Artifact parentArtifact = project.getParentArtifact();
832 try {
833 parent = build(parentArtifact, false).getProject();
834 } catch (ProjectBuildingException e) {
835
836 if (logger.isDebugEnabled()) {
837
838 logger.warn("Failed to build parent project for " + project.getId(), e);
839 } else {
840
841 logger.warn("Failed to build parent project for " + project.getId());
842 }
843 }
844 }
845 }
846 project.setParent(parent);
847 if (project.getParentFile() == null && parent != null) {
848 project.setParentFile(parent.getFile());
849 }
850 }
851 }
852
853 private ModelBuilderRequest.ModelBuilderRequestBuilder getModelBuildingRequest() {
854 ModelBuilderRequest.ModelBuilderRequestBuilder modelBuildingRequest = ModelBuilderRequest.builder();
855
856 modelBuildingRequest.session(session);
857 modelBuildingRequest.requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT);
858 modelBuildingRequest.profiles(
859 request.getProfiles() != null
860 ? request.getProfiles().stream()
861 .map(org.apache.maven.model.Profile::getDelegate)
862 .toList()
863 : null);
864 modelBuildingRequest.activeProfileIds(request.getActiveProfileIds());
865 modelBuildingRequest.inactiveProfileIds(request.getInactiveProfileIds());
866 modelBuildingRequest.systemProperties(toMap(request.getSystemProperties()));
867 modelBuildingRequest.userProperties(toMap(request.getUserProperties()));
868 modelBuildingRequest.repositoryMerging(ModelBuilderRequest.RepositoryMerging.valueOf(
869 request.getRepositoryMerging().name()));
870 modelBuildingRequest.repositories(request.getRemoteRepositories().stream()
871 .map(r -> session.getRemoteRepository(RepositoryUtils.toRepo(r)))
872 .toList());
873 return modelBuildingRequest;
874 }
875
876 private DependencyResolutionResult resolveDependencies(MavenProject project) {
877 DependencyResolutionResult resolutionResult;
878
879 RepositorySystemSession session = this.session.getSession();
880 try {
881 DefaultDependencyResolutionRequest resolution =
882 new DefaultDependencyResolutionRequest(project, session);
883 resolutionResult = dependencyResolver.resolve(resolution);
884 } catch (DependencyResolutionException e) {
885 resolutionResult = e.getResult();
886 }
887
888 Set<Artifact> artifacts = new LinkedHashSet<>();
889 if (resolutionResult.getDependencyGraph() != null) {
890 RepositoryUtils.toArtifacts(
891 artifacts,
892 resolutionResult.getDependencyGraph().getChildren(),
893 Collections.singletonList(project.getArtifact().getId()),
894 null);
895
896
897 LocalRepositoryManager lrm = session.getLocalRepositoryManager();
898 for (Artifact artifact : artifacts) {
899 if (!artifact.isResolved()) {
900 Path path = lrm.getAbsolutePathForLocalArtifact(RepositoryUtils.toArtifact(artifact));
901 artifact.setFile(path.toFile());
902 }
903 }
904 }
905 project.setResolvedArtifacts(artifacts);
906 project.setArtifacts(artifacts);
907
908 return resolutionResult;
909 }
910 }
911
912 private List<String> getProfileIds(List<Profile> profiles) {
913 return profiles.stream().map(Profile::getId).collect(Collectors.toList());
914 }
915
916 private static ModelSource createStubModelSource(Artifact artifact) {
917 String xml = "<?xml version='1.0'?>" + "<project>"
918 + "<modelVersion>4.0.0</modelVersion>"
919 + "<groupId>"
920 + artifact.getGroupId() + "</groupId>" + "<artifactId>"
921 + artifact.getArtifactId() + "</artifactId>" + "<version>"
922 + artifact.getBaseVersion() + "</version>" + "<packaging>"
923 + artifact.getType() + "</packaging>" + "</project>";
924 return new StubModelSource(xml, artifact);
925 }
926
927 static String getGroupId(Model model) {
928 String groupId = model.getGroupId();
929 if (groupId == null && model.getParent() != null) {
930 groupId = model.getParent().getGroupId();
931 }
932 return groupId;
933 }
934
935 static String getVersion(Model model) {
936 String version = model.getVersion();
937 if (version == null && model.getParent() != null) {
938 version = model.getParent().getVersion();
939 }
940 return version;
941 }
942
943 private static Map<String, String> toMap(Properties properties) {
944 if (properties != null && !properties.isEmpty()) {
945 return properties.entrySet().stream()
946 .collect(Collectors.toMap(e -> String.valueOf(e.getKey()), e -> String.valueOf(e.getValue())));
947 } else {
948 return null;
949 }
950 }
951
952 static class LazyMap<K, V> extends AbstractMap<K, V> {
953 private final Supplier<Map<K, V>> supplier;
954 private volatile Map<K, V> delegate;
955
956 LazyMap(Supplier<Map<K, V>> supplier) {
957 this.supplier = supplier;
958 }
959
960 @Override
961 public Set<Entry<K, V>> entrySet() {
962 if (delegate == null) {
963 synchronized (this) {
964 if (delegate == null) {
965 delegate = supplier.get();
966 }
967 }
968 }
969 return delegate.entrySet();
970 }
971 }
972
973 private Model injectLifecycleBindings(
974 Model model,
975 ModelBuilderRequest request,
976 ModelProblemCollector problems,
977 MavenProject project,
978 ProjectBuildingRequest projectBuildingRequest) {
979 org.apache.maven.model.Model model3 = new org.apache.maven.model.Model(model);
980 List<ArtifactRepository> remoteRepositories = projectBuildingRequest.getRemoteRepositories();
981 List<ArtifactRepository> pluginRepositories = projectBuildingRequest.getPluginArtifactRepositories();
982 try {
983 pluginRepositories = projectBuildingHelper.createArtifactRepositories(
984 model3.getPluginRepositories(), pluginRepositories, projectBuildingRequest);
985 } catch (Exception e) {
986 problems.add(Severity.ERROR, Version.BASE, "Invalid plugin repository: " + e.getMessage(), e);
987 }
988 project.setPluginArtifactRepositories(pluginRepositories);
989
990 if (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_PROJECT) {
991 try {
992 ProjectRealmCache.CacheRecord record =
993 projectBuildingHelper.createProjectRealm(project, model3, projectBuildingRequest);
994
995 project.setClassRealm(record.getRealm());
996 project.setExtensionDependencyFilter(record.getExtensionArtifactFilter());
997 } catch (PluginResolutionException | PluginManagerException | PluginVersionResolutionException e) {
998
999 problems.add(Severity.ERROR, Version.BASE, "Unresolvable build extension: " + e.getMessage(), e);
1000 }
1001 projectBuildingHelper.selectProjectRealm(project);
1002 }
1003
1004
1005 try {
1006 remoteRepositories = projectBuildingHelper.createArtifactRepositories(
1007 model3.getRepositories(), remoteRepositories, projectBuildingRequest);
1008 } catch (Exception e) {
1009 problems.add(Severity.ERROR, Version.BASE, "Invalid artifact repository: " + e.getMessage(), e);
1010 }
1011 project.setRemoteArtifactRepositories(remoteRepositories);
1012
1013 if (projectBuildingRequest.isProcessPlugins()) {
1014 return lifecycleBindingsInjector.injectLifecycleBindings(model3.getDelegate(), request, problems);
1015 } else {
1016 return model3.getDelegate();
1017 }
1018 }
1019 }