##// END OF EJS Templates
WIP exec api
cin -
r13:59dae0731c45 default
parent child
Show More
@@ -1,27 +1,45
1 1 package org.implab.gradle.common.dsl;
2 2
3 import java.io.File;
4 import java.io.InputStream;
3 5 import java.util.Optional;
4 6 import java.util.function.Supplier;
5 7
6 8 import org.gradle.api.provider.Provider;
7 9 import org.implab.gradle.common.exec.RedirectFrom;
8 10
9 11 public class RedirectFromSpec {
10 12 private Supplier<RedirectFrom> streamRedirect;
11
13
12 14 public boolean isRedirected() {
13 15 return streamRedirect != null;
14 16 }
15 17
16 18 public Optional<RedirectFrom> getRedirection() {
17 19 return streamRedirect != null ? Optional.ofNullable(streamRedirect.get()) : Optional.empty();
18 20 }
19 21
22 public void fromFile(File file) {
23 this.streamRedirect = () -> RedirectFrom.file(file);
24 }
25
26 public void fromFile(Provider<File> fileProvider) {
27 this.streamRedirect = fileProvider.map(RedirectFrom::file)::getOrNull;
28 }
29
30 public void fromStream(InputStream stream) {
31 this.streamRedirect = () -> RedirectFrom.stream(stream);
32 }
33
34 public void fromStream(Provider<InputStream> streamProvider) {
35 this.streamRedirect = streamProvider.map(RedirectFrom::stream)::getOrNull;
36 }
37
20 38 public void from(Object input) {
21 39 if (input instanceof Provider<?> inputProvider) {
22 40 this.streamRedirect = inputProvider.map(RedirectFrom::any)::get;
23 41 } else {
24 42 this.streamRedirect = () -> RedirectFrom.any(input);
25 43 }
26 44 }
27 45 }
@@ -1,62 +1,67
1 1 package org.implab.gradle.common.exec;
2 2
3 import java.util.stream.Stream;
4
5 3 import org.eclipse.jdt.annotation.NonNullByDefault;
6 4 import org.implab.gradle.common.utils.Values;
7 5
8 6 /** Command builder interface, used to specify the executable and parameters */
9 7 @NonNullByDefault
10 8 public interface CommandBuilder {
11 9
12 10 /** Sets the executable, the parameters are left intact. */
13 11 CommandBuilder executable(String executable);
14 12
15 /** Sets the specified executable and parameters, old executable and parameters
13 /**
14 * Sets the specified executable and parameters, old executable and parameters
16 15 * are discarded.
17 16 */
18 17 default CommandBuilder commandLine(String executable, String... args) {
19 18 return executable(executable)
20 .arguments(args);
19 .arguments(args);
21 20 }
22 21
23 /** Sets the specified executable and parameters, old executable and parameters
22 /**
23 * Sets the specified executable and parameters, old executable and parameters
24 24 * are discarded.
25 25 *
26 * @param command The command line. Must contain at least one element (executable).
26 * @param command The command line. Must contain at least one element
27 * (executable).
27 28 *
28 29 */
29 30 default CommandBuilder commandLine(Iterable<? extends String> command) {
30 31 var iterator = command.iterator();
31 32
32 33 // set executable
33 34 executable(Values.take(iterator).orElseThrow());
34 35 // cleat arguments
35 36 arguments();
37
36 38 // set new arguments
37 39 while (iterator.hasNext())
38 40 addArguments(iterator.next());
39 41
40 42 return this;
41 43 }
42 44
43 45 /** Adds the specified arguments to this builder */
44 default CommandBuilder addArguments(String arg0, String... args) {
45 return arguments(() -> Stream
46 .concat(Stream.of(arg0), Stream.of(args))
47 .iterator());
46 CommandBuilder addArguments(String arg0, String... args);
47
48 default CommandBuilder addArguments(Iterable<String> args) {
49 for (String arg : args)
50 addArguments(arg);
51
52 return this;
48 53 }
49 54
50 55 /** Replaces arguments in the builder with the specified one. */
51 56 default CommandBuilder arguments(String... args) {
52 57 return arguments(Values.iterable(args));
53 58 }
54 59
55 60 /** Replaces arguments in the builder with the specified one. */
56 61 CommandBuilder arguments(Iterable<String> args);
57 62
58 63 default CommandBuilder from(CommandSpec commandSpec) {
59 64 return executable(commandSpec.executable())
60 65 .arguments(commandSpec.arguments());
61 66 }
62 67 }
@@ -1,42 +1,39
1 1 package org.implab.gradle.common.exec;
2 2
3 3 import java.io.ByteArrayInputStream;
4 import java.io.File;
5 4 import java.io.IOException;
6 5 import java.nio.charset.StandardCharsets;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Optional;
10 6 import java.util.concurrent.CompletableFuture;
7 import java.util.stream.Collectors;
11 8
12 9 class EchoExecBuilder extends ExecBuilder {
13 10
14 11 private final boolean echoToStderr;
15 12
16 13 public EchoExecBuilder(boolean echoToStderr) {
17 14 this.echoToStderr = echoToStderr;
18 15 }
19 16
20 17 @Override
21 18 protected CompletableFuture<Integer> startInternal(
22 Map<String, String> environment,
23 Optional<File> directory,
24 List<String> commandLine,
25 Optional<RedirectFrom> stdinRedirect,
26 Optional<RedirectTo> stdoutRedirect,
27 Optional<RedirectTo> stderrRedirect) throws IOException {
19 CommandSpec command,
20 EnvironmentSpec environment,
21 PipeSpec redirect) throws IOException {
28 22
29 var outputRedirect = echoToStderr ? stderrRedirect : stdoutRedirect;
23 var outputRedirect = echoToStderr ? redirect.stderr() : redirect.stdout();
30 24
31 25 return outputRedirect
32 26 .map(to -> {
33 var bytes = String.format("exec: %s", commandLine)
27 var bytes = String
28 .format(
29 "exec: %s",
30 command.commandLine().stream().collect(Collectors.joining(" ")))
34 31 .getBytes(StandardCharsets.UTF_8);
35 32
36 33 return to.redirect(new ByteArrayInputStream(bytes))
37 34 .thenApply((x) -> 0);
38 35 })
39 36 .orElse(CompletableFuture.completedFuture(0));
40 37 }
41 38
42 39 }
@@ -1,25 +1,31
1 1 package org.implab.gradle.common.exec;
2 2
3 3 import java.io.File;
4 4 import java.util.Map;
5 5 import java.util.Optional;
6 6
7 7 import org.eclipse.jdt.annotation.NonNullByDefault;
8 8
9 9 @NonNullByDefault
10 10 public interface EnvironmentBuilder {
11 /** Sets the specified environment variable */
11 12 EnvironmentBuilder setVariable(String envVar, String value);
12 13
14 /** Replaces environment with the supplied one */
13 15 EnvironmentBuilder environment(Map<String, ? extends String> env);
14 16
17 /** Unsets the specified variable. If the variable is inherited it removed anyway. */
15 18 EnvironmentBuilder unsetVariable(String envVar);
16 19
20 /** Specifies the working directory */
17 21 EnvironmentBuilder workingDirectory(File directory);
18 22
23 /** Specifies the working directory */
19 24 EnvironmentBuilder workingDirectory(Optional<? extends File> directory);
20 25
26 /** Copies the supplied environment to this one */
21 27 default EnvironmentBuilder from(EnvironmentSpec environmentSpec) {
22 28 return environment(environmentSpec.environment())
23 29 .workingDirectory(environmentSpec.workingDirectory());
24 30 }
25 31 }
@@ -1,199 +1,265
1 1 package org.implab.gradle.common.exec;
2 2
3 3 import java.util.ArrayList;
4 4 import java.util.HashMap;
5 5 import java.util.List;
6 6 import java.util.Map;
7 7 import java.util.Optional;
8 8 import java.util.concurrent.CompletableFuture;
9 9
10 10 import org.eclipse.jdt.annotation.NonNullByDefault;
11 11 import org.eclipse.jdt.annotation.Nullable;
12 12
13 13 import java.io.File;
14 14 import java.io.IOException;
15 15
16 16 import static java.util.Objects.requireNonNull;
17 17
18 18 /** Command line builder */
19 19 @NonNullByDefault
20 20 public abstract class ExecBuilder implements
21 21 CommandBuilder,
22 22 PipeBuilder,
23 23 EnvironmentBuilder,
24 24 Runnable
25 25 {
26 26 private String executable;
27 27
28 28 private final List<String> arguments = new ArrayList<>();
29 29
30 30 private final Map<String, String> environment = new HashMap<>();
31 31
32 32 private @Nullable File directory;
33 33
34 34 private RedirectFrom inputRedirect;
35 35
36 36 private RedirectTo outputRedirect;
37 37
38 38 private RedirectTo errorRedirect;
39 39
40 40 @Override
41 41 public ExecBuilder executable(String executable) {
42 42 requireNonNull(executable, "cmd can't be null");
43 43 this.executable = executable;
44 44 return this;
45 45 }
46 46
47 47 @Override
48 48 public ExecBuilder arguments(Iterable<String> args) {
49 49 requireNonNull(args, "Args must not be null");
50 50 arguments.clear();
51 51 for(var arg: args)
52 52 arguments.add(arg);
53 53 return this;
54 54 }
55 55
56 56 @Override
57 57 public ExecBuilder addArguments(String arg0, String... args) {
58 58 requireNonNull(arg0, "arg0 parameter can't be null");
59 59 arguments.add(arg0);
60 60
61 61 for (var arg : args)
62 62 arguments.add(arg);
63 63
64 64 return this;
65 65 }
66 66
67 67 /** Sets the working directory */
68 68 @Override
69 69 public ExecBuilder workingDirectory(File directory) {
70 70 requireNonNull(directory, "directory parameter can't be null");
71 71
72 72 this.directory = directory;
73 73 return this;
74 74 }
75 75
76 76 @Override
77 77 public ExecBuilder workingDirectory(Optional<? extends File> directory) {
78 78 requireNonNull(directory, "directory parameter can't be null");
79 79
80 80 this.directory = directory.orElse(null);
81 81 return this;
82 82 }
83 83
84 84 /**
85 85 * Sets the environment value. The value cannot be null.
86 86 *
87 87 * @param envVar The name of the environment variable
88 88 * @param value The value to set,
89 89 */
90 90 @Override
91 91 public ExecBuilder setVariable(String envVar, String value) {
92 92 requireNonNull(value, "Value can't be null");
93 93 requireNonNull(envVar, "envVar parameter can't be null");
94 94
95 95 environment.put(envVar, value);
96 96 return this;
97 97 }
98 98
99 99 @Override
100 public ExecBuilder unsetVariable(String envVar) {
101 requireNonNull(envVar, "envVar parameter can't be null");
102
103 environment.remove(envVar);
104 return this;
105 }
106
107 @Override
100 108 public ExecBuilder environment(Map<String,? extends String> env) {
101 109 requireNonNull(env, "env parameter can't be null");
102 110
103 111 environment.clear();
104 112 environment.putAll(env);
105 113 return this;
106 114 }
107 115
108 116 /**
109 117 * Sets redirection for the stdin, {@link RedirectFrom} will be applied
110 118 * every time the process is started.
111 119 *
112 120 * <p>
113 121 * If redirection
114 122 */
115 123 @Override
116 124 public ExecBuilder stdin(RedirectFrom from) {
117 125 requireNonNull(from, "from parameter can't be null");
118 126
119 127 inputRedirect = from;
120 128 return this;
121 129 }
122 130
123 131 @Override
124 public PipeBuilder stdin(Optional<? extends RedirectFrom> from) {
132 public ExecBuilder stdin(Optional<? extends RedirectFrom> from) {
125 133 requireNonNull(from, "from parameter can't be null");
126 134 inputRedirect = from.orElse(null);
127 135 return this;
128 136 }
129 137
130 138 /**
131 139 * Sets redirection for the stdout, {@link RedirectTo} will be applied
132 140 * every time the process is started.
133 141 */
134 142 @Override
135 143 public ExecBuilder stdout(RedirectTo out) {
136 144 requireNonNull(out, "out parameter can't be null");
137 145 outputRedirect = out;
138 146 return this;
139 147 }
140 148
141 149 @Override
142 public PipeBuilder stdout(Optional<? extends RedirectTo> to) {
150 public ExecBuilder stdout(Optional<? extends RedirectTo> to) {
143 151 requireNonNull(to, "from parameter can't be null");
144 152 outputRedirect = to.orElse(null);
145 153 return this;
146 154 }
147 155
148 156 /**
149 157 * Sets redirection for the stderr, {@link RedirectTo} will be applied
150 158 * every time the process is started.
151 159 */
152 160 @Override
153 161 public ExecBuilder stderr(RedirectTo err) {
154 162 requireNonNull(err, "err parameter can't be null");
155 163 errorRedirect = err;
156 164 return this;
157 165 }
158 166
159 167 @Override
160 public PipeBuilder stderr(Optional<? extends RedirectTo> to) {
168 public ExecBuilder stderr(Optional<? extends RedirectTo> to) {
161 169 requireNonNull(to, "from parameter can't be null");
162 170 errorRedirect = to.orElse(null);
163 171 return this;
164 172 }
165 173
174 @Override
175 public ExecBuilder from(CommandSpec commandSpec) {
176 CommandBuilder.super.from(commandSpec);
177 return this;
178 }
179
180 @Override
181 public ExecBuilder from(PipeSpec pipeSpec) {
182 PipeBuilder.super.from(pipeSpec);
183 return this;
184 }
185
186 @Override
187 public ExecBuilder from(EnvironmentSpec environmentSpec) {
188 EnvironmentBuilder.super.from(environmentSpec);
189 return this;
190 }
191
166 192 /** Implement this function to */
167 193 protected abstract CompletableFuture<Integer> startInternal(
168 Map<String, String> environment,
169 Optional<File> directory,
170 List<String> commandLine,
171 Optional<RedirectFrom> stdinRedirect,
172 Optional<RedirectTo> stdoutRedirect,
173 Optional<RedirectTo> stderrRedirect) throws IOException;
194 CommandSpec command,
195 EnvironmentSpec environment,
196 PipeSpec redirect) throws IOException;
174 197
175 198 /**
176 199 * Creates and starts new process and returns {@link CompletableFuture}. The
177 200 * process may be a remote process, or a shell process or etc.
178 201 *
179 202 * @return
180 203 * @throws IOException
181 204 */
182 205 public CompletableFuture<Integer> run() throws IOException {
183 206 if (executable == null || executable.isEmpty())
184 207 throw new IllegalStateException("The executable isn't set");
185 208
186 209 var commandLine = new ArrayList<String>();
187 210 commandLine.add(executable);
188 211 commandLine.addAll(arguments);
189 212
190 213 return startInternal(
191 environment,
192 Optional.ofNullable(directory),
193 commandLine,
194 Optional.ofNullable(inputRedirect),
195 Optional.ofNullable(outputRedirect),
196 Optional.ofNullable(errorRedirect));
214 new SelfCommandSpec(),
215 new SelfEnvironmentSpec(),
216 new SelfPipeSpec()
217 );
218 }
219
220 private class SelfCommandSpec implements CommandSpec {
221
222 @Override
223 public String executable() {
224 return executable;
225 }
226
227 @Override
228 public List<String> arguments() {
229 return arguments;
230 }
231 }
232
233 private class SelfEnvironmentSpec implements EnvironmentSpec {
234
235 @Override
236 public Map<String, String> environment() {
237 return environment;
238 }
239
240 @Override
241 public Optional<File> workingDirectory() {
242 return Optional.ofNullable( directory);
243 }
244 }
245
246 private class SelfPipeSpec implements PipeSpec {
247
248 @Override
249 public Optional<RedirectTo> stdout() {
250 return Optional.ofNullable(outputRedirect);
251 }
252
253 @Override
254 public Optional<RedirectTo> stderr() {
255 return Optional.ofNullable(errorRedirect);
256 }
257
258 @Override
259 public Optional<RedirectFrom> stdin() {
260 return Optional.ofNullable(inputRedirect);
261 }
262
197 263 }
198 264
199 265 }
@@ -1,58 +1,59
1 1 package org.implab.gradle.common.exec;
2 2
3 import java.io.File;
4 3 import java.io.IOException;
5 4 import java.util.List;
6 import java.util.Map;
7 import java.util.Optional;
8 5 import java.util.concurrent.CompletableFuture;
9 6 import java.util.function.Consumer;
10 7
11 8 /** Shell used to start processes */
12 9 public interface ExecShell {
13 10
14 11 /** Creates new process builder {@link ExecBuilder} */
15 12 ExecBuilder executable();
16 13
17 14 /**
18 15 * Creates default process execution "shell" which will execute processes
19 16 * directly.
20 17 */
21 18 static ExecShell system() {
22 19 return () -> new SystemExecBuilder();
23 20 }
24 21
25 22 /**
26 23 * Creates a stub shell which will print command to STDERR and return 0 (no
27 24 * error).
28 25 */
29 26 static ExecShell echoStderr() {
30 27 return () -> new EchoExecBuilder(true);
31 28 }
32 29
33 30 /**
34 31 * Creates a stub shell which will print command to STDOUT and return 0 (no
35 32 * error).
36 33 */
37 34
38 35 static ExecShell echo() {
39 36 return () -> new EchoExecBuilder(false);
40 37 }
41 38
42 /** Creates a stub shell which will call the specified consumer and will supply a command line to it.
39 /**
40 * Creates a stub shell which will call the specified consumer and will supply a
41 * command line to it.
43 42 * The command line will be passed as a list of strings.
44 * @param consumer The consumer fot the command line
43 *
44 * @param consumer The consumer fot the command line
45 45 * @return
46 46 */
47 47 static ExecShell echo(Consumer<List<String>> consumer) {
48 48 return () -> new ExecBuilder() {
49 49 @Override
50 protected CompletableFuture<Integer> startInternal(Map<String, String> environment, Optional<File> directory,
51 List<String> commandLine, Optional<RedirectFrom> stdinRedirect, Optional<RedirectTo> stdoutRedirect,
52 Optional<RedirectTo> stderrRedirect) throws IOException {
53 consumer.accept(commandLine);
50 protected CompletableFuture<Integer> startInternal(
51 CommandSpec command,
52 EnvironmentSpec environment,
53 PipeSpec redirect) throws IOException {
54 consumer.accept(command.commandLine());
54 55 return CompletableFuture.completedFuture(0);
55 56 }
56 57 };
57 58 }
58 59 }
@@ -1,49 +1,41
1 1 package org.implab.gradle.common.exec;
2 2
3 import java.io.File;
4 3 import java.io.IOException;
5 4 import java.lang.ProcessBuilder.Redirect;
6 5 import java.util.ArrayList;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Optional;
10 6 import java.util.concurrent.CompletableFuture;
11 7
12 8 class SystemExecBuilder extends ExecBuilder {
13 9 @Override
14 10 protected CompletableFuture<Integer> startInternal(
15 Map<String, String> environment,
16 Optional<File> directory,
17 List<String> commandLine,
18 Optional<RedirectFrom> stdinRedirect,
19 Optional<RedirectTo> stdoutRedirect,
20 Optional<RedirectTo> stderrRedirect) throws IOException {
11 CommandSpec command,
12 EnvironmentSpec environment,
13 PipeSpec redirect) throws IOException {
21 14
22 var builder = new ProcessBuilder(commandLine);
23
24 directory.ifPresent(builder::directory);
15 var builder = new ProcessBuilder(command.commandLine());
25 16
26 builder.environment().putAll(environment);
17 environment.workingDirectory().ifPresent(builder::directory);
27 18
28 // TODO Auto-generated method stub
19 builder.environment().putAll(environment.environment());
20
29 21 var tasks = new ArrayList<CompletableFuture<?>>();
30 22
31 if (!stdoutRedirect.isPresent())
23 if (!redirect.stdout().isPresent())
32 24 builder.redirectOutput(Redirect.DISCARD);
33 if (!stderrRedirect.isPresent())
25 if (!redirect.stderr().isPresent())
34 26 builder.redirectError(Redirect.DISCARD);
35 27
36 28 // run process
37 29 var proc = builder.start();
38 30
39 31 tasks.add(proc.onExit());
40 32
41 stdinRedirect.map(from -> from.redirect(proc.getOutputStream())).ifPresent(tasks::add);
42 stdoutRedirect.map(to -> to.redirect(proc.getInputStream())).ifPresent(tasks::add);
43 stderrRedirect.map(to -> to.redirect(proc.getErrorStream())).ifPresent(tasks::add);
33 redirect.stdin().map(from -> from.redirect(proc.getOutputStream())).ifPresent(tasks::add);
34 redirect.stdout().map(to -> to.redirect(proc.getInputStream())).ifPresent(tasks::add);
35 redirect.stderr().map(to -> to.redirect(proc.getErrorStream())).ifPresent(tasks::add);
44 36
45 37 return CompletableFuture
46 38 .allOf(tasks.toArray(new CompletableFuture<?>[0]))
47 39 .thenApply(t -> proc.exitValue());
48 40 }
49 41 }
@@ -1,110 +1,110
1 1 package org.implab.gradle.common.tasks;
2 2
3 3 import java.io.IOException;
4 4 import java.util.Map;
5 5 import java.util.concurrent.ExecutionException;
6 6 import java.util.stream.Stream;
7 7
8 8 import org.gradle.api.DefaultTask;
9 9 import org.gradle.api.file.DirectoryProperty;
10 10 import org.gradle.api.provider.ListProperty;
11 11 import org.gradle.api.provider.MapProperty;
12 12 import org.gradle.api.tasks.Internal;
13 13 import org.gradle.api.tasks.TaskAction;
14 14 import org.implab.gradle.common.dsl.CommandSpec;
15 15 import org.implab.gradle.common.dsl.PipeSpec;
16 16 import org.implab.gradle.common.dsl.RedirectFromSpec;
17 17 import org.implab.gradle.common.dsl.RedirectToSpec;
18 18 import org.implab.gradle.common.dsl.EnvironmentSpec;
19 19 import org.implab.gradle.common.exec.ExecBuilder;
20 20 import org.implab.gradle.common.utils.ObjectsMixin;
21 21 import org.implab.gradle.common.utils.Strings;
22 22 import org.implab.gradle.common.utils.ThrowingConsumer;
23 23
24 24 public abstract class ShellExecTask
25 25 extends DefaultTask
26 26 implements CommandSpec, PipeSpec, EnvironmentSpec, ObjectsMixin {
27 27
28 28 private final RedirectToSpec redirectStderr = new RedirectToSpec();
29 29
30 30 private final RedirectToSpec redirectStdout = new RedirectToSpec();
31 31
32 32 private final RedirectFromSpec redirectStdin = new RedirectFromSpec();
33 33
34 34 @Internal
35 35 @Override
36 36 public abstract DirectoryProperty getWorkingDirectory();
37 37
38 38 @Internal
39 39 @Override
40 40 public abstract MapProperty<String, String> getEnvironment();
41 41
42 42 @Internal
43 43 @Override
44 44 public abstract ListProperty<String> getCommandLine();
45 45
46 46 /**
47 47 * STDIN redirection, if not specified, no input will be passed to the command
48 48 */
49 49 @Internal
50 50 @Override
51 51 public RedirectFromSpec getStdin() {
52 52 return redirectStdin;
53 53 }
54 54
55 55 /**
56 56 * STDOUT redirection, if not specified, redirected to logger::info
57 57 */
58 58 @Internal
59 59 @Override
60 60 public RedirectToSpec getStdout() {
61 61 return redirectStdout;
62 62 }
63 63
64 64 /**
65 65 * STDERR redirection, if not specified, redirected to logger::error
66 66 */
67 67 @Internal
68 68 @Override
69 69 public RedirectToSpec getStderr() {
70 70 return redirectStderr;
71 71 }
72 72
73 73 @Override
74 74 public void commandLine(Object arg0, Object... args) {
75 75 getCommandLine().set(provider(() -> Stream.concat(
76 76 Stream.of(arg0),
77 77 Stream.of(args))
78 78 .map(Strings::asString).toList()));
79 79
80 80 }
81 81
82 82 @Override
83 83 public void args(Object arg0, Object... args) {
84 84 getCommandLine().addAll(provider(() -> Stream.concat(
85 85 Stream.of(arg0),
86 86 Stream.of(args))
87 87 .map(Strings::asString).toList()));
88 88 }
89 89
90 90 protected abstract ExecBuilder execBuilder();
91 91
92 92 @TaskAction
93 93 public final void run() throws IOException, InterruptedException, ExecutionException {
94 var execBuilder = execBuilder()
95 .workingDirectory(getWorkingDirectory().get().getAsFile())
96 .environment(getEnvironment().getOrElse(Map.of()))
97 .commandLine(getCommandLine().get());
94 var execBuilder = execBuilder();
95 execBuilder.workingDirectory(getWorkingDirectory().get().getAsFile());
96 execBuilder.environment(getEnvironment().getOrElse(Map.of()));
97 execBuilder.commandLine(getCommandLine().get());
98 98
99 99 getStdout().getRedirection().ifPresent(execBuilder::stdout);
100 100 getStderr().getRedirection().ifPresent(execBuilder::stderr);
101 101 getStdin().getRedirection().ifPresent(execBuilder::stdin);
102 102
103 103 execBuilder.run().thenAccept(ThrowingConsumer.guard(this::checkRetCode)).join();
104 104 }
105 105
106 protected void checkRetCode(Integer code) throws IOException{
106 protected void checkRetCode(Integer code) throws IOException {
107 107 throw new IOException(String.format("The process is terminated with code %s", code));
108 108 }
109 109
110 110 }
@@ -1,88 +1,89
1 1 package org.implab.gradle.common.utils;
2 2
3 3 import java.util.Iterator;
4 4 import java.util.Map;
5 import java.util.Spliterator;
6 5 import java.util.Spliterators;
7 6 import java.util.Map.Entry;
8 7 import java.util.Optional;
9 8 import java.util.function.Function;
10 9 import java.util.function.Supplier;
11 10 import java.util.stream.Collectors;
12 11 import java.util.stream.Stream;
13 12 import java.util.stream.StreamSupport;
14 13
15 14 import org.gradle.api.provider.Provider;
16 15
17 16 public final class Values {
18 17
19 18 private Values() {
20 19 }
21 20
22 21 /**
23 22 * Converts values in the specified map
23 *
24 24 * @param <K>
25 25 * @param <V>
26 26 * @param <U>
27 27 * @param map
28 28 * @param mapper
29 29 * @return
30 30 */
31 31 public static <K, V, U> Map<K, U> mapValues(Map<K, V> map, Function<V, U> mapper) {
32 32 Function<Entry<K, V>, V> getter = Entry::getValue;
33 33
34 34 return map.entrySet().stream()
35 35 .collect(Collectors.toMap(Entry::getKey, getter.andThen(mapper)));
36 36 }
37 37
38 /** Converts the supplied value to a string.
38 /**
39 * Converts the supplied value to a string.
39 40 */
40 41 public static String toString(Object value) {
41 42 if (value == null) {
42 return null;
43 } else if (value instanceof String string) {
43 return null;
44 } else if (value instanceof String string) {
44 45 return string;
45 46 } else if (value instanceof Provider<?> provider) {
46 47 return toString(provider.getOrNull());
47 48 } else if (value instanceof Supplier<?> supplier) {
48 49 return toString(supplier.get());
49 50 } else {
50 51 return value.toString();
51 52 }
52 53 }
53 54
54 55 public static <T> Stream<T> stream(Iterator<T> remaining) {
55 var spliterator = Spliterators.spliteratorUnknownSize(remaining, 0);
56
57 return StreamSupport.stream(spliterator, false);
56 return StreamSupport.stream(
57 Spliterators.spliteratorUnknownSize(remaining, 0),
58 false);
58 59 }
59 60
60 61 public static <T> Optional<T> take(Iterator<T> iterator) {
61 62 return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.empty();
62 63 }
63 64
64 65 public static <T> Iterable<T> iterable(T[] values) {
65 66 return () -> new ArrayIterator<>(values);
66 67 }
67 68
68 69 private static class ArrayIterator<T> implements Iterator<T> {
69 70 private final T[] data;
70 71
71 72 private int pos = 0;
72 73
73 74 ArrayIterator(T[] data) {
74 75 this.data = data;
75 76 }
76 77
77 78 @Override
78 79 public boolean hasNext() {
79 80 return pos < data.length;
80 81 }
81 82
82 83 @Override
83 84 public T next() {
84 85 return data[pos++];
85 86 }
86 87 }
87 88
88 89 }
General Comments 0
You need to be logged in to leave comments. Login now