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-8535] Full std stream support for executor #2082

Merged
merged 16 commits into from
Feb 8, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ public interface InvokerRequest {
*/
boolean parsingFailed();

/**
* Returns {@code true} if this call happens in "embedded" mode.
*
* @see ParserRequest#embedded()
*/
default boolean embedded() {
return parserRequest().embedded();
}

/**
* Returns the current working directory for the Maven execution.
* This is typically the directory from which Maven was invoked.
Expand Down Expand Up @@ -138,23 +147,29 @@ default Lookup lookup() {
* @return an {@link Optional} containing the input stream, or empty if not applicable
*/
@Nonnull
Optional<InputStream> in();
default Optional<InputStream> stdIn() {
return Optional.ofNullable(parserRequest().stdIn());
}

/**
* Returns the output stream for the Maven execution, if running in embedded mode.
*
* @return an {@link Optional} containing the output stream, or empty if not applicable
*/
@Nonnull
Optional<OutputStream> out();
default Optional<OutputStream> stdOut() {
return Optional.ofNullable(parserRequest().stdOut());
}

/**
* Returns the error stream for the Maven execution, if running in embedded mode.
*
* @return an {@link Optional} containing the error stream, or empty if not applicable
*/
@Nonnull
Optional<OutputStream> err();
default Optional<OutputStream> stdErr() {
return Optional.ofNullable(parserRequest().stdErr());
}

/**
* Returns a list of core extensions, if configured in the .mvn/extensions.xml file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,30 +125,37 @@ public interface ParserRequest {

/**
* Returns the input stream to be used for the Maven execution.
* If not set, System.in will be used by default.
* If not set, {@link System#in} will be used by default.
*
* @return the input stream, or null if not set
*/
@Nullable
InputStream in();
InputStream stdIn();

/**
* Returns the output stream to be used for the Maven execution.
* If not set, System.out will be used by default.
* If not set, {@link System#out} will be used by default.
*
* @return the output stream, or null if not set
*/
@Nullable
OutputStream out();
OutputStream stdOut();

/**
* Returns the error stream to be used for the Maven execution.
* If not set, System.err will be used by default.
* If not set, {@link System#err} will be used by default.
*
* @return the error stream, or null if not set
*/
@Nullable
OutputStream err();
OutputStream stdErr();

/**
* Returns {@code true} if this call happens in "embedded" mode, for example by another application that
* embeds Maven. When running in "embedded" mode, Maven will not try to grab system terminal and will use
* provided {@link #stdIn()} or {@link InputStream#nullInputStream()} as standard in stream.
*/
boolean embedded();

/**
* Creates a new Builder instance for constructing a Maven ParserRequest.
Expand Down Expand Up @@ -251,9 +258,10 @@ class Builder {
private Path cwd;
private Path mavenHome;
private Path userHome;
private InputStream in;
private OutputStream out;
private OutputStream err;
private InputStream stdIn;
private OutputStream stdOut;
private OutputStream stdErr;
private boolean embedded = false;

private Builder(
String command, String commandName, List<String> args, MessageBuilderFactory messageBuilderFactory) {
Expand Down Expand Up @@ -284,18 +292,23 @@ public Builder userHome(Path userHome) {
return this;
}

public Builder in(InputStream in) {
this.in = in;
public Builder stdIn(InputStream stdIn) {
this.stdIn = stdIn;
return this;
}

public Builder out(OutputStream out) {
this.out = out;
public Builder stdOut(OutputStream stdOut) {
this.stdOut = stdOut;
return this;
}

public Builder err(OutputStream err) {
this.err = err;
public Builder stdErr(OutputStream stdErr) {
this.stdErr = stdErr;
return this;
}

public Builder embedded(boolean embedded) {
this.embedded = embedded;
return this;
}

Expand All @@ -310,9 +323,10 @@ public ParserRequest build() {
cwd,
mavenHome,
userHome,
in,
out,
err);
stdIn,
stdOut,
stdErr,
embedded);
}

@SuppressWarnings("ParameterNumber")
Expand All @@ -326,9 +340,10 @@ private static class ParserRequestImpl implements ParserRequest {
private final Path cwd;
private final Path mavenHome;
private final Path userHome;
private final InputStream in;
private final OutputStream out;
private final OutputStream err;
private final InputStream stdIn;
private final OutputStream stdOut;
private final OutputStream stdErr;
private final boolean embedded;

private ParserRequestImpl(
String command,
Expand All @@ -340,9 +355,10 @@ private ParserRequestImpl(
Path cwd,
Path mavenHome,
Path userHome,
InputStream in,
OutputStream out,
OutputStream err) {
InputStream stdIn,
OutputStream stdOut,
OutputStream stdErr,
boolean embedded) {
this.command = requireNonNull(command, "command");
this.commandName = requireNonNull(commandName, "commandName");
this.args = List.copyOf(requireNonNull(args, "args"));
Expand All @@ -352,9 +368,10 @@ private ParserRequestImpl(
this.cwd = cwd;
this.mavenHome = mavenHome;
this.userHome = userHome;
this.in = in;
this.out = out;
this.err = err;
this.stdIn = stdIn;
this.stdOut = stdOut;
this.stdErr = stdErr;
this.embedded = embedded;
}

@Override
Expand Down Expand Up @@ -403,18 +420,23 @@ public Path userHome() {
}

@Override
public InputStream in() {
return in;
public InputStream stdIn() {
return stdIn;
}

@Override
public OutputStream stdOut() {
return stdOut;
}

@Override
public OutputStream out() {
return out;
public OutputStream stdErr() {
return stdErr;
}

@Override
public OutputStream err() {
return err;
public boolean embedded() {
return embedded;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.apache.maven.api.services;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
Expand Down Expand Up @@ -121,9 +122,10 @@ void testStreamReading() throws IOException {
Files.writeString(testFile, content);

Source source = Sources.fromPath(testFile);
String readContent = new String(source.openStream().readAllBytes());

assertEquals(content, readContent);
try (InputStream inputStream = source.openStream()) {
String readContent = new String(inputStream.readAllBytes());
assertEquals(content, readContent);
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ protected File projectFile(String groupId, String artifactId) {
// ----------------------------------------------------------------------

protected File getLocalRepositoryPath() {
return getTestFile("src/test/resources/inheritance-repo/" + getTestSeries());
return getTestFile("target/test-classes/inheritance-repo/" + getTestSeries());
}

@Override
Expand Down
21 changes: 21 additions & 0 deletions impl/maven-cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,31 @@ under the License.
<artifactId>maven-resolver-transport-jdk</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-native</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-jline-native</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeArtifactIds>jline-native</includeArtifactIds>
<includes>org/jline/nativ/**</includes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.modello</groupId>
<artifactId>modello-maven-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@
package org.apache.maven.cling;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.maven.api.annotations.Nullable;
import org.apache.maven.api.cli.Invoker;
import org.apache.maven.api.cli.InvokerException;
import org.apache.maven.api.cli.InvokerRequest;
import org.apache.maven.api.cli.Parser;
import org.apache.maven.api.cli.ParserRequest;
import org.apache.maven.api.services.MessageBuilderFactory;
import org.apache.maven.cling.invoker.logging.SystemLogger;
import org.apache.maven.jline.JLineMessageBuilderFactory;
import org.codehaus.plexus.classworlds.ClassWorld;

import static java.util.Objects.requireNonNull;
Expand Down Expand Up @@ -59,14 +65,26 @@ private ClingSupport(ClassWorld classWorld, boolean classWorldManaged) {
/**
* The main entry point.
*/
public int run(String[] args) throws IOException {
public int run(
String[] args,
@Nullable InputStream stdIn,
@Nullable OutputStream stdOut,
@Nullable OutputStream stdErr,
boolean embedded)
throws IOException {
try (Invoker invoker = createInvoker()) {
return invoker.invoke(parseArguments(args));
return invoker.invoke(createParser()
.parseInvocation(createParserRequestBuilder(args)
.stdIn(stdIn)
.stdOut(stdOut)
.stdErr(stdErr)
.embedded(embedded)
.build()));
} catch (InvokerException.ExitException e) {
return e.getExitCode();
} catch (Exception e) {
// last resort; as ideally we should get ExitException only
new SystemLogger().error(e.getMessage(), e);
new SystemLogger(stdErr).error(e.getMessage(), e);
return 1;
} finally {
if (classWorldManaged) {
Expand All @@ -75,7 +93,13 @@ public int run(String[] args) throws IOException {
}
}

protected MessageBuilderFactory createMessageBuilderFactory() {
return new JLineMessageBuilderFactory();
}

protected abstract Invoker createInvoker();

protected abstract InvokerRequest parseArguments(String[] args);
protected abstract Parser createParser();

protected abstract ParserRequest.Builder createParserRequestBuilder(String[] args);
}
Loading