From 95b40a3d8a6adf91686234ebb39281ff0c935fea Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 8 Mar 2023 00:03:49 +0100 Subject: [PATCH] Provide distributions for both maven 3.9.x and 4.0.x (#796) --- daemon-m39/pom.xml | 50 + .../org/apache/maven/cli/DaemonMavenCli.java | 1419 +++++++++++++++++ .../maven/project/SnapshotModelCache.java | 48 + .../project/SnapshotModelCacheFactory.java | 53 + .../InvalidatingPluginDescriptorCache.java | 0 .../InvalidatingPluginRealmCache.java | 125 ++ .../InvalidatingRealmCacheEventSpy.java | 0 .../execution/BuildResumptionAnalyzer.java | 57 + .../mvnd/execution/BuildResumptionData.java | 62 + .../BuildResumptionDataRepository.java | 74 + .../BuildResumptionPersistenceException.java | 49 + .../DefaultBuildResumptionAnalyzer.java | 90 ++ .../DefaultBuildResumptionDataRepository.java | 155 ++ .../plugin/CachingPluginVersionResolver.java | 79 + .../mvnd/plugin/CliMavenPluginManager.java | 779 +++++++++ .../ValidatingConfigurationListener.java | 82 + daemon-m40/pom.xml | 50 + .../org/apache/maven/cli/DaemonMavenCli.java | 10 +- .../maven/project/SnapshotModelCache.java | 6 +- .../project/SnapshotModelCacheFactory.java | 0 .../maven/settings/SettingsUtilsV4.java | 0 .../InvalidatingPluginDescriptorCache.java | 136 ++ .../InvalidatingPluginRealmCache.java | 0 .../InvalidatingRealmCacheEventSpy.java | 190 +++ .../plugin/CachingPluginVersionResolver.java | 0 daemon/pom.xml | 2 +- .../java/org/apache/maven/cli/DaemonCli.java | 37 + .../org/mvndaemon/mvnd/daemon/Server.java | 10 +- {dist => dist-m39}/pom.xml | 10 +- dist-m39/src/main/provisio/maven-distro.xml | 93 ++ dist-m40/pom.xml | 82 + .../src/main/provisio/maven-distro.xml | 15 +- .../main/resources/platform-darwin-aarch64 | 13 + dist/src/main/resources/platform-darwin-amd64 | 13 + dist/src/main/resources/platform-linux-amd64 | 13 + .../src/main/resources/platform-windows-amd64 | 13 + integration-tests/pom.xml | 91 +- pom.xml | 25 +- 38 files changed, 3895 insertions(+), 36 deletions(-) create mode 100644 daemon-m39/pom.xml create mode 100644 daemon-m39/src/main/java/org/apache/maven/cli/DaemonMavenCli.java create mode 100644 daemon-m39/src/main/java/org/apache/maven/project/SnapshotModelCache.java create mode 100644 daemon-m39/src/main/java/org/apache/maven/project/SnapshotModelCacheFactory.java rename {daemon => daemon-m39}/src/main/java/org/mvndaemon/mvnd/cache/invalidating/InvalidatingPluginDescriptorCache.java (100%) create mode 100644 daemon-m39/src/main/java/org/mvndaemon/mvnd/cache/invalidating/InvalidatingPluginRealmCache.java rename {daemon => daemon-m39}/src/main/java/org/mvndaemon/mvnd/cache/invalidating/InvalidatingRealmCacheEventSpy.java (100%) create mode 100644 daemon-m39/src/main/java/org/mvndaemon/mvnd/execution/BuildResumptionAnalyzer.java create mode 100644 daemon-m39/src/main/java/org/mvndaemon/mvnd/execution/BuildResumptionData.java create mode 100644 daemon-m39/src/main/java/org/mvndaemon/mvnd/execution/BuildResumptionDataRepository.java create mode 100644 daemon-m39/src/main/java/org/mvndaemon/mvnd/execution/BuildResumptionPersistenceException.java create mode 100644 daemon-m39/src/main/java/org/mvndaemon/mvnd/execution/DefaultBuildResumptionAnalyzer.java create mode 100644 daemon-m39/src/main/java/org/mvndaemon/mvnd/execution/DefaultBuildResumptionDataRepository.java create mode 100644 daemon-m39/src/main/java/org/mvndaemon/mvnd/plugin/CachingPluginVersionResolver.java create mode 100644 daemon-m39/src/main/java/org/mvndaemon/mvnd/plugin/CliMavenPluginManager.java create mode 100644 daemon-m39/src/main/java/org/mvndaemon/mvnd/plugin/ValidatingConfigurationListener.java create mode 100644 daemon-m40/pom.xml rename {daemon => daemon-m40}/src/main/java/org/apache/maven/cli/DaemonMavenCli.java (99%) rename {daemon => daemon-m40}/src/main/java/org/apache/maven/project/SnapshotModelCache.java (92%) rename {daemon => daemon-m40}/src/main/java/org/apache/maven/project/SnapshotModelCacheFactory.java (100%) rename {daemon => daemon-m40}/src/main/java/org/apache/maven/settings/SettingsUtilsV4.java (100%) create mode 100644 daemon-m40/src/main/java/org/mvndaemon/mvnd/cache/invalidating/InvalidatingPluginDescriptorCache.java rename {daemon => daemon-m40}/src/main/java/org/mvndaemon/mvnd/cache/invalidating/InvalidatingPluginRealmCache.java (100%) create mode 100644 daemon-m40/src/main/java/org/mvndaemon/mvnd/cache/invalidating/InvalidatingRealmCacheEventSpy.java rename {daemon => daemon-m40}/src/main/java/org/mvndaemon/mvnd/plugin/CachingPluginVersionResolver.java (100%) create mode 100644 daemon/src/main/java/org/apache/maven/cli/DaemonCli.java rename {dist => dist-m39}/pom.xml (88%) create mode 100644 dist-m39/src/main/provisio/maven-distro.xml create mode 100644 dist-m40/pom.xml rename {dist => dist-m40}/src/main/provisio/maven-distro.xml (81%) create mode 100644 dist/src/main/resources/platform-darwin-aarch64 create mode 100644 dist/src/main/resources/platform-darwin-amd64 create mode 100644 dist/src/main/resources/platform-linux-amd64 create mode 100644 dist/src/main/resources/platform-windows-amd64 diff --git a/daemon-m39/pom.xml b/daemon-m39/pom.xml new file mode 100644 index 00000000..62ec50a0 --- /dev/null +++ b/daemon-m39/pom.xml @@ -0,0 +1,50 @@ + + + + + 4.0.0 + + org.apache.maven.daemon + mvnd + 1.0.0-m5-SNAPSHOT + + + mvnd-daemon-m39 + + jar + Maven Daemon - Daemon 3.9.x specifics + + + + org.apache.maven + maven-core + ${maven3.version} + + + org.apache.maven + maven-embedder + ${maven3.version} + + + org.apache.maven.daemon + mvnd-daemon + + + + diff --git a/daemon-m39/src/main/java/org/apache/maven/cli/DaemonMavenCli.java b/daemon-m39/src/main/java/org/apache/maven/cli/DaemonMavenCli.java new file mode 100644 index 00000000..feac407e --- /dev/null +++ b/daemon-m39/src/main/java/org/apache/maven/cli/DaemonMavenCli.java @@ -0,0 +1,1419 @@ +/* + * 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.cli; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.google.inject.AbstractModule; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.ParseException; +import org.apache.maven.InternalErrorException; +import org.apache.maven.Maven; +import org.apache.maven.building.FileSource; +import org.apache.maven.building.Problem; +import org.apache.maven.building.Source; +import org.apache.maven.cli.configuration.ConfigurationProcessor; +import org.apache.maven.cli.configuration.SettingsXmlConfigurationProcessor; +import org.apache.maven.cli.event.ExecutionEventLogger; +import org.apache.maven.cli.internal.BootstrapCoreExtensionManager; +import org.apache.maven.cli.internal.extension.model.CoreExtension; +import org.apache.maven.cli.transfer.QuietMavenTransferListener; +import org.apache.maven.cli.transfer.Slf4jMavenTransferListener; +import org.apache.maven.eventspy.internal.EventSpyDispatcher; +import org.apache.maven.exception.DefaultExceptionHandler; +import org.apache.maven.exception.ExceptionHandler; +import org.apache.maven.exception.ExceptionSummary; +import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionRequestPopulationException; +import org.apache.maven.execution.MavenExecutionRequestPopulator; +import org.apache.maven.execution.MavenExecutionResult; +import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule; +import org.apache.maven.extension.internal.CoreExports; +import org.apache.maven.extension.internal.CoreExtensionEntry; +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.model.building.ModelProcessor; +import org.apache.maven.plugin.ExtensionRealmCache; +import org.apache.maven.plugin.MavenPluginManager; +import org.apache.maven.plugin.PluginArtifactsCache; +import org.apache.maven.plugin.PluginRealmCache; +import org.apache.maven.plugin.version.PluginVersionResolver; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.artifact.ProjectArtifactsCache; +import org.apache.maven.properties.internal.SystemProperties; +import org.apache.maven.session.scope.internal.SessionScopeModule; +import org.apache.maven.shared.utils.logging.MessageBuilder; +import org.apache.maven.shared.utils.logging.MessageUtils; +import org.apache.maven.toolchain.building.DefaultToolchainsBuildingRequest; +import org.apache.maven.toolchain.building.ToolchainsBuilder; +import org.apache.maven.toolchain.building.ToolchainsBuildingResult; +import org.codehaus.plexus.ContainerConfiguration; +import org.codehaus.plexus.DefaultContainerConfiguration; +import org.codehaus.plexus.DefaultPlexusContainer; +import org.codehaus.plexus.PlexusConstants; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.classworlds.ClassWorld; +import org.codehaus.plexus.classworlds.realm.ClassRealm; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.codehaus.plexus.util.StringUtils; +import org.eclipse.aether.transfer.TransferListener; +import org.mvndaemon.mvnd.cache.invalidating.InvalidatingExtensionRealmCache; +import org.mvndaemon.mvnd.cache.invalidating.InvalidatingPluginArtifactsCache; +import org.mvndaemon.mvnd.cache.invalidating.InvalidatingPluginRealmCache; +import org.mvndaemon.mvnd.cache.invalidating.InvalidatingProjectArtifactsCache; +import org.mvndaemon.mvnd.cli.EnvHelper; +import org.mvndaemon.mvnd.common.Environment; +import org.mvndaemon.mvnd.common.Os; +import org.mvndaemon.mvnd.execution.BuildResumptionPersistenceException; +import org.mvndaemon.mvnd.execution.DefaultBuildResumptionAnalyzer; +import org.mvndaemon.mvnd.execution.DefaultBuildResumptionDataRepository; +import org.mvndaemon.mvnd.logging.internal.Slf4jLoggerManager; +import org.mvndaemon.mvnd.logging.smart.BuildEventListener; +import org.mvndaemon.mvnd.logging.smart.LoggingExecutionListener; +import org.mvndaemon.mvnd.logging.smart.LoggingOutputStream; +import org.mvndaemon.mvnd.plugin.CachingPluginVersionResolver; +import org.mvndaemon.mvnd.plugin.CliMavenPluginManager; +import org.mvndaemon.mvnd.transfer.DaemonMavenTransferListener; +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; +import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; + +import static java.util.Comparator.comparing; +import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; + +/** + * File origin: + * https://github.com/apache/maven/blob/maven-3.6.2/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java + * + * @author Jason van Zyl + */ +public class DaemonMavenCli implements DaemonCli { + public static final String LOCAL_REPO_PROPERTY = "maven.repo.local"; + + public static final String MULTIMODULE_PROJECT_DIRECTORY = "maven.multiModuleProjectDirectory"; + + public static final String USER_HOME = System.getProperty("user.home"); + + public static final File USER_MAVEN_CONFIGURATION_HOME = new File(USER_HOME, ".m2"); + + public static final File DEFAULT_USER_TOOLCHAINS_FILE = new File(USER_MAVEN_CONFIGURATION_HOME, "toolchains.xml"); + + public static final File DEFAULT_GLOBAL_TOOLCHAINS_FILE = + new File(System.getProperty("maven.conf"), "toolchains.xml"); + + private static final String EXT_CLASS_PATH = "maven.ext.class.path"; + + private static final String EXTENSIONS_FILENAME = ".mvn/extensions.xml"; + + private static final String MVN_MAVEN_CONFIG = ".mvn/maven.config"; + + public static final String STYLE_COLOR_PROPERTY = "style.color"; + + public static final String RESUME = "r"; + + public static final String RAW_STREAMS = "raw-streams"; + + private final Slf4jLoggerManager plexusLoggerManager; + + private final ILoggerFactory slf4jLoggerFactory; + + private final Logger slf4jLogger; + + private final ClassWorld classWorld; + + private final DefaultPlexusContainer container; + + private final EventSpyDispatcher eventSpyDispatcher; + + private final ModelProcessor modelProcessor; + + private final Maven maven; + + private final MavenExecutionRequestPopulator executionRequestPopulator; + + private final ToolchainsBuilder toolchainsBuilder; + + private final DefaultSecDispatcher dispatcher; + + private final Map configurationProcessors; + + private final LoggingExecutionListener executionListener; + + /** Non-volatile, assuming that it is accessed only from the main thread */ + private BuildEventListener buildEventListener = BuildEventListener.dummy(); + + public DaemonMavenCli() throws Exception { + slf4jLoggerFactory = LoggerFactory.getILoggerFactory(); + slf4jLogger = slf4jLoggerFactory.getLogger(this.getClass().getName()); + plexusLoggerManager = new Slf4jLoggerManager(); + + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + classWorld = new ClassWorld("plexus.core", cl); + + container = container(); + + eventSpyDispatcher = container.lookup(EventSpyDispatcher.class); + maven = container.lookup(Maven.class); + executionRequestPopulator = container.lookup(MavenExecutionRequestPopulator.class); + modelProcessor = createModelProcessor(container); + configurationProcessors = container.lookupMap(ConfigurationProcessor.class); + toolchainsBuilder = container.lookup(ToolchainsBuilder.class); + dispatcher = (DefaultSecDispatcher) container.lookup(SecDispatcher.class, "maven"); + executionListener = container.lookup(LoggingExecutionListener.class); + } + + public int main( + List arguments, + String workingDirectory, + String projectDirectory, + Map clientEnv, + BuildEventListener buildEventListener) + throws Exception { + this.buildEventListener = buildEventListener; + try { + CliRequest req = new CliRequest(null, null); + req.args = arguments.toArray(new String[0]); + req.workingDirectory = new File(workingDirectory).getCanonicalPath(); + req.multiModuleProjectDirectory = new File(projectDirectory); + return doMain(req, clientEnv); + } finally { + this.buildEventListener = BuildEventListener.dummy(); + } + } + + public int doMain(CliRequest cliRequest, Map clientEnv) throws Exception { + Properties props = (Properties) System.getProperties().clone(); + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(container.getContainerRealm()); + initialize(cliRequest); + environment(cliRequest.workingDirectory, clientEnv); + cli(cliRequest); + properties(cliRequest); + help(cliRequest); + logging(cliRequest); + container(cliRequest); + configure(cliRequest, eventSpyDispatcher, configurationProcessors); + version(cliRequest); + toolchains(cliRequest); + populateRequest(cliRequest); + encryption(cliRequest); + repository(cliRequest); + return execute(cliRequest); + } catch (ExitException e) { + return e.exitCode; + } finally { + eventSpyDispatcher.close(); + System.setProperties(props); + Thread.currentThread().setContextClassLoader(tccl); + } + } + + void initialize(CliRequest cliRequest) throws ExitException { + cliRequest.classWorld = classWorld; + + if (cliRequest.workingDirectory == null) { + cliRequest.workingDirectory = System.getProperty("user.dir"); + } + + if (cliRequest.multiModuleProjectDirectory == null) { + buildEventListener.log(String.format("-D%s system property is not set.", MULTIMODULE_PROJECT_DIRECTORY)); + throw new ExitException(1); + } + System.setProperty("maven.multiModuleProjectDirectory", cliRequest.multiModuleProjectDirectory.toString()); + } + + void cli(CliRequest cliRequest) throws Exception { + CLIManager cliManager = newCLIManager(); + + List args = new ArrayList<>(); + CommandLine mavenConfig = null; + try { + File configFile = new File(cliRequest.multiModuleProjectDirectory, MVN_MAVEN_CONFIG); + + if (configFile.isFile()) { + for (String arg : new String(Files.readAllBytes(configFile.toPath())).split("\\s+")) { + if (!arg.isEmpty()) { + args.add(arg); + } + } + + mavenConfig = cliManager.parse(args.toArray(new String[0])); + List unrecongized = mavenConfig.getArgList(); + if (!unrecongized.isEmpty()) { + throw new ParseException("Unrecognized maven.config entries: " + unrecongized); + } + } + } catch (ParseException e) { + buildEventListener.log("Unable to parse maven.config: " + e.getMessage()); + buildEventListener.log("Run 'mvnd --help' for available options."); + throw new ExitException(1); + } + + try { + if (mavenConfig == null) { + cliRequest.commandLine = cliManager.parse(cliRequest.args); + } else { + cliRequest.commandLine = cliMerge(cliManager.parse(cliRequest.args), mavenConfig); + } + } catch (ParseException e) { + buildEventListener.log("Unable to parse command line options: " + e.getMessage()); + buildEventListener.log("Run 'mvnd --help' for available options."); + throw new ExitException(1); + } + } + + private void help(CliRequest cliRequest) throws Exception { + if (cliRequest.commandLine.hasOption(CLIManager.HELP)) { + buildEventListener.log(MvndHelpFormatter.displayHelp(newCLIManager())); + throw new ExitException(0); + } + } + + private CLIManager newCLIManager() { + CLIManager cliManager = new CLIManager(); + cliManager.options.addOption(Option.builder(RESUME) + .longOpt("resume") + .desc("Resume reactor from " + + "the last failed project, using the resume.properties file in the build directory") + .build()); + cliManager.options.addOption(Option.builder() + .longOpt(RAW_STREAMS) + .desc("Do not decorate output and error streams") + .build()); + return cliManager; + } + + private CommandLine cliMerge(CommandLine mavenArgs, CommandLine mavenConfig) { + CommandLine.Builder commandLineBuilder = new CommandLine.Builder(); + + // the args are easy, cli first then config file + for (String arg : mavenArgs.getArgs()) { + commandLineBuilder.addArg(arg); + } + for (String arg : mavenConfig.getArgs()) { + commandLineBuilder.addArg(arg); + } + + // now add all options, except for -D with cli first then config file + List