From a3e8da805c7e8d743700f13924bd2aafe3fe6783 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 29 Feb 2024 00:56:36 +0100 Subject: [PATCH] Make LifecycleStarter pluggable (#1424) --- .../java/org/apache/maven/DefaultMaven.java | 7 +- .../internal/DefaultLifecycleStarter.java | 139 ++++++++++++++++++ .../lifecycle/internal/LifecycleStarter.java | 116 +-------------- 3 files changed, 144 insertions(+), 118 deletions(-) create mode 100644 maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleStarter.java diff --git a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java index ae58fc8a93..c44a039342 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -91,8 +91,6 @@ public class DefaultMaven implements Maven { private final Lookup lookup; - private final LifecycleStarter lifecycleStarter; - private final ExecutionEventCatapult eventCatapult; private final LegacySupport legacySupport; @@ -119,7 +117,6 @@ public class DefaultMaven implements Maven { @SuppressWarnings("checkstyle:ParameterNumber") public DefaultMaven( Lookup lookup, - LifecycleStarter lifecycleStarter, ExecutionEventCatapult eventCatapult, LegacySupport legacySupport, SessionScope sessionScope, @@ -131,7 +128,6 @@ public class DefaultMaven implements Maven { DefaultSessionFactory defaultSessionFactory, @Nullable @Named("ide") WorkspaceReader ideWorkspaceReader) { this.lookup = lookup; - this.lifecycleStarter = lifecycleStarter; this.eventCatapult = eventCatapult; this.legacySupport = legacySupport; this.sessionScope = sessionScope; @@ -309,6 +305,9 @@ public class DefaultMaven implements Maven { validateOptionalProfiles(session, request.getProfileActivation()); + LifecycleStarter lifecycleStarter = lookup.lookupOptional(LifecycleStarter.class, request.getBuilderId()) + .orElseGet(() -> lookup.lookup(LifecycleStarter.class)); + lifecycleStarter.execute(session); validateOptionalProjects(request, session); diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleStarter.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleStarter.java new file mode 100644 index 0000000000..645c6e8692 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleStarter.java @@ -0,0 +1,139 @@ +/* + * 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.internal; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import java.util.List; +import java.util.Map; + +import org.apache.maven.execution.ExecutionEvent; +import org.apache.maven.execution.MavenExecutionResult; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.lifecycle.DefaultLifecycles; +import org.apache.maven.lifecycle.MissingProjectException; +import org.apache.maven.lifecycle.NoGoalSpecifiedException; +import org.apache.maven.lifecycle.internal.builder.Builder; +import org.apache.maven.lifecycle.internal.builder.BuilderNotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Starts the build life cycle + * + */ +@Named +@Singleton +public class DefaultLifecycleStarter implements LifecycleStarter { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final ExecutionEventCatapult eventCatapult; + + private final DefaultLifecycles defaultLifeCycles; + + private final BuildListCalculator buildListCalculator; + + private final LifecycleDebugLogger lifecycleDebugLogger; + + private final LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator; + + private final Map builders; + + @Inject + public DefaultLifecycleStarter( + ExecutionEventCatapult eventCatapult, + DefaultLifecycles defaultLifeCycles, + BuildListCalculator buildListCalculator, + LifecycleDebugLogger lifecycleDebugLogger, + LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator, + Map builders) { + this.eventCatapult = eventCatapult; + this.defaultLifeCycles = defaultLifeCycles; + this.buildListCalculator = buildListCalculator; + this.lifecycleDebugLogger = lifecycleDebugLogger; + this.lifecycleTaskSegmentCalculator = lifecycleTaskSegmentCalculator; + this.builders = builders; + } + + @Override + public void execute(MavenSession session) { + eventCatapult.fire(ExecutionEvent.Type.SessionStarted, session, null); + + ReactorContext reactorContext = null; + ProjectBuildList projectBuilds = null; + MavenExecutionResult result = session.getResult(); + + try { + if (buildExecutionRequiresProject(session) && projectIsNotPresent(session)) { + throw new MissingProjectException("The goal you specified requires a project to execute" + + " but there is no POM in this directory (" + session.getExecutionRootDirectory() + ")." + + " Please verify you invoked Maven from the correct directory."); + } + + List taskSegments = lifecycleTaskSegmentCalculator.calculateTaskSegments(session); + projectBuilds = buildListCalculator.calculateProjectBuilds(session, taskSegments); + + if (projectBuilds.isEmpty()) { + throw new NoGoalSpecifiedException("No goals have been specified for this build." + + " You must specify a valid lifecycle phase or a goal in the format : or" + + " :[:]:." + + " Available lifecycle phases are: " + defaultLifeCycles.getLifecyclePhaseList() + "."); + } + + if (logger.isDebugEnabled()) { + lifecycleDebugLogger.debugReactorPlan(projectBuilds); + } + + ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader(); + ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus(session.getProjectDependencyGraph()); + reactorContext = new ReactorContext(result, oldContextClassLoader, reactorBuildStatus); + + String builderId = session.getRequest().getBuilderId(); + Builder builder = builders.get(builderId); + if (builder == null) { + throw new BuilderNotFoundException( + String.format("The builder requested using id = %s cannot be" + " found", builderId)); + } + + int degreeOfConcurrency = session.getRequest().getDegreeOfConcurrency(); + if (degreeOfConcurrency > 1) { + logger.info(""); + logger.info(String.format( + "Using the %s implementation with a thread count of %d", + builder.getClass().getSimpleName(), degreeOfConcurrency)); + } + builder.build(session, reactorContext, projectBuilds, taskSegments, reactorBuildStatus); + + } catch (Exception e) { + result.addException(e); + } finally { + eventCatapult.fire(ExecutionEvent.Type.SessionEnded, session, null); + } + } + + private boolean buildExecutionRequiresProject(MavenSession session) { + return lifecycleTaskSegmentCalculator.requiresProject(session); + } + + private boolean projectIsNotPresent(MavenSession session) { + return !session.getRequest().isProjectPresent(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java index 48c9308c9e..1c97f2084c 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java @@ -18,125 +18,13 @@ */ package org.apache.maven.lifecycle.internal; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; - -import java.util.List; -import java.util.Map; - -import org.apache.maven.execution.ExecutionEvent; -import org.apache.maven.execution.MavenExecutionResult; import org.apache.maven.execution.MavenSession; -import org.apache.maven.lifecycle.DefaultLifecycles; -import org.apache.maven.lifecycle.MissingProjectException; -import org.apache.maven.lifecycle.NoGoalSpecifiedException; -import org.apache.maven.lifecycle.internal.builder.Builder; -import org.apache.maven.lifecycle.internal.builder.BuilderNotFoundException; -import org.apache.maven.session.scope.internal.SessionScope; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Starts the build life cycle * */ -@Named -@Singleton -public class LifecycleStarter { - private final Logger logger = LoggerFactory.getLogger(getClass()); +public interface LifecycleStarter { - private final ExecutionEventCatapult eventCatapult; - - private final DefaultLifecycles defaultLifeCycles; - - private final BuildListCalculator buildListCalculator; - - private final LifecycleDebugLogger lifecycleDebugLogger; - - private final LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator; - - private final Map builders; - - @Inject - public LifecycleStarter( - ExecutionEventCatapult eventCatapult, - DefaultLifecycles defaultLifeCycles, - BuildListCalculator buildListCalculator, - LifecycleDebugLogger lifecycleDebugLogger, - LifecycleTaskSegmentCalculator lifecycleTaskSegmentCalculator, - Map builders, - SessionScope sessionScope) { - this.eventCatapult = eventCatapult; - this.defaultLifeCycles = defaultLifeCycles; - this.buildListCalculator = buildListCalculator; - this.lifecycleDebugLogger = lifecycleDebugLogger; - this.lifecycleTaskSegmentCalculator = lifecycleTaskSegmentCalculator; - this.builders = builders; - } - - public void execute(MavenSession session) { - eventCatapult.fire(ExecutionEvent.Type.SessionStarted, session, null); - - ReactorContext reactorContext = null; - ProjectBuildList projectBuilds = null; - MavenExecutionResult result = session.getResult(); - - try { - if (buildExecutionRequiresProject(session) && projectIsNotPresent(session)) { - throw new MissingProjectException("The goal you specified requires a project to execute" - + " but there is no POM in this directory (" + session.getExecutionRootDirectory() + ")." - + " Please verify you invoked Maven from the correct directory."); - } - - List taskSegments = lifecycleTaskSegmentCalculator.calculateTaskSegments(session); - projectBuilds = buildListCalculator.calculateProjectBuilds(session, taskSegments); - - if (projectBuilds.isEmpty()) { - throw new NoGoalSpecifiedException("No goals have been specified for this build." - + " You must specify a valid lifecycle phase or a goal in the format : or" - + " :[:]:." - + " Available lifecycle phases are: " + defaultLifeCycles.getLifecyclePhaseList() + "."); - } - - ProjectIndex projectIndex = new ProjectIndex(session.getProjects()); - - if (logger.isDebugEnabled()) { - lifecycleDebugLogger.debugReactorPlan(projectBuilds); - } - - ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader(); - ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus(session.getProjectDependencyGraph()); - reactorContext = new ReactorContext(result, oldContextClassLoader, reactorBuildStatus); - - String builderId = session.getRequest().getBuilderId(); - Builder builder = builders.get(builderId); - if (builder == null) { - throw new BuilderNotFoundException( - String.format("The builder requested using id = %s cannot be" + " found", builderId)); - } - - int degreeOfConcurrency = session.getRequest().getDegreeOfConcurrency(); - if (degreeOfConcurrency > 1) { - logger.info(""); - logger.info(String.format( - "Using the %s implementation with a thread count of %d", - builder.getClass().getSimpleName(), degreeOfConcurrency)); - } - builder.build(session, reactorContext, projectBuilds, taskSegments, reactorBuildStatus); - - } catch (Exception e) { - result.addException(e); - } finally { - eventCatapult.fire(ExecutionEvent.Type.SessionEnded, session, null); - } - } - - private boolean buildExecutionRequiresProject(MavenSession session) { - return lifecycleTaskSegmentCalculator.requiresProject(session); - } - - private boolean projectIsNotPresent(MavenSession session) { - return !session.getRequest().isProjectPresent(); - } + void execute(MavenSession session); }