[MNG-8123] Fix Lifecycle in v3 (#1524)

This commit is contained in:
Guillaume Nodet 2024-05-22 15:45:13 +02:00 committed by GitHub
parent df7280182e
commit 2942aadcc3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 132 additions and 68 deletions

View File

@ -18,16 +18,14 @@
*/
package org.apache.maven.api.services;
import java.util.List;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.apache.maven.api.Lifecycle;
public interface LifecycleRegistry extends ExtensibleEnumRegistry<Lifecycle>, Iterable<Lifecycle> {
default Stream<Lifecycle> stream() {
return StreamSupport.stream(spliterator(), false);
}
List<String> computePhases(Lifecycle lifecycle);
}

View File

@ -311,10 +311,6 @@ public Optional<Type> lookup(String id) {
@Provides
static LifecycleRegistry newLifecycleRegistry() {
return new LifecycleRegistry() {
@Override
public List<String> computePhases(Lifecycle lifecycle) {
return List.of();
}
@Override
public Iterator<Lifecycle> iterator() {

View File

@ -52,10 +52,6 @@ public class EmptyLifecycleBindingsInjector extends DefaultLifecycleBindingsInje
private static PackagingRegistry packagingRegistry;
private static final LifecycleRegistry emptyLifecycleRegistry = new LifecycleRegistry() {
@Override
public List<String> computePhases(Lifecycle lifecycle) {
return List.of();
}
@Override
public Iterator<Lifecycle> iterator() {
@ -136,11 +132,6 @@ public Optional<Lifecycle> lookup(String id) {
return getDelegate().lookup(id);
}
@Override
public List<String> computePhases(Lifecycle lifecycle) {
return getDelegate().computePhases(lifecycle);
}
@Override
public Iterator<Lifecycle> iterator() {
return getDelegate().iterator();

View File

@ -20,6 +20,7 @@
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import java.util.ArrayList;
@ -27,15 +28,24 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.maven.api.Lifecycle;
import org.apache.maven.api.model.Plugin;
import org.apache.maven.api.services.LifecycleRegistry;
import org.apache.maven.api.services.LookupException;
import org.apache.maven.api.spi.ExtensibleEnumProvider;
import org.apache.maven.api.spi.LifecycleProvider;
import org.apache.maven.lifecycle.mapping.LifecyclePhase;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import static java.util.Arrays.asList;
import static java.util.Collections.singleton;
@ -47,23 +57,19 @@
*/
@Named
@Singleton
public class DefaultLifecycleRegistry
extends ExtensibleEnumRegistries.DefaultExtensibleEnumRegistry<Lifecycle, LifecycleProvider>
implements LifecycleRegistry {
public class DefaultLifecycleRegistry implements LifecycleRegistry {
private final List<LifecycleProvider> providers;
public DefaultLifecycleRegistry() {
super(Collections.emptyList());
this(Collections.emptyList());
}
@Inject
public DefaultLifecycleRegistry(
List<LifecycleProvider> providers, Map<String, org.apache.maven.lifecycle.Lifecycle> lifecycles) {
super(
concat(providers, new LifecycleWrapperProvider(lifecycles)),
new CleanLifecycle(),
new DefaultLifecycle(),
new SiteLifecycle(),
new WrapperLifecycle());
public DefaultLifecycleRegistry(List<LifecycleProvider> providers) {
List<LifecycleProvider> p = new ArrayList<>(providers);
p.add(() -> List.of(new CleanLifecycle(), new DefaultLifecycle(), new SiteLifecycle(), new WrapperLifecycle()));
this.providers = p;
// validate lifecycle
for (Lifecycle lifecycle : this) {
Set<String> set = new HashSet<>();
@ -78,37 +84,44 @@ public DefaultLifecycleRegistry(
@Override
public Iterator<Lifecycle> iterator() {
return values.values().iterator();
return stream().toList().iterator();
}
@Override
public Stream<Lifecycle> stream() {
return values.values().stream();
}
static <T> List<T> concat(List<T> l, T t) {
List<T> nl = new ArrayList<>(l.size() + 1);
nl.addAll(l);
nl.add(t);
return nl;
return providers.stream().map(ExtensibleEnumProvider::provides).flatMap(Collection::stream);
}
@Override
public List<String> computePhases(Lifecycle lifecycle) {
return lifecycle.phases().stream().map(Lifecycle.Phase::name).toList();
public Optional<Lifecycle> lookup(String id) {
return stream().filter(lf -> Objects.equals(id, lf.id())).findAny();
}
static class LifecycleWrapperProvider implements LifecycleProvider {
private final Map<String, org.apache.maven.lifecycle.Lifecycle> lifecycles;
@Named
@Singleton
public static class LifecycleWrapperProvider implements LifecycleProvider {
private final PlexusContainer container;
@Inject
LifecycleWrapperProvider(Map<String, org.apache.maven.lifecycle.Lifecycle> lifecycles) {
this.lifecycles = lifecycles;
public LifecycleWrapperProvider(PlexusContainer container) {
this.container = container;
}
@Override
public Collection<Lifecycle> provides() {
return lifecycles.values().stream().map(this::wrap).collect(Collectors.toList());
try {
Map<String, org.apache.maven.lifecycle.Lifecycle> all =
container.lookupMap(org.apache.maven.lifecycle.Lifecycle.class);
return all.keySet().stream()
.filter(id -> !Lifecycle.CLEAN.equals(id)
&& !Lifecycle.DEFAULT.equals(id)
&& !Lifecycle.SITE.equals(id)
&& !Lifecycle.WRAPPER.equals(id))
.map(id -> wrap(all.get(id)))
.collect(Collectors.toList());
} catch (ComponentLookupException e) {
throw new LookupException(e);
}
}
private Lifecycle wrap(org.apache.maven.lifecycle.Lifecycle lifecycle) {
@ -120,13 +133,90 @@ public String id() {
@Override
public Collection<Phase> phases() {
// TODO: implement
throw new UnsupportedOperationException();
return lifecycle.getPhases().stream()
.map(name -> (Phase) new Phase() {
@Override
public String name() {
return name;
}
@Override
public List<Plugin> plugins() {
Map<String, LifecyclePhase> lfPhases = lifecycle.getDefaultLifecyclePhases();
LifecyclePhase phase = lfPhases != null ? lfPhases.get(name) : null;
if (phase != null) {
Map<String, Plugin> plugins = new LinkedHashMap<>();
DefaultPackagingRegistry.parseLifecyclePhaseDefinitions(plugins, name, phase);
return plugins.values().stream().toList();
}
return List.of();
}
})
.toList();
}
};
}
}
static class WrappedLifecycle extends org.apache.maven.lifecycle.Lifecycle {
WrappedLifecycle(Lifecycle lifecycle) {
super(lifecycle);
}
}
abstract static class BaseLifecycleProvider implements Provider<org.apache.maven.lifecycle.Lifecycle> {
@Inject
private PlexusContainer lookup;
private final String name;
BaseLifecycleProvider(String name) {
this.name = name;
}
@Override
public org.apache.maven.lifecycle.Lifecycle get() {
try {
LifecycleRegistry registry = lookup.lookup(LifecycleRegistry.class);
return new WrappedLifecycle(registry.require(name));
} catch (ComponentLookupException e) {
throw new LookupException(e);
}
}
}
@Singleton
@Named(Lifecycle.CLEAN)
static class CleanLifecycleProvider extends BaseLifecycleProvider {
CleanLifecycleProvider() {
super(Lifecycle.CLEAN);
}
}
@Singleton
@Named(Lifecycle.DEFAULT)
static class DefaultLifecycleProvider extends BaseLifecycleProvider {
DefaultLifecycleProvider() {
super(Lifecycle.DEFAULT);
}
}
@Singleton
@Named(Lifecycle.SITE)
static class SiteLifecycleProvider extends BaseLifecycleProvider {
SiteLifecycleProvider() {
super(Lifecycle.SITE);
}
}
@Singleton
@Named(Lifecycle.WRAPPER)
static class WrapperLifecycleProvider extends BaseLifecycleProvider {
WrapperLifecycleProvider() {
super(Lifecycle.WRAPPER);
}
}
static class CleanLifecycle implements Lifecycle {
private static final String MAVEN_CLEAN_PLUGIN_VERSION = "3.2.0";

View File

@ -104,7 +104,7 @@ private Map<String, PluginContainer> getPlugins(LifecycleMapping lifecycleMappin
return lfs;
}
private void parseLifecyclePhaseDefinitions(Map<String, Plugin> plugins, String phase, LifecyclePhase goals) {
static void parseLifecyclePhaseDefinitions(Map<String, Plugin> plugins, String phase, LifecyclePhase goals) {
InputSource inputSource =
new InputSource(DefaultLifecyclePluginAnalyzer.DEFAULTLIFECYCLEBINDINGS_MODELID, null);
InputLocation location = new InputLocation(-1, -1, inputSource, 0);

View File

@ -155,11 +155,9 @@ private Map<String, Lifecycle> lookupLifecycles() {
// Lifecycles cannot be cached as extensions might add custom lifecycles later in the execution.
try {
Map<String, Lifecycle> lifecycles = new HashMap<>(lookup.lookupMap(Lifecycle.class));
for (org.apache.maven.api.Lifecycle lf : registry) {
lifecycles.put(lf.id(), new Lifecycle(registry, lf));
}
return lifecycles;
return registry != null
? registry.stream().collect(Collectors.toMap(lf -> lf.id(), lf -> new Lifecycle(lf)))
: Map.of();
} catch (LookupException e) {
throw new IllegalStateException("Unable to lookup lifecycles from the plexus container", e);
}

View File

@ -35,11 +35,12 @@ public Lifecycle(String id, List<String> phases, Map<String, LifecyclePhase> def
this.defaultPhases = defaultPhases;
}
public Lifecycle(
org.apache.maven.api.services.LifecycleRegistry registry, org.apache.maven.api.Lifecycle lifecycle) {
public Lifecycle(org.apache.maven.api.Lifecycle lifecycle) {
this.lifecycle = lifecycle;
this.id = lifecycle.id();
this.phases = registry.computePhases(lifecycle);
this.phases = lifecycle.phases().stream()
.map(org.apache.maven.api.Lifecycle.Phase::name)
.toList();
this.defaultPhases = getDefaultPhases(lifecycle);
}

View File

@ -68,6 +68,6 @@ public Plugin getPlugin() {
@Override
public String toString() {
return "ExecutionPlanItem{" + ", mojoExecution=" + mojoExecution + '}' + super.toString();
return "ExecutionPlanItem{" + mojoExecution.toString() + "}@" + Integer.toHexString(hashCode());
}
}

View File

@ -96,7 +96,8 @@ void testCustomLifecycle() throws ComponentLookupException {
when(mockedPlexusContainer.lookupMap(Lifecycle.class)).thenReturn(lifeCycles);
DefaultLifecycles dl = new DefaultLifecycles(
new DefaultLifecycleRegistry(Collections.emptyList(), Collections.emptyMap()),
new DefaultLifecycleRegistry(
List.of(new DefaultLifecycleRegistry.LifecycleWrapperProvider(mockedPlexusContainer))),
new DefaultLookup(mockedPlexusContainer));
assertThat(dl.getLifeCycles().get(0).getId(), is("clean"));

View File

@ -38,8 +38,6 @@ void testFindLastInPhase() throws Exception {
MavenExecutionPlan plan = LifecycleExecutionPlanCalculatorStub.getProjectAExecutionPlan();
ExecutionPlanItem expected = plan.findLastInPhase("package");
ExecutionPlanItem beerPhase = plan.findLastInPhase("BEER"); // Beer comes straight after package in stub
assertEquals(expected, beerPhase);
assertNotNull(expected);
}

View File

@ -51,10 +51,6 @@ public class EmptyLifecycleBindingsInjector extends DefaultLifecycleBindingsInje
private static PackagingRegistry packagingRegistry;
private static final LifecycleRegistry emptyLifecycleRegistry = new LifecycleRegistry() {
@Override
public List<String> computePhases(Lifecycle lifecycle) {
return List.of();
}
@Override
public Iterator<Lifecycle> iterator() {
@ -135,11 +131,6 @@ public Optional<Lifecycle> lookup(String id) {
return getDelegate().lookup(id);
}
@Override
public List<String> computePhases(Lifecycle lifecycle) {
return getDelegate().computePhases(lifecycle);
}
@Override
public Iterator<Lifecycle> iterator() {
return getDelegate().iterator();