##// END OF EJS Templates
Exec traits, echo ExecShell
cin -
r8:6a7283d1ebf1 default
parent child
Show More
@@ -0,0 +1,32
1 package org.implab.gradle.common.exec;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.File;
5 import java.io.IOException;
6 import java.nio.charset.StandardCharsets;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Optional;
10 import java.util.concurrent.CompletableFuture;
11
12 class EchoExecBuilder extends ExecBuilder {
13
14 private final boolean echoToStderr;
15
16 public EchoExecBuilder(boolean echoToStderr) {
17 this.echoToStderr = echoToStderr;
18 }
19
20 @Override
21 protected CompletableFuture<Integer> startInternal(Map<String, String> environment, File directory,
22 List<String> commandLine, Optional<RedirectFrom> stdinRedirect, Optional<RedirectTo> stdoutRedirect,
23 Optional<RedirectTo> stderrRedirect) throws IOException {
24 var outputRedirect = echoToStderr ? stderrRedirect : stdoutRedirect;
25
26 return outputRedirect.map(to -> {
27 var bytes = String.format("exec: %s", commandLine).getBytes(StandardCharsets.UTF_8);
28 return to.redirect(new ByteArrayInputStream(bytes)).thenApply((x) -> 0);
29 }).orElse(CompletableFuture.completedFuture(0));
30 }
31
32 }
@@ -1,6 +1,13
1 1 package org.implab.gradle.common.exec;
2 2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Objects;
8 import java.util.Optional;
3 9 import java.util.concurrent.CompletableFuture;
10 import java.util.stream.Stream;
4 11
5 12 import org.eclipse.jdt.annotation.NonNullByDefault;
6 13
@@ -9,53 +16,109 import java.io.IOException;
9 16
10 17 /** Command line builder */
11 18 @NonNullByDefault
12 public interface ExecBuilder {
19 public abstract class ExecBuilder {
20
21 private final List<String> commandLine = new ArrayList<>();
22
23 private final Map<String, String> environment = new HashMap<>();
24
25 private File directory;
26
27 private RedirectFrom inputRedirect;
28
29 private RedirectTo outputRedirect;
30
31 private RedirectTo errorRedirect;
13 32
14 33 /** Sets command line, clears previous one if any */
15 void command(String cmd, String... args);
34 public void command(String cmd, String... args) {
35 commandLine.clear();
36 commandLine.add(cmd);
37 Stream.of(args).forEach(commandLine::add);
38 }
16 39
17 40 /** Adds an argument to the command line */
18 void argument(String arg);
41 public void argument(String arg) {
42 Objects.requireNonNull(arg, "arg parameter can't be null");
43 commandLine.add(arg);
44 }
19 45
20 46 /** Sets the working directory */
21 void directory(File directory);
47 public void directory(File directory) {
48 Objects.requireNonNull(directory, "directory parameter can't be null");
49 this.directory = directory;
50 }
22 51
23 52 /**
24 53 * Sets the environment value. The value cannot be null.
25 54 *
26 55 * @param envVar The name of the environment variable
27 * @param value The value to set,
56 * @param value The value to set,
28 57 */
29 void setEnvironment(String envVar, String value);
58 public void setEnvironment(String envVar, String value) {
59 Objects.requireNonNull(value, "Value can't be null");
60 Objects.requireNonNull(envVar, "envVar parameter can't be null");
61 environment.put(envVar, value);
62 }
30 63
31 void unsetEnvironment(String envVar);
64 public void unsetEnvironment(String envVar) {
65 environment.remove(envVar);
66 }
32 67
33 68 /**
34 69 * Sets redirection for the stdin, {@link RedirectFrom} will be applied
35 70 * every time the process is started.
36 71 *
37 * <p>If redirection
72 * <p>
73 * If redirection
38 74 */
39 void stdin(RedirectFrom from);
75 public void stdin(RedirectFrom from) {
76 Objects.requireNonNull(from, "from parameter can't be null");
77 inputRedirect = from;
78 }
40 79
41 80 /**
42 81 * Sets redirection for the stdout, {@link RedirectTo} will be applied
43 82 * every time the process is started.
44 83 */
45 void stdout(RedirectTo out);
84 public void stdout(RedirectTo out) {
85 Objects.requireNonNull(out, "out parameter can't be null");
86 outputRedirect = out;
87 }
46 88
47 89 /**
48 90 * Sets redirection for the stderr, {@link RedirectTo} will be applied
49 91 * every time the process is started.
50 92 */
51 void stderr(RedirectTo err);
93 public void stderr(RedirectTo err) {
94 Objects.requireNonNull(err, "err parameter can't be null");
95 errorRedirect = err;
96 }
97
98 /** Implement this function to */
99 protected abstract CompletableFuture<Integer> startInternal(
100 Map<String, String> environment,
101 File directory,
102 List<String> commandLine,
103 Optional<RedirectFrom> stdinRedirect,
104 Optional<RedirectTo> stdoutRedirect,
105 Optional<RedirectTo> stderrRedirect) throws IOException;
52 106
53 107 /**
54 108 * Creates and starts new process and returns {@link CompletableFuture}. The
55 109 * process may be a remote process, or a shell process or etc.
110 *
56 111 * @return
57 112 * @throws IOException
58 113 */
59 CompletableFuture<Integer> start() throws IOException;
114 public CompletableFuture<Integer> start() throws IOException {
115 return startInternal(
116 environment,
117 directory,
118 commandLine,
119 Optional.ofNullable(inputRedirect),
120 Optional.ofNullable(outputRedirect),
121 Optional.ofNullable(errorRedirect));
122 }
60 123
61 124 }
@@ -1,5 +1,13
1 1 package org.implab.gradle.common.exec;
2 2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Optional;
8 import java.util.concurrent.CompletableFuture;
9 import java.util.function.Consumer;
10
3 11 /** Shell used to start processes */
4 12 public interface ExecShell {
5 13
@@ -13,4 +21,38 public interface ExecShell {
13 21 static ExecShell system() {
14 22 return () -> new SystemExecBuilder();
15 23 }
24
25 /**
26 * Creates a stub shell which will print command to STDERR and return 0 (no
27 * error).
28 */
29 static ExecShell echoStderr() {
30 return () -> new EchoExecBuilder(true);
31 }
32
33 /**
34 * Creates a stub shell which will print command to STDOUT and return 0 (no
35 * error).
36 */
37
38 static ExecShell echo() {
39 return () -> new EchoExecBuilder(false);
40 }
41
42 /** Creates a stub shell which will call the specified consumer and will supply a command line to it.
43 * The command line will be passed as a list of strings.
44 * @param consumer The consumer fot the command line
45 * @return
46 */
47 static ExecShell echo(Consumer<List<String>> consumer) {
48 return () -> new ExecBuilder() {
49 @Override
50 protected CompletableFuture<Integer> startInternal(Map<String, String> environment, File directory,
51 List<String> commandLine, Optional<RedirectFrom> stdinRedirect, Optional<RedirectTo> stdoutRedirect,
52 Optional<RedirectTo> stderrRedirect) throws IOException {
53 consumer.accept(commandLine);
54 return CompletableFuture.completedFuture(0);
55 }
56 };
57 }
16 58 }
@@ -4,29 +4,28 import java.io.File;
4 4 import java.io.IOException;
5 5 import java.lang.ProcessBuilder.Redirect;
6 6 import java.util.ArrayList;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Optional;
7 10 import java.util.concurrent.CompletableFuture;
8 11
9 class SystemExecBuilder implements ExecBuilder {
10
11 private final ProcessBuilder builder = new ProcessBuilder();
12
13 private RedirectFrom inputRedirect;
12 class SystemExecBuilder extends ExecBuilder {
13 @Override
14 protected CompletableFuture<Integer> startInternal(Map<String, String> environment, File directory,
15 List<String> commandLine, Optional<RedirectFrom> stdinRedirect, Optional<RedirectTo> stdoutRedirect,
16 Optional<RedirectTo> stderrRedirect) throws IOException {
14 17
15 private RedirectTo outputRedirect;
18 var builder = new ProcessBuilder(commandLine)
19 .directory(directory);
16 20
17 private RedirectTo errorRedirect;
21 builder.environment().putAll(environment);
18 22
19 @Override
20 public CompletableFuture<Integer> start() throws IOException {
21 23 // TODO Auto-generated method stub
22 24 var tasks = new ArrayList<CompletableFuture<?>>();
23 25
24 // discard stdout if not redirected
25 if (outputRedirect == null)
26 if (!stdoutRedirect.isPresent())
26 27 builder.redirectOutput(Redirect.DISCARD);
27
28 // discard stderr if not redirected
29 if (errorRedirect == null)
28 if (!stderrRedirect.isPresent())
30 29 builder.redirectError(Redirect.DISCARD);
31 30
32 31 // run process
@@ -34,65 +33,12 class SystemExecBuilder implements ExecB
34 33
35 34 tasks.add(proc.onExit());
36 35
37 if (inputRedirect != null)
38 tasks.add(inputRedirect.redirect(proc.getOutputStream()));
39
40 if (outputRedirect != null)
41 tasks.add(outputRedirect.redirect(proc.getInputStream()));
42
43 if (errorRedirect != null)
44 tasks.add(errorRedirect.redirect(proc.getErrorStream()));
36 stdinRedirect.map(from -> from.redirect(proc.getOutputStream())).ifPresent(tasks::add);
37 stdoutRedirect.map(to -> to.redirect(proc.getInputStream())).ifPresent(tasks::add);
38 stderrRedirect.map(to -> to.redirect(proc.getErrorStream())).ifPresent(tasks::add);
45 39
46 40 return CompletableFuture
47 41 .allOf(tasks.toArray(new CompletableFuture<?>[0]))
48 42 .thenApply(t -> proc.exitValue());
49 43 }
50
51 @Override
52 public void directory(File workingDir) {
53 builder.directory(workingDir);
54 }
55
56 @Override
57 public void stderr(RedirectTo to) {
58 errorRedirect = to;
59 }
60
61 @Override
62 public void stdin(RedirectFrom from) {
63 inputRedirect = from;
64 }
65
66 @Override
67 public void stdout(RedirectTo to) {
68 outputRedirect = to;
69 }
70
71 @Override
72 public void argument(String arg) {
73 builder.command().add(arg);
74 }
75
76 @Override
77 public void setEnvironment(String envVar, String value) {
78 builder.environment().put(envVar, value);
79
80 }
81
82 @Override
83 public void unsetEnvironment(String envVar) {
84 builder.environment().remove(envVar);
85 }
86
87 @Override
88 public void command(String cmd, String... args) {
89 var commandLine = new ArrayList<String>();
90
91 commandLine.add(cmd);
92 for (var arg : args)
93 commandLine.add(arg);
94
95 builder.command(commandLine);
96 }
97
98 44 }
@@ -4,6 +4,7 import java.util.function.Supplier;
4 4
5 5 import javax.inject.Inject;
6 6
7 import org.gradle.api.NamedDomainObjectContainer;
7 8 import org.gradle.api.model.ObjectFactory;
8 9 import org.gradle.api.provider.Provider;
9 10 import org.gradle.api.provider.ProviderFactory;
@@ -24,4 +25,16 public interface ObjectsMixin {
24 25 default <T> Provider<T> provider(Closure<T> closure) {
25 26 return getProviders().provider(closure);
26 27 }
28
29 default <T> T newInstance(Class<T> clazz) {
30 return getObjects().newInstance(clazz);
31 }
32
33 default <T> T newInstance(Class<T> clazz, Object... params) {
34 return getObjects().newInstance(clazz, params);
35 }
36
37 default <T> NamedDomainObjectContainer<T> newContainer(Class<T> clazz) {
38 return getObjects().domainObjectContainer(clazz);
39 }
27 40 }
General Comments 0
You need to be logged in to leave comments. Login now