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