Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MNG-8403] Maven ITs use maven-executor #1940

Merged
merged 43 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
d60ff92
Maven ITs use maven-executor
cstamas Nov 27, 2024
3ac1f83
Undo this change, is move to other PR
cstamas Nov 28, 2024
1140a87
WIP
cstamas Nov 28, 2024
199f404
Merge remote-tracking branch 'upstream/master' into it-maven-executir
cstamas Nov 28, 2024
c79b98d
WIP
cstamas Nov 28, 2024
1c2c3fc
WIP
cstamas Nov 28, 2024
d92d7d8
Hack out rogue AnsiConsole
cstamas Nov 28, 2024
3230486
WIP
cstamas Nov 28, 2024
e839ef2
Fix UT
cstamas Nov 28, 2024
548e1d3
Undo rename, causes huge PR
cstamas Nov 28, 2024
f668773
Hack when needed only
cstamas Nov 28, 2024
d84b8e1
Log full request
cstamas Nov 28, 2024
6cc20de
Logging was missed
cstamas Nov 28, 2024
743aa38
Add diag dump in case of failure
cstamas Nov 29, 2024
7a07b49
Fix
cstamas Nov 29, 2024
fe4c27b
More fixes
cstamas Nov 29, 2024
c52f027
Return to AUTO and fix stupid mistake
cstamas Nov 29, 2024
3ac45f2
Ability to cache context
cstamas Nov 29, 2024
033c824
Small fixes
cstamas Nov 29, 2024
31ee7ff
Push all the logic to single place
cstamas Nov 29, 2024
d25fbc0
Merge remote-tracking branch 'upstream/master' into it-maven-executir
cstamas Nov 30, 2024
9a03eed
Reformat
cstamas Nov 30, 2024
485f68f
Return caching
cstamas Nov 30, 2024
858be1b
Simplify
cstamas Nov 30, 2024
82fd978
Merge remote-tracking branch 'upstream/master' into it-maven-executir
cstamas Dec 2, 2024
d32840b
Embedded executor should dispose runtime added realms
cstamas Dec 2, 2024
f403b14
Fix embedded CWD
cstamas Dec 2, 2024
1203013
Cleanup
cstamas Dec 2, 2024
eb76a1e
Update gh CI and drop unsupported stuff
cstamas Dec 2, 2024
88f6bfd
More fixes
cstamas Dec 3, 2024
2f59d76
Merge remote-tracking branch 'upstream/master' into it-maven-executir
cstamas Dec 3, 2024
300ca39
Fixes for executors
cstamas Dec 3, 2024
78054ba
Fixes
cstamas Dec 3, 2024
56d88f5
Fixes
cstamas Dec 3, 2024
d83d449
Reformat
cstamas Dec 3, 2024
babf1f7
Fixes
cstamas Dec 3, 2024
cf4a8c5
No code change, just tidy up
cstamas Dec 4, 2024
63806d8
Handle head/tail
cstamas Dec 4, 2024
cd0a620
Use verifier get local repo that is head aware
cstamas Dec 4, 2024
1dcb0d1
Last fixes
cstamas Dec 4, 2024
ea87c58
Tidy up
cstamas Dec 4, 2024
5cc14ce
Merge remote-tracking branch 'upstream/master' into it-maven-executir
cstamas Dec 4, 2024
7c93643
Merge verifiers
gnodet Dec 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
package org.apache.maven.api.cli;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.maven.api.annotations.Experimental;
Expand Down Expand Up @@ -82,16 +85,34 @@ public interface ExecutorRequest {
@Nonnull
Path userHomeDirectory();

/**
* Returns the map of environment variables to set before executing process.
* This property is used ONLY by executors that spawn a new JVM.
*
* @return an Optional containing the map of environment variables, or empty if not specified
*/
@Nonnull
Optional<Map<String, String>> environmentVariables();

/**
* Returns the list of extra JVM arguments to be passed to the forked process.
* These arguments allow for customization of the JVM environment in which tool will run.
* This property is used ONLY by executors and invokers that spawn a new JVM.
* This property is used ONLY by executors that spawn a new JVM.
*
* @return an Optional containing the list of extra JVM arguments, or empty if not specified
*/
@Nonnull
Optional<List<String>> jvmArguments();

/**
* Optional consumer for STD out of the Maven. If given, this consumer will get all output from the std out of
* Maven. Note: whether consumer gets to consume anything depends on invocation arguments passed in
* {@link #arguments()}, as if log file is set, not much will go to stdout.
*
* @return an Optional containing the stdout consumer, or empty if not specified.
*/
Optional<OutputStream> stdoutConsumer();

/**
* Returns {@link Builder} for this instance.
*/
Expand All @@ -103,7 +124,9 @@ default Builder toBuilder() {
cwd(),
installationDirectory(),
userHomeDirectory(),
jvmArguments().orElse(null));
environmentVariables().orElse(null),
jvmArguments().orElse(null),
stdoutConsumer().orElse(null));
}

/**
Expand All @@ -125,6 +148,8 @@ static Builder mavenBuilder(@Nullable Path installationDirectory) {
getCanonicalPath(Paths.get(System.getProperty("user.dir"))),
installationDirectory != null ? getCanonicalPath(installationDirectory) : discoverMavenHome(),
getCanonicalPath(Paths.get(System.getProperty("user.home"))),
null,
null,
null);
}

Expand All @@ -134,23 +159,30 @@ class Builder {
private Path cwd;
private Path installationDirectory;
private Path userHomeDirectory;
private Map<String, String> environmentVariables;
private List<String> jvmArguments;
private OutputStream stdoutConsumer;

private Builder() {}

@SuppressWarnings("ParameterNumber")
private Builder(
String command,
List<String> arguments,
Path cwd,
Path installationDirectory,
Path userHomeDirectory,
List<String> jvmArguments) {
Map<String, String> environmentVariables,
List<String> jvmArguments,
OutputStream stdoutConsumer) {
this.command = command;
this.arguments = arguments;
this.cwd = cwd;
this.installationDirectory = installationDirectory;
this.userHomeDirectory = userHomeDirectory;
this.environmentVariables = environmentVariables;
this.jvmArguments = jvmArguments;
this.stdoutConsumer = stdoutConsumer;
}

@Nonnull
Expand Down Expand Up @@ -192,6 +224,23 @@ public Builder userHomeDirectory(Path userHomeDirectory) {
return this;
}

@Nonnull
public Builder environmentVariables(Map<String, String> 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<String> jvmArguments) {
this.jvmArguments = jvmArguments;
Expand All @@ -207,9 +256,23 @@ public Builder jvmArgument(String jvmArgument) {
return this;
}

@Nonnull
public Builder stdoutConsumer(OutputStream stdoutConsumer) {
this.stdoutConsumer = stdoutConsumer;
return this;
}

@Nonnull
public ExecutorRequest build() {
return new Impl(command, arguments, cwd, installationDirectory, userHomeDirectory, jvmArguments);
return new Impl(
command,
arguments,
cwd,
installationDirectory,
userHomeDirectory,
environmentVariables,
jvmArguments,
stdoutConsumer);
}

private static class Impl implements ExecutorRequest {
Expand All @@ -218,21 +281,28 @@ private static class Impl implements ExecutorRequest {
private final Path cwd;
private final Path installationDirectory;
private final Path userHomeDirectory;
private final Map<String, String> environmentVariables;
private final List<String> jvmArguments;
private final OutputStream stdoutConsumer;

@SuppressWarnings("ParameterNumber")
private Impl(
String command,
List<String> arguments,
Path cwd,
Path installationDirectory,
Path userHomeDirectory,
List<String> jvmArguments) {
Map<String, String> environmentVariables,
List<String> jvmArguments,
OutputStream stdoutConsumer) {
this.command = requireNonNull(command);
this.arguments = arguments == null ? List.of() : List.copyOf(arguments);
this.cwd = requireNonNull(cwd);
this.installationDirectory = requireNonNull(installationDirectory);
this.userHomeDirectory = requireNonNull(userHomeDirectory);
this.environmentVariables = environmentVariables != null ? Map.copyOf(environmentVariables) : null;
this.jvmArguments = jvmArguments != null ? List.copyOf(jvmArguments) : null;
this.stdoutConsumer = stdoutConsumer;
}

@Override
Expand Down Expand Up @@ -260,20 +330,32 @@ public Path userHomeDirectory() {
return userHomeDirectory;
}

@Override
public Optional<Map<String, String>> environmentVariables() {
return Optional.ofNullable(environmentVariables);
}

@Override
public Optional<List<String>> jvmArguments() {
return Optional.ofNullable(jvmArguments);
}

@Override
public Optional<OutputStream> stdoutConsumer() {
return Optional.ofNullable(stdoutConsumer);
}

@Override
public String toString() {
return "ExecutionRequest{" + "command='"
return "Impl{" + "command='"
+ command + '\'' + ", arguments="
+ arguments + ", cwd="
+ cwd + ", installationDirectory="
+ installationDirectory + ", userHomeDirectory="
+ userHomeDirectory + ", jvmArguments="
+ jvmArguments + '}';
+ userHomeDirectory + ", environmentVariables="
+ environmentVariables + ", jvmArguments="
+ jvmArguments + ", stdoutConsumer="
+ stdoutConsumer + '}';
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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.nio.file.Path;
import java.nio.file.Paths;

import org.apache.maven.api.annotations.Nullable;
import org.apache.maven.api.cli.Executor;
import org.apache.maven.api.cli.ExecutorRequest;
import org.apache.maven.cling.executor.forked.ForkedMavenExecutor;

import static java.util.Objects.requireNonNull;

/**
* Helper class for some common tasks.
*/
public class MavenExecutorHelper {
public enum Mode {
AUTO,
EMBEDDED,
FORKED
}

private final Path installationDirectory;

public MavenExecutorHelper(Path installationDirectory) {
this.installationDirectory = requireNonNull(installationDirectory);
}

public Path localRepository(@Nullable Path userSettings) {
// mvn help:evaluate -Dexpression=settings.localRepository -q -DforceStdout
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
try (Executor ex = new ForkedMavenExecutor()) {
ex.execute(ExecutorRequest.mavenBuilder(installationDirectory)
.argument("help:evaluate")
.argument("-Dexpression=settings.localRepository")
.argument("-DforceStdout=true")
.argument("--quiet")
.stdoutConsumer(stdout)
.build());
}
return Paths.get(stdout.toString().replace("\n", "").replace("\r", ""));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ public Context(
}
}

private final PrintStream originalStdout;
private final Properties originalProperties;
private final ClassLoader originalClassLoader;
private final ConcurrentHashMap<Path, Context> contexts;

public EmbeddedMavenExecutor() {
this.originalStdout = System.out;
this.originalClassLoader = Thread.currentThread().getContextClassLoader();
this.contexts = new ConcurrentHashMap<>();
this.originalProperties = System.getProperties();
Expand All @@ -93,10 +95,14 @@ public int execute(ExecutorRequest executorRequest) throws ExecutorException {
System.setProperties(context.properties);
Thread.currentThread().setContextClassLoader(context.tccl);
try {
if (executorRequest.stdoutConsumer().isPresent()) {
System.setOut(new PrintStream(executorRequest.stdoutConsumer().get(), true));
}
return context.exec.apply(executorRequest);
} catch (Exception e) {
throw new ExecutorException("Failed to execute", e);
} finally {
System.setOut(originalStdout);
Thread.currentThread().setContextClassLoader(originalClassLoader);
System.setProperties(originalProperties);
}
Expand All @@ -114,6 +120,12 @@ protected Context mayCreate(ExecutorRequest executorRequest) {
if (!Files.isDirectory(installation)) {
throw new IllegalArgumentException("Installation directory must point to existing directory");
}
if (executorRequest.environmentVariables().isPresent()) {
throw new IllegalArgumentException(getClass().getSimpleName() + " does not support environment variables");
}
if (executorRequest.jvmArguments().isPresent()) {
throw new IllegalArgumentException(getClass().getSimpleName() + " does not support jvmArguments");
}
return contexts.computeIfAbsent(installation, k -> {
Path mavenHome = installation.toAbsolutePath().normalize();
Path boot = mavenHome.resolve("boot");
Expand Down
Loading
Loading