mirror of https://github.com/apache/maven.git
[MNG-8084] Include lifecycle in the API
This commit is contained in:
parent
84e2d8ad3f
commit
9be08ccef8
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.api;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Immutable;
|
||||
import org.apache.maven.api.model.Plugin;
|
||||
|
||||
/**
|
||||
* Lifecycle definition
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
@Immutable
|
||||
public interface Lifecycle extends ExtensibleEnum {
|
||||
|
||||
String CLEAN = "clean";
|
||||
|
||||
String DEFAULT = "default";
|
||||
|
||||
String SITE = "site";
|
||||
|
||||
String WRAPPER = "wrapper";
|
||||
|
||||
/**
|
||||
* Name or identifier of this lifecycle.
|
||||
*
|
||||
* @return the unique identifier for this lifecycle
|
||||
*/
|
||||
@Override
|
||||
String id();
|
||||
|
||||
/**
|
||||
* Collection of phases for this lifecycle
|
||||
*/
|
||||
Collection<Phase> phases();
|
||||
|
||||
/**
|
||||
* Pre-ordered list of phases.
|
||||
* If not provided, a default order will be computed.
|
||||
*/
|
||||
default Optional<List<String>> orderedPhases() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* A phase in the lifecycle.
|
||||
*/
|
||||
interface Phase {
|
||||
String name();
|
||||
|
||||
List<Plugin> plugins();
|
||||
}
|
||||
}
|
|
@ -46,6 +46,7 @@ import static org.apache.maven.api.ExtensibleEnums.pathScope;
|
|||
@Immutable
|
||||
public interface PathScope extends ExtensibleEnum {
|
||||
|
||||
// TODO: what if I simply want all dependencies ?
|
||||
@Nonnull
|
||||
ProjectScope projectScope();
|
||||
|
||||
|
|
|
@ -41,21 +41,10 @@ import org.apache.maven.api.annotations.Nonnull;
|
|||
public @interface Execute {
|
||||
/**
|
||||
* Lifecycle phase to fork. Note that specifying a phase overrides specifying a goal.
|
||||
* For custom lifecycle phase ids use {@link #customPhase()} instead.
|
||||
* Only one of {@link #customPhase()} and {@link #phase()} must be set.
|
||||
* @return the phase
|
||||
*/
|
||||
@Nonnull
|
||||
LifecyclePhase phase() default LifecyclePhase.NONE;
|
||||
|
||||
/**
|
||||
* Custom lifecycle phase to fork. Note that specifying a phase overrides specifying a goal.
|
||||
* This element should only be used for non-standard phases. For standard phases rather use {@link #phase()}.
|
||||
* Only one of {@link #customPhase()} and {@link #phase()} must be set.
|
||||
* @return the custom phase id
|
||||
*/
|
||||
@Nonnull
|
||||
String customPhase() default "";
|
||||
String phase() default "";
|
||||
|
||||
/**
|
||||
* Goal to fork. Note that specifying a phase overrides specifying a goal. The specified <code>goal</code> must be
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* 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.api.plugin.annotations;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
|
||||
/**
|
||||
* <a href="/ref/3.0.4/maven-core/lifecycles.html">Lifecycle phases</a>.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public enum LifecyclePhase {
|
||||
VALIDATE("validate"),
|
||||
INITIALIZE("initialize"),
|
||||
GENERATE_SOURCES("generate-sources"),
|
||||
PROCESS_SOURCES("process-sources"),
|
||||
GENERATE_RESOURCES("generate-resources"),
|
||||
PROCESS_RESOURCES("process-resources"),
|
||||
COMPILE("compile"),
|
||||
PROCESS_CLASSES("process-classes"),
|
||||
GENERATE_TEST_SOURCES("generate-test-sources"),
|
||||
PROCESS_TEST_SOURCES("process-test-sources"),
|
||||
GENERATE_TEST_RESOURCES("generate-test-resources"),
|
||||
PROCESS_TEST_RESOURCES("process-test-resources"),
|
||||
TEST_COMPILE("test-compile"),
|
||||
PROCESS_TEST_CLASSES("process-test-classes"),
|
||||
TEST("test"),
|
||||
PREPARE_PACKAGE("prepare-package"),
|
||||
PACKAGE("package"),
|
||||
PRE_INTEGRATION_TEST("pre-integration-test"),
|
||||
INTEGRATION_TEST("integration-test"),
|
||||
POST_INTEGRATION_TEST("post-integration-test"),
|
||||
VERIFY("verify"),
|
||||
INSTALL("install"),
|
||||
DEPLOY("deploy"),
|
||||
|
||||
PRE_CLEAN("pre-clean"),
|
||||
CLEAN("clean"),
|
||||
POST_CLEAN("post-clean"),
|
||||
|
||||
PRE_SITE("pre-site"),
|
||||
SITE("site"),
|
||||
POST_SITE("post-site"),
|
||||
SITE_DEPLOY("site-deploy"),
|
||||
|
||||
NONE("");
|
||||
|
||||
private final String id;
|
||||
|
||||
LifecyclePhase(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String id() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@ public @interface Mojo {
|
|||
* @return the default phase
|
||||
*/
|
||||
@Nonnull
|
||||
LifecyclePhase defaultPhase() default LifecyclePhase.NONE;
|
||||
String defaultPhase() default "";
|
||||
|
||||
/**
|
||||
* does your mojo requires a project to be executed?
|
||||
|
|
|
@ -16,32 +16,18 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.lifecycle.providers;
|
||||
package org.apache.maven.api.services;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* {@code wrapper} lifecycle provider.
|
||||
*/
|
||||
@Named(WrapperLifecycleProvider.LIFECYCLE_ID)
|
||||
@Singleton
|
||||
public final class WrapperLifecycleProvider extends AbstractLifecycleProvider {
|
||||
static final String LIFECYCLE_ID = "wrapper";
|
||||
import org.apache.maven.api.Lifecycle;
|
||||
|
||||
// START SNIPPET: wrapper
|
||||
private static final String[] PHASES = {"wrapper"};
|
||||
|
||||
private static final String MAVEN_WRAPPER_PLUGIN_VERSION = "3.2.0";
|
||||
|
||||
private static final String[] BINDINGS = {
|
||||
"wrapper", "org.apache.maven.plugins:maven-wrapper-plugin:" + MAVEN_WRAPPER_PLUGIN_VERSION + ":wrapper"
|
||||
};
|
||||
// END SNIPPET: wrapper
|
||||
|
||||
@Inject
|
||||
public WrapperLifecycleProvider() {
|
||||
super(LIFECYCLE_ID, PHASES, BINDINGS);
|
||||
public interface LifecycleRegistry extends ExtensibleEnumRegistry<Lifecycle>, Iterable<Lifecycle> {
|
||||
default Stream<Lifecycle> stream() {
|
||||
return StreamSupport.stream(spliterator(), false);
|
||||
}
|
||||
|
||||
List<String> computePhases(Lifecycle lifecycle);
|
||||
}
|
|
@ -16,18 +16,12 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.maven.api;
|
||||
package org.apache.maven.api.spi;
|
||||
|
||||
import org.apache.maven.api.Lifecycle;
|
||||
import org.apache.maven.api.annotations.Consumer;
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
|
||||
/**
|
||||
* Storage location for metadata
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@Experimental
|
||||
public enum MetadataStorage {
|
||||
GROUP,
|
||||
ARTIFACT,
|
||||
VERSION
|
||||
}
|
||||
@Consumer
|
||||
public interface LifecycleProvider extends ExtensibleEnumProvider<Lifecycle> {}
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* 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.internal.impl;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.maven.api.Lifecycle;
|
||||
import org.apache.maven.api.services.LifecycleRegistry;
|
||||
import org.apache.maven.api.spi.LifecycleProvider;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.*;
|
||||
import static org.apache.maven.internal.impl.Lifecycles.*;
|
||||
|
||||
/**
|
||||
* TODO: this is session scoped as SPI can contribute.
|
||||
*/
|
||||
@Named
|
||||
@Singleton
|
||||
public class DefaultLifecycleRegistry
|
||||
extends ExtensibleEnumRegistries.DefaultExtensibleEnumRegistry<Lifecycle, LifecycleProvider>
|
||||
implements LifecycleRegistry {
|
||||
|
||||
public DefaultLifecycleRegistry() {
|
||||
super(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());
|
||||
// validate lifecycle
|
||||
for (Lifecycle lifecycle : this) {
|
||||
Set<String> set = new HashSet<>();
|
||||
lifecycle.phases().forEach(phase -> {
|
||||
if (!set.add(phase.name())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Found duplicated phase '" + phase.name() + "' in '" + lifecycle.id() + "' lifecycle");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Lifecycle> iterator() {
|
||||
return values.values().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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> computePhases(Lifecycle lifecycle) {
|
||||
return lifecycle.phases().stream().map(Lifecycle.Phase::name).toList();
|
||||
}
|
||||
|
||||
static class LifecycleWrapperProvider implements LifecycleProvider {
|
||||
private final Map<String, org.apache.maven.lifecycle.Lifecycle> lifecycles;
|
||||
|
||||
@Inject
|
||||
LifecycleWrapperProvider(Map<String, org.apache.maven.lifecycle.Lifecycle> lifecycles) {
|
||||
this.lifecycles = lifecycles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Lifecycle> provides() {
|
||||
return lifecycles.values().stream().map(this::wrap).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Lifecycle wrap(org.apache.maven.lifecycle.Lifecycle lifecycle) {
|
||||
return new Lifecycle() {
|
||||
@Override
|
||||
public String id() {
|
||||
return lifecycle.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Phase> phases() {
|
||||
// TODO: implement
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static class CleanLifecycle implements Lifecycle {
|
||||
|
||||
private static final String MAVEN_CLEAN_PLUGIN_VERSION = "3.2.0";
|
||||
|
||||
@Override
|
||||
public String id() {
|
||||
return Lifecycle.CLEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Phase> phases() {
|
||||
return asList(
|
||||
phase("pre-clean"),
|
||||
phase(
|
||||
"clean",
|
||||
plugin(
|
||||
"org.apache.maven.plugins:maven-clean-plugin:" + MAVEN_CLEAN_PLUGIN_VERSION
|
||||
+ ":clean",
|
||||
"clean")),
|
||||
phase("post-clean"));
|
||||
}
|
||||
}
|
||||
|
||||
static class DefaultLifecycle implements Lifecycle {
|
||||
@Override
|
||||
public String id() {
|
||||
return Lifecycle.DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Phase> phases() {
|
||||
return asList(
|
||||
phase("validate"),
|
||||
phase("initialize"),
|
||||
phase("generate-sources"),
|
||||
phase("process-sources"),
|
||||
phase("generate-resources"),
|
||||
phase("process-resources"),
|
||||
phase("compile"),
|
||||
phase("process-classes"),
|
||||
phase("generate-test-sources"),
|
||||
phase("process-test-sources"),
|
||||
phase("generate-test-resources"),
|
||||
phase("process-test-resources"),
|
||||
phase("test-compile"),
|
||||
phase("process-test-classes"),
|
||||
phase("test"),
|
||||
phase("prepare-package"),
|
||||
phase("package"),
|
||||
phase("pre-integration-test"),
|
||||
phase("integration-test"),
|
||||
phase("post-integration-test"),
|
||||
phase("verify"),
|
||||
phase("install"),
|
||||
phase("deploy"));
|
||||
}
|
||||
}
|
||||
|
||||
static class SiteLifecycle implements Lifecycle {
|
||||
|
||||
private static final String MAVEN_SITE_PLUGIN_VERSION = "3.12.1";
|
||||
|
||||
@Override
|
||||
public String id() {
|
||||
return Lifecycle.SITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Phase> phases() {
|
||||
return asList(
|
||||
phase("pre-site"),
|
||||
phase(
|
||||
"site",
|
||||
plugin(
|
||||
"org.apache.maven.plugins:maven-site-plugin:" + MAVEN_SITE_PLUGIN_VERSION + ":site",
|
||||
"site")),
|
||||
phase("post-site"),
|
||||
phase(
|
||||
"site-deploy",
|
||||
plugin(
|
||||
"org.apache.maven.plugins:maven-site-plugin:" + MAVEN_SITE_PLUGIN_VERSION
|
||||
+ ":deploy",
|
||||
"site-deploy")));
|
||||
}
|
||||
}
|
||||
|
||||
static class WrapperLifecycle implements Lifecycle {
|
||||
|
||||
private static final String MAVEN_WRAPPER_PLUGIN_VERSION = "3.2.0";
|
||||
|
||||
@Override
|
||||
public String id() {
|
||||
return WRAPPER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Phase> phases() {
|
||||
return singleton(phase(
|
||||
"wrapper",
|
||||
plugin(
|
||||
"org.apache.maven.plugins:maven-wrapper-plugin:" + MAVEN_WRAPPER_PLUGIN_VERSION
|
||||
+ ":wrapper",
|
||||
"wrapper")));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ import javax.inject.Singleton;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
@ -33,6 +34,8 @@ import org.apache.maven.api.*;
|
|||
import org.apache.maven.api.services.*;
|
||||
import org.apache.maven.api.spi.*;
|
||||
|
||||
import static org.apache.maven.internal.impl.Utils.nonNull;
|
||||
|
||||
public class ExtensibleEnumRegistries {
|
||||
|
||||
@Named
|
||||
|
@ -76,17 +79,17 @@ public class ExtensibleEnumRegistries {
|
|||
static class DefaultExtensibleEnumRegistry<T extends ExtensibleEnum, P extends ExtensibleEnumProvider<T>>
|
||||
implements ExtensibleEnumRegistry<T> {
|
||||
|
||||
private final Map<String, T> values;
|
||||
protected final Map<String, T> values;
|
||||
|
||||
DefaultExtensibleEnumRegistry(List<P> providers, T... builtinValues) {
|
||||
values = Stream.<T>concat(
|
||||
Stream.of(builtinValues), providers.stream().flatMap(p -> p.provides().stream()))
|
||||
.collect(Collectors.toMap(t -> t.id(), t -> t));
|
||||
.collect(Collectors.toUnmodifiableMap(ExtensibleEnum::id, Function.identity()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> lookup(String id) {
|
||||
return Optional.ofNullable(values.get(id));
|
||||
return Optional.ofNullable(values.get(nonNull(id, "id")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* 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.internal.impl;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.maven.project.CycleDetectedException;
|
||||
|
||||
class Graph {
|
||||
private enum DfsState {
|
||||
VISITING,
|
||||
VISITED
|
||||
}
|
||||
|
||||
final Map<String, Vertex> vertices = new LinkedHashMap<>();
|
||||
|
||||
public Vertex getVertex(String id) {
|
||||
return vertices.get(id);
|
||||
}
|
||||
|
||||
public Collection<Vertex> getVertices() {
|
||||
return vertices.values();
|
||||
}
|
||||
|
||||
Vertex addVertex(String label) {
|
||||
return vertices.computeIfAbsent(label, Vertex::new);
|
||||
}
|
||||
|
||||
void addEdge(Vertex from, Vertex to) throws CycleDetectedException {
|
||||
from.children.add(to);
|
||||
to.parents.add(from);
|
||||
List<String> cycle = findCycle(to);
|
||||
if (cycle != null) {
|
||||
// remove edge which introduced cycle
|
||||
removeEdge(from, to);
|
||||
throw new CycleDetectedException(
|
||||
"Edge between '" + from.label + "' and '" + to.label + "' introduces to cycle in the graph", cycle);
|
||||
}
|
||||
}
|
||||
|
||||
void removeEdge(Vertex from, Vertex to) {
|
||||
from.children.remove(to);
|
||||
to.parents.remove(from);
|
||||
}
|
||||
|
||||
List<String> visitAll() {
|
||||
return visitAll(vertices.values(), new HashMap<>(), new ArrayList<>());
|
||||
}
|
||||
|
||||
List<String> findCycle(Vertex vertex) {
|
||||
return visitCycle(Collections.singleton(vertex), new HashMap<>(), new LinkedList<>());
|
||||
}
|
||||
|
||||
private static List<String> visitAll(
|
||||
Collection<Vertex> children, Map<Vertex, DfsState> stateMap, List<String> list) {
|
||||
for (Vertex v : children) {
|
||||
DfsState state = stateMap.putIfAbsent(v, DfsState.VISITING);
|
||||
if (state == null) {
|
||||
visitAll(v.children, stateMap, list);
|
||||
stateMap.put(v, DfsState.VISITED);
|
||||
list.add(v.label);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<String> visitCycle(
|
||||
Collection<Vertex> children, Map<Vertex, DfsState> stateMap, LinkedList<String> cycle) {
|
||||
for (Vertex v : children) {
|
||||
DfsState state = stateMap.putIfAbsent(v, DfsState.VISITING);
|
||||
if (state == null) {
|
||||
cycle.addLast(v.label);
|
||||
List<String> ret = visitCycle(v.children, stateMap, cycle);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
cycle.removeLast();
|
||||
stateMap.put(v, DfsState.VISITED);
|
||||
} else if (state == DfsState.VISITING) {
|
||||
// we are already visiting this vertex, this mean we have a cycle
|
||||
int pos = cycle.lastIndexOf(v.label);
|
||||
List<String> ret = cycle.subList(pos, cycle.size());
|
||||
ret.add(v.label);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static class Vertex {
|
||||
final String label;
|
||||
final List<Vertex> children = new ArrayList<>();
|
||||
final List<Vertex> parents = new ArrayList<>();
|
||||
|
||||
Vertex(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
List<Vertex> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
List<Vertex> getParents() {
|
||||
return parents;
|
||||
}
|
||||
}
|
||||
|
||||
static class CycleDetectedException extends RuntimeException {
|
||||
private final List<String> cycle;
|
||||
|
||||
CycleDetectedException(String message, List<String> cycle) {
|
||||
super(message);
|
||||
this.cycle = cycle;
|
||||
}
|
||||
|
||||
public List<String> getCycle() {
|
||||
return cycle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return super.getMessage() + " " + String.join(" --> ", cycle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.internal.impl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.api.Lifecycle;
|
||||
import org.apache.maven.api.model.Plugin;
|
||||
import org.apache.maven.api.model.PluginExecution;
|
||||
|
||||
public class Lifecycles {
|
||||
|
||||
static Lifecycle.Phase phase(String name) {
|
||||
return new DefaultPhase(name, Collections.emptyList(), Collections.emptyList());
|
||||
}
|
||||
|
||||
static Lifecycle.Phase phase(String name, Plugin plugin) {
|
||||
return new DefaultPhase(name, Collections.singletonList(plugin), Collections.emptyList());
|
||||
}
|
||||
|
||||
static Plugin plugin(String coord, String phase) {
|
||||
String[] c = coord.split(":");
|
||||
return Plugin.newBuilder()
|
||||
.groupId(c[0])
|
||||
.artifactId(c[1])
|
||||
.version(c[2])
|
||||
.executions(Collections.singletonList(PluginExecution.newBuilder()
|
||||
.id("default-" + c[3])
|
||||
.phase(phase)
|
||||
.goals(Collections.singletonList(c[3]))
|
||||
.build()))
|
||||
.build();
|
||||
}
|
||||
|
||||
static class DefaultPhase implements Lifecycle.Phase {
|
||||
private final String name;
|
||||
private final List<Plugin> plugins;
|
||||
private final List<Lifecycle.Phase> phases;
|
||||
|
||||
DefaultPhase(String name, List<Plugin> plugins, List<Lifecycle.Phase> phases) {
|
||||
this.name = name;
|
||||
this.plugins = plugins;
|
||||
this.phases = phases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Plugin> plugins() {
|
||||
return plugins;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.maven.api.services.LifecycleRegistry;
|
||||
import org.apache.maven.api.services.Lookup;
|
||||
import org.apache.maven.api.services.LookupException;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -51,24 +52,29 @@ public class DefaultLifecycles {
|
|||
|
||||
private final Lookup lookup;
|
||||
|
||||
private final LifecycleRegistry registry;
|
||||
|
||||
private Map<String, Lifecycle> customLifecycles;
|
||||
|
||||
public DefaultLifecycles() {
|
||||
this.lookup = null;
|
||||
this.registry = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Rely on {@link #DefaultLifecycles(Lookup)} instead
|
||||
* @deprecated Use {@link #DefaultLifecycles(LifecycleRegistry,Lookup)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public DefaultLifecycles(Map<String, Lifecycle> lifecycles, org.codehaus.plexus.logging.Logger logger) {
|
||||
this.customLifecycles = lifecycles;
|
||||
this.lookup = null;
|
||||
this.registry = null;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public DefaultLifecycles(Lookup lookup) {
|
||||
public DefaultLifecycles(LifecycleRegistry registry, Lookup lookup) {
|
||||
this.lookup = lookup;
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,7 +155,11 @@ public class DefaultLifecycles {
|
|||
|
||||
// Lifecycles cannot be cached as extensions might add custom lifecycles later in the execution.
|
||||
try {
|
||||
return lookup.lookupMap(Lifecycle.class);
|
||||
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;
|
||||
} catch (LookupException e) {
|
||||
throw new IllegalStateException("Unable to lookup lifecycles from the plexus container", e);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
package org.apache.maven.lifecycle;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.maven.lifecycle.mapping.LifecyclePhase;
|
||||
|
||||
|
@ -35,6 +35,14 @@ public class Lifecycle {
|
|||
this.defaultPhases = defaultPhases;
|
||||
}
|
||||
|
||||
public Lifecycle(
|
||||
org.apache.maven.api.services.LifecycleRegistry registry, org.apache.maven.api.Lifecycle lifecycle) {
|
||||
this.lifecycle = lifecycle;
|
||||
this.id = lifecycle.id();
|
||||
this.phases = registry.computePhases(lifecycle);
|
||||
this.defaultPhases = getDefaultPhases(lifecycle);
|
||||
}
|
||||
|
||||
// <lifecycle>
|
||||
// <id>clean</id>
|
||||
// <phases>
|
||||
|
@ -53,12 +61,25 @@ public class Lifecycle {
|
|||
|
||||
private Map<String, LifecyclePhase> defaultPhases;
|
||||
|
||||
private org.apache.maven.api.Lifecycle lifecycle;
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<String> getPhases() {
|
||||
return this.phases;
|
||||
return phases;
|
||||
}
|
||||
|
||||
static Map<String, LifecyclePhase> getDefaultPhases(org.apache.maven.api.Lifecycle lifecycle) {
|
||||
Map<String, List<String>> goals = new HashMap<>();
|
||||
lifecycle.phases().forEach(phase -> phase.plugins()
|
||||
.forEach(plugin -> plugin.getExecutions().forEach(exec -> exec.getGoals()
|
||||
.forEach(goal -> goals.computeIfAbsent(phase.name(), n -> new ArrayList<>())
|
||||
.add(plugin.getGroupId() + ":" + plugin.getArtifactId() + ":" + plugin.getVersion()
|
||||
+ ":" + goal)))));
|
||||
return goals.entrySet().stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> new LifecyclePhase(String.join(",", e.getValue()))));
|
||||
}
|
||||
|
||||
public Map<String, LifecyclePhase> getDefaultLifecyclePhases() {
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* 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.lifecycle.providers;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* {@code clean} lifecycle provider.
|
||||
*/
|
||||
@Named(CleanLifecycleProvider.LIFECYCLE_ID)
|
||||
@Singleton
|
||||
public final class CleanLifecycleProvider extends AbstractLifecycleProvider {
|
||||
static final String LIFECYCLE_ID = "clean";
|
||||
|
||||
// START SNIPPET: clean
|
||||
private static final String[] PHASES = {"pre-clean", "clean", "post-clean"};
|
||||
|
||||
private static final String MAVEN_CLEAN_PLUGIN_VERSION = "3.2.0";
|
||||
|
||||
private static final String[] BINDINGS = {
|
||||
"clean", "org.apache.maven.plugins:maven-clean-plugin:" + MAVEN_CLEAN_PLUGIN_VERSION + ":clean"
|
||||
};
|
||||
// END SNIPPET: clean
|
||||
|
||||
@Inject
|
||||
public CleanLifecycleProvider() {
|
||||
super(LIFECYCLE_ID, PHASES, BINDINGS);
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* 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.lifecycle.providers;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* {@code default} lifecycle provider.
|
||||
*/
|
||||
@Named(DefaultLifecycleProvider.LIFECYCLE_ID)
|
||||
@Singleton
|
||||
public final class DefaultLifecycleProvider extends AbstractLifecycleProvider {
|
||||
static final String LIFECYCLE_ID = "default";
|
||||
|
||||
// START SNIPPET: default
|
||||
private static final String[] PHASES = {
|
||||
"validate",
|
||||
"initialize",
|
||||
"generate-sources",
|
||||
"process-sources",
|
||||
"generate-resources",
|
||||
"process-resources",
|
||||
"compile",
|
||||
"process-classes",
|
||||
"generate-test-sources",
|
||||
"process-test-sources",
|
||||
"generate-test-resources",
|
||||
"process-test-resources",
|
||||
"test-compile",
|
||||
"process-test-classes",
|
||||
"test",
|
||||
"prepare-package",
|
||||
"package",
|
||||
"pre-integration-test",
|
||||
"integration-test",
|
||||
"post-integration-test",
|
||||
"verify",
|
||||
"install",
|
||||
"deploy"
|
||||
};
|
||||
// END SNIPPET: default
|
||||
|
||||
@Inject
|
||||
public DefaultLifecycleProvider() {
|
||||
super(
|
||||
LIFECYCLE_ID,
|
||||
PHASES,
|
||||
null // no global plugin bindings for default lifecycle: they are defined per-packaging in separate
|
||||
// providers
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* 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.lifecycle.providers;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* {@code site} lifecycle provider.
|
||||
*/
|
||||
@Named(SiteLifecycleProvider.LIFECYCLE_ID)
|
||||
@Singleton
|
||||
public final class SiteLifecycleProvider extends AbstractLifecycleProvider {
|
||||
static final String LIFECYCLE_ID = "site";
|
||||
|
||||
// START SNIPPET: site
|
||||
private static final String[] PHASES = {"pre-site", "site", "post-site", "site-deploy"};
|
||||
|
||||
private static final String MAVEN_SITE_PLUGIN_VERSION = "3.12.1";
|
||||
|
||||
private static final String[] BINDINGS = {
|
||||
"site", "org.apache.maven.plugins:maven-site-plugin:" + MAVEN_SITE_PLUGIN_VERSION + ":site",
|
||||
"site-deploy", "org.apache.maven.plugins:maven-site-plugin:" + MAVEN_SITE_PLUGIN_VERSION + ":deploy"
|
||||
};
|
||||
// END SNIPPET: site
|
||||
|
||||
@Inject
|
||||
public SiteLifecycleProvider() {
|
||||
super(LIFECYCLE_ID, PHASES, BINDINGS);
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.maven.internal.impl.DefaultLifecycleRegistry;
|
||||
import org.apache.maven.internal.impl.DefaultLookup;
|
||||
import org.codehaus.plexus.PlexusContainer;
|
||||
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
|
||||
|
@ -94,7 +95,9 @@ class DefaultLifecyclesTest {
|
|||
PlexusContainer mockedPlexusContainer = mock(PlexusContainer.class);
|
||||
when(mockedPlexusContainer.lookupMap(Lifecycle.class)).thenReturn(lifeCycles);
|
||||
|
||||
DefaultLifecycles dl = new DefaultLifecycles(new DefaultLookup(mockedPlexusContainer));
|
||||
DefaultLifecycles dl = new DefaultLifecycles(
|
||||
new DefaultLifecycleRegistry(Collections.emptyList(), Collections.emptyMap()),
|
||||
new DefaultLookup(mockedPlexusContainer));
|
||||
|
||||
assertThat(dl.getLifeCycles().get(0).getId(), is("clean"));
|
||||
assertThat(dl.getLifeCycles().get(1).getId(), is("default"));
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.internal.impl.DefaultLifecycleRegistry;
|
||||
import org.apache.maven.internal.impl.DefaultLookup;
|
||||
import org.apache.maven.lifecycle.DefaultLifecycles;
|
||||
import org.apache.maven.lifecycle.Lifecycle;
|
||||
|
@ -71,6 +72,7 @@ public class DefaultLifecyclesStub {
|
|||
PlexusContainer mockedContainer = mock(PlexusContainer.class);
|
||||
when(mockedContainer.lookupMap(Lifecycle.class)).thenReturn(lifeCycles);
|
||||
|
||||
return new DefaultLifecycles(new DefaultLookup(mockedContainer));
|
||||
DefaultLifecycleRegistry reg = new DefaultLifecycleRegistry();
|
||||
return new DefaultLifecycles(reg, new DefaultLookup(mockedContainer));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue