Skip to content

Commit

Permalink
[MNG-5235] interpolate available properties during default profile se…
Browse files Browse the repository at this point in the history
…lection
  • Loading branch information
mbenson committed Mar 19, 2024
1 parent 33788fd commit 6f3dfe9
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ protected ModelReader newModelReader() {
}

protected ProfileSelector newProfileSelector() {
return new DefaultProfileSelector(Arrays.asList(newProfileActivators()));
return new DefaultProfileSelector(Arrays.asList(newProfileActivators()), newModelInterpolator());
}

protected ProfileActivator[] newProfileActivators() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,28 @@
import javax.inject.Named;
import javax.inject.Singleton;

import java.io.File;
import java.nio.file.Path;
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.Optional;
import java.util.Properties;
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;

/**
Expand All @@ -44,15 +54,53 @@
@Singleton
public class DefaultProfileSelector implements ProfileSelector {

private static Properties asProperties(Map<String, String> m) {
return m.entrySet().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue(), (l, r) -> r, Properties::new));
}

private final List<ProfileActivator> activators;
private ModelInterpolator interpolator;

public DefaultProfileSelector() {
this.activators = new ArrayList<>();
this(new ArrayList<>(), new ModelInterpolator() {

@Override
public Model interpolateModel(
Model model, File projectDir, ModelBuildingRequest request, ModelProblemCollector problems) {
return model;
}

@Override
public org.apache.maven.api.model.Model interpolateModel(
org.apache.maven.api.model.Model model,
File projectDir,
ModelBuildingRequest request,
ModelProblemCollector problems) {
return model;
}

@Override
public Model interpolateModel(
Model model, Path projectDir, ModelBuildingRequest request, ModelProblemCollector problems) {
return model;
}

@Override
public org.apache.maven.api.model.Model interpolateModel(
org.apache.maven.api.model.Model model,
Path projectDir,
ModelBuildingRequest request,
ModelProblemCollector problems) {
return model;
}
});
}

@Inject
public DefaultProfileSelector(List<ProfileActivator> activators) {
public DefaultProfileSelector(List<ProfileActivator> activators, ModelInterpolator interpolator) {
this.activators = new ArrayList<>(activators);
this.interpolator = interpolator;
}

public DefaultProfileSelector addProfileActivator(ProfileActivator profileActivator) {
Expand All @@ -62,6 +110,10 @@ public DefaultProfileSelector addProfileActivator(ProfileActivator profileActiva
return this;
}

public void setInterpolator(ModelInterpolator interpolator) {
this.interpolator = interpolator;
}

@Override
public List<org.apache.maven.api.model.Profile> getActiveProfilesV4(
Collection<org.apache.maven.api.model.Profile> profiles,
Expand All @@ -76,16 +128,24 @@ public List<org.apache.maven.api.model.Profile> getActiveProfilesV4(
@Override
public List<Profile> getActiveProfiles(
Collection<Profile> profiles, ProfileActivationContext context, ModelProblemCollector problems) {

if (profiles.stream().map(Profile::getId).distinct().count() < profiles.size()) {
// invalid profile specification
return Collections.emptyList();
}
Collection<String> activatedIds = new HashSet<>(context.getActiveProfileIds());
Collection<String> deactivatedIds = new HashSet<>(context.getInactiveProfileIds());

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

Map<String, Profile> 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())) {
Expand All @@ -108,6 +168,40 @@ public List<Profile> getActiveProfiles(
return activeProfiles;
}

private Map<String, Profile> earlyInterpolateProfileActivations(
Collection<Profile> original, ProfileActivationContext context) {

org.apache.maven.api.model.Model model = org.apache.maven.api.model.Model.newBuilder()
.profiles(original.stream()
.map(p -> org.apache.maven.api.model.Profile.newBuilder()
.id(p.getId())
.activation(Optional.ofNullable(p.getActivation())
.map(Activation::getDelegate)
.orElse(null))
.build())
.collect(Collectors.toList()))
.build();

ModelBuildingRequest mbr = new DefaultModelBuildingRequest()
.setActiveProfileIds(context.getActiveProfileIds())
.setInactiveProfileIds(context.getInactiveProfileIds())
.setSystemProperties(asProperties(context.getSystemProperties()))
.setUserProperties(asProperties(context.getUserProperties()))
.setTwoPhaseBuilding(true)
.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);

model = interpolator.interpolateModel(
model,
Optional.ofNullable(context.getProjectDirectory())
.map(File::toPath)
.orElse(null),
mbr,
problem -> {});

return model.getProfiles().stream()
.collect(Collectors.toMap(org.apache.maven.api.model.Profile::getId, Profile::new));
}

private boolean isActive(Profile profile, ProfileActivationContext context, ModelProblemCollector problems) {
boolean isActive = false;
for (ProfileActivator activator : activators) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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.nio.file.Path;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.maven.api.model.Activation;
import org.apache.maven.api.model.ActivationProperty;
import org.apache.maven.api.model.Model;
import org.apache.maven.api.model.Profile;
import org.apache.maven.model.interpolation.ModelInterpolator;
import org.apache.maven.model.profile.activation.PropertyProfileActivator;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.assertj.core.api.Assertions.assertThat;

public class DefaultProfileSelectorTest {
private DefaultProfileSelector selector;
private ModelInterpolator interpolator;

@BeforeEach
public void setup() {
interpolator = Mockito.mock(ModelInterpolator.class);
selector = new DefaultProfileSelector(Collections.singletonList(new PropertyProfileActivator()), interpolator);
}

@Test
public void testProfileActivationInterpolation() {
Map<String, String> userProperties = Collections.singletonMap("foo", "bar");

Mockito.when(interpolator.interpolateModel(
Mockito.any(org.apache.maven.api.model.Model.class),
Mockito.<Path>any(),
Mockito.any(),
Mockito.any()))
.thenAnswer(invocation -> {
Model m = invocation.getArgument(0);

return Optional.ofNullable(m.getProfiles())
.map(pz -> pz.stream()
.map(p -> Optional.ofNullable(p.getActivation())
.flatMap(a -> Optional.ofNullable(a.getProperty())
.flatMap(ap -> Optional.ofNullable(ap.getName())
.map(userProperties::get)
.map(v -> ap.withValue(v)))
.map(a::withProperty))
.map(p::withActivation)
.orElse(p))
.collect(Collectors.toList()))
.map(m::withProfiles)
.orElse(m);
});

org.apache.maven.model.Profile profile = new org.apache.maven.model.Profile(Profile.newBuilder()
.id("foo")
.activation(Activation.newBuilder()
.property(ActivationProperty.newBuilder().name("foo").build())
.build())
.build());

assertThat(selector.getActiveProfiles(
Collections.singleton(profile),
new DefaultProfileActivationContext().setUserProperties(userProperties),
p -> {}))
.containsExactly(profile);
}
}

0 comments on commit 6f3dfe9

Please sign in to comment.