Skip to content

Commit 61efc04

Browse files
committed
[MNG-8535] Full std stream support for executor
The std stream support was incomplete in maven-executor --- https://issues.apache.org/jira/browse/MNG-8535
1 parent 8b3e640 commit 61efc04

File tree

20 files changed

+381
-235
lines changed

20 files changed

+381
-235
lines changed

api/maven-api-cli/src/main/java/org/apache/maven/api/cli/InvokerRequest.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ public interface InvokerRequest {
5454
*/
5555
boolean parsingFailed();
5656

57+
/**
58+
* Returns {@code true} if this call happens in "embedded" mode.
59+
*
60+
* @see ParserRequest#embedded()
61+
*/
62+
default boolean embedded() {
63+
return parserRequest().embedded();
64+
}
65+
5766
/**
5867
* Returns the current working directory for the Maven execution.
5968
* This is typically the directory from which Maven was invoked.
@@ -138,23 +147,29 @@ default Lookup lookup() {
138147
* @return an {@link Optional} containing the input stream, or empty if not applicable
139148
*/
140149
@Nonnull
141-
Optional<InputStream> in();
150+
default Optional<InputStream> stdIn() {
151+
return Optional.ofNullable(parserRequest().stdIn());
152+
}
142153

143154
/**
144155
* Returns the output stream for the Maven execution, if running in embedded mode.
145156
*
146157
* @return an {@link Optional} containing the output stream, or empty if not applicable
147158
*/
148159
@Nonnull
149-
Optional<OutputStream> out();
160+
default Optional<OutputStream> stdOut() {
161+
return Optional.ofNullable(parserRequest().stdOut());
162+
}
150163

151164
/**
152165
* Returns the error stream for the Maven execution, if running in embedded mode.
153166
*
154167
* @return an {@link Optional} containing the error stream, or empty if not applicable
155168
*/
156169
@Nonnull
157-
Optional<OutputStream> err();
170+
default Optional<OutputStream> stdErr() {
171+
return Optional.ofNullable(parserRequest().stdErr());
172+
}
158173

159174
/**
160175
* Returns a list of core extensions, if configured in the .mvn/extensions.xml file.

api/maven-api-cli/src/main/java/org/apache/maven/api/cli/ParserRequest.java

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -125,30 +125,37 @@ public interface ParserRequest {
125125

126126
/**
127127
* Returns the input stream to be used for the Maven execution.
128-
* If not set, System.in will be used by default.
128+
* If not set, {@link System#in} will be used by default.
129129
*
130130
* @return the input stream, or null if not set
131131
*/
132132
@Nullable
133-
InputStream in();
133+
InputStream stdIn();
134134

135135
/**
136136
* Returns the output stream to be used for the Maven execution.
137-
* If not set, System.out will be used by default.
137+
* If not set, {@link System#out} will be used by default.
138138
*
139139
* @return the output stream, or null if not set
140140
*/
141141
@Nullable
142-
OutputStream out();
142+
OutputStream stdOut();
143143

144144
/**
145145
* Returns the error stream to be used for the Maven execution.
146-
* If not set, System.err will be used by default.
146+
* If not set, {@link System#err} will be used by default.
147147
*
148148
* @return the error stream, or null if not set
149149
*/
150150
@Nullable
151-
OutputStream err();
151+
OutputStream stdErr();
152+
153+
/**
154+
* Returns {@code true} if this call happens in "embedded" mode, for example by another application that
155+
* embeds Maven. When running in "embedded" mode, Maven will not try to grab system terminal and will use
156+
* provided {@link #stdIn()} or {@link InputStream#nullInputStream()} as standard in stream.
157+
*/
158+
boolean embedded();
152159

153160
/**
154161
* Creates a new Builder instance for constructing a Maven ParserRequest.
@@ -251,9 +258,10 @@ class Builder {
251258
private Path cwd;
252259
private Path mavenHome;
253260
private Path userHome;
254-
private InputStream in;
255-
private OutputStream out;
256-
private OutputStream err;
261+
private InputStream stdIn;
262+
private OutputStream stdOut;
263+
private OutputStream stdErr;
264+
private boolean embedded = false;
257265

258266
private Builder(
259267
String command, String commandName, List<String> args, MessageBuilderFactory messageBuilderFactory) {
@@ -284,18 +292,23 @@ public Builder userHome(Path userHome) {
284292
return this;
285293
}
286294

287-
public Builder in(InputStream in) {
288-
this.in = in;
295+
public Builder stdIn(InputStream stdIn) {
296+
this.stdIn = stdIn;
289297
return this;
290298
}
291299

292-
public Builder out(OutputStream out) {
293-
this.out = out;
300+
public Builder stdOut(OutputStream stdOut) {
301+
this.stdOut = stdOut;
294302
return this;
295303
}
296304

297-
public Builder err(OutputStream err) {
298-
this.err = err;
305+
public Builder stdErr(OutputStream stdErr) {
306+
this.stdErr = stdErr;
307+
return this;
308+
}
309+
310+
public Builder embedded(boolean embedded) {
311+
this.embedded = embedded;
299312
return this;
300313
}
301314

@@ -310,9 +323,10 @@ public ParserRequest build() {
310323
cwd,
311324
mavenHome,
312325
userHome,
313-
in,
314-
out,
315-
err);
326+
stdIn,
327+
stdOut,
328+
stdErr,
329+
embedded);
316330
}
317331

318332
@SuppressWarnings("ParameterNumber")
@@ -326,9 +340,10 @@ private static class ParserRequestImpl implements ParserRequest {
326340
private final Path cwd;
327341
private final Path mavenHome;
328342
private final Path userHome;
329-
private final InputStream in;
330-
private final OutputStream out;
331-
private final OutputStream err;
343+
private final InputStream stdIn;
344+
private final OutputStream stdOut;
345+
private final OutputStream stdErr;
346+
private final boolean embedded;
332347

333348
private ParserRequestImpl(
334349
String command,
@@ -340,9 +355,10 @@ private ParserRequestImpl(
340355
Path cwd,
341356
Path mavenHome,
342357
Path userHome,
343-
InputStream in,
344-
OutputStream out,
345-
OutputStream err) {
358+
InputStream stdIn,
359+
OutputStream stdOut,
360+
OutputStream stdErr,
361+
boolean embedded) {
346362
this.command = requireNonNull(command, "command");
347363
this.commandName = requireNonNull(commandName, "commandName");
348364
this.args = List.copyOf(requireNonNull(args, "args"));
@@ -352,9 +368,10 @@ private ParserRequestImpl(
352368
this.cwd = cwd;
353369
this.mavenHome = mavenHome;
354370
this.userHome = userHome;
355-
this.in = in;
356-
this.out = out;
357-
this.err = err;
371+
this.stdIn = stdIn;
372+
this.stdOut = stdOut;
373+
this.stdErr = stdErr;
374+
this.embedded = embedded;
358375
}
359376

360377
@Override
@@ -403,18 +420,23 @@ public Path userHome() {
403420
}
404421

405422
@Override
406-
public InputStream in() {
407-
return in;
423+
public InputStream stdIn() {
424+
return stdIn;
425+
}
426+
427+
@Override
428+
public OutputStream stdOut() {
429+
return stdOut;
408430
}
409431

410432
@Override
411-
public OutputStream out() {
412-
return out;
433+
public OutputStream stdErr() {
434+
return stdErr;
413435
}
414436

415437
@Override
416-
public OutputStream err() {
417-
return err;
438+
public boolean embedded() {
439+
return embedded;
418440
}
419441
}
420442

impl/maven-cli/src/main/java/org/apache/maven/cling/ClingSupport.java

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,17 @@
1919
package org.apache.maven.cling;
2020

2121
import java.io.IOException;
22+
import java.io.InputStream;
23+
import java.io.OutputStream;
2224

25+
import org.apache.maven.api.annotations.Nullable;
2326
import org.apache.maven.api.cli.Invoker;
2427
import org.apache.maven.api.cli.InvokerException;
25-
import org.apache.maven.api.cli.InvokerRequest;
28+
import org.apache.maven.api.cli.Parser;
29+
import org.apache.maven.api.cli.ParserRequest;
30+
import org.apache.maven.api.services.MessageBuilderFactory;
2631
import org.apache.maven.cling.invoker.logging.SystemLogger;
32+
import org.apache.maven.jline.JLineMessageBuilderFactory;
2733
import org.codehaus.plexus.classworlds.ClassWorld;
2834

2935
import static java.util.Objects.requireNonNull;
@@ -59,14 +65,26 @@ private ClingSupport(ClassWorld classWorld, boolean classWorldManaged) {
5965
/**
6066
* The main entry point.
6167
*/
62-
public int run(String[] args) throws IOException {
68+
public int run(
69+
String[] args,
70+
@Nullable InputStream stdIn,
71+
@Nullable OutputStream stdOut,
72+
@Nullable OutputStream stdErr,
73+
boolean embedded)
74+
throws IOException {
6375
try (Invoker invoker = createInvoker()) {
64-
return invoker.invoke(parseArguments(args));
76+
return invoker.invoke(createParser()
77+
.parseInvocation(createParserRequestBuilder(args)
78+
.stdIn(stdIn)
79+
.stdOut(stdOut)
80+
.stdErr(stdErr)
81+
.embedded(embedded)
82+
.build()));
6583
} catch (InvokerException.ExitException e) {
6684
return e.getExitCode();
6785
} catch (Exception e) {
6886
// last resort; as ideally we should get ExitException only
69-
new SystemLogger().error(e.getMessage(), e);
87+
new SystemLogger(stdErr).error(e.getMessage(), e);
7088
return 1;
7189
} finally {
7290
if (classWorldManaged) {
@@ -75,7 +93,13 @@ public int run(String[] args) throws IOException {
7593
}
7694
}
7795

96+
protected MessageBuilderFactory createMessageBuilderFactory() {
97+
return new JLineMessageBuilderFactory();
98+
}
99+
78100
protected abstract Invoker createInvoker();
79101

80-
protected abstract InvokerRequest parseArguments(String[] args);
102+
protected abstract Parser createParser();
103+
104+
protected abstract ParserRequest.Builder createParserRequestBuilder(String[] args);
81105
}

impl/maven-cli/src/main/java/org/apache/maven/cling/MavenCling.java

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@
1919
package org.apache.maven.cling;
2020

2121
import java.io.IOException;
22+
import java.io.InputStream;
23+
import java.io.OutputStream;
2224

25+
import org.apache.maven.api.annotations.Nullable;
2326
import org.apache.maven.api.cli.Invoker;
24-
import org.apache.maven.api.cli.InvokerRequest;
27+
import org.apache.maven.api.cli.Parser;
2528
import org.apache.maven.api.cli.ParserRequest;
2629
import org.apache.maven.cling.invoker.ProtoLookup;
2730
import org.apache.maven.cling.invoker.mvn.MavenInvoker;
2831
import org.apache.maven.cling.invoker.mvn.MavenParser;
29-
import org.apache.maven.jline.JLineMessageBuilderFactory;
3032
import org.codehaus.plexus.classworlds.ClassWorld;
3133

3234
/**
@@ -38,15 +40,28 @@ public class MavenCling extends ClingSupport {
3840
* circumstances.
3941
*/
4042
public static void main(String[] args) throws IOException {
41-
int exitCode = new MavenCling().run(args);
43+
int exitCode = new MavenCling().run(args, null, null, null, false);
4244
System.exit(exitCode);
4345
}
4446

4547
/**
4648
* ClassWorld Launcher "enhanced" entry point: returning exitCode and accepts Class World.
4749
*/
4850
public static int main(String[] args, ClassWorld world) throws IOException {
49-
return new MavenCling(world).run(args);
51+
return new MavenCling(world).run(args, null, null, null, false);
52+
}
53+
54+
/**
55+
* ClassWorld Launcher "embedded" entry point: returning exitCode and accepts Class World and streams.
56+
*/
57+
public static int main(
58+
String[] args,
59+
ClassWorld world,
60+
@Nullable InputStream stdIn,
61+
@Nullable OutputStream stdOut,
62+
@Nullable OutputStream stdErr)
63+
throws IOException {
64+
return new MavenCling(world).run(args, stdIn, stdOut, stdErr, true);
5065
}
5166

5267
public MavenCling() {
@@ -64,9 +79,12 @@ protected Invoker createInvoker() {
6479
}
6580

6681
@Override
67-
protected InvokerRequest parseArguments(String[] args) {
68-
return new MavenParser()
69-
.parseInvocation(ParserRequest.mvn(args, new JLineMessageBuilderFactory())
70-
.build());
82+
protected Parser createParser() {
83+
return new MavenParser();
84+
}
85+
86+
@Override
87+
protected ParserRequest.Builder createParserRequestBuilder(String[] args) {
88+
return ParserRequest.mvn(args, createMessageBuilderFactory());
7189
}
7290
}

0 commit comments

Comments
 (0)