Skip to content

Commit

Permalink
Fix embedded executor
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Feb 7, 2025
1 parent 4f9a312 commit 3281d36
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -136,10 +138,6 @@ public final int invoke(InvokerRequest invokerRequest) {
} catch (Exception e) {
// other exceptions (including InvokerException but sans Exit, see above): we need to inform user
throw handleException(context, e);
} finally {
if (context.terminal != null) {
context.terminal.writer().flush();
}
}
} finally {
Thread.currentThread().setContextClassLoader(oldCL);
Expand Down Expand Up @@ -308,14 +306,16 @@ protected void createTerminal(C context) {
if (context.terminal == null) {
MessageUtils.systemInstall(
builder -> {
builder.streams(
context.invokerRequest.stdIn().orElse(null),
context.invokerRequest.stdOut().orElse(null));
builder.systemOutput(TerminalBuilder.SystemOutput.ForcedSysOut);
// The exec builder suffers from https://github.com/jline/jline3/issues/1098
// We could re-enable it when fixed to provide support for non-standard architectures,
// for which JLine does not provide any native library.
builder.exec(false);
if (context.invokerRequest.embedded()) {
InputStream in = context.invokerRequest.stdIn().orElse(InputStream.nullInputStream());
OutputStream out = context.invokerRequest.stdOut().orElse(OutputStream.nullOutputStream());
builder.streams(in, out);
builder.provider("exec");
context.coloredOutput = context.coloredOutput != null ? context.coloredOutput : false;
context.closeables.add(out::flush);
} else {
builder.systemOutput(TerminalBuilder.SystemOutput.ForcedSysOut);
}
if (context.coloredOutput != null) {
builder.color(context.coloredOutput);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
*/
package org.apache.maven.cling.invoker.mvn;

import java.io.ByteArrayOutputStream;
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.HashMap;
import java.util.List;
Expand Down Expand Up @@ -99,18 +101,34 @@ protected Map<String, String> invoke(Path cwd, Path userHome, Collection<String>
Parser parser = createParser();
try (Invoker invoker = createInvoker()) {
for (String goal : goals) {
Path logFile =
cwd.resolve(goal.replace(':', '-') + "-build.log").toAbsolutePath();
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
List<String> mvnArgs = new ArrayList<>(args);
mvnArgs.addAll(List.of("-l", logFile.toString(), goal));
mvnArgs.add(goal);
int exitCode = invoker.invoke(
parser.parseInvocation(ParserRequest.mvn(mvnArgs, new JLineMessageBuilderFactory())
.cwd(cwd)
.userHome(userHome)
.stdOut(stdout)
.stdErr(stderr)
.embedded(true)
.build()));
String log = Files.readString(logFile);
logs.put(goal, log);
assertEquals(0, exitCode, log);

// dump things out
System.out.println("===================================================");
System.out.println("args: " + Arrays.toString(mvnArgs.toArray()));
System.out.println("===================================================");
System.out.println("stdout: " + stdout);
System.out.println("===================================================");

System.err.println("===================================================");
System.err.println("args: " + Arrays.toString(mvnArgs.toArray()));
System.err.println("===================================================");
System.err.println("stderr: " + stderr);
System.err.println("===================================================");

logs.put(goal, stdout.toString());
assertEquals(0, exitCode, "OUT:" + stdout + "\nERR:" + stderr);
}
}
return logs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
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.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
Expand Down Expand Up @@ -116,6 +116,7 @@ public int hashCode() {
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;
Expand All @@ -130,6 +131,7 @@ 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();
Expand All @@ -149,19 +151,14 @@ public int execute(ExecutorRequest executorRequest) throws ExecutorException {

Thread.currentThread().setContextClassLoader(context.tccl);
try {
if (executorRequest.stdOut().isPresent()) {
System.setOut(new PrintStream(executorRequest.stdOut().get(), true));
}
if (executorRequest.stdErr().isPresent()) {
System.setErr(new PrintStream(executorRequest.stdErr().get(), true));
}
return context.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);
Expand Down Expand Up @@ -281,34 +278,40 @@ protected Context doCreate(Path mavenHome, ExecutorRequest executorRequest) {
try {
ArrayList<String> 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(), null, null
args.toArray(new String[0]), r.cwd().toString(), stdout, stderr
});
} catch (Exception e) {
throw new ExecutorException("Failed to execute", e);
}
};
} else {
// assume 4.x
Method mainMethod = cliClass.getMethod("main", String[].class, classWorld.getClass());
Class<?> ansiConsole = cliClass.getClassLoader().loadClass("org.jline.jansi.AnsiConsole");
Field ansiConsoleInstalled = ansiConsole.getDeclaredField("installed");
ansiConsoleInstalled.setAccessible(true);
Method mainMethod = cliClass.getMethod(
"main",
String[].class,
classWorld.getClass(),
InputStream.class,
OutputStream.class,
OutputStream.class);
exec = r -> {
System.setProperties(prepareProperties(r));
try {
try {
if (r.stdOut().isPresent() || r.stdErr().isPresent()) {
ansiConsoleInstalled.set(null, 1);
}
ArrayList<String> args = new ArrayList<>(mavenArgs);
args.addAll(r.arguments());
return (int) mainMethod.invoke(null, args.toArray(new String[0]), classWorld);
} finally {
if (r.stdOut().isPresent() || r.stdErr().isPresent()) {
ansiConsoleInstalled.set(null, 0);
}
}
ArrayList<String> 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);
}
Expand Down Expand Up @@ -346,8 +349,6 @@ protected Properties prepareProperties(ExecutorRequest request) {
// Maven 4.x
properties.setProperty(
"library.jline.path", mavenHome.resolve("lib/jline-native").toString());
// TODO: is this needed?
properties.setProperty("org.jline.terminal.provider", "dumb");
properties.setProperty("maven.mainClass", requireNonNull(MAIN_CLASSES.get(request.command()), "mainClass"));

if (request.jvmSystemProperties().isPresent()) {
Expand Down

0 comments on commit 3281d36

Please sign in to comment.