##// 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,61 +1,124
1 package org.implab.gradle.common.exec;
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 import java.util.concurrent.CompletableFuture;
9 import java.util.concurrent.CompletableFuture;
10 import java.util.stream.Stream;
4
11
5 import org.eclipse.jdt.annotation.NonNullByDefault;
12 import org.eclipse.jdt.annotation.NonNullByDefault;
6
13
7 import java.io.File;
14 import java.io.File;
8 import java.io.IOException;
15 import java.io.IOException;
9
16
10 /** Command line builder */
17 /** Command line builder */
11 @NonNullByDefault
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 /** Sets command line, clears previous one if any */
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 /** Adds an argument to the command line */
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 /** Sets the working directory */
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 * Sets the environment value. The value cannot be null.
53 * Sets the environment value. The value cannot be null.
25 *
54 *
26 * @param envVar The name of the environment variable
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 * Sets redirection for the stdin, {@link RedirectFrom} will be applied
69 * Sets redirection for the stdin, {@link RedirectFrom} will be applied
35 * every time the process is started.
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 * Sets redirection for the stdout, {@link RedirectTo} will be applied
81 * Sets redirection for the stdout, {@link RedirectTo} will be applied
43 * every time the process is started.
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 * Sets redirection for the stderr, {@link RedirectTo} will be applied
90 * Sets redirection for the stderr, {@link RedirectTo} will be applied
49 * every time the process is started.
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 * Creates and starts new process and returns {@link CompletableFuture}. The
108 * Creates and starts new process and returns {@link CompletableFuture}. The
55 * process may be a remote process, or a shell process or etc.
109 * process may be a remote process, or a shell process or etc.
110 *
56 * @return
111 * @return
57 * @throws IOException
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,16 +1,58
1 package org.implab.gradle.common.exec;
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 /** Shell used to start processes */
11 /** Shell used to start processes */
4 public interface ExecShell {
12 public interface ExecShell {
5
13
6 /** Creates new process builder {@link ExecBuilder} */
14 /** Creates new process builder {@link ExecBuilder} */
7 ExecBuilder builder();
15 ExecBuilder builder();
8
16
9 /**
17 /**
10 * Creates default process execution "shell" which will execute processes
18 * Creates default process execution "shell" which will execute processes
11 * directly.
19 * directly.
12 */
20 */
13 static ExecShell system() {
21 static ExecShell system() {
14 return () -> new SystemExecBuilder();
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);
16 }
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 }
58 }
@@ -1,98 +1,44
1 package org.implab.gradle.common.exec;
1 package org.implab.gradle.common.exec;
2
2
3 import java.io.File;
3 import java.io.File;
4 import java.io.IOException;
4 import java.io.IOException;
5 import java.lang.ProcessBuilder.Redirect;
5 import java.lang.ProcessBuilder.Redirect;
6 import java.util.ArrayList;
6 import java.util.ArrayList;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Optional;
7 import java.util.concurrent.CompletableFuture;
10 import java.util.concurrent.CompletableFuture;
8
11
9 class SystemExecBuilder implements ExecBuilder {
12 class SystemExecBuilder extends ExecBuilder {
10
13 @Override
11 private final ProcessBuilder builder = new ProcessBuilder();
14 protected CompletableFuture<Integer> startInternal(Map<String, String> environment, File directory,
12
15 List<String> commandLine, Optional<RedirectFrom> stdinRedirect, Optional<RedirectTo> stdoutRedirect,
13 private RedirectFrom inputRedirect;
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 // TODO Auto-generated method stub
23 // TODO Auto-generated method stub
22 var tasks = new ArrayList<CompletableFuture<?>>();
24 var tasks = new ArrayList<CompletableFuture<?>>();
23
25
24 // discard stdout if not redirected
26 if (!stdoutRedirect.isPresent())
25 if (outputRedirect == null)
26 builder.redirectOutput(Redirect.DISCARD);
27 builder.redirectOutput(Redirect.DISCARD);
27
28 if (!stderrRedirect.isPresent())
28 // discard stderr if not redirected
29 if (errorRedirect == null)
30 builder.redirectError(Redirect.DISCARD);
29 builder.redirectError(Redirect.DISCARD);
31
30
32 // run process
31 // run process
33 var proc = builder.start();
32 var proc = builder.start();
34
33
35 tasks.add(proc.onExit());
34 tasks.add(proc.onExit());
36
35
37 if (inputRedirect != null)
36 stdinRedirect.map(from -> from.redirect(proc.getOutputStream())).ifPresent(tasks::add);
38 tasks.add(inputRedirect.redirect(proc.getOutputStream()));
37 stdoutRedirect.map(to -> to.redirect(proc.getInputStream())).ifPresent(tasks::add);
39
38 stderrRedirect.map(to -> to.redirect(proc.getErrorStream())).ifPresent(tasks::add);
40 if (outputRedirect != null)
41 tasks.add(outputRedirect.redirect(proc.getInputStream()));
42
43 if (errorRedirect != null)
44 tasks.add(errorRedirect.redirect(proc.getErrorStream()));
45
39
46 return CompletableFuture
40 return CompletableFuture
47 .allOf(tasks.toArray(new CompletableFuture<?>[0]))
41 .allOf(tasks.toArray(new CompletableFuture<?>[0]))
48 .thenApply(t -> proc.exitValue());
42 .thenApply(t -> proc.exitValue());
49 }
43 }
50
51 @Override
52 public void directory(File workingDir) {
53 builder.directory(workingDir);
54 }
44 }
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 }
@@ -1,27 +1,40
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.utils;
2
2
3 import java.util.function.Supplier;
3 import java.util.function.Supplier;
4
4
5 import javax.inject.Inject;
5 import javax.inject.Inject;
6
6
7 import org.gradle.api.NamedDomainObjectContainer;
7 import org.gradle.api.model.ObjectFactory;
8 import org.gradle.api.model.ObjectFactory;
8 import org.gradle.api.provider.Provider;
9 import org.gradle.api.provider.Provider;
9 import org.gradle.api.provider.ProviderFactory;
10 import org.gradle.api.provider.ProviderFactory;
10
11
11 import groovy.lang.Closure;
12 import groovy.lang.Closure;
12
13
13 public interface ObjectsMixin {
14 public interface ObjectsMixin {
14 @Inject
15 @Inject
15 ObjectFactory getObjects();
16 ObjectFactory getObjects();
16
17
17 @Inject
18 @Inject
18 ProviderFactory getProviders();
19 ProviderFactory getProviders();
19
20
20 default <T> Provider<T> provider(Supplier<T> supplier) {
21 default <T> Provider<T> provider(Supplier<T> supplier) {
21 return getProviders().provider(supplier::get);
22 return getProviders().provider(supplier::get);
22 }
23 }
23
24
24 default <T> Provider<T> provider(Closure<T> closure) {
25 default <T> Provider<T> provider(Closure<T> closure) {
25 return getProviders().provider(closure);
26 return getProviders().provider(closure);
26 }
27 }
28
29 default <T> T newInstance(Class<T> clazz) {
30 return getObjects().newInstance(clazz);
27 }
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 }
40 }
General Comments 0
You need to be logged in to leave comments. Login now