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