[MNG-7615] Add some methods for supporting Maven 4 api to ProfileInjector / ProfileSelector

This commit is contained in:
Guillaume Nodet 2023-09-20 16:42:17 +02:00
parent 54ca01c779
commit 53ff1690de
5 changed files with 122 additions and 10 deletions

View File

@ -167,6 +167,9 @@ under the License.
<exclude>org.apache.maven.model.profile.activation.FileProfileActivator#setProfileActivationFilePathInterpolator(org.apache.maven.model.path.ProfileActivationFilePathInterpolator):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.profile.activation.FileProfileActivator#FileProfileActivator():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.profile.DefaultProfileInjector</exclude>
<exclude>org.apache.maven.model.profile.ProfileInjector#injectProfile(org.apache.maven.api.model.Model,org.apache.maven.api.model.Profile,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.profile.ProfileInjector#injectProfiles(org.apache.maven.api.model.Model,java.util.List,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.profile.ProfileSelector#getActiveProfilesV4(java.util.Collection,org.apache.maven.model.profile.ProfileActivationContext,org.apache.maven.model.building.ModelProblemCollector):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.resolution.InvalidRepositoryException#getRepository():METHOD_RETURN_TYPE_CHANGED</exclude>
<exclude>org.apache.maven.model.resolution.InvalidRepositoryException#InvalidRepositoryException(java.lang.String,org.apache.maven.model.Repository,java.lang.Throwable):CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.resolution.InvalidRepositoryException#InvalidRepositoryException(java.lang.String,org.apache.maven.model.Repository):CONSTRUCTOR_REMOVED</exclude>

View File

@ -26,6 +26,8 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.maven.api.model.Build;
import org.apache.maven.api.model.BuildBase;
@ -34,6 +36,7 @@
import org.apache.maven.api.model.Plugin;
import org.apache.maven.api.model.PluginContainer;
import org.apache.maven.api.model.PluginExecution;
import org.apache.maven.api.model.Profile;
import org.apache.maven.api.model.ReportPlugin;
import org.apache.maven.api.model.ReportSet;
import org.apache.maven.api.model.Reporting;
@ -50,6 +53,13 @@
@SuppressWarnings({"checkstyle:methodname"})
public class DefaultProfileInjector implements ProfileInjector {
private static final Map<Model, Map<List<Profile>, Model>> CACHE = Collections.synchronizedMap(new WeakHashMap<>());
// In order for the weak hash map to work correctly, we must not hold any reference to
// the model used as the key. So we use a dummy model as a placeholder to indicate that
// we want to store the model used as they key.
private static final Model KEY = Model.newInstance();
private ProfileModelMerger merger = new ProfileModelMerger();
@Override
@ -58,19 +68,42 @@ public void injectProfile(
org.apache.maven.model.Profile profile,
ModelBuildingRequest request,
ModelProblemCollector problems) {
if (profile != null) {
Model.Builder builder = Model.newBuilder(model.getDelegate());
merger.mergeModelBase(builder, model.getDelegate(), profile.getDelegate());
model.update(
injectProfile(model.getDelegate(), profile != null ? profile.getDelegate() : null, request, problems));
}
if (profile.getBuild() != null) {
Build build = model.getBuild() != null ? model.getBuild().getDelegate() : Build.newInstance();
Build.Builder bbuilder = Build.newBuilder(build);
merger.mergeBuildBase(bbuilder, build, profile.getBuild().getDelegate());
builder.build(bbuilder.build());
@Override
public Model injectProfile(
Model model, Profile profile, ModelBuildingRequest request, ModelProblemCollector problems) {
return injectProfiles(model, Collections.singletonList(profile), request, problems);
}
@Override
public Model injectProfiles(
Model model, List<Profile> profiles, ModelBuildingRequest request, ModelProblemCollector problems) {
Model result = CACHE.computeIfAbsent(model, k -> new ConcurrentHashMap<>())
.computeIfAbsent(profiles, l -> doInjectProfiles(model, profiles));
return result == KEY ? model : result;
}
private Model doInjectProfiles(Model model, List<Profile> profiles) {
Model orgModel = model;
for (Profile profile : profiles) {
if (profile != null) {
Model.Builder builder = Model.newBuilder(model);
merger.mergeModelBase(builder, model, profile);
if (profile.getBuild() != null) {
Build build = model.getBuild() != null ? model.getBuild() : Build.newInstance();
Build.Builder bbuilder = Build.newBuilder(build);
merger.mergeBuildBase(bbuilder, build, profile.getBuild());
builder.build(bbuilder.build());
}
model = builder.build();
}
model.update(builder.build());
}
return model == orgModel ? KEY : model;
}
/**

View File

@ -26,6 +26,7 @@
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.maven.model.Activation;
import org.apache.maven.model.Profile;
@ -61,6 +62,17 @@ public DefaultProfileSelector addProfileActivator(ProfileActivator profileActiva
return this;
}
@Override
public List<org.apache.maven.api.model.Profile> getActiveProfilesV4(
Collection<org.apache.maven.api.model.Profile> profiles,
ProfileActivationContext context,
ModelProblemCollector problems) {
return getActiveProfiles(profiles.stream().map(Profile::new).collect(Collectors.toList()), context, problems)
.stream()
.map(Profile::getDelegate)
.collect(Collectors.toList());
}
@Override
public List<Profile> getActiveProfiles(
Collection<Profile> profiles, ProfileActivationContext context, ModelProblemCollector problems) {

View File

@ -18,6 +18,8 @@
*/
package org.apache.maven.model.profile;
import java.util.List;
import org.apache.maven.model.Model;
import org.apache.maven.model.Profile;
import org.apache.maven.model.building.ModelBuildingRequest;
@ -39,4 +41,45 @@ public interface ProfileInjector {
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
*/
void injectProfile(Model model, Profile profile, ModelBuildingRequest request, ModelProblemCollector problems);
/**
* Merges values from the specified profile into the given model. Implementations are expected to keep the profile
* and model completely decoupled by injecting deep copies rather than the original objects from the profile.
*
* @param model The model into which to merge the values defined by the profile, must not be <code>null</code>.
* @param profile The (read-only) profile whose values should be injected, may be <code>null</code>.
* @param request The model building request that holds further settings, must not be {@code null}.
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
*/
default org.apache.maven.api.model.Model injectProfile(
org.apache.maven.api.model.Model model,
org.apache.maven.api.model.Profile profile,
ModelBuildingRequest request,
ModelProblemCollector problems) {
Model m = new Model(model);
injectProfile(m, profile != null ? new Profile(profile) : null, request, problems);
return m.getDelegate();
}
/**
* Merges values from the specified profile into the given model. Implementations are expected to keep the profile
* and model completely decoupled by injecting deep copies rather than the original objects from the profile.
*
* @param model The model into which to merge the values defined by the profile, must not be <code>null</code>.
* @param profiles The (read-only) list of profiles whose values should be injected, must not be <code>null</code>.
* @param request The model building request that holds further settings, must not be {@code null}.
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
*/
default org.apache.maven.api.model.Model injectProfiles(
org.apache.maven.api.model.Model model,
List<org.apache.maven.api.model.Profile> profiles,
ModelBuildingRequest request,
ModelProblemCollector problems) {
for (org.apache.maven.api.model.Profile profile : profiles) {
if (profile != null) {
model = injectProfile(model, profile, request, problems);
}
}
return model;
}
}

View File

@ -20,6 +20,7 @@
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.maven.model.Profile;
import org.apache.maven.model.building.ModelProblemCollector;
@ -42,4 +43,24 @@ public interface ProfileSelector {
*/
List<Profile> getActiveProfiles(
Collection<Profile> profiles, ProfileActivationContext context, ModelProblemCollector problems);
/**
* Determines the profiles which are active in the specified activation context. Active profiles will eventually be
* injected into the model.
*
* @param profiles The profiles whose activation status should be determined, must not be {@code null}.
* @param context The environmental context used to determine the activation status of a profile, must not be
* {@code null}.
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
* @return The profiles that have been activated, never {@code null}.
*/
default List<org.apache.maven.api.model.Profile> getActiveProfilesV4(
Collection<org.apache.maven.api.model.Profile> profiles,
ProfileActivationContext context,
ModelProblemCollector problems) {
return getActiveProfiles(profiles.stream().map(Profile::new).collect(Collectors.toList()), context, problems)
.stream()
.map(Profile::getDelegate)
.collect(Collectors.toList());
}
}