Skip to content

Commit 6f3dfe9

Browse files
committed
[MNG-5235] interpolate available properties during default profile selection
1 parent 33788fd commit 6f3dfe9

File tree

3 files changed

+187
-4
lines changed

3 files changed

+187
-4
lines changed

maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ protected ModelReader newModelReader() {
237237
}
238238

239239
protected ProfileSelector newProfileSelector() {
240-
return new DefaultProfileSelector(Arrays.asList(newProfileActivators()));
240+
return new DefaultProfileSelector(Arrays.asList(newProfileActivators()), newModelInterpolator());
241241
}
242242

243243
protected ProfileActivator[] newProfileActivators() {

maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java

Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,28 @@
2222
import javax.inject.Named;
2323
import javax.inject.Singleton;
2424

25+
import java.io.File;
26+
import java.nio.file.Path;
2527
import java.util.ArrayList;
2628
import java.util.Collection;
29+
import java.util.Collections;
2730
import java.util.HashSet;
2831
import java.util.List;
32+
import java.util.Map;
33+
import java.util.Optional;
34+
import java.util.Properties;
2935
import java.util.stream.Collectors;
3036

3137
import org.apache.maven.model.Activation;
38+
import org.apache.maven.model.Model;
3239
import org.apache.maven.model.Profile;
40+
import org.apache.maven.model.building.DefaultModelBuildingRequest;
41+
import org.apache.maven.model.building.ModelBuildingRequest;
3342
import org.apache.maven.model.building.ModelProblem.Severity;
3443
import org.apache.maven.model.building.ModelProblem.Version;
3544
import org.apache.maven.model.building.ModelProblemCollector;
3645
import org.apache.maven.model.building.ModelProblemCollectorRequest;
46+
import org.apache.maven.model.interpolation.ModelInterpolator;
3747
import org.apache.maven.model.profile.activation.ProfileActivator;
3848

3949
/**
@@ -44,15 +54,53 @@
4454
@Singleton
4555
public class DefaultProfileSelector implements ProfileSelector {
4656

57+
private static Properties asProperties(Map<String, String> m) {
58+
return m.entrySet().stream()
59+
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue(), (l, r) -> r, Properties::new));
60+
}
61+
4762
private final List<ProfileActivator> activators;
63+
private ModelInterpolator interpolator;
4864

4965
public DefaultProfileSelector() {
50-
this.activators = new ArrayList<>();
66+
this(new ArrayList<>(), new ModelInterpolator() {
67+
68+
@Override
69+
public Model interpolateModel(
70+
Model model, File projectDir, ModelBuildingRequest request, ModelProblemCollector problems) {
71+
return model;
72+
}
73+
74+
@Override
75+
public org.apache.maven.api.model.Model interpolateModel(
76+
org.apache.maven.api.model.Model model,
77+
File projectDir,
78+
ModelBuildingRequest request,
79+
ModelProblemCollector problems) {
80+
return model;
81+
}
82+
83+
@Override
84+
public Model interpolateModel(
85+
Model model, Path projectDir, ModelBuildingRequest request, ModelProblemCollector problems) {
86+
return model;
87+
}
88+
89+
@Override
90+
public org.apache.maven.api.model.Model interpolateModel(
91+
org.apache.maven.api.model.Model model,
92+
Path projectDir,
93+
ModelBuildingRequest request,
94+
ModelProblemCollector problems) {
95+
return model;
96+
}
97+
});
5198
}
5299

53100
@Inject
54-
public DefaultProfileSelector(List<ProfileActivator> activators) {
101+
public DefaultProfileSelector(List<ProfileActivator> activators, ModelInterpolator interpolator) {
55102
this.activators = new ArrayList<>(activators);
103+
this.interpolator = interpolator;
56104
}
57105

58106
public DefaultProfileSelector addProfileActivator(ProfileActivator profileActivator) {
@@ -62,6 +110,10 @@ public DefaultProfileSelector addProfileActivator(ProfileActivator profileActiva
62110
return this;
63111
}
64112

113+
public void setInterpolator(ModelInterpolator interpolator) {
114+
this.interpolator = interpolator;
115+
}
116+
65117
@Override
66118
public List<org.apache.maven.api.model.Profile> getActiveProfilesV4(
67119
Collection<org.apache.maven.api.model.Profile> profiles,
@@ -76,16 +128,24 @@ public List<org.apache.maven.api.model.Profile> getActiveProfilesV4(
76128
@Override
77129
public List<Profile> getActiveProfiles(
78130
Collection<Profile> profiles, ProfileActivationContext context, ModelProblemCollector problems) {
131+
132+
if (profiles.stream().map(Profile::getId).distinct().count() < profiles.size()) {
133+
// invalid profile specification
134+
return Collections.emptyList();
135+
}
79136
Collection<String> activatedIds = new HashSet<>(context.getActiveProfileIds());
80137
Collection<String> deactivatedIds = new HashSet<>(context.getInactiveProfileIds());
81138

82139
List<Profile> activeProfiles = new ArrayList<>(profiles.size());
83140
List<Profile> activePomProfilesByDefault = new ArrayList<>();
84141
boolean activatedPomProfileNotByDefault = false;
85142

143+
Map<String, Profile> activation = earlyInterpolateProfileActivations(profiles, context);
144+
86145
for (Profile profile : profiles) {
87146
if (!deactivatedIds.contains(profile.getId())) {
88-
if (activatedIds.contains(profile.getId()) || isActive(profile, context, problems)) {
147+
if (activatedIds.contains(profile.getId())
148+
|| isActive(activation.get(profile.getId()), context, problems)) {
89149
activeProfiles.add(profile);
90150

91151
if (Profile.SOURCE_POM.equals(profile.getSource())) {
@@ -108,6 +168,40 @@ public List<Profile> getActiveProfiles(
108168
return activeProfiles;
109169
}
110170

171+
private Map<String, Profile> earlyInterpolateProfileActivations(
172+
Collection<Profile> original, ProfileActivationContext context) {
173+
174+
org.apache.maven.api.model.Model model = org.apache.maven.api.model.Model.newBuilder()
175+
.profiles(original.stream()
176+
.map(p -> org.apache.maven.api.model.Profile.newBuilder()
177+
.id(p.getId())
178+
.activation(Optional.ofNullable(p.getActivation())
179+
.map(Activation::getDelegate)
180+
.orElse(null))
181+
.build())
182+
.collect(Collectors.toList()))
183+
.build();
184+
185+
ModelBuildingRequest mbr = new DefaultModelBuildingRequest()
186+
.setActiveProfileIds(context.getActiveProfileIds())
187+
.setInactiveProfileIds(context.getInactiveProfileIds())
188+
.setSystemProperties(asProperties(context.getSystemProperties()))
189+
.setUserProperties(asProperties(context.getUserProperties()))
190+
.setTwoPhaseBuilding(true)
191+
.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
192+
193+
model = interpolator.interpolateModel(
194+
model,
195+
Optional.ofNullable(context.getProjectDirectory())
196+
.map(File::toPath)
197+
.orElse(null),
198+
mbr,
199+
problem -> {});
200+
201+
return model.getProfiles().stream()
202+
.collect(Collectors.toMap(org.apache.maven.api.model.Profile::getId, Profile::new));
203+
}
204+
111205
private boolean isActive(Profile profile, ProfileActivationContext context, ModelProblemCollector problems) {
112206
boolean isActive = false;
113207
for (ProfileActivator activator : activators) {
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.model.profile;
20+
21+
import java.nio.file.Path;
22+
import java.util.Collections;
23+
import java.util.Map;
24+
import java.util.Optional;
25+
import java.util.stream.Collectors;
26+
27+
import org.apache.maven.api.model.Activation;
28+
import org.apache.maven.api.model.ActivationProperty;
29+
import org.apache.maven.api.model.Model;
30+
import org.apache.maven.api.model.Profile;
31+
import org.apache.maven.model.interpolation.ModelInterpolator;
32+
import org.apache.maven.model.profile.activation.PropertyProfileActivator;
33+
import org.junit.jupiter.api.BeforeEach;
34+
import org.junit.jupiter.api.Test;
35+
import org.mockito.Mockito;
36+
37+
import static org.assertj.core.api.Assertions.assertThat;
38+
39+
public class DefaultProfileSelectorTest {
40+
private DefaultProfileSelector selector;
41+
private ModelInterpolator interpolator;
42+
43+
@BeforeEach
44+
public void setup() {
45+
interpolator = Mockito.mock(ModelInterpolator.class);
46+
selector = new DefaultProfileSelector(Collections.singletonList(new PropertyProfileActivator()), interpolator);
47+
}
48+
49+
@Test
50+
public void testProfileActivationInterpolation() {
51+
Map<String, String> userProperties = Collections.singletonMap("foo", "bar");
52+
53+
Mockito.when(interpolator.interpolateModel(
54+
Mockito.any(org.apache.maven.api.model.Model.class),
55+
Mockito.<Path>any(),
56+
Mockito.any(),
57+
Mockito.any()))
58+
.thenAnswer(invocation -> {
59+
Model m = invocation.getArgument(0);
60+
61+
return Optional.ofNullable(m.getProfiles())
62+
.map(pz -> pz.stream()
63+
.map(p -> Optional.ofNullable(p.getActivation())
64+
.flatMap(a -> Optional.ofNullable(a.getProperty())
65+
.flatMap(ap -> Optional.ofNullable(ap.getName())
66+
.map(userProperties::get)
67+
.map(v -> ap.withValue(v)))
68+
.map(a::withProperty))
69+
.map(p::withActivation)
70+
.orElse(p))
71+
.collect(Collectors.toList()))
72+
.map(m::withProfiles)
73+
.orElse(m);
74+
});
75+
76+
org.apache.maven.model.Profile profile = new org.apache.maven.model.Profile(Profile.newBuilder()
77+
.id("foo")
78+
.activation(Activation.newBuilder()
79+
.property(ActivationProperty.newBuilder().name("foo").build())
80+
.build())
81+
.build());
82+
83+
assertThat(selector.getActiveProfiles(
84+
Collections.singleton(profile),
85+
new DefaultProfileActivationContext().setUserProperties(userProperties),
86+
p -> {}))
87+
.containsExactly(profile);
88+
}
89+
}

0 commit comments

Comments
 (0)