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