mirror of https://github.com/apache/maven.git
[MNG-8294] Consistency checks when loading parent (#1784)
This commit is contained in:
parent
445236398d
commit
fee69f2f89
|
@ -52,6 +52,10 @@ public interface ModelBuilderRequest {
|
|||
* The request is for building a model from a POM file in a project on the filesystem.
|
||||
*/
|
||||
BUILD_POM,
|
||||
/**
|
||||
* The request is for building the consumer POM.
|
||||
*/
|
||||
CONSUMER_POM,
|
||||
/**
|
||||
* The request is for building a model from a parent POM file from a downloaded artifact.
|
||||
*/
|
||||
|
|
|
@ -1744,20 +1744,16 @@
|
|||
<name>relativePath</name>
|
||||
<version>4.0.0+</version>
|
||||
<description>
|
||||
The relative path of the parent {@code pom.xml} file within the checkout.
|
||||
If not specified, it defaults to {@code ../pom.xml}.
|
||||
The relative path of the parent subproject POM file or directory within the checkout.
|
||||
If not specified, it defaults to {@code ..}, i.e. the parent directory.
|
||||
Maven looks for the parent POM first in this location on
|
||||
the filesystem, then the local repository, and lastly in the remote repo.
|
||||
{@code relativePath} allows you to select a different location,
|
||||
for example when your structure is flat, or deeper without an intermediate parent POM.
|
||||
However, the group ID, artifact ID and version are still required,
|
||||
and must match the file in the location given, or it will revert to the repository for the POM.
|
||||
This feature is only for enhancing the development in a local checkout of that project.
|
||||
Set the value to an empty string in case you want to disable the feature and always resolve
|
||||
the parent POM from the repositories.
|
||||
the filesystem if explicitly provided, then in the reactor if groupId and artifactId are provided,
|
||||
then in the default parent directory, then the local repository, and lastly in the remote repo.
|
||||
However, if the both relative path and the group ID / artifact ID are provided,
|
||||
they must match the file in the location given.
|
||||
Specify either the {@code relativePath} or the {@code groupId}/{@code artifactId}, not both.
|
||||
</description>
|
||||
<type>String</type>
|
||||
<defaultValue>..</defaultValue>
|
||||
</field>
|
||||
</fields>
|
||||
<codeSegments>
|
||||
|
|
|
@ -34,7 +34,6 @@ import java.util.LinkedHashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
@ -829,6 +828,14 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
}
|
||||
|
||||
result.setEffectiveModel(resultModel);
|
||||
// Set the default relative path for the parent in the file model
|
||||
if (result.getFileModel().getParent() != null
|
||||
&& result.getFileModel().getParent().getRelativePath() == null) {
|
||||
result.setFileModel(result.getFileModel()
|
||||
.withParent(result.getFileModel()
|
||||
.getParent()
|
||||
.withRelativePath(resultModel.getParent().getRelativePath())));
|
||||
}
|
||||
|
||||
// effective model validation
|
||||
modelValidator.validateEffectiveModel(
|
||||
|
@ -849,10 +856,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
|
||||
Parent parent = childModel.getParent();
|
||||
if (parent != null) {
|
||||
parentModel = readParentLocally(childModel);
|
||||
if (parentModel == null) {
|
||||
parentModel = resolveAndReadParentExternally(childModel);
|
||||
}
|
||||
parentModel = resolveParent(childModel);
|
||||
|
||||
if (!"pom".equals(parentModel.getPackaging())) {
|
||||
add(
|
||||
|
@ -877,43 +881,56 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
return parentModel;
|
||||
}
|
||||
|
||||
private Model resolveParent(Model childModel) {
|
||||
Model parentModel = null;
|
||||
if (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_POM
|
||||
|| request.getRequestType() == ModelBuilderRequest.RequestType.CONSUMER_POM) {
|
||||
parentModel = readParentLocally(childModel);
|
||||
}
|
||||
if (parentModel == null) {
|
||||
parentModel = resolveAndReadParentExternally(childModel);
|
||||
}
|
||||
return parentModel;
|
||||
}
|
||||
|
||||
private Model readParentLocally(Model childModel) throws ModelBuilderException {
|
||||
ModelSource candidateSource = getParentPomFile(childModel, request.getSource());
|
||||
ModelSource candidateSource = null;
|
||||
|
||||
Parent parent = childModel.getParent();
|
||||
String parentPath = parent.getRelativePath();
|
||||
if (parentPath != null && !parentPath.isEmpty()) {
|
||||
candidateSource = request.getSource().resolve(modelProcessor::locateExistingPom, parentPath);
|
||||
if (candidateSource == null) {
|
||||
wrongParentRelativePath(childModel);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (candidateSource == null) {
|
||||
candidateSource = resolveReactorModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
|
||||
}
|
||||
if (candidateSource == null) {
|
||||
candidateSource = request.getSource().resolve(modelProcessor::locateExistingPom, "..");
|
||||
}
|
||||
|
||||
if (candidateSource == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Model candidateModel = derive(candidateSource).readAsParentModel();
|
||||
|
||||
//
|
||||
// TODO jvz Why isn't all this checking the job of the duty of the workspace resolver, we know that we
|
||||
// have a model that is suitable, yet more checks are done here and the one for the version is problematic
|
||||
// before because with parents as ranges it will never work in this scenario.
|
||||
//
|
||||
|
||||
String groupId = getGroupId(candidateModel);
|
||||
String artifactId = candidateModel.getArtifactId();
|
||||
String version = getVersion(candidateModel);
|
||||
|
||||
Parent parent = childModel.getParent();
|
||||
// Ensure that relative path and GA match, if both are provided
|
||||
if (groupId == null
|
||||
|| !groupId.equals(parent.getGroupId())
|
||||
|| artifactId == null
|
||||
|| !artifactId.equals(parent.getArtifactId())) {
|
||||
StringBuilder buffer = new StringBuilder(256);
|
||||
buffer.append("'parent.relativePath'");
|
||||
if (childModel != getRootModel()) {
|
||||
buffer.append(" of POM ").append(ModelProblemUtils.toSourceHint(childModel));
|
||||
}
|
||||
buffer.append(" points at ").append(groupId).append(':').append(artifactId);
|
||||
buffer.append(" instead of ").append(parent.getGroupId()).append(':');
|
||||
buffer.append(parent.getArtifactId()).append(", please verify your project structure");
|
||||
|
||||
setSource(childModel);
|
||||
add(Severity.WARNING, Version.BASE, buffer.toString(), parent.getLocation(""));
|
||||
mismatchRelativePathAndGA(childModel, groupId, artifactId);
|
||||
return null;
|
||||
}
|
||||
|
||||
String version = getVersion(candidateModel);
|
||||
if (version != null && parent.getVersion() != null && !version.equals(parent.getVersion())) {
|
||||
try {
|
||||
VersionRange parentRange = versionParser.parseVersionRange(parent.getVersion());
|
||||
|
@ -946,15 +963,41 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Here we just need to know that a version is fine to use but this validation we can do in our workspace
|
||||
// resolver.
|
||||
//
|
||||
|
||||
return candidateModel;
|
||||
}
|
||||
|
||||
private void mismatchRelativePathAndGA(Model childModel, String groupId, String artifactId) {
|
||||
Parent parent = childModel.getParent();
|
||||
StringBuilder buffer = new StringBuilder(256);
|
||||
buffer.append("'parent.relativePath'");
|
||||
if (childModel != getRootModel()) {
|
||||
buffer.append(" of POM ").append(ModelProblemUtils.toSourceHint(childModel));
|
||||
}
|
||||
buffer.append(" points at ").append(groupId).append(':').append(artifactId);
|
||||
buffer.append(" instead of ").append(parent.getGroupId()).append(':');
|
||||
buffer.append(parent.getArtifactId()).append(", please verify your project structure");
|
||||
|
||||
setSource(childModel);
|
||||
boolean warn = MODEL_VERSION_4_0_0.equals(childModel.getModelVersion())
|
||||
|| childModel.getParent().getRelativePath() == null;
|
||||
add(warn ? Severity.WARNING : Severity.FATAL, Version.BASE, buffer.toString(), parent.getLocation(""));
|
||||
}
|
||||
|
||||
private void wrongParentRelativePath(Model childModel) {
|
||||
Parent parent = childModel.getParent();
|
||||
String parentPath = parent.getRelativePath();
|
||||
StringBuilder buffer = new StringBuilder(256);
|
||||
buffer.append("'parent.relativePath'");
|
||||
if (childModel != getRootModel()) {
|
||||
buffer.append(" of POM ").append(ModelProblemUtils.toSourceHint(childModel));
|
||||
}
|
||||
buffer.append(" points at '").append(parentPath);
|
||||
buffer.append("' but no POM could be found, please verify your project structure");
|
||||
|
||||
setSource(childModel);
|
||||
add(Severity.FATAL, Version.BASE, buffer.toString(), parent.getLocation(""));
|
||||
}
|
||||
|
||||
Model resolveAndReadParentExternally(Model childModel) throws ModelBuilderException {
|
||||
ModelBuilderRequest request = this.request;
|
||||
setSource(childModel);
|
||||
|
@ -981,7 +1024,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
|
||||
ModelSource modelSource;
|
||||
try {
|
||||
modelSource = resolveReactorModel(groupId, artifactId, version);
|
||||
modelSource = resolveReactorModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
|
||||
if (modelSource == null) {
|
||||
AtomicReference<Parent> modified = new AtomicReference<>();
|
||||
modelSource = modelResolver.resolveModel(request.getSession(), repositories, parent, modified);
|
||||
|
@ -1000,13 +1043,8 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
buffer.append(" for ").append(ModelProblemUtils.toId(childModel));
|
||||
}
|
||||
buffer.append(": ").append(e.getMessage());
|
||||
if (childModel.getProjectDirectory() != null) {
|
||||
if (parent.getRelativePath() == null
|
||||
|| parent.getRelativePath().isEmpty()) {
|
||||
buffer.append(" and 'parent.relativePath' points at no local POM");
|
||||
} else {
|
||||
buffer.append(" and 'parent.relativePath' points at wrong local POM");
|
||||
}
|
||||
if (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_POM) {
|
||||
buffer.append(" and parent could not be found in reactor");
|
||||
}
|
||||
|
||||
add(Severity.FATAL, Version.BASE, buffer.toString(), parent.getLocation(""), e);
|
||||
|
@ -1050,8 +1088,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
DefaultProfileActivationContext profileActivationContext = getProfileActivationContext(request, inputModel);
|
||||
|
||||
setSource("(external profiles)");
|
||||
List<Profile> activeExternalProfiles =
|
||||
profileSelector.getActiveProfiles(request.getProfiles(), profileActivationContext, this);
|
||||
List<Profile> activeExternalProfiles = getActiveProfiles(request.getProfiles(), profileActivationContext);
|
||||
|
||||
result.setActiveExternalProfiles(activeExternalProfiles);
|
||||
|
||||
|
@ -1066,8 +1103,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
|
||||
profileActivationContext.setProjectProperties(inputModel.getProperties());
|
||||
setSource(inputModel);
|
||||
List<Profile> activePomProfiles =
|
||||
profileSelector.getActiveProfiles(inputModel.getProfiles(), profileActivationContext, this);
|
||||
List<Profile> activePomProfiles = getActiveProfiles(inputModel.getProfiles(), profileActivationContext);
|
||||
|
||||
// model normalization
|
||||
setSource(inputModel);
|
||||
|
@ -1109,12 +1145,29 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
}
|
||||
|
||||
Model parentModel = readParent(inputModel);
|
||||
// Now that we have read the parent, we can set the relative
|
||||
// path correctly if it was not set in the input model
|
||||
if (inputModel.getParent() != null && inputModel.getParent().getRelativePath() == null) {
|
||||
String relPath;
|
||||
if (parentModel.getPomFile() != null
|
||||
&& (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_POM
|
||||
|| request.getRequestType() == ModelBuilderRequest.RequestType.CONSUMER_POM)) {
|
||||
relPath = inputModel
|
||||
.getPomFile()
|
||||
.getParent()
|
||||
.relativize(parentModel.getPomFile().getParent())
|
||||
.toString();
|
||||
} else {
|
||||
relPath = "..";
|
||||
}
|
||||
inputModel = inputModel.withParent(inputModel.getParent().withRelativePath(relPath));
|
||||
}
|
||||
|
||||
List<Profile> parentInterpolatedProfiles =
|
||||
interpolateActivations(parentModel.getProfiles(), profileActivationContext, this);
|
||||
// profile injection
|
||||
List<Profile> parentActivePomProfiles =
|
||||
profileSelector.getActiveProfiles(parentInterpolatedProfiles, profileActivationContext, this);
|
||||
getActiveProfiles(parentInterpolatedProfiles, profileActivationContext);
|
||||
Model injectedParentModel = profileInjector
|
||||
.injectProfiles(parentModel, parentActivePomProfiles, request, this)
|
||||
.withProfiles(List.of());
|
||||
|
@ -1131,8 +1184,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
interpolateActivations(model.getProfiles(), profileActivationContext, this);
|
||||
|
||||
// profile injection
|
||||
List<Profile> activePomProfiles =
|
||||
profileSelector.getActiveProfiles(interpolatedProfiles, profileActivationContext, this);
|
||||
List<Profile> activePomProfiles = getActiveProfiles(interpolatedProfiles, profileActivationContext);
|
||||
result.setActivePomProfiles(activePomProfiles);
|
||||
model = profileInjector.injectProfiles(model, activePomProfiles, request, this);
|
||||
model = profileInjector.injectProfiles(model, activeExternalProfiles, request, this);
|
||||
|
@ -1160,6 +1212,15 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
return resultModel;
|
||||
}
|
||||
|
||||
private List<Profile> getActiveProfiles(
|
||||
Collection<Profile> interpolatedProfiles, DefaultProfileActivationContext profileActivationContext) {
|
||||
if (request.getRequestType() != ModelBuilderRequest.RequestType.CONSUMER_POM) {
|
||||
return profileSelector.getActiveProfiles(interpolatedProfiles, profileActivationContext, this);
|
||||
} else {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
Model readFileModel() throws ModelBuilderException {
|
||||
Model model = cache(request.getSource(), FILE, this::doReadFileModel);
|
||||
// set the file model in the result outside the cache
|
||||
|
@ -1248,7 +1309,8 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
if (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_POM) {
|
||||
if (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_POM
|
||||
|| request.getRequestType() == ModelBuilderRequest.RequestType.CONSUMER_POM) {
|
||||
model = model.withPomFile(modelSource.getPath());
|
||||
|
||||
Parent parent = model.getParent();
|
||||
|
@ -1256,10 +1318,11 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
String groupId = parent.getGroupId();
|
||||
String artifactId = parent.getArtifactId();
|
||||
String version = parent.getVersion();
|
||||
String path = Optional.ofNullable(parent.getRelativePath()).orElse("..");
|
||||
if (version == null && !path.isEmpty()) {
|
||||
String path = parent.getRelativePath();
|
||||
if ((groupId == null || artifactId == null || version == null)
|
||||
&& (path == null || !path.isEmpty())) {
|
||||
Path pomFile = model.getPomFile();
|
||||
Path relativePath = Paths.get(path);
|
||||
Path relativePath = Paths.get(path != null ? path : "..");
|
||||
Path pomPath = pomFile.resolveSibling(relativePath).normalize();
|
||||
if (Files.isDirectory(pomPath)) {
|
||||
pomPath = modelProcessor.locateExistingPom(pomPath);
|
||||
|
@ -1267,18 +1330,23 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
if (pomPath != null && Files.isRegularFile(pomPath)) {
|
||||
Model parentModel =
|
||||
derive(ModelSource.fromPath(pomPath)).readFileModel();
|
||||
if (parentModel != null) {
|
||||
String parentGroupId = getGroupId(parentModel);
|
||||
String parentArtifactId = parentModel.getArtifactId();
|
||||
String parentVersion = getVersion(parentModel);
|
||||
if ((groupId == null || groupId.equals(parentGroupId))
|
||||
&& (artifactId == null || artifactId.equals(parentArtifactId))) {
|
||||
model = model.withParent(parent.with()
|
||||
.groupId(parentGroupId)
|
||||
.artifactId(parentArtifactId)
|
||||
.version(parentVersion)
|
||||
.build());
|
||||
}
|
||||
String parentGroupId = getGroupId(parentModel);
|
||||
String parentArtifactId = parentModel.getArtifactId();
|
||||
String parentVersion = getVersion(parentModel);
|
||||
if ((groupId == null || groupId.equals(parentGroupId))
|
||||
&& (artifactId == null || artifactId.equals(parentArtifactId))
|
||||
&& (version == null || version.equals(parentVersion))) {
|
||||
model = model.withParent(parent.with()
|
||||
.groupId(parentGroupId)
|
||||
.artifactId(parentArtifactId)
|
||||
.version(parentVersion)
|
||||
.build());
|
||||
} else {
|
||||
mismatchRelativePathAndGA(model, parentGroupId, parentArtifactId);
|
||||
}
|
||||
} else {
|
||||
if (!MODEL_VERSION_4_0_0.equals(model.getModelVersion()) && path != null) {
|
||||
wrongParentRelativePath(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1369,7 +1437,8 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
Model rawModel = readFileModel();
|
||||
|
||||
if (!MODEL_VERSION_4_0_0.equals(rawModel.getModelVersion())
|
||||
&& request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_POM) {
|
||||
&& (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_POM
|
||||
|| request.getRequestType() == ModelBuilderRequest.RequestType.CONSUMER_POM)) {
|
||||
rawModel = transformFileToRaw(rawModel);
|
||||
}
|
||||
|
||||
|
@ -1600,7 +1669,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
.source(importSource)
|
||||
.repositories(repositories)
|
||||
.build();
|
||||
DefaultModelBuilderSession modelBuilderSession = new DefaultModelBuilderSession(importRequest);
|
||||
DefaultModelBuilderSession modelBuilderSession = derive(importRequest);
|
||||
// build the effective model
|
||||
modelBuilderSession.buildEffectiveModel(importIds);
|
||||
importResult = modelBuilderSession.result;
|
||||
|
@ -1812,15 +1881,6 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
|| rawChildModelVersion.equals("${project.parent.version}");
|
||||
}
|
||||
|
||||
private ModelSource getParentPomFile(Model childModel, ModelSource source) {
|
||||
String parentPath = childModel.getParent().getRelativePath();
|
||||
if (parentPath == null || parentPath.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return source.resolve(modelProcessor::locateExistingPom, parentPath);
|
||||
}
|
||||
}
|
||||
|
||||
private Model getSuperModel(String modelVersion) {
|
||||
return superPomProvider.getSuperPom(modelVersion);
|
||||
}
|
||||
|
|
|
@ -326,6 +326,24 @@ public class DefaultModelValidator implements ModelValidator {
|
|||
"is either LATEST or RELEASE (both of them are being deprecated)",
|
||||
parent);
|
||||
}
|
||||
|
||||
if (parent.getRelativePath() != null
|
||||
&& !parent.getRelativePath().isEmpty()
|
||||
&& (parent.getGroupId() != null && !parent.getGroupId().isEmpty()
|
||||
|| parent.getArtifactId() != null
|
||||
&& !parent.getArtifactId().isEmpty())
|
||||
&& validationLevel >= ModelValidator.VALIDATION_LEVEL_MAVEN_4_0
|
||||
&& VALID_MODEL_VERSIONS.contains(m.getModelVersion())
|
||||
&& !Objects.equals(m.getModelVersion(), ModelBuilder.MODEL_VERSION_4_0_0)) {
|
||||
addViolation(
|
||||
problems,
|
||||
Severity.WARNING,
|
||||
Version.BASE,
|
||||
"parent.relativePath",
|
||||
null,
|
||||
"only specify relativePath or groupId/artifactId in modelVersion 4.1.0",
|
||||
parent);
|
||||
}
|
||||
}
|
||||
|
||||
if (validationLevel == ModelValidator.VALIDATION_LEVEL_MINIMAL) {
|
||||
|
|
|
@ -21,10 +21,14 @@ package org.apache.maven.internal.transformation.impl;
|
|||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.maven.api.SessionData;
|
||||
|
@ -35,42 +39,17 @@ import org.apache.maven.api.model.Model;
|
|||
import org.apache.maven.api.model.ModelBase;
|
||||
import org.apache.maven.api.model.Profile;
|
||||
import org.apache.maven.api.model.Repository;
|
||||
import org.apache.maven.api.services.Interpolator;
|
||||
import org.apache.maven.api.services.ModelBuilder;
|
||||
import org.apache.maven.api.services.ModelBuilderException;
|
||||
import org.apache.maven.api.services.ModelBuilderRequest;
|
||||
import org.apache.maven.api.services.ModelBuilderResult;
|
||||
import org.apache.maven.api.services.ModelProblemCollector;
|
||||
import org.apache.maven.api.services.ModelSource;
|
||||
import org.apache.maven.api.services.SuperPomProvider;
|
||||
import org.apache.maven.api.services.model.DependencyManagementImporter;
|
||||
import org.apache.maven.api.services.model.DependencyManagementInjector;
|
||||
import org.apache.maven.api.services.model.InheritanceAssembler;
|
||||
import org.apache.maven.api.services.Source;
|
||||
import org.apache.maven.api.services.model.LifecycleBindingsInjector;
|
||||
import org.apache.maven.api.services.model.ModelCacheFactory;
|
||||
import org.apache.maven.api.services.model.ModelInterpolator;
|
||||
import org.apache.maven.api.services.model.ModelNormalizer;
|
||||
import org.apache.maven.api.services.model.ModelPathTranslator;
|
||||
import org.apache.maven.api.services.model.ModelProcessor;
|
||||
import org.apache.maven.api.services.model.ModelResolver;
|
||||
import org.apache.maven.api.services.model.ModelUrlNormalizer;
|
||||
import org.apache.maven.api.services.model.ModelValidator;
|
||||
import org.apache.maven.api.services.model.ModelVersionParser;
|
||||
import org.apache.maven.api.services.model.PluginConfigurationExpander;
|
||||
import org.apache.maven.api.services.model.PluginManagementInjector;
|
||||
import org.apache.maven.api.services.model.ProfileActivationContext;
|
||||
import org.apache.maven.api.services.model.ProfileInjector;
|
||||
import org.apache.maven.api.services.model.ProfileSelector;
|
||||
import org.apache.maven.api.spi.ModelTransformer;
|
||||
import org.apache.maven.internal.impl.InternalSession;
|
||||
import org.apache.maven.internal.impl.model.DefaultModelBuilder;
|
||||
import org.apache.maven.internal.impl.model.DefaultProfileSelector;
|
||||
import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
|
||||
import org.apache.maven.model.v4.MavenModelVersion;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Named
|
||||
class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
|
||||
|
@ -78,74 +57,14 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
|
|||
|
||||
public static final String POM_PACKAGING = "pom";
|
||||
|
||||
private final ProfileInjector profileInjector;
|
||||
private final InheritanceAssembler inheritanceAssembler;
|
||||
private final DependencyManagementImporter dependencyManagementImporter;
|
||||
private final DependencyManagementInjector dependencyManagementInjector;
|
||||
private final LifecycleBindingsInjector lifecycleBindingsInjector;
|
||||
private final ModelInterpolator modelInterpolator;
|
||||
private final ModelNormalizer modelNormalizer;
|
||||
private final ModelPathTranslator modelPathTranslator;
|
||||
private final ModelProcessor modelProcessor;
|
||||
private final ModelUrlNormalizer modelUrlNormalizer;
|
||||
private final ModelValidator modelValidator;
|
||||
private final PluginConfigurationExpander pluginConfigurationExpander;
|
||||
private final PluginManagementInjector pluginManagementInjector;
|
||||
private final SuperPomProvider superPomProvider;
|
||||
private final ModelVersionParser versionParser;
|
||||
private final ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
|
||||
private final List<ModelTransformer> transformers;
|
||||
private final ModelCacheFactory modelCacheFactory;
|
||||
private final ModelResolver modelResolver;
|
||||
private final Interpolator interpolator;
|
||||
|
||||
@Inject
|
||||
@SuppressWarnings("checkstyle:ParameterNumber")
|
||||
DefaultConsumerPomBuilder(
|
||||
ProfileInjector profileInjector,
|
||||
InheritanceAssembler inheritanceAssembler,
|
||||
DependencyManagementImporter dependencyManagementImporter,
|
||||
DependencyManagementInjector dependencyManagementInjector,
|
||||
LifecycleBindingsInjector lifecycleBindingsInjector,
|
||||
ModelInterpolator modelInterpolator,
|
||||
ModelNormalizer modelNormalizer,
|
||||
ModelPathTranslator modelPathTranslator,
|
||||
ModelProcessor modelProcessor,
|
||||
ModelUrlNormalizer modelUrlNormalizer,
|
||||
ModelValidator modelValidator,
|
||||
PluginConfigurationExpander pluginConfigurationExpander,
|
||||
PluginManagementInjector pluginManagementInjector,
|
||||
SuperPomProvider superPomProvider,
|
||||
ModelVersionParser versionParser,
|
||||
ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator,
|
||||
List<ModelTransformer> transformers,
|
||||
ModelCacheFactory modelCacheFactory,
|
||||
ModelResolver modelResolver,
|
||||
Interpolator interpolator) {
|
||||
this.profileInjector = profileInjector;
|
||||
this.inheritanceAssembler = inheritanceAssembler;
|
||||
this.dependencyManagementImporter = dependencyManagementImporter;
|
||||
this.dependencyManagementInjector = dependencyManagementInjector;
|
||||
DefaultConsumerPomBuilder(LifecycleBindingsInjector lifecycleBindingsInjector) {
|
||||
this.lifecycleBindingsInjector = lifecycleBindingsInjector;
|
||||
this.modelInterpolator = modelInterpolator;
|
||||
this.modelNormalizer = modelNormalizer;
|
||||
this.modelPathTranslator = modelPathTranslator;
|
||||
this.modelProcessor = modelProcessor;
|
||||
this.modelUrlNormalizer = modelUrlNormalizer;
|
||||
this.modelValidator = modelValidator;
|
||||
this.pluginConfigurationExpander = pluginConfigurationExpander;
|
||||
this.pluginManagementInjector = pluginManagementInjector;
|
||||
this.superPomProvider = superPomProvider;
|
||||
this.versionParser = versionParser;
|
||||
this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator;
|
||||
this.transformers = transformers;
|
||||
this.modelCacheFactory = modelCacheFactory;
|
||||
this.modelResolver = modelResolver;
|
||||
this.interpolator = interpolator;
|
||||
}
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public Model build(RepositorySystemSession session, MavenProject project, Path src) throws ModelBuilderException {
|
||||
Model model = project.getModel().getDelegate();
|
||||
|
@ -174,49 +93,18 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
|
|||
|
||||
private ModelBuilderResult buildModel(RepositorySystemSession session, MavenProject project, Path src)
|
||||
throws ModelBuilderException {
|
||||
ProfileSelector customSelector = new DefaultProfileSelector() {
|
||||
@Override
|
||||
public List<Profile> getActiveProfiles(
|
||||
Collection<Profile> profiles, ProfileActivationContext context, ModelProblemCollector problems) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
};
|
||||
// TODO: the custom selector should be used as a flag on the request
|
||||
DefaultModelBuilder modelBuilder = new DefaultModelBuilder(
|
||||
modelProcessor,
|
||||
modelValidator,
|
||||
modelNormalizer,
|
||||
modelInterpolator,
|
||||
modelPathTranslator,
|
||||
modelUrlNormalizer,
|
||||
superPomProvider,
|
||||
inheritanceAssembler,
|
||||
customSelector,
|
||||
profileInjector,
|
||||
pluginManagementInjector,
|
||||
dependencyManagementInjector,
|
||||
dependencyManagementImporter,
|
||||
pluginConfigurationExpander,
|
||||
profileActivationFilePathInterpolator,
|
||||
versionParser,
|
||||
transformers,
|
||||
modelCacheFactory,
|
||||
modelResolver,
|
||||
interpolator);
|
||||
InternalSession iSession = InternalSession.from(session);
|
||||
ModelBuilderRequest.ModelBuilderRequestBuilder request = ModelBuilderRequest.builder();
|
||||
request.requestType(ModelBuilderRequest.RequestType.BUILD_POM);
|
||||
request.requestType(ModelBuilderRequest.RequestType.CONSUMER_POM);
|
||||
request.session(iSession);
|
||||
request.source(ModelSource.fromPath(src));
|
||||
// in order to resolve parents, we need to fake being at the correct location
|
||||
request.source(new PomConsumerModelSource(project.getModel().getPomPath(), src));
|
||||
request.locationTracking(false);
|
||||
request.systemProperties(session.getSystemProperties());
|
||||
request.userProperties(session.getUserProperties());
|
||||
request.lifecycleBindingsInjector(lifecycleBindingsInjector::injectLifecycleBindings);
|
||||
ModelBuilder.ModelBuilderSession mbSession =
|
||||
iSession.getData().get(SessionData.key(ModelBuilder.ModelBuilderSession.class));
|
||||
if (mbSession == null) {
|
||||
mbSession = modelBuilder.newSession();
|
||||
}
|
||||
return mbSession.build(request.build());
|
||||
}
|
||||
|
||||
|
@ -320,4 +208,63 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
|
|||
.filter(r -> !org.apache.maven.api.Repository.CENTRAL_ID.equals(r.getId()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
static class PomConsumerModelSource implements ModelSource {
|
||||
final Path path;
|
||||
final Path src;
|
||||
|
||||
PomConsumerModelSource(Path path, Path src) {
|
||||
this.path = path;
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream openStream() throws IOException {
|
||||
return Files.newInputStream(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocation() {
|
||||
return src.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Source resolve(String relative) {
|
||||
return ModelSource.fromPath(path.resolve(relative));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelSource resolve(ModelLocator locator, String relative) {
|
||||
String norm = relative.replace('\\', File.separatorChar).replace('/', File.separatorChar);
|
||||
Path path = getPath().getParent().resolve(norm);
|
||||
Path relatedPom = locator.locateExistingPom(path);
|
||||
if (relatedPom != null) {
|
||||
return ModelSource.fromPath(relatedPom);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return this == o
|
||||
|| o.getClass() == getClass()
|
||||
&& Objects.equals(path, ((PomConsumerModelSource) o).path)
|
||||
&& Objects.equals(src, ((PomConsumerModelSource) o).src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(path, src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PomConsumerModelSource[" + "path=" + path + ']';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ import org.apache.maven.artifact.repository.ArtifactRepository;
|
|||
import org.apache.maven.bridge.MavenRepositorySystem;
|
||||
import org.apache.maven.internal.impl.InternalSession;
|
||||
import org.apache.maven.internal.impl.resolver.ArtifactDescriptorUtils;
|
||||
import org.apache.maven.model.building.DefaultModelProblem;
|
||||
import org.apache.maven.model.building.FileModelSource;
|
||||
import org.apache.maven.model.building.ModelBuildingRequest;
|
||||
import org.apache.maven.model.building.ModelSource2;
|
||||
|
@ -499,6 +500,11 @@ public class DefaultProjectBuilder implements ProjectBuilder {
|
|||
List<ProjectBuildingResult> results = new ArrayList<>();
|
||||
List<ModelBuilderResult> allModels = results(result).toList();
|
||||
for (ModelBuilderResult r : allModels) {
|
||||
List<ModelProblem> problems = new ArrayList<>(r.getProblems());
|
||||
results(r)
|
||||
.filter(c -> c != r)
|
||||
.flatMap(c -> c.getProblems().stream())
|
||||
.forEach(problems::remove);
|
||||
if (r.getEffectiveModel() != null) {
|
||||
File pom = r.getSource().getPath().toFile();
|
||||
MavenProject project =
|
||||
|
@ -510,7 +516,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
|
|||
project.setExecutionRoot(pom.equals(pomFile));
|
||||
initProject(project, r);
|
||||
project.setCollectedProjects(results(r)
|
||||
.filter(cr -> cr != r)
|
||||
.filter(cr -> cr != r && cr.getEffectiveModel() != null)
|
||||
.map(cr -> projectIndex.get(cr.getEffectiveModel().getId()))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
|
@ -518,10 +524,9 @@ public class DefaultProjectBuilder implements ProjectBuilder {
|
|||
if (request.isResolveDependencies()) {
|
||||
resolutionResult = resolveDependencies(project);
|
||||
}
|
||||
results.add(
|
||||
new DefaultProjectBuildingResult(project, convert(result.getProblems()), resolutionResult));
|
||||
results.add(new DefaultProjectBuildingResult(project, convert(problems), resolutionResult));
|
||||
} else {
|
||||
results.add(new DefaultProjectBuildingResult(null, convert(result.getProblems()), null));
|
||||
results.add(new DefaultProjectBuildingResult(null, convert(problems), null));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
|
@ -535,20 +540,21 @@ public class DefaultProjectBuilder implements ProjectBuilder {
|
|||
if (problems == null) {
|
||||
return null;
|
||||
}
|
||||
return problems.stream()
|
||||
.map(p -> (org.apache.maven.model.building.ModelProblem)
|
||||
new org.apache.maven.model.building.DefaultModelProblem(
|
||||
p.getMessage(),
|
||||
org.apache.maven.model.building.ModelProblem.Severity.valueOf(
|
||||
p.getSeverity().name()),
|
||||
org.apache.maven.model.building.ModelProblem.Version.valueOf(
|
||||
p.getVersion().name()),
|
||||
p.getSource(),
|
||||
p.getLineNumber(),
|
||||
p.getColumnNumber(),
|
||||
p.getModelId(),
|
||||
p.getException()))
|
||||
.toList();
|
||||
return problems.stream().map(p -> convert(p)).toList();
|
||||
}
|
||||
|
||||
private static org.apache.maven.model.building.ModelProblem convert(ModelProblem p) {
|
||||
return new DefaultModelProblem(
|
||||
p.getMessage(),
|
||||
org.apache.maven.model.building.ModelProblem.Severity.valueOf(
|
||||
p.getSeverity().name()),
|
||||
org.apache.maven.model.building.ModelProblem.Version.valueOf(
|
||||
p.getVersion().name()),
|
||||
p.getSource(),
|
||||
p.getLineNumber(),
|
||||
p.getColumnNumber(),
|
||||
p.getModelId(),
|
||||
p.getException());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"checkstyle:methodlength", "deprecation"})
|
||||
|
|
|
@ -20,9 +20,6 @@ package org.apache.maven.internal.transformation.impl;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
|
@ -35,17 +32,17 @@ import org.apache.maven.api.SessionData;
|
|||
import org.apache.maven.api.model.Model;
|
||||
import org.apache.maven.api.model.Parent;
|
||||
import org.apache.maven.api.services.ModelBuilder;
|
||||
import org.apache.maven.api.services.ModelBuilderRequest;
|
||||
import org.apache.maven.api.services.ModelSource;
|
||||
import org.apache.maven.api.services.model.ModelResolver;
|
||||
import org.apache.maven.api.services.model.ModelResolverException;
|
||||
import org.apache.maven.api.spi.ModelTransformer;
|
||||
import org.apache.maven.api.spi.ModelTransformerException;
|
||||
import org.apache.maven.di.Injector;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.internal.impl.InternalMavenSession;
|
||||
import org.apache.maven.internal.impl.InternalSession;
|
||||
import org.apache.maven.internal.impl.model.DefaultModelBuilder;
|
||||
import org.apache.maven.internal.transformation.AbstractRepositoryTestCase;
|
||||
import org.apache.maven.model.v4.MavenStaxReader;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -58,6 +55,9 @@ public class ConsumerPomBuilderTest extends AbstractRepositoryTestCase {
|
|||
@Inject
|
||||
ConsumerPomBuilder builder;
|
||||
|
||||
@Inject
|
||||
ModelBuilder modelBuilder;
|
||||
|
||||
@BeforeEach
|
||||
void setupTransformerContext() throws Exception {
|
||||
// We need to hack things a bit here to get the transformer context to work
|
||||
|
@ -71,33 +71,30 @@ public class ConsumerPomBuilderTest extends AbstractRepositoryTestCase {
|
|||
// to maven central
|
||||
getContainer().lookup(Injector.class).bindImplicit(MyModelResolver.class);
|
||||
InternalSession iSession = InternalSession.from(session);
|
||||
// set up the transformers
|
||||
List<ModelTransformer> transformers = List.of(new CIFriendlyVersionModelTransformer(iSession));
|
||||
Field transformersField = DefaultModelBuilder.class.getDeclaredField("transformers");
|
||||
transformersField.setAccessible(true);
|
||||
DefaultModelBuilder modelBuilder = (DefaultModelBuilder) getContainer().lookup(ModelBuilder.class);
|
||||
transformersField.set(modelBuilder, transformers);
|
||||
transformersField = DefaultConsumerPomBuilder.class.getDeclaredField("transformers");
|
||||
transformersField.setAccessible(true);
|
||||
transformersField.set(builder, transformers);
|
||||
// set up the model resolver
|
||||
iSession.getData().set(SessionData.key(ModelResolver.class), new MyModelResolver());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTrivialConsumer() throws Exception {
|
||||
MavenProject project;
|
||||
Path file = Paths.get("src/test/resources/consumer/trivial/child/pom.xml");
|
||||
try (InputStream inputStream = Files.newInputStream(file)) {
|
||||
org.apache.maven.model.Model model =
|
||||
new org.apache.maven.model.Model(new MavenStaxReader().read(inputStream));
|
||||
project = new MavenProject(model);
|
||||
project.setOriginalModel(model);
|
||||
}
|
||||
InternalMavenSession.from(InternalSession.from(session))
|
||||
.getMavenSession()
|
||||
.getRequest()
|
||||
.setRootDirectory(Paths.get("src/test/resources/consumer/trivial"));
|
||||
|
||||
Path file = Paths.get("src/test/resources/consumer/trivial/child/pom.xml");
|
||||
|
||||
ModelBuilder.ModelBuilderSession mbs = modelBuilder.newSession();
|
||||
InternalSession.from(session).getData().set(SessionData.key(ModelBuilder.ModelBuilderSession.class), mbs);
|
||||
Model orgModel = mbs.build(ModelBuilderRequest.builder()
|
||||
.session(InternalSession.from(session))
|
||||
.source(ModelSource.fromPath(file))
|
||||
.requestType(ModelBuilderRequest.RequestType.BUILD_POM)
|
||||
.build())
|
||||
.getEffectiveModel();
|
||||
|
||||
MavenProject project = new MavenProject(orgModel);
|
||||
project.setOriginalModel(new org.apache.maven.model.Model(orgModel));
|
||||
Model model = builder.build(session, project, file);
|
||||
|
||||
assertNotNull(model);
|
||||
|
@ -105,24 +102,26 @@ public class ConsumerPomBuilderTest extends AbstractRepositoryTestCase {
|
|||
|
||||
@Test
|
||||
void testSimpleConsumer() throws Exception {
|
||||
MavenProject project;
|
||||
MavenExecutionRequest request = InternalMavenSession.from(InternalSession.from(session))
|
||||
.getMavenSession()
|
||||
.getRequest();
|
||||
request.setRootDirectory(Paths.get("src/test/resources/consumer/simple"));
|
||||
request.getUserProperties().setProperty("changelist", "MNG6957");
|
||||
|
||||
Path file = Paths.get("src/test/resources/consumer/simple/simple-parent/simple-weather/pom.xml");
|
||||
|
||||
InternalMavenSession.from(InternalSession.from(session))
|
||||
.getMavenSession()
|
||||
.getRequest()
|
||||
.getUserProperties()
|
||||
.setProperty("changelist", "MNG6957");
|
||||
try (InputStream inputStream = Files.newInputStream(file)) {
|
||||
org.apache.maven.model.Model model =
|
||||
new org.apache.maven.model.Model(new MavenStaxReader().read(inputStream));
|
||||
project = new MavenProject(model);
|
||||
project.setOriginalModel(model);
|
||||
}
|
||||
InternalMavenSession.from(InternalSession.from(session))
|
||||
.getMavenSession()
|
||||
.getRequest()
|
||||
.setRootDirectory(Paths.get("src/test/resources/consumer/simple"));
|
||||
ModelBuilder.ModelBuilderSession mbs = modelBuilder.newSession();
|
||||
InternalSession.from(session).getData().set(SessionData.key(ModelBuilder.ModelBuilderSession.class), mbs);
|
||||
Model orgModel = mbs.build(ModelBuilderRequest.builder()
|
||||
.session(InternalSession.from(session))
|
||||
.source(ModelSource.fromPath(file))
|
||||
.requestType(ModelBuilderRequest.RequestType.BUILD_POM)
|
||||
.build())
|
||||
.getEffectiveModel();
|
||||
|
||||
MavenProject project = new MavenProject(orgModel);
|
||||
project.setOriginalModel(new org.apache.maven.model.Model(orgModel));
|
||||
request.setRootDirectory(Paths.get("src/test/resources/consumer/simple"));
|
||||
Model model = builder.build(session, project, file);
|
||||
|
||||
assertNotNull(model);
|
||||
|
|
|
@ -1616,8 +1616,10 @@ public class DefaultModelBuilder implements ModelBuilder {
|
|||
}
|
||||
|
||||
String parentPath = childModel.getParent().getRelativePath();
|
||||
|
||||
if (parentPath == null || parentPath.isEmpty()) {
|
||||
if (parentPath == null) {
|
||||
parentPath = "..";
|
||||
childModel.getParent().setRelativePath(parentPath);
|
||||
} else if (parentPath.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue