diff --git a/maven-model-builder/pom.xml b/maven-model-builder/pom.xml
index 97347635c981..314f41d31a62 100644
--- a/maven-model-builder/pom.xml
+++ b/maven-model-builder/pom.xml
@@ -87,6 +87,11 @@ under the License.
xmlunit-matchers
test
+
+ org.mockito
+ mockito-core
+ test
+
org.powermock
powermock-reflect
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java
index 2d713b563d77..e05cd5f54d34 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java
@@ -22,17 +22,27 @@
import javax.inject.Named;
import javax.inject.Singleton;
+import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.function.UnaryOperator;
+import java.util.stream.Collectors;
import org.apache.maven.model.Activation;
+import org.apache.maven.model.Model;
import org.apache.maven.model.Profile;
+import org.apache.maven.model.building.DefaultModelBuildingRequest;
+import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelProblem.Severity;
import org.apache.maven.model.building.ModelProblem.Version;
import org.apache.maven.model.building.ModelProblemCollector;
import org.apache.maven.model.building.ModelProblemCollectorRequest;
+import org.apache.maven.model.interpolation.ModelInterpolator;
import org.apache.maven.model.profile.activation.ProfileActivator;
/**
@@ -44,9 +54,24 @@
@Singleton
public class DefaultProfileSelector implements ProfileSelector {
+ private static Properties asProperties(Map m) {
+ return m.entrySet().stream()
+ .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue(), (l, r) -> r, Properties::new));
+ }
+
@Inject
private List activators = new ArrayList<>();
+ @Inject
+ private ModelInterpolator interpolator = new ModelInterpolator() {
+
+ @Override
+ public Model interpolateModel(
+ Model model, File projectDir, ModelBuildingRequest request, ModelProblemCollector problems) {
+ return model;
+ }
+ };
+
public DefaultProfileSelector addProfileActivator(ProfileActivator profileActivator) {
if (profileActivator != null) {
activators.add(profileActivator);
@@ -54,9 +79,18 @@ public DefaultProfileSelector addProfileActivator(ProfileActivator profileActiva
return this;
}
+ public void setInterpolator(ModelInterpolator interpolator) {
+ this.interpolator = interpolator;
+ }
+
@Override
public List getActiveProfiles(
Collection profiles, ProfileActivationContext context, ModelProblemCollector problems) {
+
+ if (profiles.stream().map(Profile::getId).distinct().count() < profiles.size()) {
+ // invalid profile specification
+ return Collections.emptyList();
+ }
Collection activatedIds = new HashSet<>(context.getActiveProfileIds());
Collection deactivatedIds = new HashSet<>(context.getInactiveProfileIds());
@@ -64,9 +98,12 @@ public List getActiveProfiles(
List activePomProfilesByDefault = new ArrayList<>();
boolean activatedPomProfileNotByDefault = false;
+ Map activation = earlyInterpolateProfileActivations(profiles, context);
+
for (Profile profile : profiles) {
if (!deactivatedIds.contains(profile.getId())) {
- if (activatedIds.contains(profile.getId()) || isActive(profile, context, problems)) {
+ if (activatedIds.contains(profile.getId())
+ || isActive(activation.get(profile.getId()), context, problems)) {
activeProfiles.add(profile);
if (Profile.SOURCE_POM.equals(profile.getSource())) {
@@ -89,6 +126,35 @@ public List getActiveProfiles(
return activeProfiles;
}
+ private Map earlyInterpolateProfileActivations(
+ Collection original, ProfileActivationContext context) {
+
+ Model model = new Model();
+
+ UnaryOperator activatableProfile = p -> {
+ Profile result = new Profile();
+ result.setId(p.getId());
+ result.setActivation(p.getActivation());
+ return result;
+ };
+ model.setProfiles(original.stream().map(activatableProfile).collect(Collectors.toList()));
+
+ ModelBuildingRequest mbr = new DefaultModelBuildingRequest()
+ .setActiveProfileIds(context.getActiveProfileIds())
+ .setInactiveProfileIds(context.getInactiveProfileIds())
+ .setRawModel(model)
+ .setSystemProperties(asProperties(context.getSystemProperties()))
+ .setUserProperties(asProperties(context.getUserProperties()))
+ .setTwoPhaseBuilding(true)
+ .setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
+
+ interpolator
+ .interpolateModel(model, context.getProjectDirectory(), mbr, problem -> {})
+ .getProfiles();
+
+ return model.getProfiles().stream().collect(Collectors.toMap(Profile::getId, UnaryOperator.identity()));
+ }
+
private boolean isActive(Profile profile, ProfileActivationContext context, ModelProblemCollector problems) {
boolean isActive = false;
for (ProfileActivator activator : activators) {
diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/DefaultProfileSelectorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/DefaultProfileSelectorTest.java
new file mode 100644
index 000000000000..8f9de0434c33
--- /dev/null
+++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/DefaultProfileSelectorTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.model.profile;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.maven.model.Activation;
+import org.apache.maven.model.ActivationProperty;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Profile;
+import org.apache.maven.model.interpolation.ModelInterpolator;
+import org.apache.maven.model.profile.activation.PropertyProfileActivator;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+public class DefaultProfileSelectorTest {
+ private DefaultProfileSelector selector;
+ private ModelInterpolator interpolator;
+
+ @Before
+ public void setup() {
+ interpolator = Mockito.mock(ModelInterpolator.class);
+
+ selector = new DefaultProfileSelector();
+ selector.addProfileActivator(new PropertyProfileActivator());
+ selector.setInterpolator(interpolator);
+ }
+
+ @Test
+ public void testProfileActivationInterpolation() {
+ Map userProperties = Collections.singletonMap("foo", "bar");
+
+ Mockito.when(interpolator.interpolateModel(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()))
+ .thenAnswer(invocation -> {
+ Model m = invocation.getArgument(0);
+
+ m.getProfiles().forEach(p -> {
+ Optional.ofNullable(p.getActivation())
+ .map(Activation::getProperty)
+ .ifPresent(ap -> {
+ String name = ap.getName();
+ if (name != null) {
+ ap.setValue(userProperties.get(name));
+ }
+ });
+ });
+ return m;
+ });
+
+ ActivationProperty ap = new ActivationProperty();
+ ap.setName("foo");
+
+ Activation act = new Activation();
+ act.setProperty(ap);
+ Profile profile = new Profile();
+ profile.setId("foo");
+ profile.setActivation(act);
+
+ DefaultProfileActivationContext context = new DefaultProfileActivationContext();
+ context.setUserProperties(userProperties);
+
+ List activeProfiles = selector.getActiveProfiles(Collections.singleton(profile), context, p -> {});
+
+ assertEquals(1, activeProfiles.size());
+ assertSame(profile, activeProfiles.get(0));
+ }
+}