| @@ -0,0 +1,52 | |||
|
|
1 | package org.implab.gradle.common.exec; | |
|
|
2 | ||
|
|
3 | import static java.util.Objects.requireNonNull; | |
|
|
4 | ||
|
|
5 | import java.util.Optional; | |
|
|
6 | ||
|
|
7 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
8 | import org.implab.gradle.common.utils.Values; | |
|
|
9 | ||
|
|
10 | @NonNullByDefault | |
|
|
11 | public interface CommandArgumentsBuilder<S extends CommandArgumentsBuilder<S>> { | |
|
|
12 | ||
|
|
13 | S self(); | |
|
|
14 | ||
|
|
15 | default S flag(String name, boolean value) { | |
|
|
16 | requireNonNull(name, "Parameter name cannot be null"); | |
|
|
17 | if (value) | |
|
|
18 | addArguments(name); | |
|
|
19 | return self(); | |
|
|
20 | } | |
|
|
21 | ||
|
|
22 | default S param(String name, String value) { | |
|
|
23 | requireNonNull(name, "Parameter name cannot be null"); | |
|
|
24 | requireNonNull(value, "Parameter value cannot be null"); | |
|
|
25 | if (value != null && value.length() > 0) | |
|
|
26 | addArguments(name, value); | |
|
|
27 | return self(); | |
|
|
28 | } | |
|
|
29 | ||
|
|
30 | default S param(String name, Optional<String> value) { | |
|
|
31 | value.ifPresent(v -> param(name, v)); | |
|
|
32 | return self(); | |
|
|
33 | } | |
|
|
34 | ||
|
|
35 | /** Adds the specified arguments to this builder */ | |
|
|
36 | S addArguments(String... args); | |
|
|
37 | ||
|
|
38 | default S addArguments(Iterable<String> args) { | |
|
|
39 | for (String arg : args) | |
|
|
40 | addArguments(arg); | |
|
|
41 | ||
|
|
42 | return self(); | |
|
|
43 | } | |
|
|
44 | ||
|
|
45 | /** Replaces arguments in the builder with the specified one. */ | |
|
|
46 | default S arguments(String... args) { | |
|
|
47 | return arguments(Values.iterable(args)); | |
|
|
48 | } | |
|
|
49 | ||
|
|
50 | /** Replaces arguments in the builder with the specified one. */ | |
|
|
51 | S arguments(Iterable<String> args); | |
|
|
52 | } | |
| @@ -0,0 +1,40 | |||
|
|
1 | package org.implab.gradle.common.exec; | |
|
|
2 | ||
|
|
3 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
4 | import org.gradle.api.Action; | |
|
|
5 | ||
|
|
6 | @NonNullByDefault | |
|
|
7 | public class ShellTool { | |
|
|
8 | ||
|
|
9 | private final Shell shell; | |
|
|
10 | ||
|
|
11 | private final String executable; | |
|
|
12 | ||
|
|
13 | ShellTool(String executable, Shell shell) { | |
|
|
14 | this.shell = shell; | |
|
|
15 | this.executable = executable; | |
|
|
16 | } | |
|
|
17 | ||
|
|
18 | public ShellExec arguments(String... args) { | |
|
|
19 | return shell.create(CommandSpec.builder() | |
|
|
20 | .executable(executable) | |
|
|
21 | .arguments(args) | |
|
|
22 | .build()); | |
|
|
23 | } | |
|
|
24 | ||
|
|
25 | public ShellExec arguments(Iterable<String> args) { | |
|
|
26 | return shell.create(CommandSpec.builder() | |
|
|
27 | .executable(executable) | |
|
|
28 | .arguments(args) | |
|
|
29 | .build()); | |
|
|
30 | } | |
|
|
31 | ||
|
|
32 | public ShellExec arguments(Action<CommandArgumentsBuilder<?>> args) { | |
|
|
33 | var builder = CommandSpec.builder() | |
|
|
34 | .executable(executable); | |
|
|
35 | args.execute(builder); | |
|
|
36 | ||
|
|
37 | return shell.create(builder.build()); | |
|
|
38 | } | |
|
|
39 | ||
|
|
40 | } | |
| @@ -0,0 +1,35 | |||
|
|
1 | package org.implab.gradle.common.utils; | |
|
|
2 | ||
|
|
3 | import java.io.File; | |
|
|
4 | import java.util.Optional; | |
|
|
5 | ||
|
|
6 | import org.implab.gradle.common.utils.os.SystemResolver; | |
|
|
7 | ||
|
|
8 | public interface OperatingSystem { | |
|
|
9 | ||
|
|
10 | public static OperatingSystem CURRENT = SystemResolver.current(); | |
|
|
11 | ||
|
|
12 | public static final String WINDOWS_FAMILY = "windows"; | |
|
|
13 | ||
|
|
14 | public static final String LINUX_FAMILY = "linux"; | |
|
|
15 | ||
|
|
16 | public static final String FREE_BSD_FAMILY = "freebsd"; | |
|
|
17 | ||
|
|
18 | public static final String MAC_OS_FAMILY = "os x"; | |
|
|
19 | ||
|
|
20 | public static final String UNKNOWN_FAMILY = "unknown"; | |
|
|
21 | ||
|
|
22 | String family(); | |
|
|
23 | ||
|
|
24 | String name(); | |
|
|
25 | ||
|
|
26 | String version(); | |
|
|
27 | ||
|
|
28 | Optional<File> which(String cmd); | |
|
|
29 | ||
|
|
30 | Optional<File> which(String cmd, Iterable<? extends File> paths); | |
|
|
31 | ||
|
|
32 | public static OperatingSystem current() { | |
|
|
33 | return CURRENT; | |
|
|
34 | } | |
|
|
35 | } | |
| @@ -0,0 +1,16 | |||
|
|
1 | package org.implab.gradle.common.utils.os; | |
|
|
2 | ||
|
|
3 | import org.implab.gradle.common.utils.OperatingSystem; | |
|
|
4 | ||
|
|
5 | public class FreeBsd extends GenericSystem{ | |
|
|
6 | ||
|
|
7 | FreeBsd(String name, String version) { | |
|
|
8 | super(name, version); | |
|
|
9 | } | |
|
|
10 | ||
|
|
11 | @Override | |
|
|
12 | public String family() { | |
|
|
13 | return OperatingSystem.FREE_BSD_FAMILY; | |
|
|
14 | } | |
|
|
15 | ||
|
|
16 | } | |
| @@ -0,0 +1,64 | |||
|
|
1 | package org.implab.gradle.common.utils.os; | |
|
|
2 | ||
|
|
3 | import java.io.File; | |
|
|
4 | import java.util.Arrays; | |
|
|
5 | import java.util.Optional; | |
|
|
6 | import java.util.function.Function; | |
|
|
7 | import java.util.regex.Pattern; | |
|
|
8 | import java.util.stream.Stream; | |
|
|
9 | ||
|
|
10 | import org.implab.gradle.common.utils.OperatingSystem; | |
|
|
11 | import org.implab.gradle.common.utils.Values; | |
|
|
12 | ||
|
|
13 | class GenericSystem implements OperatingSystem { | |
|
|
14 | ||
|
|
15 | private final String name; | |
|
|
16 | ||
|
|
17 | private final String version; | |
|
|
18 | ||
|
|
19 | GenericSystem(String name, String version) { | |
|
|
20 | this.name = name; | |
|
|
21 | this.version = version; | |
|
|
22 | } | |
|
|
23 | ||
|
|
24 | public String getPathVar() { | |
|
|
25 | return "PATH"; | |
|
|
26 | } | |
|
|
27 | ||
|
|
28 | @Override | |
|
|
29 | public String family() { | |
|
|
30 | return OperatingSystem.UNKNOWN_FAMILY; | |
|
|
31 | } | |
|
|
32 | ||
|
|
33 | @Override | |
|
|
34 | public String name() { | |
|
|
35 | return name; | |
|
|
36 | } | |
|
|
37 | ||
|
|
38 | @Override | |
|
|
39 | public String version() { | |
|
|
40 | return version; | |
|
|
41 | } | |
|
|
42 | ||
|
|
43 | protected Stream<File> getPath() { | |
|
|
44 | String path = System.getenv(getPathVar()); | |
|
|
45 | return path == null | |
|
|
46 | ? Stream.empty() | |
|
|
47 | : Arrays.stream(path.split(Pattern.quote(File.pathSeparator))) | |
|
|
48 | .map(File::new); | |
|
|
49 | } | |
|
|
50 | ||
|
|
51 | protected Function<File, Stream<File>> candidates(String cmd) { | |
|
|
52 | return base -> Stream.of(new File(base, cmd)); | |
|
|
53 | } | |
|
|
54 | ||
|
|
55 | @Override | |
|
|
56 | public Optional<File> which(String cmd) { | |
|
|
57 | return getPath().flatMap(candidates(cmd)).filter(File::isFile).findAny(); | |
|
|
58 | } | |
|
|
59 | ||
|
|
60 | @Override | |
|
|
61 | public Optional<File> which(String cmd, Iterable<? extends File> paths) { | |
|
|
62 | return Values.stream(paths.iterator()).flatMap(candidates(cmd)).filter(File::isFile).findAny(); | |
|
|
63 | } | |
|
|
64 | } | |
| @@ -0,0 +1,16 | |||
|
|
1 | package org.implab.gradle.common.utils.os; | |
|
|
2 | ||
|
|
3 | import org.implab.gradle.common.utils.OperatingSystem; | |
|
|
4 | ||
|
|
5 | public class Linux extends GenericSystem { | |
|
|
6 | ||
|
|
7 | Linux(String name, String version) { | |
|
|
8 | super(name, version); | |
|
|
9 | } | |
|
|
10 | ||
|
|
11 | @Override | |
|
|
12 | public String family() { | |
|
|
13 | return OperatingSystem.LINUX_FAMILY; | |
|
|
14 | } | |
|
|
15 | ||
|
|
16 | } | |
| @@ -0,0 +1,15 | |||
|
|
1 | package org.implab.gradle.common.utils.os; | |
|
|
2 | ||
|
|
3 | import org.implab.gradle.common.utils.OperatingSystem; | |
|
|
4 | ||
|
|
5 | public class MacOs extends GenericSystem { | |
|
|
6 | ||
|
|
7 | MacOs(String name, String version) { | |
|
|
8 | super(name, version); | |
|
|
9 | } | |
|
|
10 | ||
|
|
11 | @Override | |
|
|
12 | public String family() { | |
|
|
13 | return OperatingSystem.MAC_OS_FAMILY; | |
|
|
14 | } | |
|
|
15 | } | |
| @@ -0,0 +1,29 | |||
|
|
1 | package org.implab.gradle.common.utils.os; | |
|
|
2 | ||
|
|
3 | import org.implab.gradle.common.utils.OperatingSystem; | |
|
|
4 | ||
|
|
5 | public class SystemResolver { | |
|
|
6 | public static OperatingSystem current() { | |
|
|
7 | var osName = System.getProperty("os.name"); | |
|
|
8 | var osVersion = System.getProperty("os.version"); | |
|
|
9 | ||
|
|
10 | return forName(osName, osVersion); | |
|
|
11 | } | |
|
|
12 | ||
|
|
13 | public static OperatingSystem forName(String os, String version) { | |
|
|
14 | var osName = os.toLowerCase(); | |
|
|
15 | ||
|
|
16 | if (osName.contains("windows")) { | |
|
|
17 | return new Windows(osName, version); | |
|
|
18 | } else if (osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx")) { | |
|
|
19 | return new MacOs(osName, version); | |
|
|
20 | } else if (osName.contains("linux")) { | |
|
|
21 | return new Linux(osName, version); | |
|
|
22 | } else if (osName.contains("freebsd")) { | |
|
|
23 | return new FreeBsd(osName, version); | |
|
|
24 | } else { | |
|
|
25 | // Not strictly true | |
|
|
26 | return new GenericSystem(osName, version); | |
|
|
27 | } | |
|
|
28 | } | |
|
|
29 | } | |
| @@ -0,0 +1,26 | |||
|
|
1 | package org.implab.gradle.common.utils.os; | |
|
|
2 | ||
|
|
3 | import java.io.File; | |
|
|
4 | import java.util.function.Function; | |
|
|
5 | import java.util.stream.Stream; | |
|
|
6 | ||
|
|
7 | import org.implab.gradle.common.utils.OperatingSystem; | |
|
|
8 | ||
|
|
9 | class Windows extends GenericSystem { | |
|
|
10 | ||
|
|
11 | private Stream<String> exeSuffixes = Stream.of(".cmd", ".bat", ".exe"); | |
|
|
12 | ||
|
|
13 | Windows(String name, String version) { | |
|
|
14 | super(name, version); | |
|
|
15 | } | |
|
|
16 | ||
|
|
17 | @Override | |
|
|
18 | public String family() { | |
|
|
19 | return OperatingSystem.WINDOWS_FAMILY; | |
|
|
20 | } | |
|
|
21 | ||
|
|
22 | @Override | |
|
|
23 | protected Function<File, Stream<File>> candidates(String cmd) { | |
|
|
24 | return base -> exeSuffixes.map(suffix -> new File(base, cmd + suffix)); | |
|
|
25 | } | |
|
|
26 | } | |
| @@ -1,17 +1,27 | |||
|
|
1 | 1 | package org.implab.gradle.common.exec; |
|
|
2 | 2 | |
|
|
3 | import java.util.function.Consumer; | |
|
|
3 | import java.io.File; | |
|
|
4 | 4 | |
|
|
5 | 5 | import org.eclipse.jdt.annotation.NonNullByDefault; |
|
|
6 | 6 | import org.implab.gradle.common.utils.Values; |
|
|
7 | 7 | |
|
|
8 | 8 | /** Command builder interface, used to specify the executable and parameters */ |
|
|
9 | 9 | @NonNullByDefault |
|
|
10 | public interface CommandBuilder { | |
|
|
10 | public interface CommandBuilder extends CommandArgumentsBuilder<CommandBuilder> { | |
|
|
11 | ||
|
|
12 | @Override | |
|
|
13 | default CommandBuilder self() { | |
|
|
14 | return this; | |
|
|
15 | } | |
|
|
11 | 16 | |
|
|
12 | 17 | /** Sets the executable, the parameters are left intact. */ |
|
|
13 | 18 | CommandBuilder executable(String executable); |
|
|
14 | 19 | |
|
|
20 | default CommandBuilder executable(File executable) { | |
|
|
21 | executable(executable.toString()); | |
|
|
22 | return this; | |
|
|
23 | } | |
|
|
24 | ||
|
|
15 | 25 | /** |
|
|
16 | 26 | * Sets the specified executable and parameters, old executable and parameters |
|
|
17 | 27 | * are discarded. |
| @@ -44,38 +54,6 public interface CommandBuilder { | |||
|
|
44 | 54 | return this; |
|
|
45 | 55 | } |
|
|
46 | 56 | |
|
|
47 | default Consumer<Boolean> flag(String name) { | |
|
|
48 | return f -> { | |
|
|
49 | if (f) | |
|
|
50 | addArguments(name); | |
|
|
51 | }; | |
|
|
52 | } | |
|
|
53 | ||
|
|
54 | default Consumer<String> param(String name) { | |
|
|
55 | return v -> { | |
|
|
56 | if (v != null && v.length() > 0) | |
|
|
57 | addArguments(name, v); | |
|
|
58 | }; | |
|
|
59 | } | |
|
|
60 | ||
|
|
61 | /** Adds the specified arguments to this builder */ | |
|
|
62 | CommandBuilder addArguments(String... args); | |
|
|
63 | ||
|
|
64 | default CommandBuilder addArguments(Iterable<String> args) { | |
|
|
65 | for (String arg : args) | |
|
|
66 | addArguments(arg); | |
|
|
67 | ||
|
|
68 | return this; | |
|
|
69 | } | |
|
|
70 | ||
|
|
71 | /** Replaces arguments in the builder with the specified one. */ | |
|
|
72 | default CommandBuilder arguments(String... args) { | |
|
|
73 | return arguments(Values.iterable(args)); | |
|
|
74 | } | |
|
|
75 | ||
|
|
76 | /** Replaces arguments in the builder with the specified one. */ | |
|
|
77 | CommandBuilder arguments(Iterable<String> args); | |
|
|
78 | ||
|
|
79 | 57 | default CommandBuilder from(CommandSpec commandSpec) { |
|
|
80 | 58 | return executable(commandSpec.executable()) |
|
|
81 | 59 | .arguments(commandSpec.arguments()); |
| @@ -3,6 +3,9 package org.implab.gradle.common.exec; | |||
|
|
3 | 3 | import java.util.List; |
|
|
4 | 4 | import java.util.stream.Stream; |
|
|
5 | 5 | |
|
|
6 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
7 | ||
|
|
8 | @NonNullByDefault | |
|
|
6 | 9 | public interface CommandSpec { |
|
|
7 | 10 | |
|
|
8 | 11 | String executable(); |
| @@ -1,10 +1,14 | |||
|
|
1 | 1 | package org.implab.gradle.common.exec; |
|
|
2 | 2 | |
|
|
3 | 3 | import java.util.List; |
|
|
4 | ||
|
|
5 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
6 | ||
|
|
4 | 7 | import static java.util.Objects.requireNonNull; |
|
|
5 | 8 | |
|
|
6 | 9 | import java.util.ArrayList; |
|
|
7 | 10 | |
|
|
11 | @NonNullByDefault | |
|
|
8 | 12 | public record CommandSpecRecord(String executable, List<String> arguments) implements CommandSpec { |
|
|
9 | 13 | |
|
|
10 | 14 | static class Builder implements CommandBuilder { |
| @@ -6,6 +6,9 import java.nio.charset.StandardCharsets | |||
|
|
6 | 6 | import java.util.concurrent.CompletableFuture; |
|
|
7 | 7 | import java.util.stream.Collectors; |
|
|
8 | 8 | |
|
|
9 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
10 | ||
|
|
11 | @NonNullByDefault | |
|
|
9 | 12 | class EchoExecBuilder extends AbstractExecBuilder<CommandSpec> { |
|
|
10 | 13 | |
|
|
11 | 14 | private final boolean echoToStderr; |
| @@ -4,6 +4,9 import java.io.File; | |||
|
|
4 | 4 | import java.util.Map; |
|
|
5 | 5 | import java.util.Optional; |
|
|
6 | 6 | |
|
|
7 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
8 | ||
|
|
9 | @NonNullByDefault | |
|
|
7 | 10 | public interface EnvironmentSpec { |
|
|
8 | 11 | |
|
|
9 | 12 | boolean inheritEnvironment(); |
| @@ -6,12 +6,15 import java.io.InputStream; | |||
|
|
6 | 6 | import java.io.OutputStream; |
|
|
7 | 7 | import java.util.concurrent.CompletableFuture; |
|
|
8 | 8 | |
|
|
9 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
10 | ||
|
|
9 | 11 | /** |
|
|
10 | 12 | * Describes how to redirect input streams. This interface is used to configure |
|
|
11 | 13 | * lazy redirection. {@link #redirect(OutputStream)} is called when the process |
|
|
12 | 14 | * is started. Before the process is started the redirection isn't invoked and |
|
|
13 | 15 | * no resources are allocated or used. |
|
|
14 | 16 | */ |
|
|
17 | @NonNullByDefault | |
|
|
15 | 18 | public interface RedirectFrom { |
|
|
16 | 19 | CompletableFuture<Void> redirect(OutputStream to); |
|
|
17 | 20 | |
| @@ -1,8 +1,15 | |||
|
|
1 | 1 | package org.implab.gradle.common.exec; |
|
|
2 | 2 | |
|
|
3 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
4 | ||
|
|
5 | @NonNullByDefault | |
|
|
3 | 6 | public interface Shell { |
|
|
4 | 7 | |
|
|
5 |
ShellExec |
|
|
|
8 | ShellExec create(CommandSpec spec); | |
|
|
9 | ||
|
|
10 | default ShellTool tool(String executable) { | |
|
|
11 | return new ShellTool(executable, this); | |
|
|
12 | } | |
|
|
6 | 13 | |
|
|
7 | 14 | /** Creates a new shell to start processes using ProcessBuilder. */ |
|
|
8 | 15 | static Shell system() { |
| @@ -5,8 +5,10 import java.util.ArrayList; | |||
|
|
5 | 5 | import java.util.List; |
|
|
6 | 6 | import java.util.concurrent.CompletableFuture; |
|
|
7 | 7 | |
|
|
8 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
8 | 9 | import org.implab.gradle.common.utils.Exceptions; |
|
|
9 | 10 | |
|
|
11 | @NonNullByDefault | |
|
|
10 | 12 | public interface ShellExec extends PipeBuilder, EnvironmentBuilder { |
|
|
11 | 13 | |
|
|
12 | 14 | default CompletableFuture<List<String>> readAllLines() throws IOException { |
| @@ -5,6 +5,9 import java.lang.ProcessBuilder.Redirect | |||
|
|
5 | 5 | import java.util.ArrayList; |
|
|
6 | 6 | import java.util.concurrent.CompletableFuture; |
|
|
7 | 7 | |
|
|
8 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
|
|
9 | ||
|
|
10 | @NonNullByDefault | |
|
|
8 | 11 | class SystemExecBuilder extends AbstractExecBuilder<CommandSpec> { |
|
|
9 | 12 | SystemExecBuilder(CommandSpec command) { |
|
|
10 | 13 | super(command); |
| @@ -23,7 +23,7 public abstract class ShellExecTask | |||
|
|
23 | 23 | @Override |
|
|
24 | 24 | protected ShellExec execBuilder() { |
|
|
25 | 25 | return getShell().get() |
|
|
26 |
. |
|
|
|
26 | .create(CommandSpec.builder() | |
|
|
27 | 27 | .commandLine(getCommandLine().get()) |
|
|
28 | 28 | .build()); |
|
|
29 | 29 | } |
| @@ -1,9 +1,13 | |||
|
|
1 | 1 | package org.implab.gradle.common.utils; |
|
|
2 | 2 | |
|
|
3 | import java.text.MessageFormat; | |
|
|
3 | 4 | import java.util.Iterator; |
|
|
4 | 5 | import java.util.Spliterators; |
|
|
5 | 6 | import java.util.Optional; |
|
|
7 | import java.util.Set; | |
|
|
8 | import java.util.function.Function; | |
|
|
6 | 9 | import java.util.function.Supplier; |
|
|
10 | import java.util.stream.Collectors; | |
|
|
7 | 11 | import java.util.stream.Stream; |
|
|
8 | 12 | import java.util.stream.StreamSupport; |
|
|
9 | 13 | |
| @@ -49,6 +53,17 public final class Values { | |||
|
|
49 | 53 | return provider.isPresent() ? Optional.of(provider.get()) : Optional.empty(); |
|
|
50 | 54 | } |
|
|
51 | 55 | |
|
|
56 | public static <T> T required(Provider<T> provider, String providerName) { | |
|
|
57 | if (!provider.isPresent()) | |
|
|
58 | throw new IllegalStateException( | |
|
|
59 | MessageFormat.format("The value for the '{0}' provider must be specified", providerName)); | |
|
|
60 | return provider.get(); | |
|
|
61 | } | |
|
|
62 | ||
|
|
63 | public static <U,V> Set<V> mapSet(Set<U> values, Function<U,V> mapper) { | |
|
|
64 | return values.stream().map(mapper).collect(Collectors.toUnmodifiableSet()); | |
|
|
65 | } | |
|
|
66 | ||
|
|
52 | 67 | private static class ArrayIterator<T> implements Iterator<T> { |
|
|
53 | 68 | private final T[] data; |
|
|
54 | 69 | |
|
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now
