Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import org.apache.maven.model.building.ModelProblem.Version;
import org.apache.maven.model.composition.DependencyManagementImporter;
import org.apache.maven.model.inheritance.InheritanceAssembler;
import org.apache.maven.model.interpolation.AbstractStringBasedModelInterpolator;
import org.apache.maven.model.interpolation.ModelInterpolator;
import org.apache.maven.model.io.ModelParseException;
import org.apache.maven.model.management.DependencyManagementInjector;
Expand Down Expand Up @@ -288,7 +289,6 @@ protected ModelBuildingResult build(ModelBuildingRequest request, Collection<Str
Collection<String> parentIds = new LinkedHashSet<>();
List<ModelData> lineage = new ArrayList<>();

// Models built to resolve a dependency (a dependency POM, one of its parents, or an
// Models resolved for dependency, parent or BOM POMs evaluate only platform-derived
// activation (JDK, OS, activeByDefault).
boolean externalModel = isExternalModelBuildingRequest(request);
Expand Down Expand Up @@ -509,10 +509,13 @@ void performFor(String value, String locationKey, Consumer<String> mutator) {
* rather than a POM belonging to the project being built. Such requests use
* {@link ModelBuildingRequest#VALIDATION_LEVEL_MINIMAL}, see for instance
* {@code DefaultArtifactDescriptorReader#loadPom}; a project build uses
* {@link ModelBuildingRequest#VALIDATION_LEVEL_MAVEN_2_0} or higher.
* {@link ModelBuildingRequest#VALIDATION_LEVEL_MAVEN_2_0} or higher. A request that sets
* {@value AbstractStringBasedModelInterpolator#FULL_EXTERNAL_INTERPOLATION_PROPERTY} is never external, so
* that tools building their own projects at a low validation level can opt out.
*/
private static boolean isExternalModelBuildingRequest(ModelBuildingRequest request) {
return request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
return request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0
&& !AbstractStringBasedModelInterpolator.isFullExternalModelBuild(request);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,20 @@ public Object getValue(String expression) {

private static boolean restrictExternalModelInterpolation(ModelBuildingRequest config) {
return config.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0
&& !Boolean.parseBoolean(config.getSystemProperties().getProperty(FULL_EXTERNAL_INTERPOLATION_PROPERTY))
&& !Boolean.parseBoolean(config.getUserProperties().getProperty(FULL_EXTERNAL_INTERPOLATION_PROPERTY));
&& !isFullExternalModelBuild(config);
}

/**
* Tells whether {@value #FULL_EXTERNAL_INTERPOLATION_PROPERTY} is set, as a system or a user property,
* which exempts models built below {@link ModelBuildingRequest#VALIDATION_LEVEL_MAVEN_2_0} from the
* restrictions that apply to models resolved from a repository.
*
* @param config the model building request
* @return {@code true} if the property is set to {@code true}
*/
public static boolean isFullExternalModelBuild(ModelBuildingRequest config) {
return Boolean.parseBoolean(config.getSystemProperties().getProperty(FULL_EXTERNAL_INTERPOLATION_PROPERTY))
|| Boolean.parseBoolean(config.getUserProperties().getProperty(FULL_EXTERNAL_INTERPOLATION_PROPERTY));
}

private static ValueSource restrictToSafeExpressions(ValueSource source) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Properties;

import org.apache.maven.model.Model;
import org.apache.maven.model.interpolation.AbstractStringBasedModelInterpolator;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -237,6 +238,33 @@ void testExternalModelUserPropertyActivationIsSuppressed() throws Exception {
"user-property profile must NOT fire in external model build (consumer -D suppressed)");
}

@Test
void testFullExternalInterpolationEvaluatesAllActivators() throws Exception {
// maven.model.dependencyInterpolation.full opts a MINIMAL build out of the external
// restrictions, for tools that build their own projects at that validation level (#13347).
Properties up = userPropertiesWithTestValues();
up.setProperty(AbstractStringBasedModelInterpolator.FULL_EXTERNAL_INTERPOLATION_PROPERTY, "true");
Model model = build(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL, systemPropertiesWithTestValues(), up);

assertEquals("activated", model.getProperties().get("profile.file"), "file profile must fire");
assertEquals(
"activated", model.getProperties().get("profile.user.property"), "user-property profile must fire");
assertEquals(
"activated", model.getProperties().get("profile.sys.property"), "system-property profile must fire");
assertNull(
model.getProperties().get("profile.pom.property"), "POM-declared-property profile must still NOT fire");
}

@Test
void testFullExternalInterpolationAsSystemPropertyEvaluatesUserPropertyProfile() throws Exception {
Properties sp = systemPropertiesWithTestValues();
sp.setProperty(AbstractStringBasedModelInterpolator.FULL_EXTERNAL_INTERPOLATION_PROPERTY, "true");
Model model = build(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL, sp, userPropertiesWithTestValues());

assertEquals(
"activated", model.getProperties().get("profile.user.property"), "user-property profile must fire");
}

@Test
void testExternalModelSystemPropertyActivationIsPreserved() throws Exception {
// System properties are platform facts and must drive activation even in external builds.
Expand Down
Loading