| @@ -0,0 +1,13 | |||||
|
|
1 | package org.implab.gradle.common.dsl; | |||
|
|
2 | ||||
|
|
3 | ||||
|
|
4 | import org.gradle.api.provider.ListProperty; | |||
|
|
5 | ||||
|
|
6 | public interface CommandSpec { | |||
|
|
7 | ListProperty<String> getCommandLine(); | |||
|
|
8 | ||||
|
|
9 | void commandLine(Object arg0, Object... args); | |||
|
|
10 | ||||
|
|
11 | void args(Object arg0, Object... args); | |||
|
|
12 | ||||
|
|
13 | } | |||
| @@ -0,0 +1,48 | |||||
|
|
1 | package org.implab.gradle.common.dsl; | |||
|
|
2 | ||||
|
|
3 | import java.util.HashMap; | |||
|
|
4 | import java.util.Map; | |||
|
|
5 | ||||
|
|
6 | import org.gradle.api.Action; | |||
|
|
7 | import org.gradle.api.file.DirectoryProperty; | |||
|
|
8 | import org.gradle.api.provider.MapProperty; | |||
|
|
9 | import org.implab.gradle.common.utils.Closures; | |||
|
|
10 | import org.implab.gradle.common.utils.Values; | |||
|
|
11 | ||||
|
|
12 | import groovy.lang.Closure; | |||
|
|
13 | ||||
|
|
14 | /** | |||
|
|
15 | * Configuration properties of the execution shell. This object specifies a | |||
|
|
16 | * working directory and environment variables for the processes started within | |||
|
|
17 | * this shell. | |||
|
|
18 | */ | |||
|
|
19 | public interface EnvironmentSpec { | |||
|
|
20 | ||||
|
|
21 | /** Working directory */ | |||
|
|
22 | DirectoryProperty getWorkingDirectory(); | |||
|
|
23 | ||||
|
|
24 | /** Environment variables */ | |||
|
|
25 | MapProperty<String, String> getEnvironment(); | |||
|
|
26 | ||||
|
|
27 | /** | |||
|
|
28 | * Configures the environment variable using the specified action. The | |||
|
|
29 | * action is called when the value is calculated; | |||
|
|
30 | */ | |||
|
|
31 | default void env(Action<Map<String, Object>> configure) { | |||
|
|
32 | var provider = getEnvironment() | |||
|
|
33 | .orElse(Map.of()) | |||
|
|
34 | .map((base) -> { | |||
|
|
35 | var props = new HashMap<String, Object>(base); | |||
|
|
36 | ||||
|
|
37 | configure.execute(props); | |||
|
|
38 | ||||
|
|
39 | return Values.mapValues(props, Values::toString); | |||
|
|
40 | }); | |||
|
|
41 | ||||
|
|
42 | getEnvironment().set(provider); | |||
|
|
43 | } | |||
|
|
44 | ||||
|
|
45 | default void env(Closure<?> configure) { | |||
|
|
46 | env(Closures.action(configure)); | |||
|
|
47 | } | |||
|
|
48 | } | |||
| @@ -0,0 +1,12 | |||||
|
|
1 | package org.implab.gradle.common.dsl; | |||
|
|
2 | ||||
|
|
3 | import org.eclipse.jdt.annotation.NonNullByDefault; | |||
|
|
4 | ||||
|
|
5 | @NonNullByDefault | |||
|
|
6 | public interface PipeSpec { | |||
|
|
7 | RedirectToSpec getStdout(); | |||
|
|
8 | ||||
|
|
9 | RedirectToSpec getStderr(); | |||
|
|
10 | ||||
|
|
11 | RedirectFromSpec getStdin(); | |||
|
|
12 | } | |||
| @@ -0,0 +1,34 | |||||
|
|
1 | package org.implab.gradle.common.exec; | |||
|
|
2 | ||||
|
|
3 | import java.util.stream.Stream; | |||
|
|
4 | ||||
|
|
5 | import org.eclipse.jdt.annotation.NonNullByDefault; | |||
|
|
6 | import org.implab.gradle.common.utils.Values; | |||
|
|
7 | ||||
|
|
8 | @NonNullByDefault | |||
|
|
9 | public interface CommandBuilder { | |||
|
|
10 | ||||
|
|
11 | CommandBuilder executable(String executable); | |||
|
|
12 | ||||
|
|
13 | default CommandBuilder commandLine(String executable, String... args) { | |||
|
|
14 | return executable(executable) | |||
|
|
15 | .arguments(args); | |||
|
|
16 | } | |||
|
|
17 | ||||
|
|
18 | default CommandBuilder arg(String arg0, String... args) { | |||
|
|
19 | return arguments(() -> Stream | |||
|
|
20 | .concat(Stream.of(arg0), Stream.of(args)) | |||
|
|
21 | .iterator()); | |||
|
|
22 | } | |||
|
|
23 | ||||
|
|
24 | default CommandBuilder arguments(String... args) { | |||
|
|
25 | return arguments(Values.iterable(args)); | |||
|
|
26 | } | |||
|
|
27 | ||||
|
|
28 | CommandBuilder arguments(Iterable<String> args); | |||
|
|
29 | ||||
|
|
30 | default CommandBuilder from(CommandSpec commandSpec) { | |||
|
|
31 | return executable(commandSpec.executable()) | |||
|
|
32 | .arguments(commandSpec.arguments()); | |||
|
|
33 | } | |||
|
|
34 | } | |||
| @@ -0,0 +1,16 | |||||
|
|
1 | package org.implab.gradle.common.exec; | |||
|
|
2 | ||||
|
|
3 | import java.util.List; | |||
|
|
4 | import java.util.stream.Stream; | |||
|
|
5 | ||||
|
|
6 | public interface CommandSpec { | |||
|
|
7 | ||||
|
|
8 | String executable(); | |||
|
|
9 | ||||
|
|
10 | List<String> arguments(); | |||
|
|
11 | ||||
|
|
12 | default List<String> commandLine() { | |||
|
|
13 | return Stream.concat(Stream.of(executable()), arguments().stream()).toList(); | |||
|
|
14 | } | |||
|
|
15 | ||||
|
|
16 | } | |||
| @@ -0,0 +1,25 | |||||
|
|
1 | package org.implab.gradle.common.exec; | |||
|
|
2 | ||||
|
|
3 | import java.io.File; | |||
|
|
4 | import java.util.Map; | |||
|
|
5 | import java.util.Optional; | |||
|
|
6 | ||||
|
|
7 | import org.eclipse.jdt.annotation.NonNullByDefault; | |||
|
|
8 | ||||
|
|
9 | @NonNullByDefault | |||
|
|
10 | public interface EnvironmentBuilder { | |||
|
|
11 | EnvironmentBuilder setVariable(String envVar, String value); | |||
|
|
12 | ||||
|
|
13 | EnvironmentBuilder environment(Map<String, ? extends String> env); | |||
|
|
14 | ||||
|
|
15 | EnvironmentBuilder unsetVariable(String envVar); | |||
|
|
16 | ||||
|
|
17 | EnvironmentBuilder workingDirectory(File directory); | |||
|
|
18 | ||||
|
|
19 | EnvironmentBuilder workingDirectory(Optional<? extends File> directory); | |||
|
|
20 | ||||
|
|
21 | default EnvironmentBuilder from(EnvironmentSpec environmentSpec) { | |||
|
|
22 | return environment(environmentSpec.environment()) | |||
|
|
23 | .workingDirectory(environmentSpec.workingDirectory()); | |||
|
|
24 | } | |||
|
|
25 | } | |||
| @@ -0,0 +1,11 | |||||
|
|
1 | package org.implab.gradle.common.exec; | |||
|
|
2 | ||||
|
|
3 | import java.io.File; | |||
|
|
4 | import java.util.Map; | |||
|
|
5 | import java.util.Optional; | |||
|
|
6 | ||||
|
|
7 | public interface EnvironmentSpec { | |||
|
|
8 | Map<String,String> environment(); | |||
|
|
9 | ||||
|
|
10 | Optional<File> workingDirectory(); | |||
|
|
11 | } | |||
| @@ -0,0 +1,27 | |||||
|
|
1 | package org.implab.gradle.common.exec; | |||
|
|
2 | ||||
|
|
3 | import java.util.Optional; | |||
|
|
4 | ||||
|
|
5 | import org.eclipse.jdt.annotation.NonNullByDefault; | |||
|
|
6 | ||||
|
|
7 | @NonNullByDefault | |||
|
|
8 | public interface PipeBuilder { | |||
|
|
9 | PipeBuilder stdin(RedirectFrom from); | |||
|
|
10 | ||||
|
|
11 | PipeBuilder stdin(Optional<? extends RedirectFrom> from); | |||
|
|
12 | ||||
|
|
13 | PipeBuilder stdout(RedirectTo to); | |||
|
|
14 | ||||
|
|
15 | PipeBuilder stdout(Optional<? extends RedirectTo> to); | |||
|
|
16 | ||||
|
|
17 | PipeBuilder stderr(RedirectTo to); | |||
|
|
18 | ||||
|
|
19 | PipeBuilder stderr(Optional<? extends RedirectTo> to); | |||
|
|
20 | ||||
|
|
21 | default PipeBuilder from(PipeSpec pipeSpec) { | |||
|
|
22 | return stdin(pipeSpec.stdin()) | |||
|
|
23 | .stdout(pipeSpec.stdout()) | |||
|
|
24 | .stderr(pipeSpec.stderr()); | |||
|
|
25 | } | |||
|
|
26 | ||||
|
|
27 | } | |||
| @@ -0,0 +1,14 | |||||
|
|
1 | package org.implab.gradle.common.exec; | |||
|
|
2 | ||||
|
|
3 | import java.util.Optional; | |||
|
|
4 | ||||
|
|
5 | import org.eclipse.jdt.annotation.NonNullByDefault; | |||
|
|
6 | ||||
|
|
7 | @NonNullByDefault | |||
|
|
8 | public interface PipeSpec { | |||
|
|
9 | Optional<RedirectTo> stdout(); | |||
|
|
10 | ||||
|
|
11 | Optional<RedirectTo> stderr(); | |||
|
|
12 | ||||
|
|
13 | Optional<RedirectFrom> stdin(); | |||
|
|
14 | } | |||
| @@ -0,0 +1,19 | |||||
|
|
1 | package org.implab.gradle.common.exec; | |||
|
|
2 | ||||
|
|
3 | import java.io.IOException; | |||
|
|
4 | import java.util.concurrent.CompletableFuture; | |||
|
|
5 | import java.util.concurrent.CompletionException; | |||
|
|
6 | ||||
|
|
7 | public interface Runnable { | |||
|
|
8 | CompletableFuture<Integer> run() throws IOException; | |||
|
|
9 | ||||
|
|
10 | /** Starts process and will throw error if error code is non-zero */ | |||
|
|
11 | default CompletableFuture<Integer> run(boolean throwOnError) throws IOException { | |||
|
|
12 | return run().thenApply(code -> { | |||
|
|
13 | if (!throwOnError && code != 0) | |||
|
|
14 | throw new CompletionException(new IOException( | |||
|
|
15 | String.format("The process is terminated with code %d", code))); | |||
|
|
16 | return code; | |||
|
|
17 | }); | |||
|
|
18 | } | |||
|
|
19 | } | |||
| @@ -0,0 +1,18 | |||||
|
|
1 | package org.implab.gradle.common.utils; | |||
|
|
2 | ||||
|
|
3 | import java.util.concurrent.CompletionException; | |||
|
|
4 | import java.util.function.Consumer; | |||
|
|
5 | ||||
|
|
6 | public interface ThrowingConsumer<T, E extends Throwable> { | |||
|
|
7 | void accept(T value) throws E; | |||
|
|
8 | ||||
|
|
9 | static <T> Consumer<T> guard(ThrowingConsumer<T,?> target) { | |||
|
|
10 | return arg -> { | |||
|
|
11 | try { | |||
|
|
12 | target.accept(arg); | |||
|
|
13 | } catch (Throwable err) { | |||
|
|
14 | throw new CompletionException(err); | |||
|
|
15 | } | |||
|
|
16 | }; | |||
|
|
17 | } | |||
|
|
18 | } | |||
| @@ -0,0 +1,73 | |||||
|
|
1 | package org.implab.gradle.common.utils; | |||
|
|
2 | ||||
|
|
3 | import java.util.Iterator; | |||
|
|
4 | import java.util.Map; | |||
|
|
5 | import java.util.Map.Entry; | |||
|
|
6 | import java.util.function.Function; | |||
|
|
7 | import java.util.function.Supplier; | |||
|
|
8 | import java.util.stream.Collectors; | |||
|
|
9 | ||||
|
|
10 | import org.gradle.api.provider.Provider; | |||
|
|
11 | ||||
|
|
12 | public final class Values { | |||
|
|
13 | ||||
|
|
14 | private Values() { | |||
|
|
15 | } | |||
|
|
16 | ||||
|
|
17 | /** | |||
|
|
18 | * Converts values in the specified map | |||
|
|
19 | * @param <K> | |||
|
|
20 | * @param <V> | |||
|
|
21 | * @param <U> | |||
|
|
22 | * @param map | |||
|
|
23 | * @param mapper | |||
|
|
24 | * @return | |||
|
|
25 | */ | |||
|
|
26 | 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; | |||
|
|
28 | ||||
|
|
29 | return map.entrySet().stream() | |||
|
|
30 | .collect(Collectors.toMap(Entry::getKey, getter.andThen(mapper))); | |||
|
|
31 | } | |||
|
|
32 | ||||
|
|
33 | /** Converts the supplied value to a string. | |||
|
|
34 | */ | |||
|
|
35 | public static String toString(Object value) { | |||
|
|
36 | if (value == null) { | |||
|
|
37 | return null; | |||
|
|
38 | } else if (value instanceof String string) { | |||
|
|
39 | return string; | |||
|
|
40 | } else if (value instanceof Provider<?> provider) { | |||
|
|
41 | return toString(provider.getOrNull()); | |||
|
|
42 | } else if (value instanceof Supplier<?> supplier) { | |||
|
|
43 | return toString(supplier.get()); | |||
|
|
44 | } else { | |||
|
|
45 | return value.toString(); | |||
|
|
46 | } | |||
|
|
47 | } | |||
|
|
48 | ||||
|
|
49 | public static <T> Iterable<T> iterable(T[] values) { | |||
|
|
50 | return () -> new ArrayIterator<>(values); | |||
|
|
51 | } | |||
|
|
52 | ||||
|
|
53 | private static class ArrayIterator<T> implements Iterator<T> { | |||
|
|
54 | private final T[] data; | |||
|
|
55 | ||||
|
|
56 | private int pos = 0; | |||
|
|
57 | ||||
|
|
58 | ArrayIterator(T[] data) { | |||
|
|
59 | this.data = data; | |||
|
|
60 | } | |||
|
|
61 | ||||
|
|
62 | @Override | |||
|
|
63 | public boolean hasNext() { | |||
|
|
64 | return pos < data.length; | |||
|
|
65 | } | |||
|
|
66 | ||||
|
|
67 | @Override | |||
|
|
68 | public T next() { | |||
|
|
69 | return data[pos++]; | |||
|
|
70 | } | |||
|
|
71 | } | |||
|
|
72 | ||||
|
|
73 | } | |||
| @@ -1,3 +1,4 | |||||
| 1 | syntax: glob |
|
1 | syntax: glob | |
| 2 | .gradle/ |
|
2 | .gradle/ | |
| 3 | common/build/ |
|
3 | common/build/ | |
|
|
4 | common/bin/ | |||
| @@ -1,37 +1,27 | |||||
| 1 | package org.implab.gradle.common.dsl; |
|
1 | package org.implab.gradle.common.dsl; | |
| 2 |
|
2 | |||
| 3 | import java.io.File; |
|
|||
| 4 | import java.io.InputStream; |
|
|||
| 5 | import java.util.Optional; |
|
3 | import java.util.Optional; | |
| 6 | import java.util.function.Supplier; |
|
4 | import java.util.function.Supplier; | |
| 7 |
|
5 | |||
| 8 | import org.gradle.api.provider.Provider; |
|
6 | import org.gradle.api.provider.Provider; | |
| 9 | import org.implab.gradle.common.exec.RedirectFrom; |
|
7 | import org.implab.gradle.common.exec.RedirectFrom; | |
| 10 |
|
8 | |||
| 11 | public class RedirectFromSpec { |
|
9 | public class RedirectFromSpec { | |
| 12 | private Supplier<RedirectFrom> streamRedirect; |
|
10 | private Supplier<RedirectFrom> streamRedirect; | |
| 13 |
|
11 | |||
| 14 | public boolean isRedirected() { |
|
12 | public boolean isRedirected() { | |
| 15 | return streamRedirect != null; |
|
13 | return streamRedirect != null; | |
| 16 | } |
|
14 | } | |
| 17 |
|
15 | |||
| 18 | public Optional<RedirectFrom> getRedirection() { |
|
16 | public Optional<RedirectFrom> getRedirection() { | |
| 19 | return streamRedirect != null ? Optional.ofNullable(streamRedirect.get()) : Optional.empty(); |
|
17 | return streamRedirect != null ? Optional.ofNullable(streamRedirect.get()) : Optional.empty(); | |
| 20 | } |
|
18 | } | |
| 21 |
|
19 | |||
| 22 |
public void from |
|
20 | public void from(Object input) { | |
| 23 | this.streamRedirect = () -> RedirectFrom.file(file); |
|
21 | if (input instanceof Provider<?> inputProvider) { | |
| 24 | } |
|
22 | this.streamRedirect = inputProvider.map(RedirectFrom::any)::get; | |
| 25 |
|
23 | } else { | ||
| 26 | public void fromFile(Provider<File> file) { |
|
24 | this.streamRedirect = () -> RedirectFrom.any(input); | |
| 27 | this.streamRedirect = file.map(RedirectFrom::file)::get; |
|
|||
| 28 | } |
|
|||
| 29 |
|
||||
| 30 | public void fromStream(InputStream stream) { |
|
|||
| 31 | this.streamRedirect = () -> RedirectFrom.stream(stream); |
|
|||
| 32 | } |
|
|||
| 33 |
|
||||
| 34 | public void fromStream(Provider<InputStream> stream) { |
|
|||
| 35 | this.streamRedirect = stream.map(RedirectFrom::stream)::get; |
|
|||
| 36 | } |
|
25 | } | |
| 37 | } |
|
26 | } | |
|
|
27 | } | |||
| @@ -1,42 +1,57 | |||||
| 1 | package org.implab.gradle.common.dsl; |
|
1 | package org.implab.gradle.common.dsl; | |
| 2 |
|
2 | |||
| 3 | import java.io.File; |
|
3 | import java.io.File; | |
| 4 | import java.io.OutputStream; |
|
4 | import java.io.OutputStream; | |
| 5 | import java.util.Optional; |
|
5 | import java.util.Optional; | |
| 6 | import java.util.function.Consumer; |
|
6 | import java.util.function.Consumer; | |
| 7 | import java.util.function.Supplier; |
|
7 | import java.util.function.Supplier; | |
| 8 |
|
8 | |||
|
|
9 | import org.eclipse.jdt.annotation.NonNullByDefault; | |||
|
|
10 | import org.eclipse.jdt.annotation.Nullable; | |||
| 9 | import org.gradle.api.provider.Provider; |
|
11 | import org.gradle.api.provider.Provider; | |
| 10 | import org.implab.gradle.common.exec.RedirectTo; |
|
12 | import org.implab.gradle.common.exec.RedirectTo; | |
| 11 |
|
13 | |||
|
|
14 | @NonNullByDefault | |||
| 12 | public class RedirectToSpec { |
|
15 | public class RedirectToSpec { | |
| 13 | private Supplier<RedirectTo> streamRedirect; |
|
16 | private Supplier<RedirectTo> streamRedirect; | |
| 14 |
|
17 | |||
| 15 | public boolean isRedirected() { |
|
18 | public boolean isRedirected() { | |
| 16 |
return |
|
19 | return getRedirection().isPresent(); | |
| 17 | } |
|
20 | } | |
| 18 |
|
21 | |||
| 19 | public Optional<RedirectTo> getRedirection() { |
|
22 | public Optional<RedirectTo> getRedirection() { | |
| 20 | return streamRedirect != null ? Optional.ofNullable(streamRedirect.get()) : Optional.empty(); |
|
23 | return streamRedirect != null ? Optional.ofNullable(streamRedirect.get()) : Optional.empty(); | |
| 21 | } |
|
24 | } | |
| 22 |
|
25 | |||
|
|
26 | public @Nullable RedirectTo getRedirectionOrNull() { | |||
|
|
27 | return streamRedirect != null ? streamRedirect.get() : null; | |||
|
|
28 | } | |||
|
|
29 | ||||
| 23 | public void toFile(File file) { |
|
30 | public void toFile(File file) { | |
| 24 | this.streamRedirect = () -> RedirectTo.file(file); |
|
31 | this.streamRedirect = () -> RedirectTo.file(file); | |
| 25 | } |
|
32 | } | |
| 26 |
|
33 | |||
| 27 | public void toFile(Provider<File> file) { |
|
34 | public void toFile(Provider<File> fileProvider) { | |
| 28 | this.streamRedirect = file.map(RedirectTo::file)::get; |
|
35 | this.streamRedirect = fileProvider.map(RedirectTo::file)::getOrNull; | |
| 29 | } |
|
36 | } | |
| 30 |
|
37 | |||
| 31 | public void toStream(OutputStream stream) { |
|
38 | public void toStream(OutputStream stream) { | |
| 32 | this.streamRedirect = () -> RedirectTo.stream(stream); |
|
39 | this.streamRedirect = () -> RedirectTo.stream(stream); | |
| 33 | } |
|
40 | } | |
| 34 |
|
41 | |||
| 35 | public void toStream(Provider<OutputStream> stream) { |
|
42 | public void toStream(Provider<OutputStream> streamProvider) { | |
| 36 | this.streamRedirect = stream.map(RedirectTo::stream)::get; |
|
43 | this.streamRedirect = streamProvider.map(RedirectTo::stream)::getOrNull; | |
| 37 | } |
|
44 | } | |
| 38 |
|
45 | |||
| 39 | public void toConsumer(Consumer<String> consumer) { |
|
46 | public void to(Object output) { | |
|
|
47 | if (output instanceof Provider<?> outputProvider) { | |||
|
|
48 | this.streamRedirect = outputProvider.map(RedirectTo::any)::get; | |||
|
|
49 | } else { | |||
|
|
50 | this.streamRedirect = () -> RedirectTo.any(output); | |||
|
|
51 | } | |||
|
|
52 | } | |||
|
|
53 | ||||
|
|
54 | public void consume(Consumer<String> consumer) { | |||
| 40 | this.streamRedirect = () -> RedirectTo.consumer(consumer); |
|
55 | this.streamRedirect = () -> RedirectTo.consumer(consumer); | |
| 41 | } |
|
56 | } | |
| 42 | } |
|
57 | } | |
| @@ -1,32 +1,42 | |||||
| 1 | package org.implab.gradle.common.exec; |
|
1 | package org.implab.gradle.common.exec; | |
| 2 |
|
2 | |||
| 3 | import java.io.ByteArrayInputStream; |
|
3 | import java.io.ByteArrayInputStream; | |
| 4 | import java.io.File; |
|
4 | import java.io.File; | |
| 5 | import java.io.IOException; |
|
5 | import java.io.IOException; | |
| 6 | import java.nio.charset.StandardCharsets; |
|
6 | import java.nio.charset.StandardCharsets; | |
| 7 | import java.util.List; |
|
7 | import java.util.List; | |
| 8 | import java.util.Map; |
|
8 | import java.util.Map; | |
| 9 | import java.util.Optional; |
|
9 | import java.util.Optional; | |
| 10 | import java.util.concurrent.CompletableFuture; |
|
10 | import java.util.concurrent.CompletableFuture; | |
| 11 |
|
11 | |||
| 12 | class EchoExecBuilder extends ExecBuilder { |
|
12 | class EchoExecBuilder extends ExecBuilder { | |
| 13 |
|
13 | |||
| 14 | private final boolean echoToStderr; |
|
14 | private final boolean echoToStderr; | |
| 15 |
|
15 | |||
| 16 | public EchoExecBuilder(boolean echoToStderr) { |
|
16 | public EchoExecBuilder(boolean echoToStderr) { | |
| 17 | this.echoToStderr = echoToStderr; |
|
17 | this.echoToStderr = echoToStderr; | |
| 18 | } |
|
18 | } | |
| 19 |
|
19 | |||
| 20 | @Override |
|
20 | @Override | |
| 21 |
protected CompletableFuture<Integer> startInternal( |
|
21 | protected CompletableFuture<Integer> startInternal( | |
| 22 | List<String> commandLine, Optional<RedirectFrom> stdinRedirect, Optional<RedirectTo> stdoutRedirect, |
|
22 | Map<String, String> environment, | |
|
|
23 | Optional<File> directory, | |||
|
|
24 | List<String> commandLine, | |||
|
|
25 | Optional<RedirectFrom> stdinRedirect, | |||
|
|
26 | Optional<RedirectTo> stdoutRedirect, | |||
| 23 | Optional<RedirectTo> stderrRedirect) throws IOException { |
|
27 | Optional<RedirectTo> stderrRedirect) throws IOException { | |
|
|
28 | ||||
| 24 | var outputRedirect = echoToStderr ? stderrRedirect : stdoutRedirect; |
|
29 | var outputRedirect = echoToStderr ? stderrRedirect : stdoutRedirect; | |
| 25 |
|
30 | |||
| 26 |
return outputRedirect |
|
31 | return outputRedirect | |
| 27 | var bytes = String.format("exec: %s", commandLine).getBytes(StandardCharsets.UTF_8); |
|
32 | .map(to -> { | |
| 28 | return to.redirect(new ByteArrayInputStream(bytes)).thenApply((x) -> 0); |
|
33 | var bytes = String.format("exec: %s", commandLine) | |
| 29 | }).orElse(CompletableFuture.completedFuture(0)); |
|
34 | .getBytes(StandardCharsets.UTF_8); | |
|
|
35 | ||||
|
|
36 | return to.redirect(new ByteArrayInputStream(bytes)) | |||
|
|
37 | .thenApply((x) -> 0); | |||
|
|
38 | }) | |||
|
|
39 | .orElse(CompletableFuture.completedFuture(0)); | |||
| 30 | } |
|
40 | } | |
| 31 |
|
41 | |||
| 32 | } |
|
42 | } | |
| @@ -1,147 +1,208 | |||||
| 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.Objects; |
|
|||
| 8 | import java.util.Optional; |
|
7 | import java.util.Optional; | |
| 9 | import java.util.concurrent.CompletableFuture; |
|
8 | import java.util.concurrent.CompletableFuture; | |
| 10 | import java.util.stream.Stream; |
|
|||
| 11 | import java.util.Collection; |
|
|||
| 12 |
|
9 | |||
| 13 | import org.eclipse.jdt.annotation.NonNullByDefault; |
|
10 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
11 | import org.eclipse.jdt.annotation.Nullable; | |||
| 14 |
|
12 | |||
| 15 | import java.io.File; |
|
13 | import java.io.File; | |
| 16 | import java.io.IOException; |
|
14 | import java.io.IOException; | |
| 17 |
|
15 | |||
|
|
16 | import static java.util.Objects.requireNonNull; | |||
|
|
17 | ||||
| 18 | /** Command line builder */ |
|
18 | /** Command line builder */ | |
| 19 | @NonNullByDefault |
|
19 | @NonNullByDefault | |
| 20 |
public abstract class ExecBuilder |
|
20 | public abstract class ExecBuilder implements | |
|
|
21 | CommandBuilder, | |||
|
|
22 | PipeBuilder, | |||
|
|
23 | EnvironmentBuilder, | |||
|
|
24 | Runnable | |||
|
|
25 | { | |||
|
|
26 | private String executable; | |||
| 21 |
|
27 | |||
| 22 |
private final List<String> |
|
28 | private final List<String> arguments = new ArrayList<>(); | |
| 23 |
|
29 | |||
| 24 | private final Map<String, String> environment = new HashMap<>(); |
|
30 | private final Map<String, String> environment = new HashMap<>(); | |
| 25 |
|
31 | |||
| 26 | private File directory; |
|
32 | private @Nullable File directory; | |
| 27 |
|
33 | |||
| 28 | private RedirectFrom inputRedirect; |
|
34 | private RedirectFrom inputRedirect; | |
| 29 |
|
35 | |||
| 30 | private RedirectTo outputRedirect; |
|
36 | private RedirectTo outputRedirect; | |
| 31 |
|
37 | |||
| 32 | private RedirectTo errorRedirect; |
|
38 | private RedirectTo errorRedirect; | |
| 33 |
|
39 | |||
| 34 | /** Sets command line, clears previous one if any */ |
|
40 | @Override | |
| 35 |
public ExecBuilder |
|
41 | public ExecBuilder executable(String executable) { | |
| 36 | commandLine.clear(); |
|
42 | requireNonNull(executable, "cmd can't be null"); | |
| 37 | commandLine.add(cmd); |
|
43 | this.executable = executable; | |
| 38 | Stream.of(args).forEach(commandLine::add); |
|
44 | return this; | |
|
|
45 | } | |||
|
|
46 | ||||
|
|
47 | @Override | |||
|
|
48 | public ExecBuilder arguments(Iterable<String> args) { | |||
|
|
49 | requireNonNull(args, "Args must not be null"); | |||
|
|
50 | arguments.clear(); | |||
|
|
51 | for(var arg: args) | |||
|
|
52 | arguments.add(arg); | |||
| 39 | return this; |
|
53 | return this; | |
| 40 | } |
|
54 | } | |
| 41 |
|
55 | |||
| 42 |
public ExecBuilder command( |
|
56 | public ExecBuilder commandLine(Iterable<? extends String> cmd) { | |
| 43 | this.commandLine.clear(); |
|
57 | requireNonNull(cmd, "cmd can't be null"); | |
| 44 | this.commandLine.addAll(cmd); |
|
58 | ||
|
|
59 | this.arguments.clear(); | |||
|
|
60 | for (var arg : cmd) | |||
|
|
61 | this.arguments.add(arg); | |||
| 45 | return this; |
|
62 | return this; | |
| 46 | } |
|
63 | } | |
| 47 |
|
64 | |||
| 48 | /** Adds an argument to the command line */ |
|
65 | @Override | |
| 49 |
public ExecBuilder arg |
|
66 | public ExecBuilder arg(String arg0, String... args) { | |
| 50 |
|
|
67 | requireNonNull(arg0, "arg0 parameter can't be null"); | |
| 51 |
|
|
68 | arguments.add(arg0); | |
|
|
69 | ||||
|
|
70 | for (var arg : args) | |||
|
|
71 | arguments.add(arg); | |||
|
|
72 | ||||
| 52 | return this; |
|
73 | return this; | |
| 53 | } |
|
74 | } | |
| 54 |
|
75 | |||
| 55 | /** Sets the working directory */ |
|
76 | /** Sets the working directory */ | |
| 56 | public ExecBuilder directory(File directory) { |
|
77 | @Override | |
| 57 | Objects.requireNonNull(directory, "directory parameter can't be null"); |
|
78 | public ExecBuilder workingDirectory(File directory) { | |
|
|
79 | requireNonNull(directory, "directory parameter can't be null"); | |||
|
|
80 | ||||
| 58 | this.directory = directory; |
|
81 | this.directory = directory; | |
| 59 | return this; |
|
82 | return this; | |
| 60 | } |
|
83 | } | |
| 61 |
|
84 | |||
|
|
85 | @Override | |||
|
|
86 | public ExecBuilder workingDirectory(Optional<? extends File> directory) { | |||
|
|
87 | requireNonNull(directory, "directory parameter can't be null"); | |||
|
|
88 | ||||
|
|
89 | this.directory = directory.orElse(null); | |||
|
|
90 | return this; | |||
|
|
91 | } | |||
|
|
92 | ||||
| 62 | /** |
|
93 | /** | |
| 63 | * Sets the environment value. The value cannot be null. |
|
94 | * Sets the environment value. The value cannot be null. | |
| 64 | * |
|
95 | * | |
| 65 | * @param envVar The name of the environment variable |
|
96 | * @param envVar The name of the environment variable | |
| 66 | * @param value The value to set, |
|
97 | * @param value The value to set, | |
| 67 | */ |
|
98 | */ | |
| 68 | public ExecBuilder setEnvironment(String envVar, String value) { |
|
99 | @Override | |
| 69 | Objects.requireNonNull(value, "Value can't be null"); |
|
100 | public ExecBuilder setVariable(String envVar, String value) { | |
| 70 |
|
|
101 | requireNonNull(value, "Value can't be null"); | |
|
|
102 | requireNonNull(envVar, "envVar parameter can't be null"); | |||
|
|
103 | ||||
| 71 | environment.put(envVar, value); |
|
104 | environment.put(envVar, value); | |
| 72 | return this; |
|
105 | return this; | |
| 73 | } |
|
106 | } | |
| 74 |
|
107 | |||
| 75 | public ExecBuilder setEnvironment(Map<String, String> env) { |
|
108 | @Override | |
| 76 | Objects.requireNonNull(env, "env parameter can't be null"); |
|
109 | public ExecBuilder environment(Map<String,? extends String> env) { | |
|
|
110 | requireNonNull(env, "env parameter can't be null"); | |||
| 77 |
|
111 | |||
| 78 | environment.clear(); |
|
112 | environment.clear(); | |
| 79 | environment.putAll(env); |
|
113 | environment.putAll(env); | |
| 80 | return this; |
|
114 | return this; | |
| 81 | } |
|
115 | } | |
| 82 |
|
116 | |||
| 83 | public ExecBuilder unsetEnvironment(String envVar) { |
|
|||
| 84 | environment.remove(envVar); |
|
|||
| 85 | return this; |
|
|||
| 86 | } |
|
|||
| 87 |
|
||||
| 88 | /** |
|
117 | /** | |
| 89 | * Sets redirection for the stdin, {@link RedirectFrom} will be applied |
|
118 | * Sets redirection for the stdin, {@link RedirectFrom} will be applied | |
| 90 | * every time the process is started. |
|
119 | * every time the process is started. | |
| 91 | * |
|
120 | * | |
| 92 | * <p> |
|
121 | * <p> | |
| 93 | * If redirection |
|
122 | * If redirection | |
| 94 | */ |
|
123 | */ | |
|
|
124 | @Override | |||
| 95 | public ExecBuilder stdin(RedirectFrom from) { |
|
125 | public ExecBuilder stdin(RedirectFrom from) { | |
| 96 |
|
|
126 | requireNonNull(from, "from parameter can't be null"); | |
|
|
127 | ||||
| 97 | inputRedirect = from; |
|
128 | inputRedirect = from; | |
| 98 | return this; |
|
129 | return this; | |
| 99 | } |
|
130 | } | |
| 100 |
|
131 | |||
|
|
132 | @Override | |||
|
|
133 | public PipeBuilder stdin(Optional<? extends RedirectFrom> from) { | |||
|
|
134 | requireNonNull(from, "from parameter can't be null"); | |||
|
|
135 | inputRedirect = from.orElse(null); | |||
|
|
136 | return this; | |||
|
|
137 | } | |||
|
|
138 | ||||
| 101 | /** |
|
139 | /** | |
| 102 | * Sets redirection for the stdout, {@link RedirectTo} will be applied |
|
140 | * Sets redirection for the stdout, {@link RedirectTo} will be applied | |
| 103 | * every time the process is started. |
|
141 | * every time the process is started. | |
| 104 | */ |
|
142 | */ | |
|
|
143 | @Override | |||
| 105 | public ExecBuilder stdout(RedirectTo out) { |
|
144 | public ExecBuilder stdout(RedirectTo out) { | |
| 106 |
|
|
145 | requireNonNull(out, "out parameter can't be null"); | |
| 107 | outputRedirect = out; |
|
146 | outputRedirect = out; | |
| 108 | return this; |
|
147 | return this; | |
| 109 | } |
|
148 | } | |
| 110 |
|
149 | |||
|
|
150 | @Override | |||
|
|
151 | public PipeBuilder stdout(Optional<? extends RedirectTo> to) { | |||
|
|
152 | requireNonNull(to, "from parameter can't be null"); | |||
|
|
153 | outputRedirect = to.orElse(null); | |||
|
|
154 | return this; | |||
|
|
155 | } | |||
|
|
156 | ||||
| 111 | /** |
|
157 | /** | |
| 112 | * Sets redirection for the stderr, {@link RedirectTo} will be applied |
|
158 | * Sets redirection for the stderr, {@link RedirectTo} will be applied | |
| 113 | * every time the process is started. |
|
159 | * every time the process is started. | |
| 114 | */ |
|
160 | */ | |
|
|
161 | @Override | |||
| 115 | public ExecBuilder stderr(RedirectTo err) { |
|
162 | public ExecBuilder stderr(RedirectTo err) { | |
| 116 |
|
|
163 | requireNonNull(err, "err parameter can't be null"); | |
| 117 | errorRedirect = err; |
|
164 | errorRedirect = err; | |
| 118 | return this; |
|
165 | return this; | |
| 119 | } |
|
166 | } | |
| 120 |
|
167 | |||
|
|
168 | @Override | |||
|
|
169 | public PipeBuilder stderr(Optional<? extends RedirectTo> to) { | |||
|
|
170 | requireNonNull(to, "from parameter can't be null"); | |||
|
|
171 | errorRedirect = to.orElse(null); | |||
|
|
172 | return this; | |||
|
|
173 | } | |||
|
|
174 | ||||
| 121 |
/** Implement this function to |
|
175 | /** Implement this function to */ | |
| 122 | protected abstract CompletableFuture<Integer> startInternal( |
|
176 | protected abstract CompletableFuture<Integer> startInternal( | |
| 123 | Map<String, String> environment, |
|
177 | Map<String, String> environment, | |
| 124 | File directory, |
|
178 | Optional<File> directory, | |
| 125 | List<String> commandLine, |
|
179 | List<String> commandLine, | |
| 126 | Optional<RedirectFrom> stdinRedirect, |
|
180 | Optional<RedirectFrom> stdinRedirect, | |
| 127 | Optional<RedirectTo> stdoutRedirect, |
|
181 | Optional<RedirectTo> stdoutRedirect, | |
| 128 | Optional<RedirectTo> stderrRedirect) throws IOException; |
|
182 | Optional<RedirectTo> stderrRedirect) throws IOException; | |
| 129 |
|
183 | |||
| 130 | /** |
|
184 | /** | |
| 131 | * Creates and starts new process and returns {@link CompletableFuture}. The |
|
185 | * Creates and starts new process and returns {@link CompletableFuture}. The | |
| 132 | * process may be a remote process, or a shell process or etc. |
|
186 | * process may be a remote process, or a shell process or etc. | |
| 133 | * |
|
187 | * | |
| 134 | * @return |
|
188 | * @return | |
| 135 | * @throws IOException |
|
189 | * @throws IOException | |
| 136 | */ |
|
190 | */ | |
| 137 |
public CompletableFuture<Integer> |
|
191 | public CompletableFuture<Integer> run() throws IOException { | |
|
|
192 | if (executable == null || executable.isEmpty()) | |||
|
|
193 | throw new IllegalStateException("The executable isn't set"); | |||
|
|
194 | ||||
|
|
195 | var commandLine = new ArrayList<String>(); | |||
|
|
196 | commandLine.add(executable); | |||
|
|
197 | commandLine.addAll(arguments); | |||
|
|
198 | ||||
| 138 | return startInternal( |
|
199 | return startInternal( | |
| 139 | environment, |
|
200 | environment, | |
| 140 | directory, |
|
201 | Optional.ofNullable(directory), | |
| 141 | commandLine, |
|
202 | commandLine, | |
| 142 | Optional.ofNullable(inputRedirect), |
|
203 | Optional.ofNullable(inputRedirect), | |
| 143 | Optional.ofNullable(outputRedirect), |
|
204 | Optional.ofNullable(outputRedirect), | |
| 144 | Optional.ofNullable(errorRedirect)); |
|
205 | Optional.ofNullable(errorRedirect)); | |
| 145 | } |
|
206 | } | |
| 146 |
|
207 | |||
| 147 | } |
|
208 | } | |
| @@ -1,58 +1,58 | |||||
| 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.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 | import java.util.function.Consumer; |
|
9 | import java.util.function.Consumer; | |
| 10 |
|
10 | |||
| 11 | /** Shell used to start processes */ |
|
11 | /** Shell used to start processes */ | |
| 12 | public interface ExecShell { |
|
12 | public interface ExecShell { | |
| 13 |
|
13 | |||
| 14 | /** Creates new process builder {@link ExecBuilder} */ |
|
14 | /** Creates new process builder {@link ExecBuilder} */ | |
| 15 |
ExecBuilder b |
|
15 | ExecBuilder executable(); | |
| 16 |
|
16 | |||
| 17 | /** |
|
17 | /** | |
| 18 | * Creates default process execution "shell" which will execute processes |
|
18 | * Creates default process execution "shell" which will execute processes | |
| 19 | * directly. |
|
19 | * directly. | |
| 20 | */ |
|
20 | */ | |
| 21 | static ExecShell system() { |
|
21 | static ExecShell system() { | |
| 22 | return () -> new SystemExecBuilder(); |
|
22 | return () -> new SystemExecBuilder(); | |
| 23 | } |
|
23 | } | |
| 24 |
|
24 | |||
| 25 | /** |
|
25 | /** | |
| 26 | * Creates a stub shell which will print command to STDERR and return 0 (no |
|
26 | * Creates a stub shell which will print command to STDERR and return 0 (no | |
| 27 | * error). |
|
27 | * error). | |
| 28 | */ |
|
28 | */ | |
| 29 | static ExecShell echoStderr() { |
|
29 | static ExecShell echoStderr() { | |
| 30 | return () -> new EchoExecBuilder(true); |
|
30 | return () -> new EchoExecBuilder(true); | |
| 31 | } |
|
31 | } | |
| 32 |
|
32 | |||
| 33 | /** |
|
33 | /** | |
| 34 | * Creates a stub shell which will print command to STDOUT and return 0 (no |
|
34 | * Creates a stub shell which will print command to STDOUT and return 0 (no | |
| 35 | * error). |
|
35 | * error). | |
| 36 | */ |
|
36 | */ | |
| 37 |
|
37 | |||
| 38 | static ExecShell echo() { |
|
38 | static ExecShell echo() { | |
| 39 | return () -> new EchoExecBuilder(false); |
|
39 | return () -> new EchoExecBuilder(false); | |
| 40 | } |
|
40 | } | |
| 41 |
|
41 | |||
| 42 | /** Creates a stub shell which will call the specified consumer and will supply a command line to it. |
|
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. |
|
43 | * The command line will be passed as a list of strings. | |
| 44 | * @param consumer The consumer fot the command line |
|
44 | * @param consumer The consumer fot the command line | |
| 45 | * @return |
|
45 | * @return | |
| 46 | */ |
|
46 | */ | |
| 47 | static ExecShell echo(Consumer<List<String>> consumer) { |
|
47 | static ExecShell echo(Consumer<List<String>> consumer) { | |
| 48 | return () -> new ExecBuilder() { |
|
48 | return () -> new ExecBuilder() { | |
| 49 | @Override |
|
49 | @Override | |
| 50 | protected CompletableFuture<Integer> startInternal(Map<String, String> environment, File directory, |
|
50 | protected CompletableFuture<Integer> startInternal(Map<String, String> environment, Optional<File> directory, | |
| 51 | List<String> commandLine, Optional<RedirectFrom> stdinRedirect, Optional<RedirectTo> stdoutRedirect, |
|
51 | List<String> commandLine, Optional<RedirectFrom> stdinRedirect, Optional<RedirectTo> stdoutRedirect, | |
| 52 | Optional<RedirectTo> stderrRedirect) throws IOException { |
|
52 | Optional<RedirectTo> stderrRedirect) throws IOException { | |
| 53 | consumer.accept(commandLine); |
|
53 | consumer.accept(commandLine); | |
| 54 | return CompletableFuture.completedFuture(0); |
|
54 | return CompletableFuture.completedFuture(0); | |
| 55 | } |
|
55 | } | |
| 56 | }; |
|
56 | }; | |
| 57 | } |
|
57 | } | |
| 58 | } |
|
58 | } | |
| @@ -1,37 +1,49 | |||||
| 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.FileInputStream; |
|
4 | import java.io.FileInputStream; | |
| 5 | import java.io.InputStream; |
|
5 | import java.io.InputStream; | |
| 6 | import java.io.OutputStream; |
|
6 | import java.io.OutputStream; | |
| 7 | import java.util.concurrent.CompletableFuture; |
|
7 | import java.util.concurrent.CompletableFuture; | |
| 8 |
|
8 | |||
| 9 | /** Describes how to redirect input streams. This interface is used to configure |
|
9 | /** Describes how to redirect input streams. This interface is used to configure | |
| 10 | * lazy redirection. {@link #redirect(OutputStream)} is called when the process |
|
10 | * lazy redirection. {@link #redirect(OutputStream)} is called when the process | |
| 11 | * is started. |
|
11 | * is started. | |
| 12 | */ |
|
12 | */ | |
| 13 | public interface RedirectFrom { |
|
13 | public interface RedirectFrom { | |
| 14 | CompletableFuture<Void> redirect(OutputStream to); |
|
14 | CompletableFuture<Void> redirect(OutputStream to); | |
| 15 |
|
15 | |||
| 16 | public static RedirectFrom file(final File file) { |
|
16 | public static RedirectFrom file(final File file) { | |
| 17 | return to -> CompletableFuture.runAsync(() -> { |
|
17 | return to -> CompletableFuture.runAsync(() -> { | |
| 18 | try (var from = new FileInputStream(file); to) { |
|
18 | try (var from = new FileInputStream(file); to) { | |
| 19 | from.transferTo(to); |
|
19 | from.transferTo(to); | |
| 20 | } catch (Exception e) { |
|
20 | } catch (Exception e) { | |
| 21 | // silence! |
|
21 | // silence! | |
| 22 | } |
|
22 | } | |
| 23 | }); |
|
23 | }); | |
| 24 | } |
|
24 | } | |
| 25 |
|
25 | |||
| 26 | public static RedirectFrom stream(final InputStream from) { |
|
26 | public static RedirectFrom stream(final InputStream from) { | |
| 27 | return to -> CompletableFuture.runAsync(() -> { |
|
27 | return to -> CompletableFuture.runAsync(() -> { | |
| 28 | try (from; to) { |
|
28 | try (from; to) { | |
| 29 | from.transferTo(to); |
|
29 | from.transferTo(to); | |
| 30 | } catch (Exception e) { |
|
30 | } catch (Exception e) { | |
| 31 | // silence! |
|
31 | // silence! | |
| 32 | } |
|
32 | } | |
| 33 | }); |
|
33 | }); | |
| 34 | } |
|
34 | } | |
| 35 |
|
35 | |||
|
|
36 | public static RedirectFrom any(final Object output) { | |||
|
|
37 | if (output instanceof File f) { | |||
|
|
38 | return file(f); | |||
|
|
39 | } else if (output instanceof InputStream stm) { | |||
|
|
40 | return stream(stm); | |||
|
|
41 | } else if (output instanceof RedirectFrom self) { | |||
|
|
42 | return self; | |||
|
|
43 | } else { | |||
|
|
44 | throw new IllegalArgumentException("The specified argument type isn't supported: " + output.getClass()); | |||
|
|
45 | } | |||
|
|
46 | } | |||
|
|
47 | ||||
| 36 |
|
48 | |||
| 37 | } |
|
49 | } | |
| @@ -1,47 +1,75 | |||||
| 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.FileOutputStream; |
|
4 | import java.io.FileOutputStream; | |
| 5 | import java.io.InputStream; |
|
5 | import java.io.InputStream; | |
| 6 | import java.io.OutputStream; |
|
6 | import java.io.OutputStream; | |
| 7 | import java.util.Scanner; |
|
7 | import java.util.Scanner; | |
| 8 | import java.util.concurrent.CompletableFuture; |
|
8 | import java.util.concurrent.CompletableFuture; | |
| 9 | import java.util.function.Consumer; |
|
9 | import java.util.function.Consumer; | |
| 10 |
|
10 | |||
|
|
11 | import org.eclipse.jdt.annotation.NonNullByDefault; | |||
|
|
12 | ||||
| 11 | /** |
|
13 | /** | |
| 12 | * RedirectSpec |
|
14 | * RedirectSpec | |
| 13 | */ |
|
15 | */ | |
|
|
16 | @NonNullByDefault | |||
| 14 | public interface RedirectTo { |
|
17 | public interface RedirectTo { | |
| 15 | CompletableFuture<Void> redirect(InputStream from); |
|
18 | CompletableFuture<Void> redirect(InputStream from); | |
| 16 |
|
19 | |||
|
|
20 | public interface StringConsumer extends Consumer<String> { | |||
|
|
21 | } | |||
|
|
22 | ||||
| 17 | public static RedirectTo consumer(final Consumer<String> consumer) { |
|
23 | public static RedirectTo consumer(final Consumer<String> consumer) { | |
|
|
24 | return consumer(new StringConsumer() { | |||
|
|
25 | @Override | |||
|
|
26 | public void accept(String s) { | |||
|
|
27 | consumer.accept(s); | |||
|
|
28 | } | |||
|
|
29 | }); | |||
|
|
30 | } | |||
| 18 |
|
31 | |||
|
|
32 | public static RedirectTo consumer(final StringConsumer consumer) { | |||
| 19 | return (src) -> CompletableFuture.runAsync(() -> { |
|
33 | return (src) -> CompletableFuture.runAsync(() -> { | |
| 20 | try (Scanner sc = new Scanner(src)) { |
|
34 | try (Scanner sc = new Scanner(src)) { | |
| 21 | while (sc.hasNextLine()) { |
|
35 | while (sc.hasNextLine()) { | |
| 22 | consumer.accept(sc.nextLine()); |
|
36 | consumer.accept(sc.nextLine()); | |
| 23 | } |
|
37 | } | |
| 24 | } |
|
38 | } | |
| 25 | }); |
|
39 | }); | |
| 26 | } |
|
40 | } | |
| 27 |
|
41 | |||
| 28 | public static RedirectTo file(final File file) { |
|
42 | public static RedirectTo file(final File file) { | |
| 29 | return src -> CompletableFuture.runAsync(() -> { |
|
43 | return src -> CompletableFuture.runAsync(() -> { | |
| 30 | try (OutputStream out = new FileOutputStream(file)) { |
|
44 | try (OutputStream out = new FileOutputStream(file)) { | |
| 31 | src.transferTo(out); |
|
45 | src.transferTo(out); | |
| 32 | } catch (Exception e) { |
|
46 | } catch (Exception e) { | |
| 33 | // silence! |
|
47 | // silence! | |
| 34 | } |
|
48 | } | |
| 35 | }); |
|
49 | }); | |
| 36 | } |
|
50 | } | |
| 37 |
|
51 | |||
| 38 | public static RedirectTo stream(final OutputStream dest) { |
|
52 | public static RedirectTo stream(final OutputStream dest) { | |
| 39 | return src -> CompletableFuture.runAsync(() -> { |
|
53 | return src -> CompletableFuture.runAsync(() -> { | |
| 40 | try (dest; src) { |
|
54 | try (dest; src) { | |
| 41 | src.transferTo(dest); |
|
55 | src.transferTo(dest); | |
| 42 | } catch (Exception e) { |
|
56 | } catch (Exception e) { | |
| 43 | // silence! |
|
57 | // silence! | |
| 44 | } |
|
58 | } | |
| 45 | }); |
|
59 | }); | |
| 46 | } |
|
60 | } | |
|
|
61 | ||||
|
|
62 | public static RedirectTo any(final Object output) { | |||
|
|
63 | if (output instanceof StringConsumer fn) { | |||
|
|
64 | return consumer(s -> fn.accept(s)); | |||
|
|
65 | } else if (output instanceof File f) { | |||
|
|
66 | return file(f); | |||
|
|
67 | } else if (output instanceof OutputStream stm) { | |||
|
|
68 | return stream(stm); | |||
|
|
69 | } else if (output instanceof RedirectTo self) { | |||
|
|
70 | return self; | |||
|
|
71 | } else { | |||
|
|
72 | throw new IllegalArgumentException("The specified argument type isn't supported: " + output.getClass()); | |||
|
|
73 | } | |||
|
|
74 | } | |||
| 47 | } No newline at end of file |
|
75 | } | |
| @@ -1,44 +1,49 | |||||
| 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; |
|
7 | import java.util.List; | |
| 8 | import java.util.Map; |
|
8 | import java.util.Map; | |
| 9 | import java.util.Optional; |
|
9 | import java.util.Optional; | |
| 10 | import java.util.concurrent.CompletableFuture; |
|
10 | import java.util.concurrent.CompletableFuture; | |
| 11 |
|
11 | |||
| 12 | class SystemExecBuilder extends ExecBuilder { |
|
12 | class SystemExecBuilder extends ExecBuilder { | |
| 13 | @Override |
|
13 | @Override | |
| 14 |
protected CompletableFuture<Integer> startInternal( |
|
14 | protected CompletableFuture<Integer> startInternal( | |
| 15 | List<String> commandLine, Optional<RedirectFrom> stdinRedirect, Optional<RedirectTo> stdoutRedirect, |
|
15 | Map<String, String> environment, | |
|
|
16 | Optional<File> directory, | |||
|
|
17 | List<String> commandLine, | |||
|
|
18 | Optional<RedirectFrom> stdinRedirect, | |||
|
|
19 | Optional<RedirectTo> stdoutRedirect, | |||
| 16 |
|
|
20 | Optional<RedirectTo> stderrRedirect) throws IOException { | |
| 17 |
|
21 | |||
| 18 | var builder = new ProcessBuilder(commandLine) |
|
22 | var builder = new ProcessBuilder(commandLine); | |
| 19 | .directory(directory); |
|
23 | ||
|
|
24 | directory.ifPresent(builder::directory); | |||
| 20 |
|
25 | |||
| 21 | builder.environment().putAll(environment); |
|
26 | builder.environment().putAll(environment); | |
| 22 |
|
27 | |||
| 23 | // TODO Auto-generated method stub |
|
28 | // TODO Auto-generated method stub | |
| 24 | var tasks = new ArrayList<CompletableFuture<?>>(); |
|
29 | var tasks = new ArrayList<CompletableFuture<?>>(); | |
| 25 |
|
30 | |||
| 26 | if (!stdoutRedirect.isPresent()) |
|
31 | if (!stdoutRedirect.isPresent()) | |
| 27 | builder.redirectOutput(Redirect.DISCARD); |
|
32 | builder.redirectOutput(Redirect.DISCARD); | |
| 28 | if (!stderrRedirect.isPresent()) |
|
33 | if (!stderrRedirect.isPresent()) | |
| 29 | builder.redirectError(Redirect.DISCARD); |
|
34 | builder.redirectError(Redirect.DISCARD); | |
| 30 |
|
35 | |||
| 31 | // run process |
|
36 | // run process | |
| 32 | var proc = builder.start(); |
|
37 | var proc = builder.start(); | |
| 33 |
|
38 | |||
| 34 | tasks.add(proc.onExit()); |
|
39 | tasks.add(proc.onExit()); | |
| 35 |
|
40 | |||
| 36 | stdinRedirect.map(from -> from.redirect(proc.getOutputStream())).ifPresent(tasks::add); |
|
41 | stdinRedirect.map(from -> from.redirect(proc.getOutputStream())).ifPresent(tasks::add); | |
| 37 | stdoutRedirect.map(to -> to.redirect(proc.getInputStream())).ifPresent(tasks::add); |
|
42 | stdoutRedirect.map(to -> to.redirect(proc.getInputStream())).ifPresent(tasks::add); | |
| 38 | stderrRedirect.map(to -> to.redirect(proc.getErrorStream())).ifPresent(tasks::add); |
|
43 | stderrRedirect.map(to -> to.redirect(proc.getErrorStream())).ifPresent(tasks::add); | |
| 39 |
|
44 | |||
| 40 | return CompletableFuture |
|
45 | return CompletableFuture | |
| 41 | .allOf(tasks.toArray(new CompletableFuture<?>[0])) |
|
46 | .allOf(tasks.toArray(new CompletableFuture<?>[0])) | |
| 42 | .thenApply(t -> proc.exitValue()); |
|
47 | .thenApply(t -> proc.exitValue()); | |
| 43 | } |
|
48 | } | |
| 44 | } |
|
49 | } | |
| @@ -1,52 +1,110 | |||||
| 1 | package org.implab.gradle.common.tasks; |
|
1 | package org.implab.gradle.common.tasks; | |
| 2 |
|
2 | |||
|
|
3 | import java.io.IOException; | |||
|
|
4 | import java.util.Map; | |||
|
|
5 | import java.util.concurrent.ExecutionException; | |||
|
|
6 | import java.util.stream.Stream; | |||
|
|
7 | ||||
| 3 | import org.gradle.api.DefaultTask; |
|
8 | import org.gradle.api.DefaultTask; | |
|
|
9 | import org.gradle.api.file.DirectoryProperty; | |||
| 4 | import org.gradle.api.provider.ListProperty; |
|
10 | import org.gradle.api.provider.ListProperty; | |
|
|
11 | import org.gradle.api.provider.MapProperty; | |||
| 5 | import org.gradle.api.tasks.Internal; |
|
12 | import org.gradle.api.tasks.Internal; | |
|
|
13 | import org.gradle.api.tasks.TaskAction; | |||
|
|
14 | import org.implab.gradle.common.dsl.CommandSpec; | |||
|
|
15 | import org.implab.gradle.common.dsl.PipeSpec; | |||
| 6 | import org.implab.gradle.common.dsl.RedirectFromSpec; |
|
16 | import org.implab.gradle.common.dsl.RedirectFromSpec; | |
| 7 | import org.implab.gradle.common.dsl.RedirectToSpec; |
|
17 | import org.implab.gradle.common.dsl.RedirectToSpec; | |
|
|
18 | import org.implab.gradle.common.dsl.EnvironmentSpec; | |||
|
|
19 | import org.implab.gradle.common.exec.ExecBuilder; | |||
|
|
20 | import org.implab.gradle.common.utils.ObjectsMixin; | |||
|
|
21 | import org.implab.gradle.common.utils.Strings; | |||
|
|
22 | import org.implab.gradle.common.utils.ThrowingConsumer; | |||
| 8 |
|
23 | |||
| 9 |
public abstract class Exec |
|
24 | public abstract class ShellExecTask | |
|
|
25 | extends DefaultTask | |||
|
|
26 | implements CommandSpec, PipeSpec, EnvironmentSpec, ObjectsMixin { | |||
| 10 |
|
27 | |||
| 11 | private final RedirectToSpec redirectStderr = new RedirectToSpec(); |
|
28 | private final RedirectToSpec redirectStderr = new RedirectToSpec(); | |
| 12 |
|
29 | |||
| 13 | private final RedirectToSpec redirectStdout = new RedirectToSpec(); |
|
30 | private final RedirectToSpec redirectStdout = new RedirectToSpec(); | |
| 14 |
|
31 | |||
| 15 | private final RedirectFromSpec redirectStdin = new RedirectFromSpec(); |
|
32 | private final RedirectFromSpec redirectStdin = new RedirectFromSpec(); | |
| 16 |
|
33 | |||
| 17 | @Internal |
|
34 | @Internal | |
|
|
35 | @Override | |||
|
|
36 | public abstract DirectoryProperty getWorkingDirectory(); | |||
|
|
37 | ||||
|
|
38 | @Internal | |||
|
|
39 | @Override | |||
|
|
40 | public abstract MapProperty<String, String> getEnvironment(); | |||
|
|
41 | ||||
|
|
42 | @Internal | |||
|
|
43 | @Override | |||
| 18 | public abstract ListProperty<String> getCommandLine(); |
|
44 | public abstract ListProperty<String> getCommandLine(); | |
| 19 |
|
45 | |||
| 20 |
|
||||
| 21 | /** |
|
46 | /** | |
| 22 | * STDIN redirection, if not specified, no input will be passed to the command |
|
47 | * STDIN redirection, if not specified, no input will be passed to the command | |
| 23 | */ |
|
48 | */ | |
| 24 | @Internal |
|
49 | @Internal | |
|
|
50 | @Override | |||
| 25 | public RedirectFromSpec getStdin() { |
|
51 | public RedirectFromSpec getStdin() { | |
| 26 | return redirectStdin; |
|
52 | return redirectStdin; | |
| 27 | } |
|
53 | } | |
| 28 |
|
54 | |||
| 29 | /** |
|
55 | /** | |
| 30 | * STDOUT redirection, if not specified, redirected to logger::info |
|
56 | * STDOUT redirection, if not specified, redirected to logger::info | |
| 31 | */ |
|
57 | */ | |
| 32 | @Internal |
|
58 | @Internal | |
|
|
59 | @Override | |||
| 33 | public RedirectToSpec getStdout() { |
|
60 | public RedirectToSpec getStdout() { | |
| 34 | return redirectStdout; |
|
61 | return redirectStdout; | |
| 35 | } |
|
62 | } | |
| 36 |
|
63 | |||
| 37 | /** |
|
64 | /** | |
| 38 | * STDERR redirection, if not specified, redirected to logger::error |
|
65 | * STDERR redirection, if not specified, redirected to logger::error | |
| 39 | */ |
|
66 | */ | |
| 40 | @Internal |
|
67 | @Internal | |
|
|
68 | @Override | |||
| 41 | public RedirectToSpec getStderr() { |
|
69 | public RedirectToSpec getStderr() { | |
| 42 | return redirectStderr; |
|
70 | return redirectStderr; | |
| 43 | } |
|
71 | } | |
| 44 |
|
72 | |||
|
|
73 | @Override | |||
|
|
74 | public void commandLine(Object arg0, Object... args) { | |||
|
|
75 | getCommandLine().set(provider(() -> Stream.concat( | |||
|
|
76 | Stream.of(arg0), | |||
|
|
77 | Stream.of(args)) | |||
|
|
78 | .map(Strings::asString).toList())); | |||
| 45 |
|
79 | |||
| 46 | /** Appends specified parameters to the command line */ |
|
80 | } | |
| 47 | void commandLine(String... args) { |
|
81 | ||
| 48 | getCommandLine().addAll(args); |
|
82 | @Override | |
|
|
83 | public void args(Object arg0, Object... args) { | |||
|
|
84 | getCommandLine().addAll(provider(() -> Stream.concat( | |||
|
|
85 | Stream.of(arg0), | |||
|
|
86 | Stream.of(args)) | |||
|
|
87 | .map(Strings::asString).toList())); | |||
| 49 |
|
|
88 | } | |
| 50 |
|
89 | |||
|
|
90 | protected abstract ExecBuilder execBuilder(); | |||
|
|
91 | ||||
|
|
92 | @TaskAction | |||
|
|
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()); | |||
|
|
98 | ||||
|
|
99 | getStdout().getRedirection().ifPresent(execBuilder::stdout); | |||
|
|
100 | getStderr().getRedirection().ifPresent(execBuilder::stderr); | |||
|
|
101 | getStdin().getRedirection().ifPresent(execBuilder::stdin); | |||
|
|
102 | ||||
|
|
103 | execBuilder.run().thenAccept(ThrowingConsumer.guard(this::checkRetCode)).join(); | |||
|
|
104 | } | |||
|
|
105 | ||||
|
|
106 | protected void checkRetCode(Integer code) throws IOException{ | |||
|
|
107 | throw new IOException(String.format("The process is terminated with code %s", code)); | |||
|
|
108 | } | |||
| 51 |
|
109 | |||
| 52 | } |
|
110 | } | |
| @@ -1,14 +1,32 | |||||
| 1 | package org.implab.gradle.common.utils; |
|
1 | package org.implab.gradle.common.utils; | |
| 2 |
|
2 | |||
| 3 | import java.util.regex.Pattern; |
|
3 | import java.util.regex.Pattern; | |
| 4 |
|
4 | |||
|
|
5 | import org.eclipse.jdt.annotation.NonNullByDefault; | |||
|
|
6 | import org.gradle.api.provider.Provider; | |||
|
|
7 | ||||
|
|
8 | @NonNullByDefault | |||
| 5 | public class Strings { |
|
9 | public class Strings { | |
| 6 |
|
10 | |||
| 7 | private static final Pattern firstLetter = Pattern.compile("^\\w"); |
|
11 | private static final Pattern firstLetter = Pattern.compile("^\\w"); | |
| 8 |
|
12 | |||
| 9 | public static String capitalize(String string) { |
|
13 | public static String capitalize(String string) { | |
| 10 |
|
|
14 | return string == null ? null | |
| 11 | return ""; |
|
15 | : string.length() == 0 ? string | |
| 12 |
|
|
16 | : firstLetter.matcher(string).replaceFirst(m -> m.group().toUpperCase()); | |
|
|
17 | } | |||
|
|
18 | ||||
|
|
19 | public static void argumentNotNullOrEmpty(String value, String argumentName) { | |||
|
|
20 | if (value == null || value.length() == 0) | |||
|
|
21 | throw new IllegalArgumentException(String.format("Argument %s can't be null or empty", argumentName)); | |||
|
|
22 | } | |||
|
|
23 | ||||
|
|
24 | public static String asString(Object value) { | |||
|
|
25 | if (value == null) | |||
|
|
26 | return null; | |||
|
|
27 | if (value instanceof Provider<?> provider) | |||
|
|
28 | return asString(provider.get()); | |||
|
|
29 | else | |||
|
|
30 | return value.toString(); | |||
| 13 | } |
|
31 | } | |
| 14 | } |
|
32 | } | |
| 1 | NO CONTENT: modified file, binary diff hidden |
|
NO CONTENT: modified file, binary diff hidden |
| @@ -1,7 +1,7 | |||||
| 1 | distributionBase=GRADLE_USER_HOME |
|
1 | distributionBase=GRADLE_USER_HOME | |
| 2 | distributionPath=wrapper/dists |
|
2 | distributionPath=wrapper/dists | |
| 3 |
distributionUrl=https\://services.gradle.org/distributions/gradle-8. |
|
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip | |
| 4 | networkTimeout=10000 |
|
4 | networkTimeout=10000 | |
| 5 | validateDistributionUrl=true |
|
5 | validateDistributionUrl=true | |
| 6 | zipStoreBase=GRADLE_USER_HOME |
|
6 | zipStoreBase=GRADLE_USER_HOME | |
| 7 | zipStorePath=wrapper/dists |
|
7 | zipStorePath=wrapper/dists | |
| @@ -1,92 +1,92 | |||||
| 1 | @rem |
|
1 | @rem | |
| 2 | @rem Copyright 2015 the original author or authors. |
|
2 | @rem Copyright 2015 the original author or authors. | |
| 3 | @rem |
|
3 | @rem | |
| 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); |
|
4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); | |
| 5 | @rem you may not use this file except in compliance with the License. |
|
5 | @rem you may not use this file except in compliance with the License. | |
| 6 | @rem You may obtain a copy of the License at |
|
6 | @rem You may obtain a copy of the License at | |
| 7 | @rem |
|
7 | @rem | |
| 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 |
|
8 | @rem https://www.apache.org/licenses/LICENSE-2.0 | |
| 9 | @rem |
|
9 | @rem | |
| 10 | @rem Unless required by applicable law or agreed to in writing, software |
|
10 | @rem Unless required by applicable law or agreed to in writing, software | |
| 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, |
|
11 | @rem distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 | @rem See the License for the specific language governing permissions and |
|
13 | @rem See the License for the specific language governing permissions and | |
| 14 | @rem limitations under the License. |
|
14 | @rem limitations under the License. | |
| 15 | @rem |
|
15 | @rem | |
| 16 |
|
16 | |||
| 17 | @if "%DEBUG%"=="" @echo off |
|
17 | @if "%DEBUG%"=="" @echo off | |
| 18 | @rem ########################################################################## |
|
18 | @rem ########################################################################## | |
| 19 | @rem |
|
19 | @rem | |
| 20 | @rem Gradle startup script for Windows |
|
20 | @rem Gradle startup script for Windows | |
| 21 | @rem |
|
21 | @rem | |
| 22 | @rem ########################################################################## |
|
22 | @rem ########################################################################## | |
| 23 |
|
23 | |||
| 24 | @rem Set local scope for the variables with windows NT shell |
|
24 | @rem Set local scope for the variables with windows NT shell | |
| 25 | if "%OS%"=="Windows_NT" setlocal |
|
25 | if "%OS%"=="Windows_NT" setlocal | |
| 26 |
|
26 | |||
| 27 | set DIRNAME=%~dp0 |
|
27 | set DIRNAME=%~dp0 | |
| 28 | if "%DIRNAME%"=="" set DIRNAME=. |
|
28 | if "%DIRNAME%"=="" set DIRNAME=. | |
| 29 | @rem This is normally unused |
|
29 | @rem This is normally unused | |
| 30 | set APP_BASE_NAME=%~n0 |
|
30 | set APP_BASE_NAME=%~n0 | |
| 31 | set APP_HOME=%DIRNAME% |
|
31 | set APP_HOME=%DIRNAME% | |
| 32 |
|
32 | |||
| 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. |
|
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. | |
| 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi |
|
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi | |
| 35 |
|
35 | |||
| 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
|
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |
| 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" |
|
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" | |
| 38 |
|
38 | |||
| 39 | @rem Find java.exe |
|
39 | @rem Find java.exe | |
| 40 | if defined JAVA_HOME goto findJavaFromJavaHome |
|
40 | if defined JAVA_HOME goto findJavaFromJavaHome | |
| 41 |
|
41 | |||
| 42 | set JAVA_EXE=java.exe |
|
42 | set JAVA_EXE=java.exe | |
| 43 | %JAVA_EXE% -version >NUL 2>&1 |
|
43 | %JAVA_EXE% -version >NUL 2>&1 | |
| 44 | if %ERRORLEVEL% equ 0 goto execute |
|
44 | if %ERRORLEVEL% equ 0 goto execute | |
| 45 |
|
45 | |||
| 46 | echo. |
|
46 | echo. 1>&2 | |
| 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
|
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 | |
| 48 | echo. |
|
48 | echo. 1>&2 | |
| 49 | echo Please set the JAVA_HOME variable in your environment to match the |
|
49 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | |
| 50 | echo location of your Java installation. |
|
50 | echo location of your Java installation. 1>&2 | |
| 51 |
|
51 | |||
| 52 | goto fail |
|
52 | goto fail | |
| 53 |
|
53 | |||
| 54 | :findJavaFromJavaHome |
|
54 | :findJavaFromJavaHome | |
| 55 | set JAVA_HOME=%JAVA_HOME:"=% |
|
55 | set JAVA_HOME=%JAVA_HOME:"=% | |
| 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe |
|
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe | |
| 57 |
|
57 | |||
| 58 | if exist "%JAVA_EXE%" goto execute |
|
58 | if exist "%JAVA_EXE%" goto execute | |
| 59 |
|
59 | |||
| 60 | echo. |
|
60 | echo. 1>&2 | |
| 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% |
|
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 | |
| 62 | echo. |
|
62 | echo. 1>&2 | |
| 63 | echo Please set the JAVA_HOME variable in your environment to match the |
|
63 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | |
| 64 | echo location of your Java installation. |
|
64 | echo location of your Java installation. 1>&2 | |
| 65 |
|
65 | |||
| 66 | goto fail |
|
66 | goto fail | |
| 67 |
|
67 | |||
| 68 | :execute |
|
68 | :execute | |
| 69 | @rem Setup the command line |
|
69 | @rem Setup the command line | |
| 70 |
|
70 | |||
| 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar |
|
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | |
| 72 |
|
72 | |||
| 73 |
|
73 | |||
| 74 | @rem Execute Gradle |
|
74 | @rem Execute Gradle | |
| 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* |
|
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* | |
| 76 |
|
76 | |||
| 77 | :end |
|
77 | :end | |
| 78 | @rem End local scope for the variables with windows NT shell |
|
78 | @rem End local scope for the variables with windows NT shell | |
| 79 | if %ERRORLEVEL% equ 0 goto mainEnd |
|
79 | if %ERRORLEVEL% equ 0 goto mainEnd | |
| 80 |
|
80 | |||
| 81 | :fail |
|
81 | :fail | |
| 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of |
|
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | |
| 83 | rem the _cmd.exe /c_ return code! |
|
83 | rem the _cmd.exe /c_ return code! | |
| 84 | set EXIT_CODE=%ERRORLEVEL% |
|
84 | set EXIT_CODE=%ERRORLEVEL% | |
| 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 |
|
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 | |
| 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% |
|
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% | |
| 87 | exit /b %EXIT_CODE% |
|
87 | exit /b %EXIT_CODE% | |
| 88 |
|
88 | |||
| 89 | :mainEnd |
|
89 | :mainEnd | |
| 90 | if "%OS%"=="Windows_NT" endlocal |
|
90 | if "%OS%"=="Windows_NT" endlocal | |
| 91 |
|
91 | |||
| 92 | :omega |
|
92 | :omega | |
| 1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
| 1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
| 1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now
