stdErr();
-
- /**
- * Indicate if {@code ~/.mavenrc} should be skipped during execution.
- *
- * Affected only for forked executor by adding MAVEN_SKIP_RC environment variable
- */
- boolean skipMavenRc();
-
- /**
- * Returns {@link Builder} created from this instance.
- */
- @Nonnull
- default Builder toBuilder() {
- return new Builder(
- command(),
- arguments(),
- cwd(),
- installationDirectory(),
- userHomeDirectory(),
- jvmSystemProperties().orElse(null),
- environmentVariables().orElse(null),
- jvmArguments().orElse(null),
- stdIn().orElse(null),
- stdOut().orElse(null),
- stdErr().orElse(null),
- skipMavenRc());
- }
-
- /**
- * Returns new builder pre-set to run Maven. The discovery of maven home is attempted, user cwd and home are
- * also discovered by standard means.
- */
- @Nonnull
- static Builder mavenBuilder(@Nullable Path installationDirectory) {
- return new Builder(
- MVN,
- null,
- getCanonicalPath(Paths.get(System.getProperty("user.dir"))),
- installationDirectory != null
- ? getCanonicalPath(installationDirectory)
- : discoverInstallationDirectory(),
- getCanonicalPath(Paths.get(System.getProperty("user.home"))),
- null,
- null,
- null,
- null,
- null,
- null,
- false);
- }
-
- class Builder {
- private String command;
- private List arguments;
- private Path cwd;
- private Path installationDirectory;
- private Path userHomeDirectory;
- private Map jvmSystemProperties;
- private Map environmentVariables;
- private List jvmArguments;
- private InputStream stdIn;
- private OutputStream stdOut;
- private OutputStream stdErr;
- private boolean skipMavenRc;
-
- private Builder() {}
-
- @SuppressWarnings("ParameterNumber")
- private Builder(
- String command,
- List arguments,
- Path cwd,
- Path installationDirectory,
- Path userHomeDirectory,
- Map jvmSystemProperties,
- Map environmentVariables,
- List jvmArguments,
- InputStream stdIn,
- OutputStream stdOut,
- OutputStream stdErr,
- boolean skipMavenRc) {
- this.command = command;
- this.arguments = arguments;
- this.cwd = cwd;
- this.installationDirectory = installationDirectory;
- this.userHomeDirectory = userHomeDirectory;
- this.jvmSystemProperties = jvmSystemProperties;
- this.environmentVariables = environmentVariables;
- this.jvmArguments = jvmArguments;
- this.stdIn = stdIn;
- this.stdOut = stdOut;
- this.stdErr = stdErr;
- this.skipMavenRc = skipMavenRc;
- }
-
- @Nonnull
- public Builder command(String command) {
- this.command = requireNonNull(command, "command");
- return this;
- }
-
- @Nonnull
- public Builder arguments(List arguments) {
- this.arguments = requireNonNull(arguments, "arguments");
- return this;
- }
-
- @Nonnull
- public Builder argument(String argument) {
- if (arguments == null) {
- arguments = new ArrayList<>();
- }
- this.arguments.add(requireNonNull(argument, "argument"));
- return this;
- }
-
- @Nonnull
- public Builder cwd(Path cwd) {
- this.cwd = getCanonicalPath(requireNonNull(cwd, "cwd"));
- return this;
- }
-
- @Nonnull
- public Builder installationDirectory(Path installationDirectory) {
- this.installationDirectory =
- getCanonicalPath(requireNonNull(installationDirectory, "installationDirectory"));
- return this;
- }
-
- @Nonnull
- public Builder userHomeDirectory(Path userHomeDirectory) {
- this.userHomeDirectory = getCanonicalPath(requireNonNull(userHomeDirectory, "userHomeDirectory"));
- return this;
- }
-
- @Nonnull
- public Builder jvmSystemProperties(Map jvmSystemProperties) {
- this.jvmSystemProperties = jvmSystemProperties;
- return this;
- }
-
- @Nonnull
- public Builder jvmSystemProperty(String key, String value) {
- requireNonNull(key, "env key");
- requireNonNull(value, "env value");
- if (jvmSystemProperties == null) {
- this.jvmSystemProperties = new HashMap<>();
- }
- this.jvmSystemProperties.put(key, value);
- return this;
- }
-
- @Nonnull
- public Builder environmentVariables(Map environmentVariables) {
- this.environmentVariables = environmentVariables;
- return this;
- }
-
- @Nonnull
- public Builder environmentVariable(String key, String value) {
- requireNonNull(key, "env key");
- requireNonNull(value, "env value");
- if (environmentVariables == null) {
- this.environmentVariables = new HashMap<>();
- }
- this.environmentVariables.put(key, value);
- return this;
- }
-
- @Nonnull
- public Builder jvmArguments(List jvmArguments) {
- this.jvmArguments = jvmArguments;
- return this;
- }
-
- @Nonnull
- public Builder jvmArgument(String jvmArgument) {
- if (jvmArguments == null) {
- jvmArguments = new ArrayList<>();
- }
- this.jvmArguments.add(requireNonNull(jvmArgument, "jvmArgument"));
- return this;
- }
-
- @Nonnull
- public Builder stdIn(InputStream stdIn) {
- this.stdIn = stdIn;
- return this;
- }
-
- @Nonnull
- public Builder stdOut(OutputStream stdOut) {
- this.stdOut = stdOut;
- return this;
- }
-
- @Nonnull
- public Builder stdErr(OutputStream stdErr) {
- this.stdErr = stdErr;
- return this;
- }
-
- @Nonnull
- public Builder skipMavenRc(boolean skipMavenRc) {
- this.skipMavenRc = skipMavenRc;
- return this;
- }
-
- @Nonnull
- public ExecutorRequest build() {
- return new Impl(
- command,
- arguments,
- cwd,
- installationDirectory,
- userHomeDirectory,
- jvmSystemProperties,
- environmentVariables,
- jvmArguments,
- stdIn,
- stdOut,
- stdErr,
- skipMavenRc);
- }
-
- private static class Impl implements ExecutorRequest {
- private final String command;
- private final List arguments;
- private final Path cwd;
- private final Path installationDirectory;
- private final Path userHomeDirectory;
- private final Map jvmSystemProperties;
- private final Map environmentVariables;
- private final List jvmArguments;
- private final InputStream stdIn;
- private final OutputStream stdOut;
- private final OutputStream stdErr;
- private final boolean skipMavenRc;
-
- @SuppressWarnings("ParameterNumber")
- private Impl(
- String command,
- List arguments,
- Path cwd,
- Path installationDirectory,
- Path userHomeDirectory,
- Map jvmSystemProperties,
- Map environmentVariables,
- List jvmArguments,
- InputStream stdIn,
- OutputStream stdOut,
- OutputStream stdErr,
- boolean skipMavenRc) {
- this.command = requireNonNull(command);
- this.arguments = arguments == null ? List.of() : List.copyOf(arguments);
- this.cwd = getCanonicalPath(requireNonNull(cwd));
- this.installationDirectory = getCanonicalPath(requireNonNull(installationDirectory));
- this.userHomeDirectory = getCanonicalPath(requireNonNull(userHomeDirectory));
- this.jvmSystemProperties = jvmSystemProperties != null && !jvmSystemProperties.isEmpty()
- ? Map.copyOf(jvmSystemProperties)
- : null;
- this.environmentVariables = environmentVariables != null && !environmentVariables.isEmpty()
- ? Map.copyOf(environmentVariables)
- : null;
- this.jvmArguments = jvmArguments != null && !jvmArguments.isEmpty() ? List.copyOf(jvmArguments) : null;
- this.stdIn = stdIn;
- this.stdOut = stdOut;
- this.stdErr = stdErr;
- this.skipMavenRc = skipMavenRc;
- }
-
- @Override
- public String command() {
- return command;
- }
-
- @Override
- public List arguments() {
- return arguments;
- }
-
- @Override
- public Path cwd() {
- return cwd;
- }
-
- @Override
- public Path installationDirectory() {
- return installationDirectory;
- }
-
- @Override
- public Path userHomeDirectory() {
- return userHomeDirectory;
- }
-
- @Override
- public Optional> jvmSystemProperties() {
- return Optional.ofNullable(jvmSystemProperties);
- }
-
- @Override
- public Optional> environmentVariables() {
- return Optional.ofNullable(environmentVariables);
- }
-
- @Override
- public Optional> jvmArguments() {
- return Optional.ofNullable(jvmArguments);
- }
-
- @Override
- public Optional stdIn() {
- return Optional.ofNullable(stdIn);
- }
-
- @Override
- public Optional stdOut() {
- return Optional.ofNullable(stdOut);
- }
-
- @Override
- public Optional stdErr() {
- return Optional.ofNullable(stdErr);
- }
-
- @Override
- public boolean skipMavenRc() {
- return skipMavenRc;
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + "{" + "command='"
- + command + '\'' + ", arguments="
- + arguments + ", cwd="
- + cwd + ", installationDirectory="
- + installationDirectory + ", userHomeDirectory="
- + userHomeDirectory + ", jvmSystemProperties="
- + jvmSystemProperties + ", environmentVariables="
- + environmentVariables + ", jvmArguments="
- + jvmArguments + ", stdinProvider="
- + stdIn + ", stdoutConsumer="
- + stdOut + ", stderrConsumer="
- + stdErr + ", skipMavenRc="
- + skipMavenRc + "}";
- }
- }
- }
-
- @Nonnull
- static Path discoverInstallationDirectory() {
- String mavenHome = System.getProperty("maven.home");
- if (mavenHome == null) {
- throw new ExecutorException("requires maven.home Java System Property set");
- }
- return getCanonicalPath(Paths.get(mavenHome));
- }
-
- @Nonnull
- static Path discoverUserHomeDirectory() {
- String userHome = System.getProperty("user.home");
- if (userHome == null) {
- throw new ExecutorException("requires user.home Java System Property set");
- }
- return getCanonicalPath(Paths.get(userHome));
- }
-
- @Nonnull
- static Path getCanonicalPath(Path path) {
- requireNonNull(path, "path");
- return path.toAbsolutePath().normalize();
- }
-}
diff --git a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/ExecutorTool.java b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/ExecutorTool.java
deleted file mode 100644
index 4a9776742ff8..000000000000
--- a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/ExecutorTool.java
+++ /dev/null
@@ -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.cling.executor;
-
-import java.util.Map;
-
-import org.apache.maven.api.annotations.Nullable;
-
-/**
- * A tool implementing some common Maven operations.
- */
-public interface ExecutorTool {
- /**
- * Performs a diagnostic dump of the environment.
- *
- * @param request never {@code null}
- */
- Map dump(ExecutorRequest.Builder request) throws ExecutorException;
-
- /**
- * Returns the location of local repository, as detected by Maven. The {@code userSettings} param may contain
- * some override (equivalent of {@code -s settings.xml} on CLI).
- *
- * @param request never {@code null}
- */
- String localRepository(ExecutorRequest.Builder request) throws ExecutorException;
-
- /**
- * Returns relative (to {@link #localRepository(ExecutorRequest.Builder)}) path of given artifact in local repository.
- *
- * @param request never {@code null}
- * @param gav the usual resolver artifact GAV string, never {@code null}
- * @param repositoryId the remote repository ID in case "remote artifact" is asked for
- */
- String artifactPath(ExecutorRequest.Builder request, String gav, @Nullable String repositoryId)
- throws ExecutorException;
-
- /**
- * Returns relative (to {@link #localRepository(ExecutorRequest.Builder)}) path of given metadata in local repository.
- * The metadata coordinates in form of {@code [G]:[A]:[V]:[type]}. Absence of {@code A} implies absence of {@code V}
- * as well (in other words, it can be {@code G}, {@code G:A} or {@code G:A:V}). The absence of {@code type} implies
- * it is "maven-metadata.xml". The simplest spec string is {@code :::}.
- *
- * Examples:
- *
- * {@code :::} is root metadata named "maven-metadata.xml"
- * {@code :::my-metadata.xml} is root metadata named "my-metadata.xml"
- * {@code G:::} equals to {@code G:::maven-metadata.xml}
- * {@code G:A::} equals to {@code G:A::maven-metadata.xml}
- *
- *
- * @param request never {@code null}
- * @param gav the resolver metadata GAV string
- * @param repositoryId the remote repository ID in case "remote metadata" is asked for
- */
- String metadataPath(ExecutorRequest.Builder request, String gav, @Nullable String repositoryId)
- throws ExecutorException;
-}
diff --git a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/embedded/EmbeddedMavenExecutor.java b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/embedded/EmbeddedMavenExecutor.java
deleted file mode 100644
index 0e2ddaa4f6e1..000000000000
--- a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/embedded/EmbeddedMavenExecutor.java
+++ /dev/null
@@ -1,457 +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.cling.executor.embedded;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Function;
-import java.util.stream.Stream;
-
-import org.apache.maven.cling.executor.Executor;
-import org.apache.maven.cling.executor.ExecutorException;
-import org.apache.maven.cling.executor.ExecutorRequest;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * Embedded executor implementation, that invokes Maven from installation directory within this same JVM but in isolated
- * classloader. This class supports Maven 4.x and Maven 3.x as well. The ClassWorld of Maven is kept in memory as
- * long as instance of this class is not closed. Subsequent execution requests over same installation home are cached.
- */
-public class EmbeddedMavenExecutor implements Executor {
- /**
- * Maven4 supports multiple commands from same installation directory.
- */
- protected static final Map MVN4_MAIN_CLASSES = Map.of(
- "mvn",
- "org.apache.maven.cling.MavenCling",
- "mvnenc",
- "org.apache.maven.cling.MavenEncCling",
- "mvnsh",
- "org.apache.maven.cling.MavenShellCling");
-
- /**
- * Context holds things loaded up from given Maven Installation Directory.
- */
- protected static final class Context {
- private final URLClassLoader bootClassLoader;
- private final String version;
- private final Object classWorld;
- private final Set originalClassRealmIds;
- private final ClassLoader tccl;
- private final Map> commands; // the commands
- private final Collection keepAlive; // refs things to make sure no GC takes it away
-
- private Context(
- URLClassLoader bootClassLoader,
- String version,
- Object classWorld,
- Set originalClassRealmIds,
- ClassLoader tccl,
- Map> commands,
- Collection keepAlive) {
- this.bootClassLoader = bootClassLoader;
- this.version = version;
- this.classWorld = classWorld;
- this.originalClassRealmIds = originalClassRealmIds;
- this.tccl = tccl;
- this.commands = commands;
- this.keepAlive = keepAlive;
- }
- }
-
- protected final boolean cacheContexts;
- protected final boolean useMavenArgsEnv;
- protected final AtomicBoolean closed;
- protected final InputStream originalStdin;
- protected final PrintStream originalStdout;
- protected final PrintStream originalStderr;
- protected final Properties originalProperties;
- protected final ClassLoader originalClassLoader;
- protected final ConcurrentHashMap contexts;
-
- public EmbeddedMavenExecutor() {
- this(true, true);
- }
-
- public EmbeddedMavenExecutor(boolean cacheContexts, boolean useMavenArgsEnv) {
- this.cacheContexts = cacheContexts;
- this.useMavenArgsEnv = useMavenArgsEnv;
- this.closed = new AtomicBoolean(false);
- this.originalStdin = System.in;
- this.originalStdout = System.out;
- this.originalStderr = System.err;
- this.originalClassLoader = Thread.currentThread().getContextClassLoader();
- this.contexts = new ConcurrentHashMap<>();
- this.originalProperties = new Properties();
- this.originalProperties.putAll(System.getProperties());
- }
-
- @Override
- public int execute(ExecutorRequest executorRequest) throws ExecutorException {
- requireNonNull(executorRequest);
- if (closed.get()) {
- throw new ExecutorException("Executor is closed");
- }
- validate(executorRequest);
- Context context = mayCreate(executorRequest);
- String command = executorRequest.command();
- Function exec = context.commands.get(command);
- if (exec == null) {
- throw new IllegalArgumentException(
- "Unknown command: '" + command + "' for '" + executorRequest.installationDirectory() + "'");
- }
-
- Thread.currentThread().setContextClassLoader(context.tccl);
- try {
- return exec.apply(executorRequest);
- } catch (Exception e) {
- throw new ExecutorException("Failed to execute", e);
- } finally {
- try {
- disposeRuntimeCreatedRealms(context);
- } finally {
- System.setIn(originalStdin);
- System.setOut(originalStdout);
- System.setErr(originalStderr);
- Thread.currentThread().setContextClassLoader(originalClassLoader);
- System.setProperties(originalProperties);
- if (!cacheContexts) {
- doClose(context);
- }
- }
- }
- }
-
- /**
- * Unloads dynamically loaded things, like extensions created realms. Makes sure we go back to "initial state".
- */
- protected void disposeRuntimeCreatedRealms(Context context) {
- try {
- Method getRealms = context.classWorld.getClass().getMethod("getRealms");
- Method disposeRealm = context.classWorld.getClass().getMethod("disposeRealm", String.class);
- List realms = (List) getRealms.invoke(context.classWorld);
- for (Object realm : realms) {
- String realmId = (String) realm.getClass().getMethod("getId").invoke(realm);
- if (!context.originalClassRealmIds.contains(realmId)) {
- disposeRealm.invoke(context.classWorld, realmId);
- }
- }
- } catch (Exception e) {
- throw new ExecutorException("Failed to dispose runtime created realms", e);
- }
- }
-
- @Override
- public String mavenVersion(ExecutorRequest executorRequest) throws ExecutorException {
- requireNonNull(executorRequest);
- if (closed.get()) {
- throw new ExecutorException("Executor is closed");
- }
- validate(executorRequest);
- return mayCreate(executorRequest).version;
- }
-
- protected Context mayCreate(ExecutorRequest executorRequest) {
- Path mavenHome = ExecutorRequest.getCanonicalPath(executorRequest.installationDirectory());
- if (cacheContexts) {
- return contexts.computeIfAbsent(mavenHome, k -> doCreate(mavenHome, executorRequest));
- } else {
- return doCreate(mavenHome, executorRequest);
- }
- }
-
- protected Context doCreate(Path mavenHome, ExecutorRequest executorRequest) {
- if (!Files.isDirectory(mavenHome)) {
- throw new IllegalArgumentException("Installation directory must point to existing directory: " + mavenHome);
- }
- if (!MVN4_MAIN_CLASSES.containsKey(executorRequest.command())) {
- throw new IllegalArgumentException(
- getClass().getSimpleName() + " does not support command " + executorRequest.command());
- }
- if (executorRequest.environmentVariables().isPresent()) {
- throw new IllegalArgumentException(getClass().getSimpleName() + " does not support environment variables: "
- + executorRequest.environmentVariables().get());
- }
- if (executorRequest.jvmArguments().isPresent()) {
- throw new IllegalArgumentException(getClass().getSimpleName() + " does not support jvmArguments: "
- + executorRequest.jvmArguments().get());
- }
- Path boot = mavenHome.resolve("boot");
- Path m2conf = mavenHome.resolve("bin/m2.conf");
- if (!Files.isDirectory(boot) || !Files.isRegularFile(m2conf)) {
- throw new IllegalArgumentException(
- "Installation directory does not point to Maven installation: " + mavenHome);
- }
-
- ArrayList mavenArgs = new ArrayList<>();
- String mavenArgsEnv = System.getenv("MAVEN_ARGS");
- if (useMavenArgsEnv && mavenArgsEnv != null && !mavenArgsEnv.isEmpty()) {
- Arrays.stream(mavenArgsEnv.split(" "))
- .filter(s -> !s.trim().isEmpty())
- .forEach(s -> mavenArgs.add(0, s));
- }
-
- Properties properties = prepareProperties(executorRequest);
- // set ahead of time, if the mavenHome points to Maven4, as ClassWorld Launcher needs this property
- properties.setProperty(
- "maven.mainClass", requireNonNull(MVN4_MAIN_CLASSES.get(ExecutorRequest.MVN), "mainClass"));
- System.setProperties(properties);
- URLClassLoader bootClassLoader = createMavenBootClassLoader(boot, Collections.emptyList());
- Thread.currentThread().setContextClassLoader(bootClassLoader);
- try {
- Class> launcherClass = bootClassLoader.loadClass("org.codehaus.plexus.classworlds.launcher.Launcher");
- Object launcher = launcherClass.getDeclaredConstructor().newInstance();
- Method configure = launcherClass.getMethod("configure", InputStream.class);
- try (InputStream inputStream = Files.newInputStream(m2conf)) {
- configure.invoke(launcher, inputStream);
- }
- Object classWorld = launcherClass.getMethod("getWorld").invoke(launcher);
- Set originalClassRealmIds = new HashSet<>();
-
- // collect pre-created (in m2.conf) class realms as "original ones"; the rest are created at runtime
- Method getRealms = classWorld.getClass().getMethod("getRealms");
- List realms = (List) getRealms.invoke(classWorld);
- for (Object realm : realms) {
- Method realmGetId = realm.getClass().getMethod("getId");
- originalClassRealmIds.add((String) realmGetId.invoke(realm));
- }
-
- Class> cliClass =
- (Class>) launcherClass.getMethod("getMainClass").invoke(launcher);
- String version = getMavenVersion(cliClass);
- Map> commands = new HashMap<>();
- ArrayList keepAlive = new ArrayList<>();
-
- if (version.startsWith("3.")) {
- // 3.x
- if (!ExecutorRequest.MVN.equals(executorRequest.command())) {
- throw new IllegalArgumentException(getClass().getSimpleName() + " w/ mvn3 does not support command "
- + executorRequest.command());
- }
- // 3.9.x
- mayAddToKeepAlive(keepAlive, cliClass, "org.fusesource.jansi.internal.JansiLoader");
- // 3.10.x
- mayAddToKeepAlive(keepAlive, cliClass, "org.jline.nativ.JLineNativeLoader");
-
- Constructor> newMavenCli = cliClass.getConstructor(classWorld.getClass());
- Object mavenCli = newMavenCli.newInstance(classWorld);
- Class>[] parameterTypes = {String[].class, String.class, PrintStream.class, PrintStream.class};
- Method doMain = cliClass.getMethod("doMain", parameterTypes);
- commands.put(ExecutorRequest.MVN, r -> {
- System.setProperties(prepareProperties(r));
- try {
- ArrayList args = new ArrayList<>(mavenArgs);
- args.addAll(r.arguments());
- PrintStream stdout = r.stdOut().isEmpty()
- ? null
- : new PrintStream(r.stdOut().orElseThrow(), true);
- PrintStream stderr = r.stdErr().isEmpty()
- ? null
- : new PrintStream(r.stdErr().orElseThrow(), true);
- return (int) doMain.invoke(mavenCli, new Object[] {
- args.toArray(new String[0]), r.cwd().toString(), stdout, stderr
- });
- } catch (Exception e) {
- throw new ExecutorException("Failed to execute", e);
- }
- });
- } else {
- // assume 4.x
- mayAddToKeepAlive(keepAlive, cliClass, "org.jline.nativ.JLineNativeLoader");
- for (Map.Entry cmdEntry : MVN4_MAIN_CLASSES.entrySet()) {
- Class> cmdClass = cliClass.getClassLoader().loadClass(cmdEntry.getValue());
- Method mainMethod = cmdClass.getMethod(
- "main",
- String[].class,
- classWorld.getClass(),
- InputStream.class,
- OutputStream.class,
- OutputStream.class);
- commands.put(cmdEntry.getKey(), r -> {
- System.setProperties(prepareProperties(r));
- try {
- ArrayList args = new ArrayList<>(mavenArgs);
- args.addAll(r.arguments());
- return (int) mainMethod.invoke(
- null,
- args.toArray(new String[0]),
- classWorld,
- r.stdIn().orElse(null),
- r.stdOut().orElse(null),
- r.stdErr().orElse(null));
- } catch (Exception e) {
- throw new ExecutorException("Failed to execute", e);
- }
- });
- }
- }
-
- return new Context(
- bootClassLoader,
- version,
- classWorld,
- originalClassRealmIds,
- cliClass.getClassLoader(),
- commands,
- keepAlive);
- } catch (Exception e) {
- throw new ExecutorException("Failed to create executor", e);
- } finally {
- Thread.currentThread().setContextClassLoader(originalClassLoader);
- System.setProperties(originalProperties);
- }
- }
-
- private boolean mayAddToKeepAlive(List keepAlive, Class> cliClass, String className) {
- try {
- keepAlive.add(cliClass.getClassLoader().loadClass(className));
- return true;
- } catch (ClassNotFoundException e) {
- return false;
- }
- }
-
- protected Properties prepareProperties(ExecutorRequest request) {
- System.setProperties(null); // this "inits" them!
-
- Properties properties = new Properties();
- properties.putAll(System.getProperties()); // get mandatory/expected init-ed above
-
- properties.setProperty("user.dir", request.cwd().toString());
- properties.setProperty("user.home", request.userHomeDirectory().toString());
-
- Path mavenHome = request.installationDirectory();
- properties.setProperty("maven.home", mavenHome.toString());
- properties.setProperty(
- "maven.multiModuleProjectDirectory", request.cwd().toString());
-
- // Maven 3.x
- properties.setProperty(
- "library.jansi.path", mavenHome.resolve("lib/jansi-native").toString());
-
- // Maven 4.x
- properties.setProperty(
- "library.jline.path", mavenHome.resolve("lib/jline-native").toString());
-
- if (request.jvmSystemProperties().isPresent()) {
- properties.putAll(request.jvmSystemProperties().get());
- }
-
- return properties;
- }
-
- @Override
- public void close() throws ExecutorException {
- if (closed.compareAndExchange(false, true)) {
- try {
- ArrayList exceptions = new ArrayList<>();
- for (Context context : contexts.values()) {
- try {
- doClose(context);
- } catch (Exception e) {
- exceptions.add(e);
- }
- }
- if (!exceptions.isEmpty()) {
- ExecutorException e = new ExecutorException("Could not close cleanly");
- exceptions.forEach(e::addSuppressed);
- throw e;
- }
- } finally {
- System.setProperties(originalProperties);
- }
- }
- }
-
- protected void doClose(Context context) throws ExecutorException {
- Thread.currentThread().setContextClassLoader(context.bootClassLoader);
- try {
- try {
- ((Closeable) context.classWorld).close();
- } finally {
- context.bootClassLoader.close();
- }
- } catch (Exception e) {
- throw new ExecutorException("Failed to close cleanly", e);
- } finally {
- Thread.currentThread().setContextClassLoader(originalClassLoader);
- }
- }
-
- protected void validate(ExecutorRequest executorRequest) throws ExecutorException {}
-
- protected URLClassLoader createMavenBootClassLoader(Path boot, List extraClasspath) {
- ArrayList urls = new ArrayList<>(extraClasspath);
- try (Stream stream = Files.list(boot)) {
- stream.filter(Files::isRegularFile)
- .filter(p -> p.toString().endsWith(".jar"))
- .forEach(f -> {
- try {
- urls.add(f.toUri().toURL());
- } catch (MalformedURLException e) {
- throw new ExecutorException("Failed to build classpath: " + f, e);
- }
- });
- } catch (IOException e) {
- throw new ExecutorException("Failed to build classpath: " + e, e);
- }
- if (urls.isEmpty()) {
- throw new IllegalArgumentException("Invalid Maven home directory; boot is empty");
- }
- return new URLClassLoader(
- urls.toArray(new URL[0]), ClassLoader.getSystemClassLoader().getParent());
- }
-
- protected String getMavenVersion(Class> clazz) throws IOException {
- Properties props = new Properties();
- try (InputStream is = clazz.getResourceAsStream("/META-INF/maven/org.apache.maven/maven-core/pom.properties")) {
- if (is != null) {
- props.load(is);
- }
- String version = props.getProperty("version");
- if (version != null) {
- return version;
- }
- return UNKNOWN_VERSION;
- }
- }
-}
diff --git a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/forked/ForkedMavenExecutor.java b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/forked/ForkedMavenExecutor.java
deleted file mode 100644
index 4671c7427622..000000000000
--- a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/forked/ForkedMavenExecutor.java
+++ /dev/null
@@ -1,226 +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.cling.executor.forked;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.maven.cling.executor.Executor;
-import org.apache.maven.cling.executor.ExecutorException;
-import org.apache.maven.cling.executor.ExecutorRequest;
-
-import static java.util.Objects.requireNonNull;
-import static org.apache.maven.cling.executor.ExecutorRequest.getCanonicalPath;
-
-/**
- * Forked executor implementation, that spawns a subprocess with Maven from the installation directory. Very costly
- * but provides the best isolation.
- */
-public class ForkedMavenExecutor implements Executor {
- protected final boolean useMavenArgsEnv;
- protected final AtomicBoolean closed;
-
- public ForkedMavenExecutor() {
- this(true);
- }
-
- public ForkedMavenExecutor(boolean useMavenArgsEnv) {
- this.useMavenArgsEnv = useMavenArgsEnv;
- this.closed = new AtomicBoolean(false);
- }
-
- @Override
- public int execute(ExecutorRequest executorRequest) throws ExecutorException {
- requireNonNull(executorRequest);
- if (closed.get()) {
- throw new ExecutorException("Executor is closed");
- }
- validate(executorRequest);
-
- return doExecute(executorRequest);
- }
-
- @Override
- public String mavenVersion(ExecutorRequest executorRequest) throws ExecutorException {
- requireNonNull(executorRequest);
- if (closed.get()) {
- throw new ExecutorException("Executor is closed");
- }
- validate(executorRequest);
- try {
- Path cwd = Files.createTempDirectory("forked-executor-maven-version");
- try {
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- int exitCode = execute(executorRequest.toBuilder()
- .cwd(cwd)
- .arguments(List.of("--version", "--quiet"))
- .stdOut(stdout)
- .build());
- if (exitCode == 0) {
- if (stdout.size() > 0) {
- return stdout.toString()
- .replace("\n", "")
- .replace("\r", "")
- .trim();
- }
- return UNKNOWN_VERSION;
- } else {
- throw new ExecutorException(
- "Maven version query unexpected exitCode=" + exitCode + "\nLog: " + stdout);
- }
- } finally {
- Files.deleteIfExists(cwd);
- }
- } catch (IOException e) {
- throw new ExecutorException("Failed to determine maven version", e);
- }
- }
-
- protected void validate(ExecutorRequest executorRequest) throws ExecutorException {}
-
- protected int doExecute(ExecutorRequest executorRequest) throws ExecutorException {
- ArrayList cmdAndArguments = new ArrayList<>();
- cmdAndArguments.add(executorRequest
- .installationDirectory()
- .resolve("bin")
- .resolve(IS_WINDOWS ? executorRequest.command() + ".cmd" : executorRequest.command())
- .toString());
-
- String mavenArgsEnv = System.getenv("MAVEN_ARGS");
- if (useMavenArgsEnv && mavenArgsEnv != null && !mavenArgsEnv.isEmpty()) {
- Arrays.stream(mavenArgsEnv.split(" "))
- .filter(s -> !s.trim().isEmpty())
- .forEach(cmdAndArguments::add);
- }
-
- cmdAndArguments.addAll(executorRequest.arguments());
-
- ArrayList jvmArgs = new ArrayList<>();
- if (!executorRequest.userHomeDirectory().equals(getCanonicalPath(Paths.get(System.getProperty("user.home"))))) {
- jvmArgs.add("-Duser.home=" + executorRequest.userHomeDirectory().toString());
- }
- if (executorRequest.jvmArguments().isPresent()) {
- jvmArgs.addAll(executorRequest.jvmArguments().get());
- }
- if (executorRequest.jvmSystemProperties().isPresent()) {
- jvmArgs.addAll(executorRequest.jvmSystemProperties().get().entrySet().stream()
- .map(e -> "-D" + e.getKey() + "=" + e.getValue())
- .toList());
- }
-
- HashMap env = new HashMap<>();
- if (executorRequest.environmentVariables().isPresent()) {
- env.putAll(executorRequest.environmentVariables().get());
- }
- if (!jvmArgs.isEmpty()) {
- String mavenOpts = env.getOrDefault("MAVEN_OPTS", "");
- if (!mavenOpts.isEmpty()) {
- mavenOpts += " ";
- }
- mavenOpts += String.join(" ", jvmArgs);
- env.put("MAVEN_OPTS", mavenOpts);
- }
- env.remove("MAVEN_ARGS"); // we already used it if configured to do so
-
- if (executorRequest.skipMavenRc()) {
- env.put("MAVEN_SKIP_RC", "true");
- }
-
- try {
- ProcessBuilder pb = new ProcessBuilder()
- .directory(executorRequest.cwd().toFile())
- .command(cmdAndArguments);
- if (!env.isEmpty()) {
- pb.environment().putAll(env);
- }
-
- Process process = pb.start();
- pump(process, executorRequest).await();
- return process.waitFor();
- } catch (IOException e) {
- throw new ExecutorException("IO problem while executing command: " + cmdAndArguments, e);
- } catch (InterruptedException e) {
- throw new ExecutorException("Interrupted while executing command: " + cmdAndArguments, e);
- }
- }
-
- protected CountDownLatch pump(Process p, ExecutorRequest executorRequest) {
- CountDownLatch latch = new CountDownLatch(3);
- String suffix = "-pump-" + p.pid();
- Thread stdoutPump = new Thread(() -> {
- try {
- OutputStream stdout = executorRequest.stdOut().orElse(OutputStream.nullOutputStream());
- p.getInputStream().transferTo(stdout);
- stdout.flush();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } finally {
- latch.countDown();
- }
- });
- stdoutPump.setName("stdout" + suffix);
- stdoutPump.start();
- Thread stderrPump = new Thread(() -> {
- try {
- OutputStream stderr = executorRequest.stdErr().orElse(OutputStream.nullOutputStream());
- p.getErrorStream().transferTo(stderr);
- stderr.flush();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } finally {
- latch.countDown();
- }
- });
- stderrPump.setName("stderr" + suffix);
- stderrPump.start();
- Thread stdinPump = new Thread(() -> {
- try {
- OutputStream in = p.getOutputStream();
- executorRequest.stdIn().orElse(InputStream.nullInputStream()).transferTo(in);
- in.flush();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } finally {
- latch.countDown();
- }
- });
- stdinPump.setName("stdin" + suffix);
- stdinPump.start();
- return latch;
- }
-
- @Override
- public void close() throws ExecutorException {
- if (closed.compareAndExchange(false, true)) {
- // nothing yet
- }
- }
-}
diff --git a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/HelperImpl.java b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/HelperImpl.java
deleted file mode 100644
index d8109ba3e252..000000000000
--- a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/HelperImpl.java
+++ /dev/null
@@ -1,102 +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.cling.executor.internal;
-
-import java.nio.file.Path;
-import java.util.HashMap;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.maven.api.annotations.Nullable;
-import org.apache.maven.cling.executor.Executor;
-import org.apache.maven.cling.executor.ExecutorException;
-import org.apache.maven.cling.executor.ExecutorHelper;
-import org.apache.maven.cling.executor.ExecutorRequest;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * Simple router to executors, and delegate to executor tool.
- */
-public class HelperImpl implements ExecutorHelper {
- private final Mode defaultMode;
- private final Path installationDirectory;
- private final Path userHomeDirectory;
- private final HashMap executors;
-
- private final ConcurrentHashMap cache;
-
- public HelperImpl(
- Mode defaultMode,
- @Nullable Path installationDirectory,
- @Nullable Path userHomeDirectory,
- Executor embedded,
- Executor forked) {
- this.defaultMode = requireNonNull(defaultMode);
- this.installationDirectory = installationDirectory != null
- ? ExecutorRequest.getCanonicalPath(installationDirectory)
- : ExecutorRequest.discoverInstallationDirectory();
- this.userHomeDirectory = userHomeDirectory != null
- ? ExecutorRequest.getCanonicalPath(userHomeDirectory)
- : ExecutorRequest.discoverUserHomeDirectory();
- this.executors = new HashMap<>();
-
- this.executors.put(Mode.EMBEDDED, requireNonNull(embedded, "embedded"));
- this.executors.put(Mode.FORKED, requireNonNull(forked, "forked"));
- this.cache = new ConcurrentHashMap<>();
- }
-
- @Override
- public Mode getDefaultMode() {
- return defaultMode;
- }
-
- @Override
- public ExecutorRequest.Builder executorRequest() {
- return ExecutorRequest.mavenBuilder(installationDirectory).userHomeDirectory(userHomeDirectory);
- }
-
- @Override
- public int execute(Mode mode, ExecutorRequest executorRequest) throws ExecutorException {
- return getExecutor(mode, executorRequest).execute(executorRequest);
- }
-
- @Override
- public String mavenVersion() {
- return cache.computeIfAbsent("maven.version", k -> {
- ExecutorRequest request = executorRequest().build();
- return getExecutor(Mode.AUTO, request).mavenVersion(request);
- });
- }
-
- protected Executor getExecutor(Mode mode, ExecutorRequest request) throws ExecutorException {
- return switch (mode) {
- case AUTO -> getExecutorByRequest(request);
- case EMBEDDED -> executors.get(Mode.EMBEDDED);
- case FORKED -> executors.get(Mode.FORKED);
- };
- }
-
- private Executor getExecutorByRequest(ExecutorRequest request) {
- if (request.environmentVariables().isEmpty() && request.jvmArguments().isEmpty()) {
- return getExecutor(Mode.EMBEDDED, request);
- } else {
- return getExecutor(Mode.FORKED, request);
- }
- }
-}
diff --git a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/ToolboxTool.java b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/ToolboxTool.java
deleted file mode 100644
index 2adc21c43819..000000000000
--- a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/ToolboxTool.java
+++ /dev/null
@@ -1,170 +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.cling.executor.internal;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.stream.Collectors;
-
-import org.apache.maven.cling.executor.ExecutorException;
-import org.apache.maven.cling.executor.ExecutorHelper;
-import org.apache.maven.cling.executor.ExecutorRequest;
-import org.apache.maven.cling.executor.ExecutorTool;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * {@link ExecutorTool} implementation based on Maveniverse Toolbox. It uses Toolbox mojos to implement all the
- * required operations.
- *
- * @see Maveniverse Toolbox
- */
-public class ToolboxTool implements ExecutorTool {
- private static final String TOOLBOX_PREFIX = "eu.maveniverse.maven.plugins:toolbox:";
-
- private final ExecutorHelper helper;
- private final String toolboxVersion;
- private final ExecutorHelper.Mode forceMode;
-
- /**
- * @deprecated Better specify required version yourself. This one is "cemented" to 0.13.7
- */
- @Deprecated
- public ToolboxTool(ExecutorHelper helper) {
- this(helper, "0.13.7");
- }
-
- public ToolboxTool(ExecutorHelper helper, String toolboxVersion) {
- this(helper, toolboxVersion, null);
- }
-
- public ToolboxTool(ExecutorHelper helper, String toolboxVersion, ExecutorHelper.Mode forceMode) {
- this.helper = requireNonNull(helper);
- this.toolboxVersion = requireNonNull(toolboxVersion);
- this.forceMode = forceMode; // nullable
- }
-
- @Override
- public Map dump(ExecutorRequest.Builder executorRequest) throws ExecutorException {
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- ByteArrayOutputStream stderr = new ByteArrayOutputStream();
- ExecutorRequest.Builder builder = mojo(executorRequest, "gav-dump")
- .argument("-DasProperties")
- .stdOut(stdout)
- .stdErr(stderr);
- doExecute(builder);
- try {
- Properties properties = new Properties();
- properties.load(new ByteArrayInputStream(
- validateOutput(false, stdout, stderr).getBytes()));
- return properties.entrySet().stream()
- .collect(Collectors.toMap(
- e -> String.valueOf(e.getKey()),
- e -> String.valueOf(e.getValue()),
- (prev, next) -> next,
- HashMap::new));
- } catch (IOException e) {
- throw new ExecutorException("Unable to parse properties", e);
- }
- }
-
- @Override
- public String localRepository(ExecutorRequest.Builder executorRequest) throws ExecutorException {
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- ByteArrayOutputStream stderr = new ByteArrayOutputStream();
- ExecutorRequest.Builder builder = mojo(executorRequest, "gav-local-repository-path")
- .stdOut(stdout)
- .stdErr(stderr);
- doExecute(builder);
- return validateOutput(true, stdout, stderr);
- }
-
- @Override
- public String artifactPath(ExecutorRequest.Builder executorRequest, String gav, String repositoryId)
- throws ExecutorException {
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- ByteArrayOutputStream stderr = new ByteArrayOutputStream();
- ExecutorRequest.Builder builder = mojo(executorRequest, "gav-artifact-path")
- .argument("-Dgav=" + gav)
- .stdOut(stdout)
- .stdErr(stderr);
- if (repositoryId != null) {
- builder.argument("-Drepository=" + repositoryId + "::unimportant");
- }
- doExecute(builder);
- return validateOutput(true, stdout, stderr);
- }
-
- @Override
- public String metadataPath(ExecutorRequest.Builder executorRequest, String gav, String repositoryId)
- throws ExecutorException {
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- ByteArrayOutputStream stderr = new ByteArrayOutputStream();
- ExecutorRequest.Builder builder = mojo(executorRequest, "gav-metadata-path")
- .argument("-Dgav=" + gav)
- .stdOut(stdout)
- .stdErr(stderr);
- if (repositoryId != null) {
- builder.argument("-Drepository=" + repositoryId + "::unimportant");
- }
- doExecute(builder);
- return validateOutput(true, stdout, stderr);
- }
-
- private ExecutorRequest.Builder mojo(ExecutorRequest.Builder builder, String mojo) {
- if (helper.mavenVersion().startsWith("4.")) {
- builder.argument("--raw-streams");
- }
- return builder.argument(TOOLBOX_PREFIX + toolboxVersion + ":" + mojo)
- .argument("--quiet")
- .argument("-DforceStdout");
- }
-
- private void doExecute(ExecutorRequest.Builder builder) {
- ExecutorRequest request = builder.build();
- int ec = forceMode == null ? helper.execute(request) : helper.execute(forceMode, request);
- if (ec != 0) {
- throw new ExecutorException("Unexpected exit code=" + ec + "; stdout="
- + request.stdOut().orElse(null) + "; stderr="
- + request.stdErr().orElse(null));
- }
- }
-
- /**
- * Performs "sanity check" for output, making sure no insane values like empty strings are returned.
- */
- private String validateOutput(boolean shave, ByteArrayOutputStream stdout, ByteArrayOutputStream stderr) {
- String result = stdout.toString();
- if (shave) {
- result = result.replace("\n", "").replace("\r", "");
- }
- // sanity checks: stderr has any OR result is empty string (no method should emit empty string)
- if (result.trim().isEmpty()) {
- // see bug https://github.com/apache/maven/pull/11303 Fail in this case
- // tl;dr We NEVER expect empty string as output from this tool; so fail here instead to chase ghosts
- throw new IllegalStateException("Empty output from Toolbox; stdout[" + stdout.size() + "]=" + stdout
- + "; stderr[" + stderr.size() + "]=" + stderr);
- }
- return result;
- }
-}
diff --git a/impl/maven-executor/src/site/site.xml b/impl/maven-executor/src/site/site.xml
deleted file mode 100644
index 4ee3b709cfc4..000000000000
--- a/impl/maven-executor/src/site/site.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
- ${project.scm.url}
-
-
-
-
-
-
-
-
-
-
diff --git a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/Environment.java b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/Environment.java
deleted file mode 100644
index 771661a435a9..000000000000
--- a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/Environment.java
+++ /dev/null
@@ -1,25 +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.cling.executor;
-
-public final class Environment {
- private Environment() {}
-
- public static final String TOOLBOX_VERSION = System.getProperty("version.toolbox", "UNSET version.toolbox");
-}
diff --git a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java
deleted file mode 100644
index a2a095271cf6..000000000000
--- a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java
+++ /dev/null
@@ -1,412 +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.cling.executor;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Collection;
-import java.util.List;
-
-import eu.maveniverse.maven.mimir.testing.MimirInfuser;
-import org.apache.maven.api.annotations.Nullable;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInfo;
-import org.junit.jupiter.api.Timeout;
-import org.junit.jupiter.api.condition.DisabledOnOs;
-import org.junit.jupiter.api.io.CleanupMode;
-import org.junit.jupiter.api.io.TempDir;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.condition.OS.WINDOWS;
-
-@Timeout(60)
-public abstract class MavenExecutorTestSupport {
- @TempDir(cleanup = CleanupMode.NEVER)
- private static Path tempDir;
-
- private Path cwd;
-
- private Path userHome;
-
- @BeforeEach
- void beforeEach(TestInfo testInfo) throws Exception {
- cwd = tempDir.resolve(testInfo.getTestMethod().orElseThrow().getName()).resolve("cwd");
- Files.createDirectories(cwd.resolve(".mvn"));
- userHome = tempDir.resolve(testInfo.getTestMethod().orElseThrow().getName())
- .resolve("home");
- Files.createDirectories(userHome);
-
- System.out.println("=== " + testInfo.getTestMethod().orElseThrow().getName());
- }
-
- private static Executor executor;
-
- protected final Executor createAndMemoizeExecutor() {
- if (executor == null) {
- executor = doSelectExecutor();
- }
- return executor;
- }
-
- @AfterAll
- static void afterAll() {
- if (executor != null) {
- executor.close();
- executor = null;
- }
- }
-
- protected abstract Executor doSelectExecutor();
-
- @Test
- void mvnenc4() throws Exception {
- String logfile = "m4.log";
- execute(
- cwd.resolve(logfile),
- List.of(mvn4ExecutorRequestBuilder()
- .command("mvnenc")
- .cwd(cwd)
- .userHomeDirectory(userHome)
- .argument("diag")
- .argument("-l")
- .argument(logfile)
- .build()));
- System.out.println(Files.readString(cwd.resolve(logfile)));
- }
-
- @DisabledOnOs(
- value = WINDOWS,
- disabledReason = "JUnit on Windows fails to clean up as mvn3 does not close log file properly")
- @Test
- void dump3() throws Exception {
- String logfile = "m3.log";
- execute(
- cwd.resolve(logfile),
- List.of(mvn3ExecutorRequestBuilder()
- .cwd(cwd)
- .userHomeDirectory(userHome)
- .argument("eu.maveniverse.maven.plugins:toolbox:" + Environment.TOOLBOX_VERSION + ":gav-dump")
- .argument("-l")
- .argument(logfile)
- .build()));
- System.out.println(Files.readString(cwd.resolve(logfile)));
- }
-
- @Test
- void dump4() throws Exception {
- String logfile = "m4.log";
- execute(
- cwd.resolve(logfile),
- List.of(mvn4ExecutorRequestBuilder()
- .cwd(cwd)
- .userHomeDirectory(userHome)
- .argument("eu.maveniverse.maven.plugins:toolbox:" + Environment.TOOLBOX_VERSION + ":gav-dump")
- .argument("-l")
- .argument(logfile)
- .build()));
- System.out.println(Files.readString(cwd.resolve(logfile)));
- }
-
- @DisabledOnOs(
- value = WINDOWS,
- disabledReason = "JUnit on Windows fails to clean up as mvn3 does not close log file properly")
- @Test
- void defaultFs3() throws Exception {
- layDownFiles(cwd);
- String logfile = "m3.log";
- execute(
- cwd.resolve(logfile),
- List.of(mvn3ExecutorRequestBuilder()
- .cwd(cwd)
- .argument("-V")
- .argument("verify")
- .argument("-l")
- .argument(logfile)
- .build()));
- System.out.println(Files.readString(cwd.resolve(logfile)));
- }
-
- @Test
- void defaultFs4() throws Exception {
- layDownFiles(cwd);
- String logfile = "m4.log";
- execute(
- cwd.resolve(logfile),
- List.of(mvn4ExecutorRequestBuilder()
- .cwd(cwd)
- .argument("-V")
- .argument("verify")
- .argument("-l")
- .argument(logfile)
- .build()));
- System.out.println(Files.readString(cwd.resolve(logfile)));
- }
-
- @Test
- void version3() throws Exception {
- assertEquals(
- System.getProperty("maven3version"),
- mavenVersion(mvn3ExecutorRequestBuilder().build()));
- }
-
- @Test
- void version4() throws Exception {
- assertEquals(
- System.getProperty("maven4version"),
- mavenVersion(mvn4ExecutorRequestBuilder().build()));
- }
-
- @Test
- void defaultFs4CaptureOutput() throws Exception {
- layDownFiles(cwd);
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- execute(
- null,
- List.of(mvn4ExecutorRequestBuilder()
- .cwd(cwd)
- .argument("-V")
- .argument("verify")
- .stdOut(stdout)
- .build()));
- System.out.println(stdout);
- assertFalse(stdout.toString().contains("[\u001B["), "By default no ANSI color codes");
- assertTrue(stdout.toString().contains("INFO"), "No INFO found");
- }
-
- @Test
- void defaultFs4CaptureOutputWithForcedColor() throws Exception {
- layDownFiles(cwd);
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- execute(
- null,
- List.of(mvn4ExecutorRequestBuilder()
- .cwd(cwd)
- .argument("-V")
- .argument("verify")
- .argument("--color=yes")
- .stdOut(stdout)
- .build()));
- System.out.println(stdout);
- assertTrue(stdout.toString().contains("[\u001B["), "No ANSI codes present");
- assertTrue(stdout.toString().contains("INFO"), "No INFO found");
- }
-
- @Test
- void defaultFs4CaptureOutputWithForcedOffColor() throws Exception {
- layDownFiles(cwd);
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- execute(
- null,
- List.of(mvn4ExecutorRequestBuilder()
- .cwd(cwd)
- .argument("-V")
- .argument("verify")
- .argument("--color=no")
- .stdOut(stdout)
- .build()));
- System.out.println(stdout);
- assertFalse(stdout.toString().contains("[\u001B["), "No ANSI codes present");
- assertTrue(stdout.toString().contains("INFO"), "No INFO found");
- }
-
- @Test
- void defaultFs3CaptureOutput() throws Exception {
- layDownFiles(cwd);
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- execute(
- null,
- List.of(mvn3ExecutorRequestBuilder()
- .cwd(cwd)
- .argument("-V")
- .argument("verify")
- .stdOut(stdout)
- .build()));
- System.out.println(stdout);
- // Note: we do not validate ANSI as Maven3 is weird in this respect (thinks is color but is not)
- // assertTrue(stdout.toString().contains("[\u001B["), "No ANSI codes present");
- assertTrue(stdout.toString().contains("INFO"), "No INFO found");
- }
-
- @Test
- void defaultFs3CaptureOutputWithForcedColor() throws Exception {
- layDownFiles(cwd);
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- execute(
- null,
- List.of(mvn3ExecutorRequestBuilder()
- .cwd(cwd)
- .argument("-V")
- .argument("verify")
- .argument("--color=yes")
- .stdOut(stdout)
- .build()));
- System.out.println(stdout);
- assertTrue(stdout.toString().contains("[\u001B["), "No ANSI codes present");
- assertTrue(stdout.toString().contains("INFO"), "No INFO found");
- }
-
- @Test
- void defaultFs3CaptureOutputWithForcedOffColor() throws Exception {
- layDownFiles(cwd);
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- execute(
- null,
- List.of(mvn3ExecutorRequestBuilder()
- .cwd(cwd)
- .argument("-V")
- .argument("verify")
- .argument("--color=no")
- .stdOut(stdout)
- .build()));
- System.out.println(stdout);
- assertFalse(stdout.toString().contains("[\u001B["), "No ANSI codes present");
- assertTrue(stdout.toString().contains("INFO"), "No INFO found");
- }
-
- public static final String POM_STRING = """
-
-
-
- 4.0.0
-
- org.apache.maven.samples
- sample
- 1.0.0
-
-
-
-
- org.junit
- junit-bom
- 5.11.1
- pom
- import
-
-
-
-
-
-
- org.junit.jupiter
- junit-jupiter-api
- test
-
-
-
-
- """;
-
- public static final String APP_JAVA_STRING = """
- package org.apache.maven.samples.sample;
-
- public class App {
- public static void main(String... args) {
- System.out.println("Hello World!");
- }
- }
- """;
-
- protected void execute(@Nullable Path logFile, Collection requests) throws Exception {
- Executor invoker = createAndMemoizeExecutor();
- for (ExecutorRequest request : requests) {
- if (MimirInfuser.isMimirPresentUW()) {
- if (maven3Home().equals(request.installationDirectory())) {
- MimirInfuser.doInfusePW(request.cwd(), request.userHomeDirectory());
- } else if (maven4Home().equals(request.installationDirectory())) {
- MimirInfuser.doInfuseUW(request.userHomeDirectory());
- }
- MimirInfuser.preseedItselfIntoInnerUserHome(request.userHomeDirectory());
- }
- int exitCode = invoker.execute(request);
- if (exitCode != 0) {
- throw new FailedExecution(request, exitCode, logFile == null ? "" : Files.readString(logFile));
- }
- }
- }
-
- protected String mavenVersion(ExecutorRequest request) throws Exception {
- return createAndMemoizeExecutor().mavenVersion(request);
- }
-
- public ExecutorRequest.Builder mvn3ExecutorRequestBuilder() {
- return customize(ExecutorRequest.mavenBuilder(maven3Home()));
- }
-
- private Path maven3Home() {
- return ExecutorRequest.getCanonicalPath(Paths.get(System.getProperty("maven3home")));
- }
-
- public ExecutorRequest.Builder mvn4ExecutorRequestBuilder() {
- return customize(ExecutorRequest.mavenBuilder(maven4Home()));
- }
-
- private Path maven4Home() {
- return ExecutorRequest.getCanonicalPath(Paths.get(System.getProperty("maven4home")));
- }
-
- private ExecutorRequest.Builder customize(ExecutorRequest.Builder builder) {
- builder =
- builder.cwd(cwd).userHomeDirectory(userHome).argument("-Daether.remoteRepositoryFilter.prefixes=false");
- if (System.getProperty("localRepository") != null) {
- builder.argument("-Dmaven.repo.local.tail=" + System.getProperty("localRepository"));
- }
- return builder;
- }
-
- protected void layDownFiles(Path cwd) throws IOException {
- Path pom = cwd.resolve("pom.xml").toAbsolutePath();
- Files.writeString(pom, POM_STRING);
- Path appJava = cwd.resolve("src/main/java/org/apache/maven/samples/sample/App.java");
- Files.createDirectories(appJava.getParent());
- Files.writeString(appJava, APP_JAVA_STRING);
- }
-
- protected static class FailedExecution extends Exception {
- private final ExecutorRequest request;
- private final int exitCode;
- private final String log;
-
- public FailedExecution(ExecutorRequest request, int exitCode, String log) {
- super(request.toString() + " => " + exitCode + "\n" + log);
- this.request = request;
- this.exitCode = exitCode;
- this.log = log;
- }
-
- public ExecutorRequest getRequest() {
- return request;
- }
-
- public int getExitCode() {
- return exitCode;
- }
-
- public String getLog() {
- return log;
- }
- }
-}
diff --git a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/embedded/EmbeddedMavenExecutorTest.java b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/embedded/EmbeddedMavenExecutorTest.java
deleted file mode 100644
index 6433235b6927..000000000000
--- a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/embedded/EmbeddedMavenExecutorTest.java
+++ /dev/null
@@ -1,33 +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.cling.executor.embedded;
-
-import org.apache.maven.cling.executor.Executor;
-import org.apache.maven.cling.executor.MavenExecutorTestSupport;
-
-/**
- * Embedded executor UT
- */
-public class EmbeddedMavenExecutorTest extends MavenExecutorTestSupport {
-
- @Override
- protected Executor doSelectExecutor() {
- return new EmbeddedMavenExecutor();
- }
-}
diff --git a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/forked/ForkedMavenExecutorTest.java b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/forked/ForkedMavenExecutorTest.java
deleted file mode 100644
index a1f4362eac9b..000000000000
--- a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/forked/ForkedMavenExecutorTest.java
+++ /dev/null
@@ -1,33 +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.cling.executor.forked;
-
-import org.apache.maven.cling.executor.Executor;
-import org.apache.maven.cling.executor.MavenExecutorTestSupport;
-
-/**
- * Forked executor UT
- */
-public class ForkedMavenExecutorTest extends MavenExecutorTestSupport {
-
- @Override
- protected Executor doSelectExecutor() {
- return new ForkedMavenExecutor();
- }
-}
diff --git a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/impl/ToolboxToolTest.java b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/impl/ToolboxToolTest.java
deleted file mode 100644
index fc856268248c..000000000000
--- a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/impl/ToolboxToolTest.java
+++ /dev/null
@@ -1,211 +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.cling.executor.impl;
-
-import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Map;
-
-import eu.maveniverse.maven.mimir.testing.MimirInfuser;
-import org.apache.maven.cling.executor.Environment;
-import org.apache.maven.cling.executor.Executor;
-import org.apache.maven.cling.executor.ExecutorHelper;
-import org.apache.maven.cling.executor.ExecutorRequest;
-import org.apache.maven.cling.executor.embedded.EmbeddedMavenExecutor;
-import org.apache.maven.cling.executor.forked.ForkedMavenExecutor;
-import org.apache.maven.cling.executor.internal.HelperImpl;
-import org.apache.maven.cling.executor.internal.ToolboxTool;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.TestInfo;
-import org.junit.jupiter.api.Timeout;
-import org.junit.jupiter.api.io.CleanupMode;
-import org.junit.jupiter.api.io.TempDir;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-@Timeout(60)
-public class ToolboxToolTest {
- private static final Executor EMBEDDED_MAVEN_EXECUTOR = new EmbeddedMavenExecutor();
- private static final Executor FORKED_MAVEN_EXECUTOR = new ForkedMavenExecutor();
-
- @TempDir(cleanup = CleanupMode.NEVER)
- private static Path tempDir;
-
- private Path userHome;
- private Path cwd;
-
- @BeforeEach
- void beforeEach(TestInfo testInfo) throws Exception {
- String testName = testInfo.getTestMethod().orElseThrow().getName();
- userHome = tempDir.resolve(testName);
- cwd = userHome.resolve("cwd");
- Files.createDirectories(cwd.resolve(".mvn"));
-
- if (MimirInfuser.isMimirPresentUW()) {
- if (testName.contains("3")) {
- MimirInfuser.doInfusePW(cwd, userHome);
- } else {
- MimirInfuser.doInfuseUW(userHome);
- }
- MimirInfuser.preseedItselfIntoInnerUserHome(userHome);
- }
-
- System.out.println("=== " + testInfo.getTestMethod().orElseThrow().getName());
- }
-
- private ExecutorRequest.Builder getExecutorRequest(ExecutorHelper helper) {
- ExecutorRequest.Builder builder =
- helper.executorRequest().cwd(cwd).argument("-Daether.remoteRepositoryFilter.prefixes=false");
- if (System.getProperty("localRepository") != null) {
- builder.argument("-Dmaven.repo.local.tail=" + System.getProperty("localRepository"));
- }
- return builder;
- }
-
- @ParameterizedTest
- @EnumSource(ExecutorHelper.Mode.class)
- void dump3(ExecutorHelper.Mode mode) throws Exception {
- ExecutorHelper helper =
- new HelperImpl(mode, mvn3Home(), userHome, EMBEDDED_MAVEN_EXECUTOR, FORKED_MAVEN_EXECUTOR);
- Map dump =
- new ToolboxTool(helper, Environment.TOOLBOX_VERSION).dump(getExecutorRequest(helper));
- System.out.println(mode.name() + ": " + dump.toString());
- assertEquals(System.getProperty("maven3version"), dump.get("maven.version"));
- }
-
- @ParameterizedTest
- @EnumSource(ExecutorHelper.Mode.class)
- void dump4(ExecutorHelper.Mode mode) throws Exception {
- ExecutorHelper helper =
- new HelperImpl(mode, mvn4Home(), userHome, EMBEDDED_MAVEN_EXECUTOR, FORKED_MAVEN_EXECUTOR);
- Map dump =
- new ToolboxTool(helper, Environment.TOOLBOX_VERSION).dump(getExecutorRequest(helper));
- System.out.println(mode.name() + ": " + dump.toString());
- assertEquals(System.getProperty("maven4version"), dump.get("maven.version"));
- }
-
- @ParameterizedTest
- @EnumSource(ExecutorHelper.Mode.class)
- void version3(ExecutorHelper.Mode mode) {
- ExecutorHelper helper =
- new HelperImpl(mode, mvn3Home(), userHome, EMBEDDED_MAVEN_EXECUTOR, FORKED_MAVEN_EXECUTOR);
- System.out.println(mode.name() + ": " + helper.mavenVersion());
- assertEquals(System.getProperty("maven3version"), helper.mavenVersion());
- }
-
- @ParameterizedTest
- @EnumSource(ExecutorHelper.Mode.class)
- void version4(ExecutorHelper.Mode mode) {
- ExecutorHelper helper =
- new HelperImpl(mode, mvn4Home(), userHome, EMBEDDED_MAVEN_EXECUTOR, FORKED_MAVEN_EXECUTOR);
- System.out.println(mode.name() + ": " + helper.mavenVersion());
- assertEquals(System.getProperty("maven4version"), helper.mavenVersion());
- }
-
- @ParameterizedTest
- @EnumSource(ExecutorHelper.Mode.class)
- void localRepository3(ExecutorHelper.Mode mode) {
- ExecutorHelper helper =
- new HelperImpl(mode, mvn3Home(), userHome, EMBEDDED_MAVEN_EXECUTOR, FORKED_MAVEN_EXECUTOR);
- String localRepository =
- new ToolboxTool(helper, Environment.TOOLBOX_VERSION).localRepository(getExecutorRequest(helper));
- System.out.println(mode.name() + ": " + localRepository);
- Path local = Paths.get(localRepository);
- assertTrue(Files.isDirectory(local));
- }
-
- @ParameterizedTest
- @EnumSource(ExecutorHelper.Mode.class)
- void localRepository4(ExecutorHelper.Mode mode) {
- ExecutorHelper helper =
- new HelperImpl(mode, mvn4Home(), userHome, EMBEDDED_MAVEN_EXECUTOR, FORKED_MAVEN_EXECUTOR);
- String localRepository =
- new ToolboxTool(helper, Environment.TOOLBOX_VERSION).localRepository(getExecutorRequest(helper));
- System.out.println(mode.name() + ": " + localRepository);
- Path local = Paths.get(localRepository);
- assertTrue(Files.isDirectory(local));
- }
-
- @ParameterizedTest
- @EnumSource(ExecutorHelper.Mode.class)
- void artifactPath3(ExecutorHelper.Mode mode) {
- ExecutorHelper helper =
- new HelperImpl(mode, mvn3Home(), userHome, EMBEDDED_MAVEN_EXECUTOR, FORKED_MAVEN_EXECUTOR);
- String path = new ToolboxTool(helper, Environment.TOOLBOX_VERSION)
- .artifactPath(getExecutorRequest(helper), "aopalliance:aopalliance:1.0", "central");
- System.out.println(mode.name() + ": " + path);
- // split repository: assert "ends with" as split may introduce prefixes
- assertTrue(
- path.endsWith("aopalliance" + File.separator + "aopalliance" + File.separator + "1.0" + File.separator
- + "aopalliance-1.0.jar"),
- "path=" + path);
- }
-
- @ParameterizedTest
- @EnumSource(ExecutorHelper.Mode.class)
- void artifactPath4(ExecutorHelper.Mode mode) {
- ExecutorHelper helper =
- new HelperImpl(mode, mvn4Home(), userHome, EMBEDDED_MAVEN_EXECUTOR, FORKED_MAVEN_EXECUTOR);
- String path = new ToolboxTool(helper, Environment.TOOLBOX_VERSION)
- .artifactPath(getExecutorRequest(helper), "aopalliance:aopalliance:1.0", "central");
- System.out.println(mode.name() + ": " + path);
- // split repository: assert "ends with" as split may introduce prefixes
- assertTrue(
- path.endsWith("aopalliance" + File.separator + "aopalliance" + File.separator + "1.0" + File.separator
- + "aopalliance-1.0.jar"),
- "path=" + path);
- }
-
- @ParameterizedTest
- @EnumSource(ExecutorHelper.Mode.class)
- void metadataPath3(ExecutorHelper.Mode mode) {
- ExecutorHelper helper =
- new HelperImpl(mode, mvn4Home(), userHome, EMBEDDED_MAVEN_EXECUTOR, FORKED_MAVEN_EXECUTOR);
- String path = new ToolboxTool(helper, Environment.TOOLBOX_VERSION)
- .metadataPath(getExecutorRequest(helper), "aopalliance", "someremote");
- System.out.println(mode.name() + ": " + path);
- // split repository: assert "ends with" as split may introduce prefixes
- assertTrue(path.endsWith("aopalliance" + File.separator + "maven-metadata-someremote.xml"), "path=" + path);
- }
-
- @ParameterizedTest
- @EnumSource(ExecutorHelper.Mode.class)
- void metadataPath4(ExecutorHelper.Mode mode) {
- ExecutorHelper helper =
- new HelperImpl(mode, mvn4Home(), userHome, EMBEDDED_MAVEN_EXECUTOR, FORKED_MAVEN_EXECUTOR);
- String path = new ToolboxTool(helper, Environment.TOOLBOX_VERSION)
- .metadataPath(getExecutorRequest(helper), "aopalliance", "someremote");
- System.out.println(mode.name() + ": " + path);
- // split repository: assert "ends with" as split may introduce prefixes
- assertTrue(path.endsWith("aopalliance" + File.separator + "maven-metadata-someremote.xml"), "path=" + path);
- }
-
- public Path mvn3Home() {
- return Paths.get(System.getProperty("maven3home"));
- }
-
- public Path mvn4Home() {
- return Paths.get(System.getProperty("maven4home"));
- }
-}
diff --git a/impl/pom.xml b/impl/pom.xml
index df83a63a018a..b41717c555ea 100644
--- a/impl/pom.xml
+++ b/impl/pom.xml
@@ -40,7 +40,6 @@ under the License.
maven-core
maven-cli
maven-testing
- maven-executor
diff --git a/its/core-it-support/maven-it-helper/pom.xml b/its/core-it-support/maven-it-helper/pom.xml
index 960eb651e31b..2e9fc52736a9 100644
--- a/its/core-it-support/maven-it-helper/pom.xml
+++ b/its/core-it-support/maven-it-helper/pom.xml
@@ -32,7 +32,7 @@ under the License.
- org.apache.maven
+ org.apache.maven.executor
maven-executor
diff --git a/its/core-it-support/maven-it-helper/src/main/java/org/apache/maven/it/Verifier.java b/its/core-it-support/maven-it-helper/src/main/java/org/apache/maven/it/Verifier.java
index c0f29a2b3d16..89134a03c671 100644
--- a/its/core-it-support/maven-it-helper/src/main/java/org/apache/maven/it/Verifier.java
+++ b/its/core-it-support/maven-it-helper/src/main/java/org/apache/maven/it/Verifier.java
@@ -45,14 +45,14 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import org.apache.maven.cling.executor.ExecutorException;
-import org.apache.maven.cling.executor.ExecutorRequest;
-import org.apache.maven.cling.executor.ExecutorHelper;
-import org.apache.maven.cling.executor.ExecutorTool;
-import org.apache.maven.cling.executor.embedded.EmbeddedMavenExecutor;
-import org.apache.maven.cling.executor.forked.ForkedMavenExecutor;
-import org.apache.maven.cling.executor.internal.HelperImpl;
-import org.apache.maven.cling.executor.internal.ToolboxTool;
+import org.apache.maven.executor.Executor;
+import org.apache.maven.executor.ExecutorException;
+import org.apache.maven.executor.ExecutorRequest;
+import org.apache.maven.executor.ExecutorHelper;
+import org.apache.maven.executor.ExecutorTool;
+import org.apache.maven.executor.embedded.EmbeddedMavenExecutor;
+import org.apache.maven.executor.forked.ForkedMavenExecutor;
+import org.apache.maven.executor.support.ToolboxExecutorTool;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;
@@ -62,17 +62,21 @@
*
*/
public class Verifier {
+ /**
+ * The Maven home/installation directory we are testing/executing with Executor.
+ */
+ private static final Path MAVEN_HOME = Paths.get(System.getProperty("maven.home"));
/**
* Keep executor alive, as long as Verifier is in classloader. Embedded classloader keeps embedded Maven
* ClassWorld alive, instead to re-create it per invocation, making embedded execution fast(er).
+ * Points to test subjected Maven home.
*/
- private static final EmbeddedMavenExecutor EMBEDDED_MAVEN_EXECUTOR = new EmbeddedMavenExecutor();
+ private static final EmbeddedMavenExecutor EMBEDDED_MAVEN_EXECUTOR = new EmbeddedMavenExecutor(MAVEN_HOME);
/**
* Keep executor alive, as long as Verifier is in classloader. For forked this means nothing, but is
- * at least "handled the same" as embedded counterpart. Later on, we could have some similar solution like
- * mvnd has, and keep pool of "hot" processes maybe?
+ * at least "handled the same" as embedded counterpart. Points to test subjected Maven home.
*/
- private static final ForkedMavenExecutor FORKED_MAVEN_EXECUTOR = new ForkedMavenExecutor();
+ private static final ForkedMavenExecutor FORKED_MAVEN_EXECUTOR = new ForkedMavenExecutor(MAVEN_HOME);
/**
* The "preferred" fork mode of Verifier, defaults to "auto". In fact, am unsure is any other fork mode usable,
@@ -164,13 +168,11 @@ public Verifier(String basedir, List defaultCliArguments, boolean create
this.userHomeDirectory = Paths.get(System.getProperty("maven.test.user.home", "user.home"));
Files.createDirectories(this.userHomeDirectory);
this.outerLocalRepository = Paths.get(System.getProperty("maven.test.repo.outer", ".m2/repository"));
- this.executorHelper = new HelperImpl(
+ this.executorHelper = ExecutorHelper.forExecutors(
VERIFIER_FORK_MODE,
- Paths.get(System.getProperty("maven.home")),
- this.userHomeDirectory,
EMBEDDED_MAVEN_EXECUTOR,
FORKED_MAVEN_EXECUTOR);
- this.executorTool = new ToolboxTool(executorHelper, toolboxVersion);
+ this.executorTool = new ToolboxExecutorTool(executorHelper, toolboxVersion);
this.defaultCliArguments =
new ArrayList<>(defaultCliArguments != null ? defaultCliArguments : DEFAULT_CLI_ARGUMENTS);
this.logFile = this.basedir.resolve(logFileName);
@@ -248,11 +250,9 @@ public void execute() throws VerificationException {
args.add("-Daether.remoteRepositoryFilter.prefixes=false");
try {
- ExecutorRequest.Builder builder = executorHelper
- .executorRequest()
+ ExecutorRequest.Builder builder = executorRequest()
.command(executable)
.cwd(basedir)
- .userHomeDirectory(userHomeDirectory)
.jvmArguments(jvmArguments)
.arguments(args)
.skipMavenRc(skipMavenRc);
@@ -442,10 +442,8 @@ public String getLocalRepositoryWithSettings(String settingsXml) {
if (!Files.isRegularFile(settingsFile)) {
throw new IllegalArgumentException("settings xml does not exist: " + settingsXml);
}
- return executorTool.localRepository(executorHelper
- .executorRequest()
+ return executorTool.localRepository(executorRequest()
.cwd(tempBasedir)
- .userHomeDirectory(userHomeDirectory)
.argument("-s")
.argument(settingsFile.toString()));
} else {
@@ -454,7 +452,7 @@ public String getLocalRepositoryWithSettings(String settingsXml) {
return outerHead;
} else {
return executorTool.localRepository(
- executorHelper.executorRequest().cwd(tempBasedir).userHomeDirectory(userHomeDirectory));
+ executorRequest().cwd(tempBasedir));
}
}
}
@@ -476,12 +474,12 @@ private String formatCommandLine(ExecutorRequest request, ExecutorHelper.Mode mo
cmdLine.append("# Command line: ");
// Add the Maven executable path
- Path mavenExecutable = request.installationDirectory()
+ Path mavenExecutable = MAVEN_HOME
.resolve("bin")
- .resolve(System.getProperty("os.name").toLowerCase().contains("windows")
+ .resolve(Executor.IS_WINDOWS
? request.command() + ".cmd"
: request.command());
- cmdLine.append(mavenExecutable.toString());
+ cmdLine.append(mavenExecutable);
// Add MAVEN_ARGS if they would be used (only for forked mode)
if (mode == ExecutorHelper.Mode.FORKED || mode == ExecutorHelper.Mode.AUTO) {
@@ -865,7 +863,11 @@ public String getArtifactPath(String gid, String aid, String version, String ext
}
return getLocalRepository()
+ File.separator
- + executorTool.artifactPath(executorHelper.executorRequest(), gav, null);
+ + executorTool.artifactPath(executorRequest(), gav, null);
+ }
+
+ private ExecutorRequest.Builder executorRequest() {
+ return ExecutorRequest.mavenBuilder().userHomeDirectory(userHomeDirectory);
}
private String getSupportArtifactPath(String artifact) {
@@ -923,7 +925,7 @@ public String getSupportArtifactPath(String gid, String aid, String version, Str
}
return outerLocalRepository
.resolve(executorTool.artifactPath(
- executorHelper.executorRequest().argument("-Dmaven.repo.local=" + outerLocalRepository),
+ executorRequest().argument("-Dmaven.repo.local=" + outerLocalRepository),
gav,
null))
.toString();
@@ -997,7 +999,7 @@ public String getArtifactMetadataPath(String gid, String aid, String version, St
gav += filename;
return getLocalRepository()
+ File.separator
- + executorTool.metadataPath(executorHelper.executorRequest(), gav, repoId);
+ + executorTool.metadataPath(executorRequest(), gav, repoId);
}
/**
@@ -1027,7 +1029,7 @@ public void deleteArtifact(String org, String name, String version, String ext)
* @since 1.2
*/
public void deleteArtifacts(String gid) throws IOException {
- String mdPath = executorTool.metadataPath(executorHelper.executorRequest(), gid, null);
+ String mdPath = executorTool.metadataPath(executorRequest(), gid, null);
Path dir = Paths.get(getLocalRepository()).resolve(mdPath).getParent();
FileUtils.deleteDirectory(dir.toFile());
}
@@ -1047,7 +1049,7 @@ public void deleteArtifacts(String gid, String aid, String version) throws IOExc
requireNonNull(version, "version is null");
String mdPath =
- executorTool.metadataPath(executorHelper.executorRequest(), gid + ":" + aid + ":" + version, null);
+ executorTool.metadataPath(executorRequest(), gid + ":" + aid + ":" + version, null);
Path dir = Paths.get(getLocalRepository()).resolve(mdPath).getParent();
FileUtils.deleteDirectory(dir.toFile());
}
diff --git a/its/pom.xml b/its/pom.xml
index 6aae412cbed8..96d795975c37 100644
--- a/its/pom.xml
+++ b/its/pom.xml
@@ -263,10 +263,11 @@ under the License.
maven-compat
${maven-version}
+
- org.apache.maven
+ org.apache.maven.executor
maven-executor
- ${maven-version}
+ 1.0.0-SNAPSHOT