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