mirror of https://github.com/apache/maven.git
[MNG-8391] Wrong effective model when conflicting values come from parents and profiles
This commit is contained in:
parent
175e219a56
commit
a58551d9ab
|
@ -18,11 +18,11 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.maven.api.services.model;
|
package org.apache.maven.api.services.model;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.maven.api.annotations.Nonnull;
|
import org.apache.maven.api.annotations.Nonnull;
|
||||||
|
import org.apache.maven.api.annotations.Nullable;
|
||||||
import org.apache.maven.api.model.Model;
|
import org.apache.maven.api.model.Model;
|
||||||
|
import org.apache.maven.api.services.InterpolatorException;
|
||||||
|
import org.apache.maven.api.services.ModelBuilderException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the environmental context used to determine the activation status of profiles.
|
* Describes the environmental context used to determine the activation status of profiles.
|
||||||
|
@ -34,45 +34,100 @@ import org.apache.maven.api.model.Model;
|
||||||
public interface ProfileActivationContext {
|
public interface ProfileActivationContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the identifiers of those profiles that should be activated by explicit demand.
|
* Checks if the specified profile has been explicitly activated.
|
||||||
*
|
*
|
||||||
* @return The identifiers of those profiles to activate, never {@code null}.
|
* @param profileId the profile id
|
||||||
|
* @return whether the profile has been activated
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
boolean isProfileActive(@Nonnull String profileId);
|
||||||
List<String> getActiveProfileIds();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the identifiers of those profiles that should be deactivated by explicit demand.
|
* Checks if the specified profile has been explicitly deactivated.
|
||||||
*
|
*
|
||||||
* @return The identifiers of those profiles to deactivate, never {@code null}.
|
* @param profileId the profile id
|
||||||
|
* @return whether the profile has been deactivated
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
boolean isProfileInactive(@Nonnull String profileId);
|
||||||
List<String> getInactiveProfileIds();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the system properties to use for interpolation and profile activation. The system properties are collected
|
* Gets the system property to use for interpolation and profile activation. The system properties are collected
|
||||||
* from the runtime environment like {@link System#getProperties()} and environment variables.
|
* from the runtime environment like {@link System#getProperties()} and environment variables.
|
||||||
*
|
*
|
||||||
* @return The execution properties, never {@code null}.
|
* @param key the name of the system property
|
||||||
|
* @return the system property for the specified key, or {@code null}
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nullable
|
||||||
Map<String, String> getSystemProperties();
|
String getSystemProperty(@Nonnull String key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the user properties to use for interpolation and profile activation. The user properties have been
|
* Gets the user property to use for interpolation and profile activation. The user properties have been
|
||||||
* configured directly by the user on his discretion, e.g. via the {@code -Dkey=value} parameter on the command
|
* configured directly by the user on his discretion, e.g. via the {@code -Dkey=value} parameter on the command line.
|
||||||
* line.
|
|
||||||
*
|
*
|
||||||
* @return The user properties, never {@code null}.
|
* @param key the name of the user property
|
||||||
|
* @return The user property for the specified key, or {@code null}.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nullable
|
||||||
Map<String, String> getUserProperties();
|
String getUserProperty(@Nonnull String key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the model which is being activated.
|
* Gets the model property to use for interpolation and profile activation.
|
||||||
*
|
*
|
||||||
* @return The project model, never {@code null}.
|
* @param key the name of the model property
|
||||||
|
* @return The model property for the specified key, or {@code null};
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nullable
|
||||||
Model getModel();
|
String getModelProperty(@Nonnull String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the artifactId from the current model.
|
||||||
|
*
|
||||||
|
* @return The artifactId of the current model, or {@code null} if not set.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
String getModelArtifactId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the packaging type from the current model.
|
||||||
|
*
|
||||||
|
* @return The packaging type of the current model, or {@code null} if not set.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
String getModelPackaging();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the root directory of the current model.
|
||||||
|
*
|
||||||
|
* @return The root directory path of the current model, or {@code null} if not set.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
String getModelRootDirectory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the base directory of the current model.
|
||||||
|
*
|
||||||
|
* @return The base directory path of the current model, or {@code null} if not set.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
String getModelBaseDirectory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interpolates the given path string using the current context's properties.
|
||||||
|
*
|
||||||
|
* @param path The path string to interpolate
|
||||||
|
* @return The interpolated path string
|
||||||
|
* @throws InterpolatorException if an error occurs during interpolation
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
String interpolatePath(@Nullable String path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a file or directory matching the given glob pattern exists at the specified path.
|
||||||
|
*
|
||||||
|
* @param path the base path to check
|
||||||
|
* @param glob whether the path can be a glob expression
|
||||||
|
* @return {@code true} if a matching file exists, {@code false} otherwise
|
||||||
|
* @throws ModelBuilderException if an error occurs while checking the path
|
||||||
|
* @throws InterpolatorException if an error occurs during interpolation
|
||||||
|
*/
|
||||||
|
boolean exists(@Nullable String path, boolean glob);
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,7 @@ import org.apache.maven.api.services.model.ModelResolverException;
|
||||||
import org.apache.maven.api.services.model.ModelUrlNormalizer;
|
import org.apache.maven.api.services.model.ModelUrlNormalizer;
|
||||||
import org.apache.maven.api.services.model.ModelValidator;
|
import org.apache.maven.api.services.model.ModelValidator;
|
||||||
import org.apache.maven.api.services.model.ModelVersionParser;
|
import org.apache.maven.api.services.model.ModelVersionParser;
|
||||||
|
import org.apache.maven.api.services.model.PathTranslator;
|
||||||
import org.apache.maven.api.services.model.PluginConfigurationExpander;
|
import org.apache.maven.api.services.model.PluginConfigurationExpander;
|
||||||
import org.apache.maven.api.services.model.PluginManagementInjector;
|
import org.apache.maven.api.services.model.PluginManagementInjector;
|
||||||
import org.apache.maven.api.services.model.ProfileInjector;
|
import org.apache.maven.api.services.model.ProfileInjector;
|
||||||
|
@ -145,12 +146,13 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
private final DependencyManagementInjector dependencyManagementInjector;
|
private final DependencyManagementInjector dependencyManagementInjector;
|
||||||
private final DependencyManagementImporter dependencyManagementImporter;
|
private final DependencyManagementImporter dependencyManagementImporter;
|
||||||
private final PluginConfigurationExpander pluginConfigurationExpander;
|
private final PluginConfigurationExpander pluginConfigurationExpander;
|
||||||
private final ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
|
|
||||||
private final ModelVersionParser versionParser;
|
private final ModelVersionParser versionParser;
|
||||||
private final List<ModelTransformer> transformers;
|
private final List<ModelTransformer> transformers;
|
||||||
private final ModelCacheFactory modelCacheFactory;
|
private final ModelCacheFactory modelCacheFactory;
|
||||||
private final ModelResolver modelResolver;
|
private final ModelResolver modelResolver;
|
||||||
private final Interpolator interpolator;
|
private final Interpolator interpolator;
|
||||||
|
private final PathTranslator pathTranslator;
|
||||||
|
private final RootLocator rootLocator;
|
||||||
|
|
||||||
@SuppressWarnings("checkstyle:ParameterNumber")
|
@SuppressWarnings("checkstyle:ParameterNumber")
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -169,12 +171,13 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
DependencyManagementInjector dependencyManagementInjector,
|
DependencyManagementInjector dependencyManagementInjector,
|
||||||
DependencyManagementImporter dependencyManagementImporter,
|
DependencyManagementImporter dependencyManagementImporter,
|
||||||
PluginConfigurationExpander pluginConfigurationExpander,
|
PluginConfigurationExpander pluginConfigurationExpander,
|
||||||
ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator,
|
|
||||||
ModelVersionParser versionParser,
|
ModelVersionParser versionParser,
|
||||||
List<ModelTransformer> transformers,
|
List<ModelTransformer> transformers,
|
||||||
ModelCacheFactory modelCacheFactory,
|
ModelCacheFactory modelCacheFactory,
|
||||||
ModelResolver modelResolver,
|
ModelResolver modelResolver,
|
||||||
Interpolator interpolator) {
|
Interpolator interpolator,
|
||||||
|
PathTranslator pathTranslator,
|
||||||
|
RootLocator rootLocator) {
|
||||||
this.modelProcessor = modelProcessor;
|
this.modelProcessor = modelProcessor;
|
||||||
this.modelValidator = modelValidator;
|
this.modelValidator = modelValidator;
|
||||||
this.modelNormalizer = modelNormalizer;
|
this.modelNormalizer = modelNormalizer;
|
||||||
|
@ -189,12 +192,13 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
this.dependencyManagementInjector = dependencyManagementInjector;
|
this.dependencyManagementInjector = dependencyManagementInjector;
|
||||||
this.dependencyManagementImporter = dependencyManagementImporter;
|
this.dependencyManagementImporter = dependencyManagementImporter;
|
||||||
this.pluginConfigurationExpander = pluginConfigurationExpander;
|
this.pluginConfigurationExpander = pluginConfigurationExpander;
|
||||||
this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator;
|
|
||||||
this.versionParser = versionParser;
|
this.versionParser = versionParser;
|
||||||
this.transformers = transformers;
|
this.transformers = transformers;
|
||||||
this.modelCacheFactory = modelCacheFactory;
|
this.modelCacheFactory = modelCacheFactory;
|
||||||
this.modelResolver = modelResolver;
|
this.modelResolver = modelResolver;
|
||||||
this.interpolator = interpolator;
|
this.interpolator = interpolator;
|
||||||
|
this.pathTranslator = pathTranslator;
|
||||||
|
this.rootLocator = rootLocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelBuilderSession newSession() {
|
public ModelBuilderSession newSession() {
|
||||||
|
@ -862,12 +866,12 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Model readParent(Model childModel) throws ModelBuilderException {
|
Model readParent(Model childModel, DefaultProfileActivationContext profileActivationContext) {
|
||||||
Model parentModel;
|
Model parentModel;
|
||||||
|
|
||||||
Parent parent = childModel.getParent();
|
Parent parent = childModel.getParent();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parentModel = resolveParent(childModel);
|
parentModel = resolveParent(childModel, profileActivationContext);
|
||||||
|
|
||||||
if (!"pom".equals(parentModel.getPackaging())) {
|
if (!"pom".equals(parentModel.getPackaging())) {
|
||||||
add(
|
add(
|
||||||
|
@ -892,18 +896,20 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
return parentModel;
|
return parentModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Model resolveParent(Model childModel) throws ModelBuilderException {
|
private Model resolveParent(Model childModel, DefaultProfileActivationContext profileActivationContext)
|
||||||
|
throws ModelBuilderException {
|
||||||
Model parentModel = null;
|
Model parentModel = null;
|
||||||
if (isBuildRequest()) {
|
if (isBuildRequest()) {
|
||||||
parentModel = readParentLocally(childModel);
|
parentModel = readParentLocally(childModel, profileActivationContext);
|
||||||
}
|
}
|
||||||
if (parentModel == null) {
|
if (parentModel == null) {
|
||||||
parentModel = resolveAndReadParentExternally(childModel);
|
parentModel = resolveAndReadParentExternally(childModel, profileActivationContext);
|
||||||
}
|
}
|
||||||
return parentModel;
|
return parentModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Model readParentLocally(Model childModel) throws ModelBuilderException {
|
private Model readParentLocally(Model childModel, DefaultProfileActivationContext profileActivationContext)
|
||||||
|
throws ModelBuilderException {
|
||||||
ModelSource candidateSource;
|
ModelSource candidateSource;
|
||||||
|
|
||||||
Parent parent = childModel.getParent();
|
Parent parent = childModel.getParent();
|
||||||
|
@ -938,7 +944,9 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Model candidateModel = derive(candidateSource).readAsParentModel();
|
ModelBuilderSessionState derived = derive(candidateSource);
|
||||||
|
Model candidateModel = derived.readAsParentModel(profileActivationContext);
|
||||||
|
addActivePomProfiles(derived.result.getActivePomProfiles());
|
||||||
|
|
||||||
String groupId = getGroupId(candidateModel);
|
String groupId = getGroupId(candidateModel);
|
||||||
String artifactId = candidateModel.getArtifactId();
|
String artifactId = candidateModel.getArtifactId();
|
||||||
|
@ -1020,7 +1028,8 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
add(Severity.FATAL, Version.BASE, buffer.toString(), parent.getLocation(""));
|
add(Severity.FATAL, Version.BASE, buffer.toString(), parent.getLocation(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
Model resolveAndReadParentExternally(Model childModel) throws ModelBuilderException {
|
Model resolveAndReadParentExternally(Model childModel, DefaultProfileActivationContext profileActivationContext)
|
||||||
|
throws ModelBuilderException {
|
||||||
ModelBuilderRequest request = this.request;
|
ModelBuilderRequest request = this.request;
|
||||||
setSource(childModel);
|
setSource(childModel);
|
||||||
|
|
||||||
|
@ -1078,7 +1087,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
.source(modelSource)
|
.source(modelSource)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Model parentModel = derive(lenientRequest).readAsParentModel();
|
Model parentModel = derive(lenientRequest).readAsParentModel(profileActivationContext);
|
||||||
|
|
||||||
if (!parent.getVersion().equals(version)) {
|
if (!parent.getVersion().equals(version)) {
|
||||||
String rawChildModelVersion = childModel.getVersion();
|
String rawChildModelVersion = childModel.getVersion();
|
||||||
|
@ -1119,7 +1128,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
for (Profile profile : activeExternalProfiles) {
|
for (Profile profile : activeExternalProfiles) {
|
||||||
profileProps.putAll(profile.getProperties());
|
profileProps.putAll(profile.getProperties());
|
||||||
}
|
}
|
||||||
profileProps.putAll(profileActivationContext.getUserProperties());
|
profileProps.putAll(request.getUserProperties());
|
||||||
profileActivationContext.setUserProperties(profileProps);
|
profileActivationContext.setUserProperties(profileProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1163,11 +1172,12 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
for (Profile profile : activeExternalProfiles) {
|
for (Profile profile : activeExternalProfiles) {
|
||||||
profileProps.putAll(profile.getProperties());
|
profileProps.putAll(profile.getProperties());
|
||||||
}
|
}
|
||||||
profileProps.putAll(profileActivationContext.getUserProperties());
|
profileProps.putAll(request.getUserProperties());
|
||||||
profileActivationContext.setUserProperties(profileProps);
|
profileActivationContext.setUserProperties(profileProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
Model parentModel = readParent(activatedFileModel);
|
Model parentModel = readParent(activatedFileModel, profileActivationContext);
|
||||||
|
|
||||||
// Now that we have read the parent, we can set the relative
|
// Now that we have read the parent, we can set the relative
|
||||||
// path correctly if it was not set in the input model
|
// path correctly if it was not set in the input model
|
||||||
if (inputModel.getParent() != null && inputModel.getParent().getRelativePath() == null) {
|
if (inputModel.getParent() != null && inputModel.getParent().getRelativePath() == null) {
|
||||||
|
@ -1186,16 +1196,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
inputModel = inputModel.withParent(inputModel.getParent().withRelativePath(relPath));
|
inputModel = inputModel.withParent(inputModel.getParent().withRelativePath(relPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Profile> parentInterpolatedProfiles =
|
Model model = inheritanceAssembler.assembleModelInheritance(inputModel, parentModel, request, this);
|
||||||
interpolateActivations(parentModel.getProfiles(), profileActivationContext, this);
|
|
||||||
// profile injection
|
|
||||||
List<Profile> parentActivePomProfiles =
|
|
||||||
getActiveProfiles(parentInterpolatedProfiles, profileActivationContext);
|
|
||||||
Model injectedParentModel = profileInjector
|
|
||||||
.injectProfiles(parentModel, parentActivePomProfiles, request, this)
|
|
||||||
.withProfiles(List.of());
|
|
||||||
|
|
||||||
Model model = inheritanceAssembler.assembleModelInheritance(inputModel, injectedParentModel, request, this);
|
|
||||||
|
|
||||||
// model normalization
|
// model normalization
|
||||||
model = modelNormalizer.mergeDuplicates(model, request, this);
|
model = modelNormalizer.mergeDuplicates(model, request, this);
|
||||||
|
@ -1211,10 +1212,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
model = profileInjector.injectProfiles(model, activePomProfiles, request, this);
|
model = profileInjector.injectProfiles(model, activePomProfiles, request, this);
|
||||||
model = profileInjector.injectProfiles(model, activeExternalProfiles, request, this);
|
model = profileInjector.injectProfiles(model, activeExternalProfiles, request, this);
|
||||||
|
|
||||||
List<Profile> allProfiles = new ArrayList<>(parentActivePomProfiles.size() + activePomProfiles.size());
|
addActivePomProfiles(activePomProfiles);
|
||||||
allProfiles.addAll(parentActivePomProfiles);
|
|
||||||
allProfiles.addAll(activePomProfiles);
|
|
||||||
result.setActivePomProfiles(allProfiles);
|
|
||||||
|
|
||||||
// model interpolation
|
// model interpolation
|
||||||
Model resultModel = model;
|
Model resultModel = model;
|
||||||
|
@ -1239,6 +1237,15 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
return resultModel;
|
return resultModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addActivePomProfiles(List<Profile> activePomProfiles) {
|
||||||
|
if (activePomProfiles != null) {
|
||||||
|
if (result.getActivePomProfiles() == null) {
|
||||||
|
result.setActivePomProfiles(new ArrayList<>());
|
||||||
|
}
|
||||||
|
result.getActivePomProfiles().addAll(activePomProfiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<Profile> getActiveProfiles(
|
private List<Profile> getActiveProfiles(
|
||||||
Collection<Profile> interpolatedProfiles, DefaultProfileActivationContext profileActivationContext) {
|
Collection<Profile> interpolatedProfiles, DefaultProfileActivationContext profileActivationContext) {
|
||||||
if (isBuildRequestWithActivation()) {
|
if (isBuildRequestWithActivation()) {
|
||||||
|
@ -1491,13 +1498,25 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
/**
|
/**
|
||||||
* Reads the request source's parent.
|
* Reads the request source's parent.
|
||||||
*/
|
*/
|
||||||
Model readAsParentModel() throws ModelBuilderException {
|
Model readAsParentModel(DefaultProfileActivationContext profileActivationContext) throws ModelBuilderException {
|
||||||
return cache(request.getSource(), PARENT, this::doReadAsParentModel);
|
Map<DefaultProfileActivationContext.Record, Model> parentsPerContext =
|
||||||
|
cache(request.getSource(), PARENT, ConcurrentHashMap::new);
|
||||||
|
for (Map.Entry<DefaultProfileActivationContext.Record, Model> e : parentsPerContext.entrySet()) {
|
||||||
|
if (e.getKey().matches(profileActivationContext)) {
|
||||||
|
return e.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DefaultProfileActivationContext.Record prev = profileActivationContext.start();
|
||||||
|
Model model = doReadAsParentModel(profileActivationContext);
|
||||||
|
DefaultProfileActivationContext.Record record = profileActivationContext.stop(prev);
|
||||||
|
parentsPerContext.put(record, model);
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Model doReadAsParentModel() throws ModelBuilderException {
|
private Model doReadAsParentModel(DefaultProfileActivationContext profileActivationContext)
|
||||||
|
throws ModelBuilderException {
|
||||||
Model raw = readRawModel();
|
Model raw = readRawModel();
|
||||||
Model parentData = readParent(raw);
|
Model parentData = readParent(raw, profileActivationContext);
|
||||||
Model parent = new DefaultInheritanceAssembler(new DefaultInheritanceAssembler.InheritanceModelMerger() {
|
Model parent = new DefaultInheritanceAssembler(new DefaultInheritanceAssembler.InheritanceModelMerger() {
|
||||||
@Override
|
@Override
|
||||||
protected void mergeModel_Modules(
|
protected void mergeModel_Modules(
|
||||||
|
@ -1514,23 +1533,21 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
Model source,
|
Model source,
|
||||||
boolean sourceDominant,
|
boolean sourceDominant,
|
||||||
Map<Object, Object> context) {}
|
Map<Object, Object> context) {}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
protected void mergeModel_Profiles(
|
|
||||||
Model.Builder builder,
|
|
||||||
Model target,
|
|
||||||
Model source,
|
|
||||||
boolean sourceDominant,
|
|
||||||
Map<Object, Object> context) {
|
|
||||||
builder.profiles(Stream.concat(source.getProfiles().stream(), target.getProfiles().stream())
|
|
||||||
.map(p -> p.withModules(null).withSubprojects(null))
|
|
||||||
.toList());
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.assembleModelInheritance(raw, parentData, request, this);
|
.assembleModelInheritance(raw, parentData, request, this);
|
||||||
|
|
||||||
return parent.withParent(null);
|
// activate profiles
|
||||||
|
List<Profile> parentInterpolatedProfiles =
|
||||||
|
interpolateActivations(parent.getProfiles(), profileActivationContext, this);
|
||||||
|
// profile injection
|
||||||
|
List<Profile> parentActivePomProfiles =
|
||||||
|
getActiveProfiles(parentInterpolatedProfiles, profileActivationContext);
|
||||||
|
Model injectedParentModel = profileInjector
|
||||||
|
.injectProfiles(parent, parentActivePomProfiles, request, this)
|
||||||
|
.withProfiles(List.of());
|
||||||
|
addActivePomProfiles(parentActivePomProfiles);
|
||||||
|
|
||||||
|
return injectedParentModel.withParent(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Model importDependencyManagement(Model model, Collection<String> importIds) {
|
private Model importDependencyManagement(Model model, Collection<String> importIds) {
|
||||||
|
@ -1763,9 +1780,8 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
ProfileInterpolator() {
|
ProfileInterpolator() {
|
||||||
super(s -> {
|
super(s -> {
|
||||||
try {
|
try {
|
||||||
Map<String, String> map1 = context.getUserProperties();
|
return interpolator.interpolate(
|
||||||
Map<String, String> map2 = context.getSystemProperties();
|
s, Interpolator.chain(context::getUserProperty, context::getSystemProperty));
|
||||||
return interpolator.interpolate(s, Interpolator.chain(map1::get, map2::get));
|
|
||||||
} catch (InterpolatorException e) {
|
} catch (InterpolatorException e) {
|
||||||
problems.add(Severity.ERROR, Version.BASE, e.getMessage(), e);
|
problems.add(Severity.ERROR, Version.BASE, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
@ -1809,7 +1825,7 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
|
|
||||||
private String transformPath(String path, ActivationFile target, String locationKey) {
|
private String transformPath(String path, ActivationFile target, String locationKey) {
|
||||||
try {
|
try {
|
||||||
return profileActivationFilePathInterpolator.interpolate(path, context);
|
return context.interpolatePath(path);
|
||||||
} catch (InterpolatorException e) {
|
} catch (InterpolatorException e) {
|
||||||
problems.add(
|
problems.add(
|
||||||
Severity.ERROR,
|
Severity.ERROR,
|
||||||
|
@ -1860,7 +1876,8 @@ public class DefaultModelBuilder implements ModelBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefaultProfileActivationContext getProfileActivationContext(ModelBuilderRequest request, Model model) {
|
private DefaultProfileActivationContext getProfileActivationContext(ModelBuilderRequest request, Model model) {
|
||||||
DefaultProfileActivationContext context = new DefaultProfileActivationContext();
|
DefaultProfileActivationContext context =
|
||||||
|
new DefaultProfileActivationContext(pathTranslator, rootLocator, interpolator);
|
||||||
|
|
||||||
context.setActiveProfileIds(request.getActiveProfileIds());
|
context.setActiveProfileIds(request.getActiveProfileIds());
|
||||||
context.setInactiveProfileIds(request.getInactiveProfileIds());
|
context.setInactiveProfileIds(request.getInactiveProfileIds());
|
||||||
|
|
|
@ -18,32 +18,168 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.maven.internal.impl.model;
|
package org.apache.maven.internal.impl.model;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.FileVisitResult;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.PathMatcher;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.SimpleFileVisitor;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import org.apache.maven.api.model.Model;
|
import org.apache.maven.api.model.Model;
|
||||||
|
import org.apache.maven.api.services.Interpolator;
|
||||||
|
import org.apache.maven.api.services.InterpolatorException;
|
||||||
|
import org.apache.maven.api.services.ModelBuilderException;
|
||||||
|
import org.apache.maven.api.services.ProjectBuilderException;
|
||||||
|
import org.apache.maven.api.services.model.PathTranslator;
|
||||||
import org.apache.maven.api.services.model.ProfileActivationContext;
|
import org.apache.maven.api.services.model.ProfileActivationContext;
|
||||||
|
import org.apache.maven.api.services.model.RootLocator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the environmental context used to determine the activation status of profiles.
|
* Describes the environmental context used to determine the activation status of profiles.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class DefaultProfileActivationContext implements ProfileActivationContext {
|
public class DefaultProfileActivationContext implements ProfileActivationContext {
|
||||||
|
|
||||||
|
record ExistRequest(String path, boolean enableGlob) {}
|
||||||
|
|
||||||
|
enum ModelInfo {
|
||||||
|
ArtifactId,
|
||||||
|
Packaging,
|
||||||
|
BaseDirectory,
|
||||||
|
RootDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class keeps track of information that are used during profile activation.
|
||||||
|
* This allows to cache the activated parent and check if the result of the
|
||||||
|
* activation will be the same by verifying that the used keys are the same.
|
||||||
|
*/
|
||||||
|
static class Record {
|
||||||
|
private final Map<String, Boolean> usedActiveProfiles = new HashMap<>();
|
||||||
|
private final Map<String, Boolean> usedInactiveProfiles = new HashMap<>();
|
||||||
|
private final Map<String, String> usedSystemProperties = new HashMap<>();
|
||||||
|
private final Map<String, String> usedUserProperties = new HashMap<>();
|
||||||
|
private final Map<String, String> usedModelProperties = new HashMap<>();
|
||||||
|
private final Map<ModelInfo, String> usedModelInfos = new HashMap<>();
|
||||||
|
private final Map<ExistRequest, Boolean> usedExists = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof Record record) {
|
||||||
|
return Objects.equals(usedActiveProfiles, record.usedActiveProfiles)
|
||||||
|
&& Objects.equals(usedInactiveProfiles, record.usedInactiveProfiles)
|
||||||
|
&& Objects.equals(usedSystemProperties, record.usedSystemProperties)
|
||||||
|
&& Objects.equals(usedUserProperties, record.usedUserProperties)
|
||||||
|
&& Objects.equals(usedModelProperties, record.usedModelProperties)
|
||||||
|
&& Objects.equals(usedModelInfos, record.usedModelInfos)
|
||||||
|
&& Objects.equals(usedExists, record.usedExists);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(
|
||||||
|
usedActiveProfiles,
|
||||||
|
usedInactiveProfiles,
|
||||||
|
usedSystemProperties,
|
||||||
|
usedUserProperties,
|
||||||
|
usedModelProperties,
|
||||||
|
usedModelInfos,
|
||||||
|
usedExists);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean matches(DefaultProfileActivationContext context) {
|
||||||
|
return matchesProfiles(usedActiveProfiles, context.activeProfileIds)
|
||||||
|
&& matchesProfiles(usedInactiveProfiles, context.inactiveProfileIds)
|
||||||
|
&& matchesProperties(usedSystemProperties, context.systemProperties)
|
||||||
|
&& matchesProperties(usedUserProperties, context.userProperties)
|
||||||
|
&& matchesProperties(usedModelProperties, context.model.getProperties())
|
||||||
|
&& matchesModelInfos(usedModelInfos, context)
|
||||||
|
&& matchesExists(usedExists, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesProfiles(Map<String, Boolean> expected, List<String> actual) {
|
||||||
|
return expected.entrySet().stream()
|
||||||
|
.allMatch(e -> Objects.equals(e.getValue(), actual.contains(e.getKey())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesProperties(Map<String, String> expected, Map<String, String> actual) {
|
||||||
|
return expected.entrySet().stream().allMatch(e -> Objects.equals(e.getValue(), actual.get(e.getKey())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesModelInfos(Map<ModelInfo, String> infos, DefaultProfileActivationContext context) {
|
||||||
|
return infos.entrySet().stream()
|
||||||
|
.allMatch(e -> Objects.equals(e.getValue(), getModelValue(e.getKey(), context)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getModelValue(ModelInfo key, DefaultProfileActivationContext context) {
|
||||||
|
return switch (key) {
|
||||||
|
case ArtifactId -> context.model.getArtifactId();
|
||||||
|
case Packaging -> context.model.getPackaging();
|
||||||
|
case BaseDirectory -> context.doGetModelBaseDirectory();
|
||||||
|
case RootDirectory -> context.doGetModelRootDirectory();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesExists(Map<ExistRequest, Boolean> exists, DefaultProfileActivationContext context) {
|
||||||
|
return exists.entrySet().stream()
|
||||||
|
.allMatch(e -> Objects.equals(
|
||||||
|
e.getValue(),
|
||||||
|
context.doExists(e.getKey().path(), e.getKey().enableGlob())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final PathTranslator pathTranslator;
|
||||||
|
private final RootLocator rootLocator;
|
||||||
|
private final Interpolator interpolator;
|
||||||
|
|
||||||
private List<String> activeProfileIds = Collections.emptyList();
|
private List<String> activeProfileIds = Collections.emptyList();
|
||||||
|
|
||||||
private List<String> inactiveProfileIds = Collections.emptyList();
|
private List<String> inactiveProfileIds = Collections.emptyList();
|
||||||
|
|
||||||
private Map<String, String> systemProperties = Collections.emptyMap();
|
private Map<String, String> systemProperties = Collections.emptyMap();
|
||||||
|
|
||||||
private Map<String, String> userProperties = Collections.emptyMap();
|
private Map<String, String> userProperties = Collections.emptyMap();
|
||||||
|
|
||||||
private Model model;
|
private Model model;
|
||||||
|
|
||||||
|
private final ThreadLocal<Record> records = new ThreadLocal<>();
|
||||||
|
|
||||||
|
public DefaultProfileActivationContext(
|
||||||
|
PathTranslator pathTranslator, RootLocator rootLocator, Interpolator interpolator) {
|
||||||
|
this.pathTranslator = pathTranslator;
|
||||||
|
this.rootLocator = rootLocator;
|
||||||
|
this.interpolator = interpolator;
|
||||||
|
}
|
||||||
|
|
||||||
|
Record start() {
|
||||||
|
Record record = records.get();
|
||||||
|
records.set(new Record());
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
Record stop(Record previous) {
|
||||||
|
Record record = records.get();
|
||||||
|
records.set(previous);
|
||||||
|
// only keep keys for which the value is `true`
|
||||||
|
record.usedActiveProfiles.values().removeIf(value -> !value);
|
||||||
|
record.usedInactiveProfiles.values().removeIf(value -> !value);
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getActiveProfileIds() {
|
public boolean isProfileActive(String profileId) {
|
||||||
return activeProfileIds;
|
Record record = records.get();
|
||||||
|
if (record != null) {
|
||||||
|
return record.usedActiveProfiles.computeIfAbsent(profileId, activeProfileIds::contains);
|
||||||
|
} else {
|
||||||
|
return activeProfileIds.contains(profileId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,8 +194,13 @@ public class DefaultProfileActivationContext implements ProfileActivationContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getInactiveProfileIds() {
|
public boolean isProfileInactive(String profileId) {
|
||||||
return inactiveProfileIds;
|
Record record = records.get();
|
||||||
|
if (record != null) {
|
||||||
|
return record.usedInactiveProfiles.computeIfAbsent(profileId, inactiveProfileIds::contains);
|
||||||
|
} else {
|
||||||
|
return inactiveProfileIds.contains(profileId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,8 +215,13 @@ public class DefaultProfileActivationContext implements ProfileActivationContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getSystemProperties() {
|
public String getSystemProperty(String key) {
|
||||||
return systemProperties;
|
Record record = records.get();
|
||||||
|
if (record != null) {
|
||||||
|
return record.usedSystemProperties.computeIfAbsent(key, systemProperties::get);
|
||||||
|
} else {
|
||||||
|
return systemProperties.get(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,8 +237,13 @@ public class DefaultProfileActivationContext implements ProfileActivationContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getUserProperties() {
|
public String getUserProperty(String key) {
|
||||||
return userProperties;
|
Record record = records.get();
|
||||||
|
if (record != null) {
|
||||||
|
return record.usedUserProperties.computeIfAbsent(key, userProperties::get);
|
||||||
|
} else {
|
||||||
|
return userProperties.get(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,16 +260,164 @@ public class DefaultProfileActivationContext implements ProfileActivationContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Model getModel() {
|
public String getModelArtifactId() {
|
||||||
return model;
|
Record record = records.get();
|
||||||
|
if (record != null) {
|
||||||
|
return record.usedModelInfos.computeIfAbsent(ModelInfo.ArtifactId, k -> model.getArtifactId());
|
||||||
|
} else {
|
||||||
|
return model.getArtifactId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModelPackaging() {
|
||||||
|
Record record = records.get();
|
||||||
|
if (record != null) {
|
||||||
|
return record.usedModelInfos.computeIfAbsent(ModelInfo.Packaging, k -> model.getPackaging());
|
||||||
|
} else {
|
||||||
|
return model.getPackaging();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModelProperty(String key) {
|
||||||
|
Record record = records.get();
|
||||||
|
if (record != null) {
|
||||||
|
return record.usedModelProperties.computeIfAbsent(
|
||||||
|
key, k -> model.getProperties().get(k));
|
||||||
|
} else {
|
||||||
|
return model.getProperties().get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModelBaseDirectory() {
|
||||||
|
Record record = records.get();
|
||||||
|
if (record != null) {
|
||||||
|
return record.usedModelInfos.computeIfAbsent(ModelInfo.BaseDirectory, k -> doGetModelBaseDirectory());
|
||||||
|
} else {
|
||||||
|
return doGetModelBaseDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String doGetModelBaseDirectory() {
|
||||||
|
Path basedir = model.getProjectDirectory();
|
||||||
|
return basedir != null ? basedir.toAbsolutePath().toString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModelRootDirectory() {
|
||||||
|
Record record = records.get();
|
||||||
|
if (record != null) {
|
||||||
|
return record.usedModelInfos.computeIfAbsent(ModelInfo.RootDirectory, k -> doGetModelRootDirectory());
|
||||||
|
} else {
|
||||||
|
return doGetModelRootDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String doGetModelRootDirectory() {
|
||||||
|
Path basedir = model != null ? model.getProjectDirectory() : null;
|
||||||
|
Path rootdir = rootLocator != null ? rootLocator.findRoot(basedir) : null;
|
||||||
|
return rootdir != null ? rootdir.toAbsolutePath().toString() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultProfileActivationContext setModel(Model model) {
|
public DefaultProfileActivationContext setModel(Model model) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String interpolatePath(String path) throws InterpolatorException {
|
||||||
|
if (path == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String absolutePath = interpolator.interpolate(path, s -> {
|
||||||
|
if ("basedir".equals(s) || "project.basedir".equals(s)) {
|
||||||
|
return getModelBaseDirectory();
|
||||||
|
}
|
||||||
|
if ("project.rootDirectory".equals(s)) {
|
||||||
|
return getModelRootDirectory();
|
||||||
|
}
|
||||||
|
String r = getModelProperty(s);
|
||||||
|
if (r == null) {
|
||||||
|
r = getUserProperty(s);
|
||||||
|
}
|
||||||
|
if (r == null) {
|
||||||
|
r = getSystemProperty(s);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
});
|
||||||
|
return pathTranslator.alignToBaseDirectory(absolutePath, model.getProjectDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean exists(String path, boolean enableGlob) throws ModelBuilderException {
|
||||||
|
Record record = records.get();
|
||||||
|
if (record != null) {
|
||||||
|
return record.usedExists.computeIfAbsent(
|
||||||
|
new ExistRequest(path, enableGlob), r -> doExists(r.path, r.enableGlob));
|
||||||
|
} else {
|
||||||
|
return doExists(path, enableGlob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doExists(String path, boolean enableGlob) throws ModelBuilderException {
|
||||||
|
String pattern = interpolatePath(path);
|
||||||
|
String fixed, glob;
|
||||||
|
if (enableGlob) {
|
||||||
|
int asteriskIndex = pattern.indexOf('*');
|
||||||
|
int questionMarkIndex = pattern.indexOf('?');
|
||||||
|
int firstWildcardIndex = questionMarkIndex < 0
|
||||||
|
? asteriskIndex
|
||||||
|
: asteriskIndex < 0 ? questionMarkIndex : Math.min(asteriskIndex, questionMarkIndex);
|
||||||
|
if (firstWildcardIndex < 0) {
|
||||||
|
fixed = pattern;
|
||||||
|
glob = "";
|
||||||
|
} else {
|
||||||
|
int lastSep = pattern.substring(0, firstWildcardIndex).lastIndexOf(File.separatorChar);
|
||||||
|
if (lastSep < 0) {
|
||||||
|
fixed = "";
|
||||||
|
glob = pattern;
|
||||||
|
} else {
|
||||||
|
fixed = pattern.substring(0, lastSep);
|
||||||
|
glob = pattern.substring(lastSep + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fixed = pattern;
|
||||||
|
glob = "";
|
||||||
|
}
|
||||||
|
Path fixedPath = Paths.get(fixed);
|
||||||
|
return doExists(fixedPath, glob);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Boolean doExists(Path fixedPath, String glob) {
|
||||||
|
if (fixedPath == null || !Files.exists(fixedPath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (glob != null && !glob.isEmpty()) {
|
||||||
|
try {
|
||||||
|
PathMatcher matcher = fixedPath.getFileSystem().getPathMatcher("glob:" + glob);
|
||||||
|
AtomicBoolean found = new AtomicBoolean(false);
|
||||||
|
Files.walkFileTree(fixedPath, new SimpleFileVisitor<>() {
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||||
|
if (found.get() || matcher.matches(fixedPath.relativize(file))) {
|
||||||
|
found.set(true);
|
||||||
|
return FileVisitResult.TERMINATE;
|
||||||
|
}
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return found.get();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ProjectBuilderException(
|
||||||
|
"Unable to verify file existence for '" + glob + "' inside '" + fixedPath + "'", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static List<String> unmodifiable(List<String> list) {
|
private static List<String> unmodifiable(List<String> list) {
|
||||||
return list != null ? Collections.unmodifiableList(list) : Collections.emptyList();
|
return list != null ? Collections.unmodifiableList(list) : Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ package org.apache.maven.internal.impl.model;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.maven.api.di.Inject;
|
import org.apache.maven.api.di.Inject;
|
||||||
|
@ -64,16 +63,13 @@ public class DefaultProfileSelector implements ProfileSelector {
|
||||||
@Override
|
@Override
|
||||||
public List<Profile> getActiveProfiles(
|
public List<Profile> getActiveProfiles(
|
||||||
Collection<Profile> profiles, ProfileActivationContext context, ModelProblemCollector problems) {
|
Collection<Profile> profiles, ProfileActivationContext context, ModelProblemCollector problems) {
|
||||||
Collection<String> activatedIds = new HashSet<>(context.getActiveProfileIds());
|
|
||||||
Collection<String> deactivatedIds = new HashSet<>(context.getInactiveProfileIds());
|
|
||||||
|
|
||||||
List<Profile> activeProfiles = new ArrayList<>(profiles.size());
|
List<Profile> activeProfiles = new ArrayList<>(profiles.size());
|
||||||
List<Profile> activePomProfilesByDefault = new ArrayList<>();
|
List<Profile> activePomProfilesByDefault = new ArrayList<>();
|
||||||
boolean activatedPomProfileNotByDefault = false;
|
boolean activatedPomProfileNotByDefault = false;
|
||||||
|
|
||||||
for (Profile profile : profiles) {
|
for (Profile profile : profiles) {
|
||||||
if (!deactivatedIds.contains(profile.getId())) {
|
if (!context.isProfileInactive(profile.getId())) {
|
||||||
if (activatedIds.contains(profile.getId()) || isActive(profile, context, problems)) {
|
if (context.isProfileActive(profile.getId()) || isActive(profile, context, problems)) {
|
||||||
activeProfiles.add(profile);
|
activeProfiles.add(profile);
|
||||||
if (Profile.SOURCE_POM.equals(profile.getSource())) {
|
if (Profile.SOURCE_POM.equals(profile.getSource())) {
|
||||||
activatedPomProfileNotByDefault = true;
|
activatedPomProfileNotByDefault = true;
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.internal.impl.model;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
import org.apache.maven.api.di.Inject;
|
|
||||||
import org.apache.maven.api.di.Named;
|
|
||||||
import org.apache.maven.api.di.Singleton;
|
|
||||||
import org.apache.maven.api.model.ActivationFile;
|
|
||||||
import org.apache.maven.api.services.Interpolator;
|
|
||||||
import org.apache.maven.api.services.InterpolatorException;
|
|
||||||
import org.apache.maven.api.services.model.PathTranslator;
|
|
||||||
import org.apache.maven.api.services.model.ProfileActivationContext;
|
|
||||||
import org.apache.maven.api.services.model.RootLocator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds an absolute path for {@link ActivationFile#getExists()} or {@link ActivationFile#getMissing()}
|
|
||||||
*/
|
|
||||||
@Named
|
|
||||||
@Singleton
|
|
||||||
public class ProfileActivationFilePathInterpolator {
|
|
||||||
|
|
||||||
private final PathTranslator pathTranslator;
|
|
||||||
|
|
||||||
private final RootLocator rootLocator;
|
|
||||||
|
|
||||||
private final Interpolator interpolator;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public ProfileActivationFilePathInterpolator(
|
|
||||||
PathTranslator pathTranslator, RootLocator rootLocator, Interpolator interpolator) {
|
|
||||||
this.pathTranslator = pathTranslator;
|
|
||||||
this.rootLocator = rootLocator;
|
|
||||||
this.interpolator = interpolator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interpolates given {@code path}.
|
|
||||||
*
|
|
||||||
* @return absolute path or {@code null} if the input was {@code null}
|
|
||||||
*/
|
|
||||||
public String interpolate(String path, ProfileActivationContext context) throws InterpolatorException {
|
|
||||||
if (path == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Path basedir = context.getModel().getProjectDirectory();
|
|
||||||
|
|
||||||
String absolutePath = interpolator.interpolate(path, s -> {
|
|
||||||
if ("basedir".equals(s) || "project.basedir".equals(s)) {
|
|
||||||
return basedir != null ? basedir.toFile().getAbsolutePath() : null;
|
|
||||||
}
|
|
||||||
if ("project.rootDirectory".equals(s)) {
|
|
||||||
Path root = rootLocator.findMandatoryRoot(basedir);
|
|
||||||
return root.toFile().getAbsolutePath();
|
|
||||||
}
|
|
||||||
String r = context.getModel().getProperties().get(s);
|
|
||||||
if (r == null) {
|
|
||||||
r = context.getUserProperties().get(s);
|
|
||||||
}
|
|
||||||
if (r == null) {
|
|
||||||
r = context.getSystemProperties().get(s);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
});
|
|
||||||
|
|
||||||
return pathTranslator.alignToBaseDirectory(absolutePath, basedir);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,21 +18,12 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.maven.internal.impl.model.profile;
|
package org.apache.maven.internal.impl.model.profile;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.FileVisitResult;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.PathMatcher;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.SimpleFileVisitor;
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
|
import org.apache.maven.api.services.InterpolatorException;
|
||||||
|
import org.apache.maven.api.services.ModelBuilderException;
|
||||||
import org.apache.maven.api.services.VersionParser;
|
import org.apache.maven.api.services.VersionParser;
|
||||||
import org.apache.maven.api.services.model.ProfileActivationContext;
|
import org.apache.maven.api.services.model.ProfileActivationContext;
|
||||||
import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
|
|
||||||
|
|
||||||
import static org.apache.maven.internal.impl.model.profile.ConditionParser.toInt;
|
import static org.apache.maven.internal.impl.model.profile.ConditionParser.toInt;
|
||||||
|
|
||||||
|
@ -45,22 +36,16 @@ import static org.apache.maven.internal.impl.model.profile.ConditionParser.toInt
|
||||||
public class ConditionFunctions {
|
public class ConditionFunctions {
|
||||||
private final ProfileActivationContext context;
|
private final ProfileActivationContext context;
|
||||||
private final VersionParser versionParser;
|
private final VersionParser versionParser;
|
||||||
private final ProfileActivationFilePathInterpolator interpolator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new ConditionFunctions instance.
|
* Constructs a new ConditionFunctions instance.
|
||||||
*
|
*
|
||||||
* @param context The profile activation context
|
* @param context The profile activation context
|
||||||
* @param versionParser The version parser for comparing versions
|
* @param versionParser The version parser for comparing versions
|
||||||
* @param interpolator The interpolator for resolving file paths
|
|
||||||
*/
|
*/
|
||||||
public ConditionFunctions(
|
public ConditionFunctions(ProfileActivationContext context, VersionParser versionParser) {
|
||||||
ProfileActivationContext context,
|
|
||||||
VersionParser versionParser,
|
|
||||||
ProfileActivationFilePathInterpolator interpolator) {
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.versionParser = versionParser;
|
this.versionParser = versionParser;
|
||||||
this.interpolator = interpolator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -207,75 +192,34 @@ public class ConditionFunctions {
|
||||||
* Checks if a file or directory exists at the given path.
|
* Checks if a file or directory exists at the given path.
|
||||||
*
|
*
|
||||||
* @param args A list containing a single string argument representing the path
|
* @param args A list containing a single string argument representing the path
|
||||||
* @return true if the file or directory exists, false otherwise
|
* @return {@code true} if the file or directory exists, {@code false} otherwise
|
||||||
* @throws IllegalArgumentException if the number of arguments is not exactly one
|
* @throws IllegalArgumentException if the number of arguments is not exactly one
|
||||||
* @throws IOException if a problem occurs while walking the file system
|
* @throws ModelBuilderException if a problem occurs while walking the file system
|
||||||
|
* @throws InterpolatorException if an error occurs during interpolation
|
||||||
*/
|
*/
|
||||||
public Object exists(List<Object> args) throws IOException {
|
public Object exists(List<Object> args) {
|
||||||
if (args.size() != 1) {
|
if (args.size() != 1) {
|
||||||
throw new IllegalArgumentException("exists function requires exactly one argument");
|
throw new IllegalArgumentException("exists function requires exactly one argument");
|
||||||
}
|
}
|
||||||
String path = ConditionParser.toString(args.get(0));
|
String path = ConditionParser.toString(args.get(0));
|
||||||
return fileExists(path);
|
return context.exists(path, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a file or directory is missing at the given path.
|
* Checks if a file or directory is missing at the given path.
|
||||||
*
|
*
|
||||||
* @param args A list containing a single string argument representing the path
|
* @param args A list containing a single string argument representing the path
|
||||||
* @return true if the file or directory does not exist, false otherwise
|
* @return {@code true} if the file or directory does not exist, {@code false} otherwise
|
||||||
* @throws IllegalArgumentException if the number of arguments is not exactly one
|
* @throws IllegalArgumentException if the number of arguments is not exactly one
|
||||||
* @throws IOException if a problem occurs while walking the file system
|
* @throws ModelBuilderException if a problem occurs while walking the file system
|
||||||
|
* @throws InterpolatorException if an error occurs during interpolation
|
||||||
*/
|
*/
|
||||||
public Object missing(List<Object> args) throws IOException {
|
public Object missing(List<Object> args) {
|
||||||
if (args.size() != 1) {
|
if (args.size() != 1) {
|
||||||
throw new IllegalArgumentException("missing function requires exactly one argument");
|
throw new IllegalArgumentException("missing function requires exactly one argument");
|
||||||
}
|
}
|
||||||
String path = ConditionParser.toString(args.get(0));
|
String path = ConditionParser.toString(args.get(0));
|
||||||
return !fileExists(path);
|
return !context.exists(path, true);
|
||||||
}
|
|
||||||
|
|
||||||
private boolean fileExists(String path) throws IOException {
|
|
||||||
String pattern = interpolator.interpolate(path, context);
|
|
||||||
int asteriskIndex = pattern.indexOf('*');
|
|
||||||
int questionMarkIndex = pattern.indexOf('?');
|
|
||||||
int firstWildcardIndex = questionMarkIndex < 0
|
|
||||||
? asteriskIndex
|
|
||||||
: asteriskIndex < 0 ? questionMarkIndex : Math.min(asteriskIndex, questionMarkIndex);
|
|
||||||
String fixed, glob;
|
|
||||||
if (firstWildcardIndex < 0) {
|
|
||||||
fixed = pattern;
|
|
||||||
glob = "";
|
|
||||||
} else {
|
|
||||||
int lastSep = pattern.substring(0, firstWildcardIndex).lastIndexOf(File.separatorChar);
|
|
||||||
if (lastSep < 0) {
|
|
||||||
fixed = "";
|
|
||||||
glob = pattern;
|
|
||||||
} else {
|
|
||||||
fixed = pattern.substring(0, lastSep);
|
|
||||||
glob = pattern.substring(lastSep + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Path fixedPath = Paths.get(fixed);
|
|
||||||
if (!Files.exists(fixedPath)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!glob.isEmpty()) {
|
|
||||||
PathMatcher matcher = fixedPath.getFileSystem().getPathMatcher("glob:" + glob);
|
|
||||||
AtomicBoolean found = new AtomicBoolean(false);
|
|
||||||
Files.walkFileTree(fixedPath, new SimpleFileVisitor<>() {
|
|
||||||
@Override
|
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
|
||||||
if (found.get() || matcher.matches(fixedPath.relativize(file))) {
|
|
||||||
found.set(true);
|
|
||||||
return FileVisitResult.TERMINATE;
|
|
||||||
}
|
|
||||||
return FileVisitResult.CONTINUE;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return found.get();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.maven.internal.impl.model.profile;
|
package org.apache.maven.internal.impl.model.profile;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -34,9 +33,7 @@ import org.apache.maven.api.services.ModelProblemCollector;
|
||||||
import org.apache.maven.api.services.VersionParser;
|
import org.apache.maven.api.services.VersionParser;
|
||||||
import org.apache.maven.api.services.model.ProfileActivationContext;
|
import org.apache.maven.api.services.model.ProfileActivationContext;
|
||||||
import org.apache.maven.api.services.model.ProfileActivator;
|
import org.apache.maven.api.services.model.ProfileActivator;
|
||||||
import org.apache.maven.api.services.model.RootLocator;
|
|
||||||
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
||||||
import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
|
|
||||||
|
|
||||||
import static org.apache.maven.internal.impl.model.profile.ConditionParser.toBoolean;
|
import static org.apache.maven.internal.impl.model.profile.ConditionParser.toBoolean;
|
||||||
|
|
||||||
|
@ -49,22 +46,15 @@ import static org.apache.maven.internal.impl.model.profile.ConditionParser.toBoo
|
||||||
public class ConditionProfileActivator implements ProfileActivator {
|
public class ConditionProfileActivator implements ProfileActivator {
|
||||||
|
|
||||||
private final VersionParser versionParser;
|
private final VersionParser versionParser;
|
||||||
private final ProfileActivationFilePathInterpolator interpolator;
|
|
||||||
private final RootLocator rootLocator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new ConditionProfileActivator with the necessary dependencies.
|
* Constructs a new ConditionProfileActivator with the necessary dependencies.
|
||||||
*
|
*
|
||||||
* @param versionParser The parser for handling version comparisons
|
* @param versionParser The parser for handling version comparisons
|
||||||
* @param interpolator The interpolator for resolving file paths
|
|
||||||
* @param rootLocator The locator for finding the project root directory
|
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
public ConditionProfileActivator(
|
public ConditionProfileActivator(VersionParser versionParser) {
|
||||||
VersionParser versionParser, ProfileActivationFilePathInterpolator interpolator, RootLocator rootLocator) {
|
|
||||||
this.versionParser = versionParser;
|
this.versionParser = versionParser;
|
||||||
this.interpolator = interpolator;
|
|
||||||
this.rootLocator = rootLocator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,9 +72,8 @@ public class ConditionProfileActivator implements ProfileActivator {
|
||||||
}
|
}
|
||||||
String condition = profile.getActivation().getCondition();
|
String condition = profile.getActivation().getCondition();
|
||||||
try {
|
try {
|
||||||
Map<String, ConditionParser.ExpressionFunction> functions =
|
Map<String, ConditionParser.ExpressionFunction> functions = registerFunctions(context, versionParser);
|
||||||
registerFunctions(context, versionParser, interpolator);
|
Function<String, String> propertyResolver = s -> property(context, s);
|
||||||
Function<String, String> propertyResolver = s -> property(context, rootLocator, s);
|
|
||||||
return toBoolean(new ConditionParser(functions, propertyResolver).parse(condition));
|
return toBoolean(new ConditionParser(functions, propertyResolver).parse(condition));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
problems.add(
|
problems.add(
|
||||||
|
@ -115,16 +104,13 @@ public class ConditionProfileActivator implements ProfileActivator {
|
||||||
*
|
*
|
||||||
* @param context The profile activation context
|
* @param context The profile activation context
|
||||||
* @param versionParser The parser for handling version comparisons
|
* @param versionParser The parser for handling version comparisons
|
||||||
* @param interpolator The interpolator for resolving file paths
|
|
||||||
* @return A map of function names to their implementations
|
* @return A map of function names to their implementations
|
||||||
*/
|
*/
|
||||||
public static Map<String, ConditionParser.ExpressionFunction> registerFunctions(
|
public static Map<String, ConditionParser.ExpressionFunction> registerFunctions(
|
||||||
ProfileActivationContext context,
|
ProfileActivationContext context, VersionParser versionParser) {
|
||||||
VersionParser versionParser,
|
|
||||||
ProfileActivationFilePathInterpolator interpolator) {
|
|
||||||
Map<String, ConditionParser.ExpressionFunction> functions = new HashMap<>();
|
Map<String, ConditionParser.ExpressionFunction> functions = new HashMap<>();
|
||||||
|
|
||||||
ConditionFunctions conditionFunctions = new ConditionFunctions(context, versionParser, interpolator);
|
ConditionFunctions conditionFunctions = new ConditionFunctions(context, versionParser);
|
||||||
|
|
||||||
for (java.lang.reflect.Method method : ConditionFunctions.class.getDeclaredMethods()) {
|
for (java.lang.reflect.Method method : ConditionFunctions.class.getDeclaredMethods()) {
|
||||||
String methodName = method.getName();
|
String methodName = method.getName();
|
||||||
|
@ -170,43 +156,37 @@ public class ConditionProfileActivator implements ProfileActivator {
|
||||||
* @return The value of the property, or null if not found
|
* @return The value of the property, or null if not found
|
||||||
* @throws IllegalArgumentException if the number of arguments is not exactly one
|
* @throws IllegalArgumentException if the number of arguments is not exactly one
|
||||||
*/
|
*/
|
||||||
static String property(ProfileActivationContext context, RootLocator rootLocator, String name) {
|
static String property(ProfileActivationContext context, String name) {
|
||||||
String value = doGetProperty(context, rootLocator, name);
|
String value = doGetProperty(context, name);
|
||||||
return new DefaultInterpolator().interpolate(value, s -> doGetProperty(context, rootLocator, s));
|
return new DefaultInterpolator().interpolate(value, s -> doGetProperty(context, s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static String doGetProperty(ProfileActivationContext context, RootLocator rootLocator, String name) {
|
static String doGetProperty(ProfileActivationContext context, String name) {
|
||||||
// Handle special project-related properties
|
// Handle special project-related properties
|
||||||
if ("project.basedir".equals(name)) {
|
if ("project.basedir".equals(name)) {
|
||||||
Path basedir = context.getModel().getProjectDirectory();
|
return context.getModelBaseDirectory();
|
||||||
return basedir != null ? basedir.toFile().getAbsolutePath() : null;
|
|
||||||
}
|
}
|
||||||
if ("project.rootDirectory".equals(name)) {
|
if ("project.rootDirectory".equals(name)) {
|
||||||
Path basedir = context.getModel().getProjectDirectory();
|
return context.getModelRootDirectory();
|
||||||
if (basedir != null) {
|
|
||||||
Path root = rootLocator.findMandatoryRoot(basedir);
|
|
||||||
return root.toFile().getAbsolutePath();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
if ("project.artifactId".equals(name)) {
|
if ("project.artifactId".equals(name)) {
|
||||||
return context.getModel().getArtifactId();
|
return context.getModelArtifactId();
|
||||||
}
|
}
|
||||||
if ("project.packaging".equals(name)) {
|
if ("project.packaging".equals(name)) {
|
||||||
return context.getModel().getPackaging();
|
return context.getModelPackaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check user properties
|
// Check user properties
|
||||||
String v = context.getUserProperties().get(name);
|
String v = context.getUserProperty(name);
|
||||||
if (v == null) {
|
if (v == null) {
|
||||||
// Check project properties
|
// Check project properties
|
||||||
// TODO: this may leads to instability between file model activation and effective model activation
|
// TODO: this may leads to instability between file model activation and effective model activation
|
||||||
// as the effective model properties may be different from the file model
|
// as the effective model properties may be different from the file model
|
||||||
v = context.getModel().getProperties().get(name);
|
v = context.getModelProperty(name);
|
||||||
}
|
}
|
||||||
if (v == null) {
|
if (v == null) {
|
||||||
// Check system properties
|
// Check system properties
|
||||||
v = context.getSystemProperties().get(name);
|
v = context.getSystemProperty(name);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,21 +18,17 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.maven.internal.impl.model.profile;
|
package org.apache.maven.internal.impl.model.profile;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import org.apache.maven.api.di.Inject;
|
|
||||||
import org.apache.maven.api.di.Named;
|
import org.apache.maven.api.di.Named;
|
||||||
import org.apache.maven.api.di.Singleton;
|
import org.apache.maven.api.di.Singleton;
|
||||||
import org.apache.maven.api.model.Activation;
|
import org.apache.maven.api.model.Activation;
|
||||||
import org.apache.maven.api.model.ActivationFile;
|
import org.apache.maven.api.model.ActivationFile;
|
||||||
import org.apache.maven.api.model.Profile;
|
import org.apache.maven.api.model.Profile;
|
||||||
import org.apache.maven.api.services.BuilderProblem;
|
import org.apache.maven.api.services.BuilderProblem;
|
||||||
import org.apache.maven.api.services.InterpolatorException;
|
import org.apache.maven.api.services.MavenException;
|
||||||
import org.apache.maven.api.services.ModelProblem;
|
import org.apache.maven.api.services.ModelProblem;
|
||||||
import org.apache.maven.api.services.ModelProblemCollector;
|
import org.apache.maven.api.services.ModelProblemCollector;
|
||||||
import org.apache.maven.api.services.model.ProfileActivationContext;
|
import org.apache.maven.api.services.model.ProfileActivationContext;
|
||||||
import org.apache.maven.api.services.model.ProfileActivator;
|
import org.apache.maven.api.services.model.ProfileActivator;
|
||||||
import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines profile activation based on the existence/absence of some file.
|
* Determines profile activation based on the existence/absence of some file.
|
||||||
|
@ -46,13 +42,6 @@ import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolato
|
||||||
@Singleton
|
@Singleton
|
||||||
public class FileProfileActivator implements ProfileActivator {
|
public class FileProfileActivator implements ProfileActivator {
|
||||||
|
|
||||||
private final ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public FileProfileActivator(ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator) {
|
|
||||||
this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive(Profile profile, ProfileActivationContext context, ModelProblemCollector problems) {
|
public boolean isActive(Profile profile, ProfileActivationContext context, ModelProblemCollector problems) {
|
||||||
Activation activation = profile.getActivation();
|
Activation activation = profile.getActivation();
|
||||||
|
@ -92,31 +81,20 @@ public class FileProfileActivator implements ProfileActivator {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean fileExists;
|
||||||
try {
|
try {
|
||||||
path = profileActivationFilePathInterpolator.interpolate(path, context);
|
fileExists = context.exists(path, false);
|
||||||
} catch (InterpolatorException e) {
|
} catch (MavenException e) {
|
||||||
problems.add(
|
problems.add(
|
||||||
BuilderProblem.Severity.ERROR,
|
BuilderProblem.Severity.ERROR,
|
||||||
ModelProblem.Version.BASE,
|
ModelProblem.Version.BASE,
|
||||||
"Failed to interpolate file location " + path + " for profile " + profile.getId() + ": "
|
"Failed to check file existence " + path + " for profile " + profile.getId() + ": "
|
||||||
+ e.getMessage(),
|
+ e.getMessage(),
|
||||||
file.getLocation(missing ? "missing" : "exists"),
|
file.getLocation(missing ? "missing" : "exists"),
|
||||||
e);
|
e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
File f = new File(path);
|
|
||||||
|
|
||||||
if (!f.isAbsolute()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean fileExists = f.exists();
|
|
||||||
|
|
||||||
return missing != fileExists;
|
return missing != fileExists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class JdkVersionProfileActivator implements ProfileActivator {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String version = context.getSystemProperties().get("java.version");
|
String version = context.getSystemProperty("java.version");
|
||||||
|
|
||||||
if (version == null || version.isEmpty()) {
|
if (version == null || version.isEmpty()) {
|
||||||
problems.add(
|
problems.add(
|
||||||
|
|
|
@ -56,15 +56,10 @@ public class OperatingSystemProfileActivator implements ProfileActivator {
|
||||||
|
|
||||||
boolean active = ensureAtLeastOneNonNull(os);
|
boolean active = ensureAtLeastOneNonNull(os);
|
||||||
|
|
||||||
String actualOsName = context.getSystemProperties()
|
String actualOsName = getSystemProperty(context, "os.name", Os.OS_NAME).toLowerCase(Locale.ENGLISH);
|
||||||
.getOrDefault("os.name", Os.OS_NAME)
|
String actualOsArch = getSystemProperty(context, "os.arch", Os.OS_ARCH).toLowerCase(Locale.ENGLISH);
|
||||||
.toLowerCase(Locale.ENGLISH);
|
String actualOsVersion =
|
||||||
String actualOsArch = context.getSystemProperties()
|
getSystemProperty(context, "os.version", Os.OS_VERSION).toLowerCase(Locale.ENGLISH);
|
||||||
.getOrDefault("os.arch", Os.OS_ARCH)
|
|
||||||
.toLowerCase(Locale.ENGLISH);
|
|
||||||
String actualOsVersion = context.getSystemProperties()
|
|
||||||
.getOrDefault("os.version", Os.OS_VERSION)
|
|
||||||
.toLowerCase(Locale.ENGLISH);
|
|
||||||
|
|
||||||
if (active && os.getFamily() != null) {
|
if (active && os.getFamily() != null) {
|
||||||
active = determineFamilyMatch(os.getFamily(), actualOsName);
|
active = determineFamilyMatch(os.getFamily(), actualOsName);
|
||||||
|
@ -82,6 +77,11 @@ public class OperatingSystemProfileActivator implements ProfileActivator {
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getSystemProperty(ProfileActivationContext context, String key, String defValue) {
|
||||||
|
String val = context.getSystemProperty(key);
|
||||||
|
return val != null ? val : defValue;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean presentInConfig(Profile profile, ProfileActivationContext context, ModelProblemCollector problems) {
|
public boolean presentInConfig(Profile profile, ProfileActivationContext context, ModelProblemCollector problems) {
|
||||||
Activation activation = profile.getActivation();
|
Activation activation = profile.getActivation();
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class PackagingProfileActivator implements ProfileActivator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPackaging(ProfileActivationContext context, String p) {
|
private static boolean isPackaging(ProfileActivationContext context, String p) {
|
||||||
String packaging = context.getModel().getPackaging();
|
String packaging = context.getModelPackaging();
|
||||||
return Objects.equals(p, packaging);
|
return Objects.equals(p, packaging);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,12 +69,12 @@ public class PropertyProfileActivator implements ProfileActivator {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String sysValue = context.getUserProperties().get(name);
|
String sysValue = context.getUserProperty(name);
|
||||||
if (sysValue == null && "packaging".equals(name)) {
|
if (sysValue == null && "packaging".equals(name)) {
|
||||||
sysValue = context.getModel().getPackaging();
|
sysValue = context.getModelPackaging();
|
||||||
}
|
}
|
||||||
if (sysValue == null) {
|
if (sysValue == null) {
|
||||||
sysValue = context.getSystemProperties().get(name);
|
sysValue = context.getSystemProperty(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
String propValue = property.getValue();
|
String propValue = property.getValue();
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* 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.internal.impl.model;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
import org.apache.maven.api.Session;
|
||||||
|
import org.apache.maven.api.services.ModelBuilder;
|
||||||
|
import org.apache.maven.api.services.ModelBuilderRequest;
|
||||||
|
import org.apache.maven.api.services.ModelBuilderResult;
|
||||||
|
import org.apache.maven.api.services.ModelSource;
|
||||||
|
import org.apache.maven.internal.impl.standalone.ApiRunner;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class DefaultModelBuilderTest {
|
||||||
|
|
||||||
|
Session session;
|
||||||
|
ModelBuilder builder;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
session = ApiRunner.createSession();
|
||||||
|
builder = session.getService(ModelBuilder.class);
|
||||||
|
assertNotNull(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPropertiesAndProfiles() {
|
||||||
|
ModelBuilderRequest request = ModelBuilderRequest.builder()
|
||||||
|
.session(session)
|
||||||
|
.requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
|
||||||
|
.source(ModelSource.fromPath(getPom("props-and-profiles")))
|
||||||
|
.build();
|
||||||
|
ModelBuilderResult result = builder.newSession().build(request);
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals("21", result.getEffectiveModel().getProperties().get("maven.compiler.release"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path getPom(String name) {
|
||||||
|
return Paths.get("src/test/resources/poms/factory/" + name + ".xml").toAbsolutePath();
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,8 @@ import org.apache.maven.api.model.Model;
|
||||||
import org.apache.maven.api.model.Profile;
|
import org.apache.maven.api.model.Profile;
|
||||||
import org.apache.maven.api.services.model.ProfileActivationContext;
|
import org.apache.maven.api.services.model.ProfileActivationContext;
|
||||||
import org.apache.maven.api.services.model.ProfileActivator;
|
import org.apache.maven.api.services.model.ProfileActivator;
|
||||||
|
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
||||||
|
import org.apache.maven.internal.impl.model.DefaultPathTranslator;
|
||||||
import org.apache.maven.internal.impl.model.DefaultProfileActivationContext;
|
import org.apache.maven.internal.impl.model.DefaultProfileActivationContext;
|
||||||
import org.apache.maven.internal.impl.model.rootlocator.DefaultRootLocator;
|
import org.apache.maven.internal.impl.model.rootlocator.DefaultRootLocator;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -55,7 +57,8 @@ public abstract class AbstractProfileActivatorTest<T extends ProfileActivator> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DefaultProfileActivationContext newContext() {
|
protected DefaultProfileActivationContext newContext() {
|
||||||
return new DefaultProfileActivationContext();
|
return new DefaultProfileActivationContext(
|
||||||
|
new DefaultPathTranslator(), new FakeRootLocator(), new DefaultInterpolator());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ProfileActivationContext newContext(
|
protected ProfileActivationContext newContext(
|
||||||
|
|
|
@ -28,7 +28,6 @@ import org.apache.maven.internal.impl.DefaultVersionParser;
|
||||||
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
||||||
import org.apache.maven.internal.impl.model.DefaultPathTranslator;
|
import org.apache.maven.internal.impl.model.DefaultPathTranslator;
|
||||||
import org.apache.maven.internal.impl.model.DefaultProfileActivationContext;
|
import org.apache.maven.internal.impl.model.DefaultProfileActivationContext;
|
||||||
import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
|
|
||||||
import org.apache.maven.internal.impl.model.profile.ConditionParser.ExpressionFunction;
|
import org.apache.maven.internal.impl.model.profile.ConditionParser.ExpressionFunction;
|
||||||
import org.apache.maven.internal.impl.model.rootlocator.DefaultRootLocator;
|
import org.apache.maven.internal.impl.model.rootlocator.DefaultRootLocator;
|
||||||
import org.eclipse.aether.util.version.GenericVersionScheme;
|
import org.eclipse.aether.util.version.GenericVersionScheme;
|
||||||
|
@ -51,19 +50,18 @@ class ConditionParserTest {
|
||||||
ProfileActivationContext context = createMockContext();
|
ProfileActivationContext context = createMockContext();
|
||||||
DefaultVersionParser versionParser =
|
DefaultVersionParser versionParser =
|
||||||
new DefaultVersionParser(new DefaultModelVersionParser(new GenericVersionScheme()));
|
new DefaultVersionParser(new DefaultModelVersionParser(new GenericVersionScheme()));
|
||||||
ProfileActivationFilePathInterpolator interpolator = new ProfileActivationFilePathInterpolator(
|
|
||||||
new DefaultPathTranslator(),
|
|
||||||
new AbstractProfileActivatorTest.FakeRootLocator(),
|
|
||||||
new DefaultInterpolator());
|
|
||||||
DefaultRootLocator rootLocator = new DefaultRootLocator();
|
DefaultRootLocator rootLocator = new DefaultRootLocator();
|
||||||
|
|
||||||
functions = ConditionProfileActivator.registerFunctions(context, versionParser, interpolator);
|
functions = ConditionProfileActivator.registerFunctions(context, versionParser);
|
||||||
propertyResolver = s -> ConditionProfileActivator.property(context, rootLocator, s);
|
propertyResolver = s -> ConditionProfileActivator.property(context, s);
|
||||||
parser = new ConditionParser(functions, propertyResolver);
|
parser = new ConditionParser(functions, propertyResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProfileActivationContext createMockContext() {
|
private ProfileActivationContext createMockContext() {
|
||||||
DefaultProfileActivationContext context = new DefaultProfileActivationContext();
|
DefaultProfileActivationContext context = new DefaultProfileActivationContext(
|
||||||
|
new DefaultPathTranslator(),
|
||||||
|
new AbstractProfileActivatorTest.FakeRootLocator(),
|
||||||
|
new DefaultInterpolator());
|
||||||
context.setSystemProperties(Map.of(
|
context.setSystemProperties(Map.of(
|
||||||
"os.name", "windows",
|
"os.name", "windows",
|
||||||
"os.arch", "amd64",
|
"os.arch", "amd64",
|
||||||
|
|
|
@ -33,8 +33,6 @@ import org.apache.maven.internal.impl.DefaultVersionParser;
|
||||||
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
||||||
import org.apache.maven.internal.impl.model.DefaultPathTranslator;
|
import org.apache.maven.internal.impl.model.DefaultPathTranslator;
|
||||||
import org.apache.maven.internal.impl.model.DefaultProfileActivationContext;
|
import org.apache.maven.internal.impl.model.DefaultProfileActivationContext;
|
||||||
import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
|
|
||||||
import org.apache.maven.internal.impl.model.rootlocator.DefaultRootLocator;
|
|
||||||
import org.eclipse.aether.util.version.GenericVersionScheme;
|
import org.eclipse.aether.util.version.GenericVersionScheme;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
@ -55,10 +53,7 @@ public class ConditionProfileActivatorTest extends AbstractProfileActivatorTest<
|
||||||
@Override
|
@Override
|
||||||
void setUp() throws Exception {
|
void setUp() throws Exception {
|
||||||
activator = new ConditionProfileActivator(
|
activator = new ConditionProfileActivator(
|
||||||
new DefaultVersionParser(new DefaultModelVersionParser(new GenericVersionScheme())),
|
new DefaultVersionParser(new DefaultModelVersionParser(new GenericVersionScheme())));
|
||||||
new ProfileActivationFilePathInterpolator(
|
|
||||||
new DefaultPathTranslator(), new FakeRootLocator(), new DefaultInterpolator()),
|
|
||||||
new DefaultRootLocator());
|
|
||||||
|
|
||||||
Path file = tempDir.resolve("file.txt");
|
Path file = tempDir.resolve("file.txt");
|
||||||
Files.createFile(file);
|
Files.createFile(file);
|
||||||
|
@ -484,7 +479,9 @@ public class ConditionProfileActivatorTest extends AbstractProfileActivatorTest<
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ProfileActivationContext newFileContext(Path path) {
|
protected ProfileActivationContext newFileContext(Path path) {
|
||||||
DefaultProfileActivationContext context = new DefaultProfileActivationContext();
|
DefaultProfileActivationContext context = new DefaultProfileActivationContext(
|
||||||
|
new DefaultPathTranslator(), new FakeRootLocator(), new DefaultInterpolator());
|
||||||
|
|
||||||
context.setModel(Model.newBuilder().pomFile(path.resolve("pom.xml")).build());
|
context.setModel(Model.newBuilder().pomFile(path.resolve("pom.xml")).build());
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,7 @@ import org.apache.maven.api.model.ActivationFile;
|
||||||
import org.apache.maven.api.model.Model;
|
import org.apache.maven.api.model.Model;
|
||||||
import org.apache.maven.api.model.Profile;
|
import org.apache.maven.api.model.Profile;
|
||||||
import org.apache.maven.api.services.model.RootLocator;
|
import org.apache.maven.api.services.model.RootLocator;
|
||||||
import org.apache.maven.internal.impl.model.DefaultInterpolator;
|
|
||||||
import org.apache.maven.internal.impl.model.DefaultPathTranslator;
|
|
||||||
import org.apache.maven.internal.impl.model.DefaultProfileActivationContext;
|
import org.apache.maven.internal.impl.model.DefaultProfileActivationContext;
|
||||||
import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
@ -47,13 +44,12 @@ class FileProfileActivatorTest extends AbstractProfileActivatorTest<FileProfileA
|
||||||
@TempDir
|
@TempDir
|
||||||
Path tempDir;
|
Path tempDir;
|
||||||
|
|
||||||
private final DefaultProfileActivationContext context = new DefaultProfileActivationContext();
|
private final DefaultProfileActivationContext context = newContext();
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@Override
|
@Override
|
||||||
void setUp() throws Exception {
|
void setUp() throws Exception {
|
||||||
activator = new FileProfileActivator(new ProfileActivationFilePathInterpolator(
|
activator = new FileProfileActivator();
|
||||||
new DefaultPathTranslator(), new FakeRootLocator(), new DefaultInterpolator()));
|
|
||||||
|
|
||||||
context.setModel(Model.newBuilder().pomFile(tempDir.resolve("pom.xml")).build());
|
context.setModel(Model.newBuilder().pomFile(tempDir.resolve("pom.xml")).build());
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ import org.apache.maven.internal.impl.model.DefaultPathTranslator;
|
||||||
import org.apache.maven.internal.impl.model.DefaultPluginManagementInjector;
|
import org.apache.maven.internal.impl.model.DefaultPluginManagementInjector;
|
||||||
import org.apache.maven.internal.impl.model.DefaultProfileInjector;
|
import org.apache.maven.internal.impl.model.DefaultProfileInjector;
|
||||||
import org.apache.maven.internal.impl.model.DefaultProfileSelector;
|
import org.apache.maven.internal.impl.model.DefaultProfileSelector;
|
||||||
import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
|
|
||||||
import org.apache.maven.internal.impl.model.rootlocator.DefaultRootLocator;
|
import org.apache.maven.internal.impl.model.rootlocator.DefaultRootLocator;
|
||||||
import org.apache.maven.internal.impl.resolver.DefaultArtifactDescriptorReader;
|
import org.apache.maven.internal.impl.resolver.DefaultArtifactDescriptorReader;
|
||||||
import org.apache.maven.internal.impl.resolver.DefaultModelResolver;
|
import org.apache.maven.internal.impl.resolver.DefaultModelResolver;
|
||||||
|
@ -1058,13 +1057,13 @@ public class RepositorySystemSupplier implements Supplier<RepositorySystem> {
|
||||||
new DefaultDependencyManagementInjector(),
|
new DefaultDependencyManagementInjector(),
|
||||||
new DefaultDependencyManagementImporter(),
|
new DefaultDependencyManagementImporter(),
|
||||||
new DefaultPluginConfigurationExpander(),
|
new DefaultPluginConfigurationExpander(),
|
||||||
new ProfileActivationFilePathInterpolator(
|
|
||||||
new DefaultPathTranslator(), new DefaultRootLocator(), new DefaultInterpolator()),
|
|
||||||
new DefaultModelVersionParser(getVersionScheme()),
|
new DefaultModelVersionParser(getVersionScheme()),
|
||||||
List.of(),
|
List.of(),
|
||||||
new DefaultModelCacheFactory(),
|
new DefaultModelCacheFactory(),
|
||||||
new DefaultModelResolver(),
|
new DefaultModelResolver(),
|
||||||
new DefaultInterpolator());
|
new DefaultInterpolator(),
|
||||||
|
new DefaultPathTranslator(),
|
||||||
|
new DefaultRootLocator());
|
||||||
}
|
}
|
||||||
|
|
||||||
private RepositorySystem repositorySystem;
|
private RepositorySystem repositorySystem;
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!---
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.1.0">
|
||||||
|
<groupId>org.apache.maven.tests</groupId>
|
||||||
|
<artifactId>props-and-profiles-grand-parent</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>jdk9+</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.release>17</maven.compiler.release>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!---
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.1.0">
|
||||||
|
<parent>
|
||||||
|
<relativePath>props-and-profiles-grand-parent.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<artifactId>props-and-profiles</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.release>21</maven.compiler.release>
|
||||||
|
</properties>
|
||||||
|
</project>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!---
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.1.0">
|
||||||
|
<parent>
|
||||||
|
<relativePath>props-and-profiles-parent.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<artifactId>props-and-profiles</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</project>
|
Loading…
Reference in New Issue