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