diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 065f2c8c7d23..a9b9399209bd 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -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; @@ -288,7 +289,6 @@ protected ModelBuildingResult build(ModelBuildingRequest request, Collection parentIds = new LinkedHashSet<>(); List 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); @@ -509,10 +509,13 @@ void performFor(String value, String locationKey, Consumer 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); } /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java index 41399878eb8f..45037908716c 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java @@ -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) { diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/ResolvedDependencyProfileActivationTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/ResolvedDependencyProfileActivationTest.java index ab6d38ca2006..faa53153ed86 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/ResolvedDependencyProfileActivationTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/ResolvedDependencyProfileActivationTest.java @@ -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; @@ -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.