##// END OF EJS Templates
Added OS tools to resolve exec path, minor changes
cin -
r20:8e171ef3106f default
parent child
Show More
@@ -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 of(CommandSpec spec);
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 .of(CommandSpec.builder()
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