##// END OF EJS Templates
WIP minor changes
cin -
r12:9ce58f1128fc default
parent child
Show More
@@ -1,34 +1,62
1 1 package org.implab.gradle.common.exec;
2 2
3 3 import java.util.stream.Stream;
4 4
5 5 import org.eclipse.jdt.annotation.NonNullByDefault;
6 6 import org.implab.gradle.common.utils.Values;
7 7
8 /** Command builder interface, used to specify the executable and parameters */
8 9 @NonNullByDefault
9 10 public interface CommandBuilder {
10 11
12 /** Sets the executable, the parameters are left intact. */
11 13 CommandBuilder executable(String executable);
12 14
15 /** Sets the specified executable and parameters, old executable and parameters
16 * are discarded.
17 */
13 18 default CommandBuilder commandLine(String executable, String... args) {
14 19 return executable(executable)
15 20 .arguments(args);
16 21 }
17 22
18 default CommandBuilder arg(String arg0, String... args) {
23 /** Sets the specified executable and parameters, old executable and parameters
24 * are discarded.
25 *
26 * @param command The command line. Must contain at least one element (executable).
27 *
28 */
29 default CommandBuilder commandLine(Iterable<? extends String> command) {
30 var iterator = command.iterator();
31
32 // set executable
33 executable(Values.take(iterator).orElseThrow());
34 // cleat arguments
35 arguments();
36 // set new arguments
37 while (iterator.hasNext())
38 addArguments(iterator.next());
39
40 return this;
41 }
42
43 /** Adds the specified arguments to this builder */
44 default CommandBuilder addArguments(String arg0, String... args) {
19 45 return arguments(() -> Stream
20 46 .concat(Stream.of(arg0), Stream.of(args))
21 47 .iterator());
22 48 }
23 49
50 /** Replaces arguments in the builder with the specified one. */
24 51 default CommandBuilder arguments(String... args) {
25 52 return arguments(Values.iterable(args));
26 53 }
27 54
55 /** Replaces arguments in the builder with the specified one. */
28 56 CommandBuilder arguments(Iterable<String> args);
29 57
30 58 default CommandBuilder from(CommandSpec commandSpec) {
31 59 return executable(commandSpec.executable())
32 60 .arguments(commandSpec.arguments());
33 61 }
34 62 }
@@ -1,208 +1,199
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 public ExecBuilder commandLine(Iterable<? extends String> cmd) {
57 requireNonNull(cmd, "cmd can't be null");
58
59 this.arguments.clear();
60 for (var arg : cmd)
61 this.arguments.add(arg);
62 return this;
63 }
64
65 56 @Override
66 public ExecBuilder arg(String arg0, String... args) {
57 public ExecBuilder addArguments(String arg0, String... args) {
67 58 requireNonNull(arg0, "arg0 parameter can't be null");
68 59 arguments.add(arg0);
69 60
70 61 for (var arg : args)
71 62 arguments.add(arg);
72 63
73 64 return this;
74 65 }
75 66
76 67 /** Sets the working directory */
77 68 @Override
78 69 public ExecBuilder workingDirectory(File directory) {
79 70 requireNonNull(directory, "directory parameter can't be null");
80 71
81 72 this.directory = directory;
82 73 return this;
83 74 }
84 75
85 76 @Override
86 77 public ExecBuilder workingDirectory(Optional<? extends File> directory) {
87 78 requireNonNull(directory, "directory parameter can't be null");
88 79
89 80 this.directory = directory.orElse(null);
90 81 return this;
91 82 }
92 83
93 84 /**
94 85 * Sets the environment value. The value cannot be null.
95 86 *
96 87 * @param envVar The name of the environment variable
97 88 * @param value The value to set,
98 89 */
99 90 @Override
100 91 public ExecBuilder setVariable(String envVar, String value) {
101 92 requireNonNull(value, "Value can't be null");
102 93 requireNonNull(envVar, "envVar parameter can't be null");
103 94
104 95 environment.put(envVar, value);
105 96 return this;
106 97 }
107 98
108 99 @Override
109 100 public ExecBuilder environment(Map<String,? extends String> env) {
110 101 requireNonNull(env, "env parameter can't be null");
111 102
112 103 environment.clear();
113 104 environment.putAll(env);
114 105 return this;
115 106 }
116 107
117 108 /**
118 109 * Sets redirection for the stdin, {@link RedirectFrom} will be applied
119 110 * every time the process is started.
120 111 *
121 112 * <p>
122 113 * If redirection
123 114 */
124 115 @Override
125 116 public ExecBuilder stdin(RedirectFrom from) {
126 117 requireNonNull(from, "from parameter can't be null");
127 118
128 119 inputRedirect = from;
129 120 return this;
130 121 }
131 122
132 123 @Override
133 124 public PipeBuilder stdin(Optional<? extends RedirectFrom> from) {
134 125 requireNonNull(from, "from parameter can't be null");
135 126 inputRedirect = from.orElse(null);
136 127 return this;
137 128 }
138 129
139 130 /**
140 131 * Sets redirection for the stdout, {@link RedirectTo} will be applied
141 132 * every time the process is started.
142 133 */
143 134 @Override
144 135 public ExecBuilder stdout(RedirectTo out) {
145 136 requireNonNull(out, "out parameter can't be null");
146 137 outputRedirect = out;
147 138 return this;
148 139 }
149 140
150 141 @Override
151 142 public PipeBuilder stdout(Optional<? extends RedirectTo> to) {
152 143 requireNonNull(to, "from parameter can't be null");
153 144 outputRedirect = to.orElse(null);
154 145 return this;
155 146 }
156 147
157 148 /**
158 149 * Sets redirection for the stderr, {@link RedirectTo} will be applied
159 150 * every time the process is started.
160 151 */
161 152 @Override
162 153 public ExecBuilder stderr(RedirectTo err) {
163 154 requireNonNull(err, "err parameter can't be null");
164 155 errorRedirect = err;
165 156 return this;
166 157 }
167 158
168 159 @Override
169 160 public PipeBuilder stderr(Optional<? extends RedirectTo> to) {
170 161 requireNonNull(to, "from parameter can't be null");
171 162 errorRedirect = to.orElse(null);
172 163 return this;
173 164 }
174 165
175 166 /** Implement this function to */
176 167 protected abstract CompletableFuture<Integer> startInternal(
177 168 Map<String, String> environment,
178 169 Optional<File> directory,
179 170 List<String> commandLine,
180 171 Optional<RedirectFrom> stdinRedirect,
181 172 Optional<RedirectTo> stdoutRedirect,
182 173 Optional<RedirectTo> stderrRedirect) throws IOException;
183 174
184 175 /**
185 176 * Creates and starts new process and returns {@link CompletableFuture}. The
186 177 * process may be a remote process, or a shell process or etc.
187 178 *
188 179 * @return
189 180 * @throws IOException
190 181 */
191 182 public CompletableFuture<Integer> run() throws IOException {
192 183 if (executable == null || executable.isEmpty())
193 184 throw new IllegalStateException("The executable isn't set");
194 185
195 186 var commandLine = new ArrayList<String>();
196 187 commandLine.add(executable);
197 188 commandLine.addAll(arguments);
198 189
199 190 return startInternal(
200 191 environment,
201 192 Optional.ofNullable(directory),
202 193 commandLine,
203 194 Optional.ofNullable(inputRedirect),
204 195 Optional.ofNullable(outputRedirect),
205 196 Optional.ofNullable(errorRedirect));
206 197 }
207 198
208 199 }
@@ -1,73 +1,88
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 import java.util.Spliterators;
5 7 import java.util.Map.Entry;
8 import java.util.Optional;
6 9 import java.util.function.Function;
7 10 import java.util.function.Supplier;
8 11 import java.util.stream.Collectors;
12 import java.util.stream.Stream;
13 import java.util.stream.StreamSupport;
9 14
10 15 import org.gradle.api.provider.Provider;
11 16
12 17 public final class Values {
13 18
14 19 private Values() {
15 20 }
16 21
17 22 /**
18 23 * Converts values in the specified map
19 24 * @param <K>
20 25 * @param <V>
21 26 * @param <U>
22 27 * @param map
23 28 * @param mapper
24 29 * @return
25 30 */
26 31 public static <K, V, U> Map<K, U> mapValues(Map<K, V> map, Function<V, U> mapper) {
27 32 Function<Entry<K, V>, V> getter = Entry::getValue;
28 33
29 34 return map.entrySet().stream()
30 35 .collect(Collectors.toMap(Entry::getKey, getter.andThen(mapper)));
31 36 }
32 37
33 38 /** Converts the supplied value to a string.
34 39 */
35 40 public static String toString(Object value) {
36 41 if (value == null) {
37 42 return null;
38 43 } else if (value instanceof String string) {
39 44 return string;
40 45 } else if (value instanceof Provider<?> provider) {
41 46 return toString(provider.getOrNull());
42 47 } else if (value instanceof Supplier<?> supplier) {
43 48 return toString(supplier.get());
44 49 } else {
45 50 return value.toString();
46 51 }
47 52 }
48 53
54 public static <T> Stream<T> stream(Iterator<T> remaining) {
55 var spliterator = Spliterators.spliteratorUnknownSize(remaining, 0);
56
57 return StreamSupport.stream(spliterator, false);
58 }
59
60 public static <T> Optional<T> take(Iterator<T> iterator) {
61 return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.empty();
62 }
63
49 64 public static <T> Iterable<T> iterable(T[] values) {
50 65 return () -> new ArrayIterator<>(values);
51 66 }
52 67
53 68 private static class ArrayIterator<T> implements Iterator<T> {
54 69 private final T[] data;
55 70
56 71 private int pos = 0;
57 72
58 73 ArrayIterator(T[] data) {
59 74 this.data = data;
60 75 }
61 76
62 77 @Override
63 78 public boolean hasNext() {
64 79 return pos < data.length;
65 80 }
66 81
67 82 @Override
68 83 public T next() {
69 84 return data[pos++];
70 85 }
71 86 }
72 87
73 88 }
General Comments 0
You need to be logged in to leave comments. Login now