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.File;
26 import java.io.IOException;
27 import java.util.*;
28 import java.util.concurrent.ConcurrentHashMap;
29 import java.util.concurrent.ForkJoinPool;
30 import java.util.concurrent.ForkJoinTask;
31 import java.util.function.Supplier;
32 import java.util.stream.Collectors;
33
34 import org.apache.maven.ProjectCycleException;
35 import org.apache.maven.RepositoryUtils;
36 import org.apache.maven.api.feature.Features;
37 import org.apache.maven.artifact.Artifact;
38 import org.apache.maven.artifact.InvalidArtifactRTException;
39 import org.apache.maven.artifact.InvalidRepositoryException;
40 import org.apache.maven.artifact.repository.ArtifactRepository;
41 import org.apache.maven.bridge.MavenRepositorySystem;
42 import org.apache.maven.internal.impl.InternalSession;
43 import org.apache.maven.model.Build;
44 import org.apache.maven.model.Dependency;
45 import org.apache.maven.model.DependencyManagement;
46 import org.apache.maven.model.DeploymentRepository;
47 import org.apache.maven.model.Extension;
48 import org.apache.maven.model.Model;
49 import org.apache.maven.model.Plugin;
50 import org.apache.maven.model.Profile;
51 import org.apache.maven.model.ReportPlugin;
52 import org.apache.maven.model.building.ArtifactModelSource;
53 import org.apache.maven.model.building.DefaultModelBuilder;
54 import org.apache.maven.model.building.DefaultModelBuildingRequest;
55 import org.apache.maven.model.building.DefaultModelProblem;
56 import org.apache.maven.model.building.FileModelSource;
57 import org.apache.maven.model.building.ModelBuilder;
58 import org.apache.maven.model.building.ModelBuildingException;
59 import org.apache.maven.model.building.ModelBuildingRequest;
60 import org.apache.maven.model.building.ModelBuildingResult;
61 import org.apache.maven.model.building.ModelProblem;
62 import org.apache.maven.model.building.ModelProcessor;
63 import org.apache.maven.model.building.ModelSource;
64 import org.apache.maven.model.building.StringModelSource;
65 import org.apache.maven.model.building.TransformerContext;
66 import org.apache.maven.model.building.TransformerContextBuilder;
67 import org.apache.maven.model.resolution.ModelResolver;
68 import org.apache.maven.model.root.RootLocator;
69 import org.apache.maven.repository.internal.ArtifactDescriptorUtils;
70 import org.apache.maven.repository.internal.ModelCacheFactory;
71 import org.apache.maven.utils.Os;
72 import org.eclipse.aether.RepositorySystem;
73 import org.eclipse.aether.RepositorySystemSession;
74 import org.eclipse.aether.RequestTrace;
75 import org.eclipse.aether.impl.RemoteRepositoryManager;
76 import org.eclipse.aether.repository.LocalRepositoryManager;
77 import org.eclipse.aether.repository.RemoteRepository;
78 import org.eclipse.aether.repository.WorkspaceRepository;
79 import org.eclipse.aether.resolution.ArtifactRequest;
80 import org.eclipse.aether.resolution.ArtifactResult;
81 import org.slf4j.Logger;
82 import org.slf4j.LoggerFactory;
83
84
85
86
87 @Named
88 @Singleton
89 public class DefaultProjectBuilder implements ProjectBuilder {
90 public static final String BUILDER_PARALLELISM = "maven.projectBuilder.parallelism";
91 public static final int DEFAULT_BUILDER_PARALLELISM = 4;
92
93 private final Logger logger = LoggerFactory.getLogger(getClass());
94 private final ModelBuilder modelBuilder;
95 private final ModelProcessor modelProcessor;
96 private final ProjectBuildingHelper projectBuildingHelper;
97 private final MavenRepositorySystem repositorySystem;
98 private final org.eclipse.aether.RepositorySystem repoSystem;
99 private final RemoteRepositoryManager repositoryManager;
100 private final ProjectDependenciesResolver dependencyResolver;
101 private final ModelCacheFactory modelCacheFactory;
102
103 private final RootLocator rootLocator;
104
105 @SuppressWarnings("checkstyle:ParameterNumber")
106 @Inject
107 public DefaultProjectBuilder(
108 ModelBuilder modelBuilder,
109 ModelProcessor modelProcessor,
110 ProjectBuildingHelper projectBuildingHelper,
111 MavenRepositorySystem repositorySystem,
112 RepositorySystem repoSystem,
113 RemoteRepositoryManager repositoryManager,
114 ProjectDependenciesResolver dependencyResolver,
115 ModelCacheFactory modelCacheFactory,
116 RootLocator rootLocator) {
117 this.modelBuilder = modelBuilder;
118 this.modelProcessor = modelProcessor;
119 this.projectBuildingHelper = projectBuildingHelper;
120 this.repositorySystem = repositorySystem;
121 this.repoSystem = repoSystem;
122 this.repositoryManager = repositoryManager;
123 this.dependencyResolver = dependencyResolver;
124 this.modelCacheFactory = modelCacheFactory;
125 this.rootLocator = rootLocator;
126 }
127
128
129
130
131 @Override
132 public ProjectBuildingResult build(File pomFile, ProjectBuildingRequest request) throws ProjectBuildingException {
133 try (BuildSession bs = new BuildSession(request, false)) {
134 return bs.build(pomFile, new FileModelSource(pomFile));
135 }
136 }
137
138 @Override
139 public ProjectBuildingResult build(ModelSource modelSource, ProjectBuildingRequest request)
140 throws ProjectBuildingException {
141 try (BuildSession bs = new BuildSession(request, false)) {
142 return bs.build(null, modelSource);
143 }
144 }
145
146 @Override
147 public ProjectBuildingResult build(Artifact artifact, ProjectBuildingRequest request)
148 throws ProjectBuildingException {
149 return build(artifact, false, request);
150 }
151
152 @Override
153 public ProjectBuildingResult build(Artifact artifact, boolean allowStubModel, ProjectBuildingRequest request)
154 throws ProjectBuildingException {
155 try (BuildSession bs = new BuildSession(request, false)) {
156 return bs.build(artifact, allowStubModel);
157 }
158 }
159
160 @Override
161 public List<ProjectBuildingResult> build(List<File> pomFiles, boolean recursive, ProjectBuildingRequest request)
162 throws ProjectBuildingException {
163 try (BuildSession bs = new BuildSession(request, true)) {
164 return bs.build(pomFiles, recursive);
165 }
166 }
167
168 static class InterimResult {
169
170 File pomFile;
171
172 ModelBuildingRequest request;
173
174 ModelBuildingResult result;
175
176 MavenProject project;
177
178 boolean root;
179
180 List<InterimResult> modules = Collections.emptyList();
181
182 ProjectBuildingResult projectBuildingResult;
183
184 InterimResult(
185 File pomFile,
186 ModelBuildingRequest request,
187 ModelBuildingResult result,
188 MavenProject project,
189 boolean root) {
190 this.pomFile = pomFile;
191 this.request = request;
192 this.result = result;
193 this.project = project;
194 this.root = root;
195 }
196
197 InterimResult(ModelBuildingRequest request, ProjectBuildingResult projectBuildingResult) {
198 this.request = request;
199 this.projectBuildingResult = projectBuildingResult;
200 this.pomFile = projectBuildingResult.getPomFile();
201 this.project = projectBuildingResult.getProject();
202 }
203 }
204
205 class BuildSession implements AutoCloseable {
206 private final ProjectBuildingRequest request;
207 private final RepositorySystemSession session;
208 private final List<RemoteRepository> repositories;
209 private final ReactorModelPool modelPool;
210 private final TransformerContextBuilder transformerContextBuilder;
211 private final ForkJoinPool forkJoinPool;
212
213 BuildSession(ProjectBuildingRequest request, boolean localProjects) {
214 this.request = request;
215 this.session =
216 RepositoryUtils.overlay(request.getLocalRepository(), request.getRepositorySession(), repoSystem);
217 this.repositories = RepositoryUtils.toRepos(request.getRemoteRepositories());
218 this.forkJoinPool = new ForkJoinPool(getParallelism(request));
219 if (localProjects) {
220 this.modelPool = new ReactorModelPool();
221 this.transformerContextBuilder = modelBuilder.newTransformerContextBuilder();
222 } else {
223 this.modelPool = null;
224 this.transformerContextBuilder = null;
225 }
226 }
227
228 @Override
229 public void close() {
230 this.forkJoinPool.shutdownNow();
231 }
232
233 private int getParallelism(ProjectBuildingRequest request) {
234 int parallelism = DEFAULT_BUILDER_PARALLELISM;
235 try {
236 String str = request.getUserProperties().getProperty(BUILDER_PARALLELISM);
237 if (str == null) {
238 str = request.getSystemProperties().getProperty(BUILDER_PARALLELISM);
239 }
240 if (str != null) {
241 parallelism = Integer.parseInt(str);
242 }
243 } catch (Exception e) {
244
245 }
246 return Math.max(1, Math.min(parallelism, Runtime.getRuntime().availableProcessors()));
247 }
248
249 ProjectBuildingResult build(File pomFile, ModelSource modelSource) throws ProjectBuildingException {
250 ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
251
252 try {
253 MavenProject project = request.getProject();
254
255 List<ModelProblem> modelProblems = null;
256 Throwable error = null;
257
258 if (project == null) {
259 ModelBuildingRequest request = getModelBuildingRequest();
260
261 project = new MavenProject();
262 project.setFile(pomFile);
263
264 DefaultModelBuildingListener listener =
265 new DefaultModelBuildingListener(project, projectBuildingHelper, this.request);
266 request.setModelBuildingListener(listener);
267
268 request.setPomFile(pomFile);
269 request.setModelSource(modelSource);
270 request.setLocationTracking(true);
271
272 if (pomFile != null) {
273 project.setRootDirectory(
274 rootLocator.findRoot(pomFile.getParentFile().toPath()));
275 }
276
277 ModelBuildingResult result;
278 try {
279 result = modelBuilder.build(request);
280 } catch (ModelBuildingException e) {
281 result = e.getResult();
282 if (result == null || result.getEffectiveModel() == null) {
283 throw new ProjectBuildingException(e.getModelId(), e.getMessage(), pomFile, e);
284 }
285
286 error = e;
287 }
288
289 modelProblems = result.getProblems();
290
291 initProject(project, Collections.emptyMap(), result);
292 } else if (request.isResolveDependencies()) {
293 projectBuildingHelper.selectProjectRealm(project);
294 }
295
296 DependencyResolutionResult resolutionResult = null;
297
298 if (request.isResolveDependencies()) {
299 resolutionResult = resolveDependencies(project);
300 }
301
302 ProjectBuildingResult result =
303 new DefaultProjectBuildingResult(project, modelProblems, resolutionResult);
304
305 if (error != null) {
306 ProjectBuildingException e = new ProjectBuildingException(Arrays.asList(result));
307 e.initCause(error);
308 throw e;
309 }
310
311 return result;
312 } finally {
313 Thread.currentThread().setContextClassLoader(oldContextClassLoader);
314 }
315 }
316
317 ProjectBuildingResult build(Artifact artifact, boolean allowStubModel) throws ProjectBuildingException {
318 org.eclipse.aether.artifact.Artifact pomArtifact = RepositoryUtils.toArtifact(artifact);
319 pomArtifact = ArtifactDescriptorUtils.toPomArtifact(pomArtifact);
320
321 boolean localProject;
322
323 try {
324 ArtifactRequest pomRequest = new ArtifactRequest();
325 pomRequest.setArtifact(pomArtifact);
326 pomRequest.setRepositories(repositories);
327 ArtifactResult pomResult = repoSystem.resolveArtifact(session, pomRequest);
328
329 pomArtifact = pomResult.getArtifact();
330 localProject = pomResult.getRepository() instanceof WorkspaceRepository;
331 } catch (org.eclipse.aether.resolution.ArtifactResolutionException e) {
332 if (e.getResults().get(0).isMissing() && allowStubModel) {
333 return build(null, createStubModelSource(artifact));
334 }
335 throw new ProjectBuildingException(
336 artifact.getId(), "Error resolving project artifact: " + e.getMessage(), e);
337 }
338
339 File pomFile = pomArtifact.getFile();
340
341 if ("pom".equals(artifact.getType())) {
342 artifact.selectVersion(pomArtifact.getVersion());
343 artifact.setFile(pomFile);
344 artifact.setResolved(true);
345 }
346
347 if (localProject) {
348 return build(pomFile, new FileModelSource(pomFile));
349 } else {
350 return build(
351 null,
352 new ArtifactModelSource(
353 pomFile, artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()));
354 }
355 }
356
357 List<ProjectBuildingResult> build(List<File> pomFiles, boolean recursive) throws ProjectBuildingException {
358 ForkJoinTask<List<ProjectBuildingResult>> task = forkJoinPool.submit(() -> doBuild(pomFiles, recursive));
359
360
361
362 task.quietlyJoin();
363 if (task.isCompletedAbnormally()) {
364 Throwable e = task.getException();
365 Throwable c = e.getCause();
366 uncheckedThrow(c != null && c.getClass() == e.getClass() ? c : e);
367 }
368
369 List<ProjectBuildingResult> results = task.getRawResult();
370 if (results.stream()
371 .flatMap(r -> r.getProblems().stream())
372 .anyMatch(p -> p.getSeverity() != ModelProblem.Severity.WARNING)) {
373 ModelProblem cycle = results.stream()
374 .flatMap(r -> r.getProblems().stream())
375 .filter(p -> p.getException() instanceof CycleDetectedException)
376 .findAny()
377 .orElse(null);
378 if (cycle != null) {
379 throw new RuntimeException(new ProjectCycleException(
380 "The projects in the reactor contain a cyclic reference: " + cycle.getMessage(),
381 (CycleDetectedException) cycle.getException()));
382 }
383 throw new ProjectBuildingException(results);
384 }
385
386 return results;
387 }
388
389 List<ProjectBuildingResult> doBuild(List<File> pomFiles, boolean recursive) {
390 Map<File, MavenProject> projectIndex = new ConcurrentHashMap<>(256);
391
392
393 List<InterimResult> interimResults = build(projectIndex, pomFiles, new LinkedHashSet<>(), true, recursive);
394
395 ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
396
397 try {
398
399 List<ProjectBuildingResult> results = build(projectIndex, interimResults);
400
401 if (Features.buildConsumer(request.getUserProperties())) {
402 request.getRepositorySession()
403 .getData()
404 .set(TransformerContext.KEY, transformerContextBuilder.build());
405 }
406
407 return results;
408 } finally {
409 Thread.currentThread().setContextClassLoader(oldContextClassLoader);
410 }
411 }
412
413 @SuppressWarnings("checkstyle:parameternumber")
414 private List<InterimResult> build(
415 Map<File, MavenProject> projectIndex,
416 List<File> pomFiles,
417 Set<File> aggregatorFiles,
418 boolean root,
419 boolean recursive) {
420 List<ForkJoinTask<InterimResult>> tasks = pomFiles.stream()
421 .map(pomFile -> ForkJoinTask.adapt(
422 () -> build(projectIndex, pomFile, concat(aggregatorFiles, pomFile), root, recursive)))
423 .collect(Collectors.toList());
424
425 return ForkJoinTask.invokeAll(tasks).stream()
426 .map(ForkJoinTask::getRawResult)
427 .collect(Collectors.toList());
428 }
429
430 private <T> Set<T> concat(Set<T> set, T elem) {
431 Set<T> newSet = new HashSet<>(set);
432 newSet.add(elem);
433 return newSet;
434 }
435
436 @SuppressWarnings("checkstyle:parameternumber")
437 private InterimResult build(
438 Map<File, MavenProject> projectIndex,
439 File pomFile,
440 Set<File> aggregatorFiles,
441 boolean isRoot,
442 boolean recursive) {
443 MavenProject project = new MavenProject();
444 project.setFile(pomFile);
445
446 project.setRootDirectory(
447 rootLocator.findRoot(pomFile.getParentFile().toPath()));
448
449 ModelBuildingRequest modelBuildingRequest = getModelBuildingRequest()
450 .setPomFile(pomFile)
451 .setTwoPhaseBuilding(true)
452 .setLocationTracking(true);
453
454 DefaultModelBuildingListener listener =
455 new DefaultModelBuildingListener(project, projectBuildingHelper, request);
456 modelBuildingRequest.setModelBuildingListener(listener);
457
458 ModelBuildingResult result;
459 try {
460 result = modelBuilder.build(modelBuildingRequest);
461 } catch (ModelBuildingException e) {
462 result = e.getResult();
463 if (result == null || result.getFileModel() == null) {
464 return new InterimResult(
465 modelBuildingRequest,
466 new DefaultProjectBuildingResult(e.getModelId(), pomFile, e.getProblems()));
467 }
468
469
470 }
471
472 Model model = modelBuildingRequest.getFileModel();
473
474 modelPool.put(model.getPomFile().toPath(), model);
475
476 InterimResult interimResult = new InterimResult(pomFile, modelBuildingRequest, result, project, isRoot);
477
478 if (recursive) {
479 File basedir = pomFile.getParentFile();
480 List<File> moduleFiles = new ArrayList<>();
481 for (String module : model.getModules()) {
482 if (module == null || module.isEmpty()) {
483 continue;
484 }
485
486 module = module.replace('\\', File.separatorChar).replace('/', File.separatorChar);
487
488 File moduleFile = modelProcessor.locateExistingPom(new File(basedir, module));
489
490 if (moduleFile == null) {
491 ModelProblem problem = new DefaultModelProblem(
492 "Child module " + moduleFile + " of " + pomFile + " does not exist",
493 ModelProblem.Severity.ERROR,
494 ModelProblem.Version.BASE,
495 model,
496 -1,
497 -1,
498 null);
499 result.getProblems().add(problem);
500
501 continue;
502 }
503
504 if (Os.IS_WINDOWS) {
505
506 try {
507 moduleFile = moduleFile.getCanonicalFile();
508 } catch (IOException e) {
509 moduleFile = moduleFile.getAbsoluteFile();
510 }
511 } else {
512 moduleFile = new File(moduleFile.toURI().normalize());
513 }
514
515 if (aggregatorFiles.contains(moduleFile)) {
516 StringBuilder buffer = new StringBuilder(256);
517 for (File aggregatorFile : aggregatorFiles) {
518 buffer.append(aggregatorFile).append(" -> ");
519 }
520 buffer.append(moduleFile);
521
522 ModelProblem problem = new DefaultModelProblem(
523 "Child module " + moduleFile + " of " + pomFile + " forms aggregation cycle " + buffer,
524 ModelProblem.Severity.ERROR,
525 ModelProblem.Version.BASE,
526 model,
527 -1,
528 -1,
529 null);
530 result.getProblems().add(problem);
531
532 continue;
533 }
534
535 moduleFiles.add(moduleFile);
536 }
537
538 if (!moduleFiles.isEmpty()) {
539 interimResult.modules = build(projectIndex, moduleFiles, aggregatorFiles, false, recursive);
540 }
541 }
542
543 projectIndex.put(pomFile, project);
544
545 return interimResult;
546 }
547
548 private List<ProjectBuildingResult> build(
549 Map<File, MavenProject> projectIndex, List<InterimResult> interimResults) {
550
551
552
553
554 if (modelBuilder instanceof DefaultModelBuilder) {
555 List<ProjectBuildingResult> results = new ArrayList<>();
556 DefaultModelBuilder dmb = (DefaultModelBuilder) modelBuilder;
557 boolean failure = false;
558 for (InterimResult r : interimResults) {
559 DefaultProjectBuildingResult res;
560 try {
561 Model model = dmb.buildRawModel(r.request);
562 res = new DefaultProjectBuildingResult(model.getId(), model.getPomFile(), null);
563 } catch (ModelBuildingException e) {
564 failure = true;
565 res = new DefaultProjectBuildingResult(e.getModelId(), r.request.getPomFile(), e.getProblems());
566 }
567 results.add(res);
568 }
569 if (failure) {
570 return results;
571 }
572 }
573
574 return interimResults.parallelStream()
575 .map(interimResult -> doBuild(projectIndex, interimResult))
576 .flatMap(List::stream)
577 .collect(Collectors.toList());
578 }
579
580 private List<ProjectBuildingResult> doBuild(Map<File, MavenProject> projectIndex, InterimResult interimResult) {
581 if (interimResult.projectBuildingResult != null) {
582 return Collections.singletonList(interimResult.projectBuildingResult);
583 }
584 MavenProject project = interimResult.project;
585 try {
586 ModelBuildingResult result = modelBuilder.build(interimResult.request, interimResult.result);
587
588
589 try {
590 initProject(project, projectIndex, result);
591 } catch (InvalidArtifactRTException iarte) {
592 result.getProblems()
593 .add(new DefaultModelProblem(
594 null,
595 ModelProblem.Severity.ERROR,
596 null,
597 result.getEffectiveModel(),
598 -1,
599 -1,
600 iarte));
601 }
602
603 List<ProjectBuildingResult> results = build(projectIndex, interimResult.modules);
604
605 project.setExecutionRoot(interimResult.root);
606 project.setCollectedProjects(
607 results.stream().map(ProjectBuildingResult::getProject).collect(Collectors.toList()));
608 DependencyResolutionResult resolutionResult = null;
609 if (request.isResolveDependencies()) {
610 resolutionResult = resolveDependencies(project);
611 }
612
613 results.add(new DefaultProjectBuildingResult(project, result.getProblems(), resolutionResult));
614
615 return results;
616 } catch (ModelBuildingException e) {
617 DefaultProjectBuildingResult result;
618 if (project == null || interimResult.result.getEffectiveModel() == null) {
619 result = new DefaultProjectBuildingResult(e.getModelId(), interimResult.pomFile, e.getProblems());
620 } else {
621 project.setModel(interimResult.result.getEffectiveModel());
622 result = new DefaultProjectBuildingResult(project, e.getProblems(), null);
623 }
624 return Collections.singletonList(result);
625 }
626 }
627
628 @SuppressWarnings("checkstyle:methodlength")
629 private void initProject(MavenProject project, Map<File, MavenProject> projects, ModelBuildingResult result) {
630 project.setModel(result.getEffectiveModel());
631 project.setOriginalModel(result.getFileModel());
632
633 initParent(project, projects, result);
634
635 Artifact projectArtifact = repositorySystem.createArtifact(
636 project.getGroupId(), project.getArtifactId(), project.getVersion(), null, project.getPackaging());
637 project.setArtifact(projectArtifact);
638
639
640 if (project.getFile() != null) {
641 Build build = project.getBuild();
642 project.addScriptSourceRoot(build.getScriptSourceDirectory());
643 project.addCompileSourceRoot(build.getSourceDirectory());
644 project.addTestCompileSourceRoot(build.getTestSourceDirectory());
645 }
646
647 List<Profile> activeProfiles = new ArrayList<>();
648 activeProfiles.addAll(
649 result.getActivePomProfiles(result.getModelIds().get(0)));
650 activeProfiles.addAll(result.getActiveExternalProfiles());
651 project.setActiveProfiles(activeProfiles);
652
653 project.setInjectedProfileIds("external", getProfileIds(result.getActiveExternalProfiles()));
654 for (String modelId : result.getModelIds()) {
655 project.setInjectedProfileIds(modelId, getProfileIds(result.getActivePomProfiles(modelId)));
656 }
657
658
659
660
661
662 project.setProjectBuildingRequest(request);
663
664
665 Set<Artifact> pluginArtifacts = new HashSet<>();
666 for (Plugin plugin : project.getBuildPlugins()) {
667 Artifact artifact = repositorySystem.createPluginArtifact(plugin);
668
669 if (artifact != null) {
670 pluginArtifacts.add(artifact);
671 }
672 }
673 project.setPluginArtifacts(pluginArtifacts);
674
675
676 Set<Artifact> reportArtifacts = new HashSet<>();
677 for (ReportPlugin report : project.getReportPlugins()) {
678 Plugin pp = new Plugin();
679 pp.setGroupId(report.getGroupId());
680 pp.setArtifactId(report.getArtifactId());
681 pp.setVersion(report.getVersion());
682
683 Artifact artifact = repositorySystem.createPluginArtifact(pp);
684
685 if (artifact != null) {
686 reportArtifacts.add(artifact);
687 }
688 }
689 project.setReportArtifacts(reportArtifacts);
690
691
692 Set<Artifact> extensionArtifacts = new HashSet<>();
693 List<Extension> extensions = project.getBuildExtensions();
694 if (extensions != null) {
695 for (Extension ext : extensions) {
696 String version;
697 if (ext.getVersion() == null || ext.getVersion().isEmpty()) {
698 version = "RELEASE";
699 } else {
700 version = ext.getVersion();
701 }
702
703 Artifact artifact = repositorySystem.createArtifact(
704 ext.getGroupId(), ext.getArtifactId(), version, null, "jar");
705
706 if (artifact != null) {
707 extensionArtifacts.add(artifact);
708 }
709 }
710 }
711 project.setExtensionArtifacts(extensionArtifacts);
712
713
714 Map<String, Artifact> map = Collections.emptyMap();
715 final DependencyManagement dependencyManagement = project.getDependencyManagement();
716 if (dependencyManagement != null
717 && dependencyManagement.getDependencies() != null
718 && !dependencyManagement.getDependencies().isEmpty()) {
719 map = new LazyMap<>(() -> {
720 Map<String, Artifact> tmp = new HashMap<>();
721 for (Dependency d : dependencyManagement.getDependencies()) {
722 Artifact artifact = repositorySystem.createDependencyArtifact(d);
723 if (artifact != null) {
724 tmp.put(d.getManagementKey(), artifact);
725 }
726 }
727 return Collections.unmodifiableMap(tmp);
728 });
729 }
730 project.setManagedVersionMap(map);
731
732
733 if (project.getDistributionManagement() != null
734 && project.getDistributionManagement().getRepository() != null) {
735 try {
736 DeploymentRepository r = project.getDistributionManagement().getRepository();
737 if (r.getId() != null
738 && !r.getId().isEmpty()
739 && r.getUrl() != null
740 && !r.getUrl().isEmpty()) {
741 ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository(r);
742 repositorySystem.injectProxy(request.getRepositorySession(), Arrays.asList(repo));
743 repositorySystem.injectAuthentication(request.getRepositorySession(), Arrays.asList(repo));
744 project.setReleaseArtifactRepository(repo);
745 }
746 } catch (InvalidRepositoryException e) {
747 throw new IllegalStateException(
748 "Failed to create release distribution repository for " + project.getId(), e);
749 }
750 }
751
752
753 if (project.getDistributionManagement() != null
754 && project.getDistributionManagement().getSnapshotRepository() != null) {
755 try {
756 DeploymentRepository r = project.getDistributionManagement().getSnapshotRepository();
757 if (r.getId() != null
758 && !r.getId().isEmpty()
759 && r.getUrl() != null
760 && !r.getUrl().isEmpty()) {
761 ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository(r);
762 repositorySystem.injectProxy(request.getRepositorySession(), Arrays.asList(repo));
763 repositorySystem.injectAuthentication(request.getRepositorySession(), Arrays.asList(repo));
764 project.setSnapshotArtifactRepository(repo);
765 }
766 } catch (InvalidRepositoryException e) {
767 throw new IllegalStateException(
768 "Failed to create snapshot distribution repository for " + project.getId(), e);
769 }
770 }
771 }
772
773 private void initParent(MavenProject project, Map<File, MavenProject> projects, ModelBuildingResult result) {
774 Model parentModel = result.getModelIds().size() > 1
775 && !result.getModelIds().get(1).isEmpty()
776 ? result.getRawModel(result.getModelIds().get(1))
777 : null;
778
779 if (parentModel != null) {
780 final String parentGroupId = inheritedGroupId(result, 1);
781 final String parentVersion = inheritedVersion(result, 1);
782
783 project.setParentArtifact(repositorySystem.createProjectArtifact(
784 parentGroupId, parentModel.getArtifactId(), parentVersion));
785
786
787 String parentModelId = result.getModelIds().get(1);
788 File parentPomFile = result.getRawModel(parentModelId).getPomFile();
789 MavenProject parent = parentPomFile != null ? projects.get(parentPomFile) : null;
790 if (parent == null) {
791
792
793
794
795
796 request.setRemoteRepositories(project.getRemoteArtifactRepositories());
797 if (parentPomFile != null) {
798 project.setParentFile(parentPomFile);
799 try {
800 parent = build(parentPomFile, new FileModelSource(parentPomFile))
801 .getProject();
802 } catch (ProjectBuildingException e) {
803
804 if (logger.isDebugEnabled()) {
805
806 logger.warn("Failed to build parent project for " + project.getId(), e);
807 } else {
808
809 logger.warn("Failed to build parent project for " + project.getId());
810 }
811 }
812 } else {
813 Artifact parentArtifact = project.getParentArtifact();
814 try {
815 parent = build(parentArtifact, false).getProject();
816 } catch (ProjectBuildingException e) {
817
818 if (logger.isDebugEnabled()) {
819
820 logger.warn("Failed to build parent project for " + project.getId(), e);
821 } else {
822
823 logger.warn("Failed to build parent project for " + project.getId());
824 }
825 }
826 }
827 }
828 project.setParent(parent);
829 if (project.getParentFile() == null && parent != null) {
830 project.setParentFile(parent.getFile());
831 }
832 }
833 }
834
835 private ModelBuildingRequest getModelBuildingRequest() {
836 ModelBuildingRequest modelBuildingRequest = new DefaultModelBuildingRequest();
837
838 RequestTrace trace = RequestTrace.newChild(null, request).newChild(modelBuildingRequest);
839
840 ModelResolver resolver = new ProjectModelResolver(
841 session,
842 trace,
843 repoSystem,
844 repositoryManager,
845 repositories,
846 request.getRepositoryMerging(),
847 modelPool);
848
849 modelBuildingRequest.setValidationLevel(request.getValidationLevel());
850 modelBuildingRequest.setProcessPlugins(request.isProcessPlugins());
851 modelBuildingRequest.setProfiles(request.getProfiles());
852 modelBuildingRequest.setActiveProfileIds(request.getActiveProfileIds());
853 modelBuildingRequest.setInactiveProfileIds(request.getInactiveProfileIds());
854 modelBuildingRequest.setSystemProperties(request.getSystemProperties());
855 modelBuildingRequest.setUserProperties(request.getUserProperties());
856 modelBuildingRequest.setBuildStartTime(request.getBuildStartTime());
857 modelBuildingRequest.setModelResolver(resolver);
858
859 if (modelPool != null) {
860 modelBuildingRequest.setModelCache(modelCacheFactory.createCache(session));
861 }
862 modelBuildingRequest.setTransformerContextBuilder(transformerContextBuilder);
863 InternalSession session = (InternalSession) this.session.getData().get(InternalSession.class);
864 if (session != null) {
865 try {
866 modelBuildingRequest.setRootDirectory(session.getRootDirectory());
867 } catch (IllegalStateException e) {
868
869 }
870 }
871
872 return modelBuildingRequest;
873 }
874
875 private DependencyResolutionResult resolveDependencies(MavenProject project) {
876 DependencyResolutionResult resolutionResult;
877
878 try {
879 DefaultDependencyResolutionRequest resolution =
880 new DefaultDependencyResolutionRequest(project, session);
881 resolutionResult = dependencyResolver.resolve(resolution);
882 } catch (DependencyResolutionException e) {
883 resolutionResult = e.getResult();
884 }
885
886 Set<Artifact> artifacts = new LinkedHashSet<>();
887 if (resolutionResult.getDependencyGraph() != null) {
888 RepositoryUtils.toArtifacts(
889 artifacts,
890 resolutionResult.getDependencyGraph().getChildren(),
891 Collections.singletonList(project.getArtifact().getId()),
892 null);
893
894
895 LocalRepositoryManager lrm = session.getLocalRepositoryManager();
896 for (Artifact artifact : artifacts) {
897 if (!artifact.isResolved()) {
898 String path = lrm.getPathForLocalArtifact(RepositoryUtils.toArtifact(artifact));
899 artifact.setFile(new File(lrm.getRepository().getBasedir(), path));
900 }
901 }
902 }
903 project.setResolvedArtifacts(artifacts);
904 project.setArtifacts(artifacts);
905
906 return resolutionResult;
907 }
908 }
909
910 private List<String> getProfileIds(List<org.apache.maven.model.Profile> profiles) {
911 return profiles.stream().map(org.apache.maven.model.Profile::getId).collect(Collectors.toList());
912 }
913
914 private static ModelSource createStubModelSource(Artifact artifact) {
915 StringBuilder buffer = new StringBuilder(1024);
916
917 buffer.append("<?xml version='1.0'?>");
918 buffer.append("<project>");
919 buffer.append("<modelVersion>4.0.0</modelVersion>");
920 buffer.append("<groupId>").append(artifact.getGroupId()).append("</groupId>");
921 buffer.append("<artifactId>").append(artifact.getArtifactId()).append("</artifactId>");
922 buffer.append("<version>").append(artifact.getBaseVersion()).append("</version>");
923 buffer.append("<packaging>").append(artifact.getType()).append("</packaging>");
924 buffer.append("</project>");
925
926 return new StringModelSource(buffer, artifact.getId());
927 }
928
929 private static String inheritedGroupId(final ModelBuildingResult result, final int modelIndex) {
930 String groupId = null;
931 final String modelId = result.getModelIds().get(modelIndex);
932
933 if (!modelId.isEmpty()) {
934 final Model model = result.getRawModel(modelId);
935 groupId = model.getGroupId() != null ? model.getGroupId() : inheritedGroupId(result, modelIndex + 1);
936 }
937
938 return groupId;
939 }
940
941 private static String inheritedVersion(final ModelBuildingResult result, final int modelIndex) {
942 String version = null;
943 final String modelId = result.getModelIds().get(modelIndex);
944
945 if (!modelId.isEmpty()) {
946 version = result.getRawModel(modelId).getVersion();
947 if (version == null) {
948 version = inheritedVersion(result, modelIndex + 1);
949 }
950 }
951
952 return version;
953 }
954
955 static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
956 throw (T) t;
957 }
958
959 static class LazyMap<K, V> extends AbstractMap<K, V> {
960 private final Supplier<Map<K, V>> supplier;
961 private volatile Map<K, V> delegate;
962
963 LazyMap(Supplier<Map<K, V>> supplier) {
964 this.supplier = supplier;
965 }
966
967 @Override
968 public Set<Entry<K, V>> entrySet() {
969 if (delegate == null) {
970 synchronized (this) {
971 if (delegate == null) {
972 delegate = supplier.get();
973 }
974 }
975 }
976 return delegate.entrySet();
977 }
978 }
979 }