blob: be9e14c50030ff30c72eef7df06ebab0a9bcb7a7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.project;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.maven.ProjectCycleException;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.api.feature.Features;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.InvalidArtifactRTException;
import org.apache.maven.artifact.InvalidRepositoryException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.bridge.MavenRepositorySystem;
import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.DeploymentRepository;
import org.apache.maven.model.Extension;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.Profile;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.model.building.ArtifactModelSource;
import org.apache.maven.model.building.DefaultModelBuilder;
import org.apache.maven.model.building.DefaultModelBuildingRequest;
import org.apache.maven.model.building.DefaultModelProblem;
import org.apache.maven.model.building.FileModelSource;
import org.apache.maven.model.building.ModelBuilder;
import org.apache.maven.model.building.ModelBuildingException;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelBuildingResult;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.building.ModelProcessor;
import org.apache.maven.model.building.ModelSource;
import org.apache.maven.model.building.StringModelSource;
import org.apache.maven.model.building.TransformerContext;
import org.apache.maven.model.building.TransformerContextBuilder;
import org.apache.maven.model.resolution.ModelResolver;
import org.apache.maven.model.root.RootLocator;
import org.apache.maven.repository.internal.ArtifactDescriptorUtils;
import org.apache.maven.repository.internal.ModelCacheFactory;
import org.apache.maven.utils.Os;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.RequestTrace;
import org.eclipse.aether.impl.RemoteRepositoryManager;
import org.eclipse.aether.repository.LocalRepositoryManager;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.WorkspaceRepository;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* DefaultProjectBuilder
*/
@Named
@Singleton
public class DefaultProjectBuilder implements ProjectBuilder {
public static final String BUILDER_PARALLELISM = "maven.projectBuilder.parallelism";
public static final int DEFAULT_BUILDER_PARALLELISM = 4;
private final Logger logger = LoggerFactory.getLogger(getClass());
private final ModelBuilder modelBuilder;
private final ModelProcessor modelProcessor;
private final ProjectBuildingHelper projectBuildingHelper;
private final MavenRepositorySystem repositorySystem;
private final org.eclipse.aether.RepositorySystem repoSystem;
private final RemoteRepositoryManager repositoryManager;
private final ProjectDependenciesResolver dependencyResolver;
private final ModelCacheFactory modelCacheFactory;
private final RootLocator rootLocator;
@SuppressWarnings("checkstyle:ParameterNumber")
@Inject
public DefaultProjectBuilder(
ModelBuilder modelBuilder,
ModelProcessor modelProcessor,
ProjectBuildingHelper projectBuildingHelper,
MavenRepositorySystem repositorySystem,
RepositorySystem repoSystem,
RemoteRepositoryManager repositoryManager,
ProjectDependenciesResolver dependencyResolver,
ModelCacheFactory modelCacheFactory,
RootLocator rootLocator) {
this.modelBuilder = modelBuilder;
this.modelProcessor = modelProcessor;
this.projectBuildingHelper = projectBuildingHelper;
this.repositorySystem = repositorySystem;
this.repoSystem = repoSystem;
this.repositoryManager = repositoryManager;
this.dependencyResolver = dependencyResolver;
this.modelCacheFactory = modelCacheFactory;
this.rootLocator = rootLocator;
}
// ----------------------------------------------------------------------
// MavenProjectBuilder Implementation
// ----------------------------------------------------------------------
@Override
public ProjectBuildingResult build(File pomFile, ProjectBuildingRequest request) throws ProjectBuildingException {
try (BuildSession bs = new BuildSession(request, false)) {
return bs.build(pomFile, new FileModelSource(pomFile));
}
}
@Override
public ProjectBuildingResult build(ModelSource modelSource, ProjectBuildingRequest request)
throws ProjectBuildingException {
try (BuildSession bs = new BuildSession(request, false)) {
return bs.build(null, modelSource);
}
}
@Override
public ProjectBuildingResult build(Artifact artifact, ProjectBuildingRequest request)
throws ProjectBuildingException {
return build(artifact, false, request);
}
@Override
public ProjectBuildingResult build(Artifact artifact, boolean allowStubModel, ProjectBuildingRequest request)
throws ProjectBuildingException {
try (BuildSession bs = new BuildSession(request, false)) {
return bs.build(artifact, allowStubModel);
}
}
@Override
public List<ProjectBuildingResult> build(List<File> pomFiles, boolean recursive, ProjectBuildingRequest request)
throws ProjectBuildingException {
try (BuildSession bs = new BuildSession(request, true)) {
return bs.build(pomFiles, recursive);
}
}
static class InterimResult {
File pomFile;
ModelBuildingRequest request;
ModelBuildingResult result;
MavenProject project;
boolean root;
List<InterimResult> modules = Collections.emptyList();
ProjectBuildingResult projectBuildingResult;
InterimResult(
File pomFile,
ModelBuildingRequest request,
ModelBuildingResult result,
MavenProject project,
boolean root) {
this.pomFile = pomFile;
this.request = request;
this.result = result;
this.project = project;
this.root = root;
}
InterimResult(ModelBuildingRequest request, ProjectBuildingResult projectBuildingResult) {
this.request = request;
this.projectBuildingResult = projectBuildingResult;
this.pomFile = projectBuildingResult.getPomFile();
this.project = projectBuildingResult.getProject();
}
}
class BuildSession implements AutoCloseable {
private final ProjectBuildingRequest request;
private final RepositorySystemSession session;
private final List<RemoteRepository> repositories;
private final ReactorModelPool modelPool;
private final TransformerContextBuilder transformerContextBuilder;
private final ForkJoinPool forkJoinPool;
BuildSession(ProjectBuildingRequest request, boolean localProjects) {
this.request = request;
this.session =
RepositoryUtils.overlay(request.getLocalRepository(), request.getRepositorySession(), repoSystem);
this.repositories = RepositoryUtils.toRepos(request.getRemoteRepositories());
this.forkJoinPool = new ForkJoinPool(getParallelism(request));
if (localProjects) {
this.modelPool = new ReactorModelPool();
this.transformerContextBuilder = modelBuilder.newTransformerContextBuilder();
} else {
this.modelPool = null;
this.transformerContextBuilder = null;
}
}
@Override
public void close() {
this.forkJoinPool.shutdownNow();
}
private int getParallelism(ProjectBuildingRequest request) {
int parallelism = DEFAULT_BUILDER_PARALLELISM;
try {
String str = request.getUserProperties().getProperty(BUILDER_PARALLELISM);
if (str == null) {
str = request.getSystemProperties().getProperty(BUILDER_PARALLELISM);
}
if (str != null) {
parallelism = Integer.parseInt(str);
}
} catch (Exception e) {
// ignore
}
return Math.max(1, Math.min(parallelism, Runtime.getRuntime().availableProcessors()));
}
ProjectBuildingResult build(File pomFile, ModelSource modelSource) throws ProjectBuildingException {
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
MavenProject project = request.getProject();
List<ModelProblem> modelProblems = null;
Throwable error = null;
if (project == null) {
ModelBuildingRequest request = getModelBuildingRequest();
project = new MavenProject();
project.setFile(pomFile);
DefaultModelBuildingListener listener =
new DefaultModelBuildingListener(project, projectBuildingHelper, this.request);
request.setModelBuildingListener(listener);
request.setPomFile(pomFile);
request.setModelSource(modelSource);
request.setLocationTracking(true);
if (pomFile != null) {
project.setRootDirectory(
rootLocator.findRoot(pomFile.getParentFile().toPath()));
}
ModelBuildingResult result;
try {
result = modelBuilder.build(request);
} catch (ModelBuildingException e) {
result = e.getResult();
if (result == null || result.getEffectiveModel() == null) {
throw new ProjectBuildingException(e.getModelId(), e.getMessage(), pomFile, e);
}
// validation error, continue project building and delay failing to help IDEs
error = e;
}
modelProblems = result.getProblems();
initProject(project, Collections.emptyMap(), result);
} else if (request.isResolveDependencies()) {
projectBuildingHelper.selectProjectRealm(project);
}
DependencyResolutionResult resolutionResult = null;
if (request.isResolveDependencies()) {
resolutionResult = resolveDependencies(project);
}
ProjectBuildingResult result =
new DefaultProjectBuildingResult(project, modelProblems, resolutionResult);
if (error != null) {
ProjectBuildingException e = new ProjectBuildingException(Arrays.asList(result));
e.initCause(error);
throw e;
}
return result;
} finally {
Thread.currentThread().setContextClassLoader(oldContextClassLoader);
}
}
ProjectBuildingResult build(Artifact artifact, boolean allowStubModel) throws ProjectBuildingException {
org.eclipse.aether.artifact.Artifact pomArtifact = RepositoryUtils.toArtifact(artifact);
pomArtifact = ArtifactDescriptorUtils.toPomArtifact(pomArtifact);
boolean localProject;
try {
ArtifactRequest pomRequest = new ArtifactRequest();
pomRequest.setArtifact(pomArtifact);
pomRequest.setRepositories(repositories);
ArtifactResult pomResult = repoSystem.resolveArtifact(session, pomRequest);
pomArtifact = pomResult.getArtifact();
localProject = pomResult.getRepository() instanceof WorkspaceRepository;
} catch (org.eclipse.aether.resolution.ArtifactResolutionException e) {
if (e.getResults().get(0).isMissing() && allowStubModel) {
return build(null, createStubModelSource(artifact));
}
throw new ProjectBuildingException(
artifact.getId(), "Error resolving project artifact: " + e.getMessage(), e);
}
File pomFile = pomArtifact.getFile();
if ("pom".equals(artifact.getType())) {
artifact.selectVersion(pomArtifact.getVersion());
artifact.setFile(pomFile);
artifact.setResolved(true);
}
if (localProject) {
return build(pomFile, new FileModelSource(pomFile));
} else {
return build(
null,
new ArtifactModelSource(
pomFile, artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()));
}
}
List<ProjectBuildingResult> build(List<File> pomFiles, boolean recursive) throws ProjectBuildingException {
ForkJoinTask<List<ProjectBuildingResult>> task = forkJoinPool.submit(() -> doBuild(pomFiles, recursive));
// ForkJoinTask.getException rewraps the exception in a weird way
// which cause an additional layer of exception, so try to unwrap it
task.quietlyJoin();
if (task.isCompletedAbnormally()) {
Throwable e = task.getException();
Throwable c = e.getCause();
uncheckedThrow(c != null && c.getClass() == e.getClass() ? c : e);
}
List<ProjectBuildingResult> results = task.getRawResult();
if (results.stream()
.flatMap(r -> r.getProblems().stream())
.anyMatch(p -> p.getSeverity() != ModelProblem.Severity.WARNING)) {
ModelProblem cycle = results.stream()
.flatMap(r -> r.getProblems().stream())
.filter(p -> p.getException() instanceof CycleDetectedException)
.findAny()
.orElse(null);
if (cycle != null) {
throw new RuntimeException(new ProjectCycleException(
"The projects in the reactor contain a cyclic reference: " + cycle.getMessage(),
(CycleDetectedException) cycle.getException()));
}
throw new ProjectBuildingException(results);
}
return results;
}
List<ProjectBuildingResult> doBuild(List<File> pomFiles, boolean recursive) {
Map<File, MavenProject> projectIndex = new ConcurrentHashMap<>(256);
// phase 1: get file Models from the reactor.
List<InterimResult> interimResults = build(projectIndex, pomFiles, new LinkedHashSet<>(), true, recursive);
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
// Phase 2: get effective models from the reactor
List<ProjectBuildingResult> results = build(projectIndex, interimResults);
if (Features.buildConsumer(request.getUserProperties())) {
request.getRepositorySession()
.getData()
.set(TransformerContext.KEY, transformerContextBuilder.build());
}
return results;
} finally {
Thread.currentThread().setContextClassLoader(oldContextClassLoader);
}
}
@SuppressWarnings("checkstyle:parameternumber")
private List<InterimResult> build(
Map<File, MavenProject> projectIndex,
List<File> pomFiles,
Set<File> aggregatorFiles,
boolean root,
boolean recursive) {
List<ForkJoinTask<InterimResult>> tasks = pomFiles.stream()
.map(pomFile -> ForkJoinTask.adapt(
() -> build(projectIndex, pomFile, concat(aggregatorFiles, pomFile), root, recursive)))
.collect(Collectors.toList());
return ForkJoinTask.invokeAll(tasks).stream()
.map(ForkJoinTask::getRawResult)
.collect(Collectors.toList());
}
private <T> Set<T> concat(Set<T> set, T elem) {
Set<T> newSet = new HashSet<>(set);
newSet.add(elem);
return newSet;
}
@SuppressWarnings("checkstyle:parameternumber")
private InterimResult build(
Map<File, MavenProject> projectIndex,
File pomFile,
Set<File> aggregatorFiles,
boolean isRoot,
boolean recursive) {
MavenProject project = new MavenProject();
project.setFile(pomFile);
project.setRootDirectory(
rootLocator.findRoot(pomFile.getParentFile().toPath()));
ModelBuildingRequest modelBuildingRequest = getModelBuildingRequest()
.setPomFile(pomFile)
.setTwoPhaseBuilding(true)
.setLocationTracking(true);
DefaultModelBuildingListener listener =
new DefaultModelBuildingListener(project, projectBuildingHelper, request);
modelBuildingRequest.setModelBuildingListener(listener);
ModelBuildingResult result;
try {
result = modelBuilder.build(modelBuildingRequest);
} catch (ModelBuildingException e) {
result = e.getResult();
if (result == null || result.getFileModel() == null) {
return new InterimResult(
modelBuildingRequest,
new DefaultProjectBuildingResult(e.getModelId(), pomFile, e.getProblems()));
}
// validation error, continue project building and delay failing to help IDEs
// result.getProblems().addAll(e.getProblems()) ?
}
Model model = modelBuildingRequest.getFileModel();
modelPool.put(model.getPomFile().toPath(), model);
InterimResult interimResult = new InterimResult(pomFile, modelBuildingRequest, result, project, isRoot);
if (recursive) {
File basedir = pomFile.getParentFile();
List<File> moduleFiles = new ArrayList<>();
for (String module : model.getModules()) {
if (module == null || module.isEmpty()) {
continue;
}
module = module.replace('\\', File.separatorChar).replace('/', File.separatorChar);
File moduleFile = modelProcessor.locateExistingPom(new File(basedir, module));
if (moduleFile == null) {
ModelProblem problem = new DefaultModelProblem(
"Child module " + moduleFile + " of " + pomFile + " does not exist",
ModelProblem.Severity.ERROR,
ModelProblem.Version.BASE,
model,
-1,
-1,
null);
result.getProblems().add(problem);
continue;
}
if (Os.IS_WINDOWS) {
// we don't canonicalize on unix to avoid interfering with symlinks
try {
moduleFile = moduleFile.getCanonicalFile();
} catch (IOException e) {
moduleFile = moduleFile.getAbsoluteFile();
}
} else {
moduleFile = new File(moduleFile.toURI().normalize());
}
if (aggregatorFiles.contains(moduleFile)) {
StringBuilder buffer = new StringBuilder(256);
for (File aggregatorFile : aggregatorFiles) {
buffer.append(aggregatorFile).append(" -> ");
}
buffer.append(moduleFile);
ModelProblem problem = new DefaultModelProblem(
"Child module " + moduleFile + " of " + pomFile + " forms aggregation cycle " + buffer,
ModelProblem.Severity.ERROR,
ModelProblem.Version.BASE,
model,
-1,
-1,
null);
result.getProblems().add(problem);
continue;
}
moduleFiles.add(moduleFile);
}
if (!moduleFiles.isEmpty()) {
interimResult.modules = build(projectIndex, moduleFiles, aggregatorFiles, false, recursive);
}
}
projectIndex.put(pomFile, project);
return interimResult;
}
private List<ProjectBuildingResult> build(
Map<File, MavenProject> projectIndex, List<InterimResult> interimResults) {
// The transformation may need to access dependencies raw models,
// which may cause some re-entrance in the build() method and can
// actually cause deadlocks. In order to workaround the problem,
// we do a first pass by reading all rawModels in order.
if (modelBuilder instanceof DefaultModelBuilder) {
List<ProjectBuildingResult> results = new ArrayList<>();
DefaultModelBuilder dmb = (DefaultModelBuilder) modelBuilder;
boolean failure = false;
for (InterimResult r : interimResults) {
DefaultProjectBuildingResult res;
try {
Model model = dmb.buildRawModel(r.request);
res = new DefaultProjectBuildingResult(model.getId(), model.getPomFile(), null);
} catch (ModelBuildingException e) {
failure = true;
res = new DefaultProjectBuildingResult(e.getModelId(), r.request.getPomFile(), e.getProblems());
}
results.add(res);
}
if (failure) {
return results;
}
}
return interimResults.parallelStream()
.map(interimResult -> doBuild(projectIndex, interimResult))
.flatMap(List::stream)
.collect(Collectors.toList());
}
private List<ProjectBuildingResult> doBuild(Map<File, MavenProject> projectIndex, InterimResult interimResult) {
if (interimResult.projectBuildingResult != null) {
return Collections.singletonList(interimResult.projectBuildingResult);
}
MavenProject project = interimResult.project;
try {
ModelBuildingResult result = modelBuilder.build(interimResult.request, interimResult.result);
// 2nd pass of initialization: resolve and build parent if necessary
try {
initProject(project, projectIndex, result);
} catch (InvalidArtifactRTException iarte) {
result.getProblems()
.add(new DefaultModelProblem(
null,
ModelProblem.Severity.ERROR,
null,
result.getEffectiveModel(),
-1,
-1,
iarte));
}
List<ProjectBuildingResult> results = build(projectIndex, interimResult.modules);
project.setExecutionRoot(interimResult.root);
project.setCollectedProjects(
results.stream().map(ProjectBuildingResult::getProject).collect(Collectors.toList()));
DependencyResolutionResult resolutionResult = null;
if (request.isResolveDependencies()) {
resolutionResult = resolveDependencies(project);
}
results.add(new DefaultProjectBuildingResult(project, result.getProblems(), resolutionResult));
return results;
} catch (ModelBuildingException e) {
DefaultProjectBuildingResult result;
if (project == null || interimResult.result.getEffectiveModel() == null) {
result = new DefaultProjectBuildingResult(e.getModelId(), interimResult.pomFile, e.getProblems());
} else {
project.setModel(interimResult.result.getEffectiveModel());
result = new DefaultProjectBuildingResult(project, e.getProblems(), null);
}
return Collections.singletonList(result);
}
}
@SuppressWarnings("checkstyle:methodlength")
private void initProject(MavenProject project, Map<File, MavenProject> projects, ModelBuildingResult result) {
project.setModel(result.getEffectiveModel());
project.setOriginalModel(result.getFileModel());
initParent(project, projects, result);
Artifact projectArtifact = repositorySystem.createArtifact(
project.getGroupId(), project.getArtifactId(), project.getVersion(), null, project.getPackaging());
project.setArtifact(projectArtifact);
// only set those on 2nd phase, ignore on 1st pass
if (project.getFile() != null) {
Build build = project.getBuild();
project.addScriptSourceRoot(build.getScriptSourceDirectory());
project.addCompileSourceRoot(build.getSourceDirectory());
project.addTestCompileSourceRoot(build.getTestSourceDirectory());
}
List<Profile> activeProfiles = new ArrayList<>();
activeProfiles.addAll(
result.getActivePomProfiles(result.getModelIds().get(0)));
activeProfiles.addAll(result.getActiveExternalProfiles());
project.setActiveProfiles(activeProfiles);
project.setInjectedProfileIds("external", getProfileIds(result.getActiveExternalProfiles()));
for (String modelId : result.getModelIds()) {
project.setInjectedProfileIds(modelId, getProfileIds(result.getActivePomProfiles(modelId)));
}
//
// All the parts that were taken out of MavenProject for Maven 4.0.0
//
project.setProjectBuildingRequest(request);
// pluginArtifacts
Set<Artifact> pluginArtifacts = new HashSet<>();
for (Plugin plugin : project.getBuildPlugins()) {
Artifact artifact = repositorySystem.createPluginArtifact(plugin);
if (artifact != null) {
pluginArtifacts.add(artifact);
}
}
project.setPluginArtifacts(pluginArtifacts);
// reportArtifacts
Set<Artifact> reportArtifacts = new HashSet<>();
for (ReportPlugin report : project.getReportPlugins()) {
Plugin pp = new Plugin();
pp.setGroupId(report.getGroupId());
pp.setArtifactId(report.getArtifactId());
pp.setVersion(report.getVersion());
Artifact artifact = repositorySystem.createPluginArtifact(pp);
if (artifact != null) {
reportArtifacts.add(artifact);
}
}
project.setReportArtifacts(reportArtifacts);
// extensionArtifacts
Set<Artifact> extensionArtifacts = new HashSet<>();
List<Extension> extensions = project.getBuildExtensions();
if (extensions != null) {
for (Extension ext : extensions) {
String version;
if (ext.getVersion() == null || ext.getVersion().isEmpty()) {
version = "RELEASE";
} else {
version = ext.getVersion();
}
Artifact artifact = repositorySystem.createArtifact(
ext.getGroupId(), ext.getArtifactId(), version, null, "jar");
if (artifact != null) {
extensionArtifacts.add(artifact);
}
}
}
project.setExtensionArtifacts(extensionArtifacts);
// managedVersionMap
Map<String, Artifact> map = Collections.emptyMap();
final DependencyManagement dependencyManagement = project.getDependencyManagement();
if (dependencyManagement != null
&& dependencyManagement.getDependencies() != null
&& !dependencyManagement.getDependencies().isEmpty()) {
map = new LazyMap<>(() -> {
Map<String, Artifact> tmp = new HashMap<>();
for (Dependency d : dependencyManagement.getDependencies()) {
Artifact artifact = repositorySystem.createDependencyArtifact(d);
if (artifact != null) {
tmp.put(d.getManagementKey(), artifact);
}
}
return Collections.unmodifiableMap(tmp);
});
}
project.setManagedVersionMap(map);
// release artifact repository
if (project.getDistributionManagement() != null
&& project.getDistributionManagement().getRepository() != null) {
try {
DeploymentRepository r = project.getDistributionManagement().getRepository();
if (r.getId() != null
&& !r.getId().isEmpty()
&& r.getUrl() != null
&& !r.getUrl().isEmpty()) {
ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository(r);
repositorySystem.injectProxy(request.getRepositorySession(), Arrays.asList(repo));
repositorySystem.injectAuthentication(request.getRepositorySession(), Arrays.asList(repo));
project.setReleaseArtifactRepository(repo);
}
} catch (InvalidRepositoryException e) {
throw new IllegalStateException(
"Failed to create release distribution repository for " + project.getId(), e);
}
}
// snapshot artifact repository
if (project.getDistributionManagement() != null
&& project.getDistributionManagement().getSnapshotRepository() != null) {
try {
DeploymentRepository r = project.getDistributionManagement().getSnapshotRepository();
if (r.getId() != null
&& !r.getId().isEmpty()
&& r.getUrl() != null
&& !r.getUrl().isEmpty()) {
ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository(r);
repositorySystem.injectProxy(request.getRepositorySession(), Arrays.asList(repo));
repositorySystem.injectAuthentication(request.getRepositorySession(), Arrays.asList(repo));
project.setSnapshotArtifactRepository(repo);
}
} catch (InvalidRepositoryException e) {
throw new IllegalStateException(
"Failed to create snapshot distribution repository for " + project.getId(), e);
}
}
}
private void initParent(MavenProject project, Map<File, MavenProject> projects, ModelBuildingResult result) {
Model parentModel = result.getModelIds().size() > 1
&& !result.getModelIds().get(1).isEmpty()
? result.getRawModel(result.getModelIds().get(1))
: null;
if (parentModel != null) {
final String parentGroupId = inheritedGroupId(result, 1);
final String parentVersion = inheritedVersion(result, 1);
project.setParentArtifact(repositorySystem.createProjectArtifact(
parentGroupId, parentModel.getArtifactId(), parentVersion));
// org.apache.maven.its.mng4834:parent:0.1
String parentModelId = result.getModelIds().get(1);
File parentPomFile = result.getRawModel(parentModelId).getPomFile();
MavenProject parent = parentPomFile != null ? projects.get(parentPomFile) : null;
if (parent == null) {
//
// At this point the DefaultModelBuildingListener has fired and it populates the
// remote repositories with those found in the pom.xml, along with the existing externally
// defined repositories.
//
request.setRemoteRepositories(project.getRemoteArtifactRepositories());
if (parentPomFile != null) {
project.setParentFile(parentPomFile);
try {
parent = build(parentPomFile, new FileModelSource(parentPomFile))
.getProject();
} catch (ProjectBuildingException e) {
// MNG-4488 where let invalid parents slide on by
if (logger.isDebugEnabled()) {
// Message below is checked for in the MNG-2199 core IT.
logger.warn("Failed to build parent project for " + project.getId(), e);
} else {
// Message below is checked for in the MNG-2199 core IT.
logger.warn("Failed to build parent project for " + project.getId());
}
}
} else {
Artifact parentArtifact = project.getParentArtifact();
try {
parent = build(parentArtifact, false).getProject();
} catch (ProjectBuildingException e) {
// MNG-4488 where let invalid parents slide on by
if (logger.isDebugEnabled()) {
// Message below is checked for in the MNG-2199 core IT.
logger.warn("Failed to build parent project for " + project.getId(), e);
} else {
// Message below is checked for in the MNG-2199 core IT.
logger.warn("Failed to build parent project for " + project.getId());
}
}
}
}
project.setParent(parent);
if (project.getParentFile() == null && parent != null) {
project.setParentFile(parent.getFile());
}
}
}
private ModelBuildingRequest getModelBuildingRequest() {
ModelBuildingRequest modelBuildingRequest = new DefaultModelBuildingRequest();
RequestTrace trace = RequestTrace.newChild(null, request).newChild(modelBuildingRequest);
ModelResolver resolver = new ProjectModelResolver(
session,
trace,
repoSystem,
repositoryManager,
repositories,
request.getRepositoryMerging(),
modelPool);
modelBuildingRequest.setValidationLevel(request.getValidationLevel());
modelBuildingRequest.setProcessPlugins(request.isProcessPlugins());
modelBuildingRequest.setProfiles(request.getProfiles());
modelBuildingRequest.setActiveProfileIds(request.getActiveProfileIds());
modelBuildingRequest.setInactiveProfileIds(request.getInactiveProfileIds());
modelBuildingRequest.setSystemProperties(request.getSystemProperties());
modelBuildingRequest.setUserProperties(request.getUserProperties());
modelBuildingRequest.setBuildStartTime(request.getBuildStartTime());
modelBuildingRequest.setModelResolver(resolver);
// this is a hint that we want to build 1 file, so don't cache. See MNG-7063
if (modelPool != null) {
modelBuildingRequest.setModelCache(modelCacheFactory.createCache(session));
}
modelBuildingRequest.setTransformerContextBuilder(transformerContextBuilder);
InternalSession session = (InternalSession) this.session.getData().get(InternalSession.class);
if (session != null) {
try {
modelBuildingRequest.setRootDirectory(session.getRootDirectory());
} catch (IllegalStateException e) {
// can happen if root directory cannot be found, just ignore
}
}
return modelBuildingRequest;
}
private DependencyResolutionResult resolveDependencies(MavenProject project) {
DependencyResolutionResult resolutionResult;
try {
DefaultDependencyResolutionRequest resolution =
new DefaultDependencyResolutionRequest(project, session);
resolutionResult = dependencyResolver.resolve(resolution);
} catch (DependencyResolutionException e) {
resolutionResult = e.getResult();
}
Set<Artifact> artifacts = new LinkedHashSet<>();
if (resolutionResult.getDependencyGraph() != null) {
RepositoryUtils.toArtifacts(
artifacts,
resolutionResult.getDependencyGraph().getChildren(),
Collections.singletonList(project.getArtifact().getId()),
null);
// Maven 2.x quirk: an artifact always points at the local repo, regardless whether resolved or not
LocalRepositoryManager lrm = session.getLocalRepositoryManager();
for (Artifact artifact : artifacts) {
if (!artifact.isResolved()) {
String path = lrm.getPathForLocalArtifact(RepositoryUtils.toArtifact(artifact));
artifact.setFile(new File(lrm.getRepository().getBasedir(), path));
}
}
}
project.setResolvedArtifacts(artifacts);
project.setArtifacts(artifacts);
return resolutionResult;
}
}
private List<String> getProfileIds(List<org.apache.maven.model.Profile> profiles) {
return profiles.stream().map(org.apache.maven.model.Profile::getId).collect(Collectors.toList());
}
private static ModelSource createStubModelSource(Artifact artifact) {
StringBuilder buffer = new StringBuilder(1024);
buffer.append("<?xml version='1.0'?>");
buffer.append("<project>");
buffer.append("<modelVersion>4.0.0</modelVersion>");
buffer.append("<groupId>").append(artifact.getGroupId()).append("</groupId>");
buffer.append("<artifactId>").append(artifact.getArtifactId()).append("</artifactId>");
buffer.append("<version>").append(artifact.getBaseVersion()).append("</version>");
buffer.append("<packaging>").append(artifact.getType()).append("</packaging>");
buffer.append("</project>");
return new StringModelSource(buffer, artifact.getId());
}
private static String inheritedGroupId(final ModelBuildingResult result, final int modelIndex) {
String groupId = null;
final String modelId = result.getModelIds().get(modelIndex);
if (!modelId.isEmpty()) {
final Model model = result.getRawModel(modelId);
groupId = model.getGroupId() != null ? model.getGroupId() : inheritedGroupId(result, modelIndex + 1);
}
return groupId;
}
private static String inheritedVersion(final ModelBuildingResult result, final int modelIndex) {
String version = null;
final String modelId = result.getModelIds().get(modelIndex);
if (!modelId.isEmpty()) {
version = result.getRawModel(modelId).getVersion();
if (version == null) {
version = inheritedVersion(result, modelIndex + 1);
}
}
return version;
}
static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
throw (T) t; // rely on vacuous cast
}
static class LazyMap<K, V> extends AbstractMap<K, V> {
private final Supplier<Map<K, V>> supplier;
private volatile Map<K, V> delegate;
LazyMap(Supplier<Map<K, V>> supplier) {
this.supplier = supplier;
}
@Override
public Set<Entry<K, V>> entrySet() {
if (delegate == null) {
synchronized (this) {
if (delegate == null) {
delegate = supplier.get();
}
}
}
return delegate.entrySet();
}
}
}