diff --git a/common/src/main/java/org/implab/gradle/common/exec/Executor.java b/common/src/main/java/org/implab/gradle/common/exec/Executor.java new file mode 100644 --- /dev/null +++ b/common/src/main/java/org/implab/gradle/common/exec/Executor.java @@ -0,0 +1,25 @@ +package org.implab.gradle.common.exec; + +import java.util.concurrent.CompletableFuture; + +import java.io.File; +import java.io.IOException; + +/** Interface for a command line execution. */ +public interface Executor { + void argument(String arg); + + void directory(File directory); + + void stdin(RedirectFrom from); + + void stdout(RedirectTo out); + + void stderr(RedirectTo err); + + CompletableFuture start() throws IOException; + + public static Executor system() { + return new SystemExec(); + } +} diff --git a/common/src/main/java/org/implab/gradle/common/exec/SystemExec.java b/common/src/main/java/org/implab/gradle/common/exec/SystemExec.java new file mode 100644 --- /dev/null +++ b/common/src/main/java/org/implab/gradle/common/exec/SystemExec.java @@ -0,0 +1,76 @@ +package org.implab.gradle.common.exec; + +import java.io.File; +import java.io.IOException; +import java.lang.ProcessBuilder.Redirect; +import java.util.ArrayList; +import java.util.concurrent.CompletableFuture; + +class SystemExec implements Executor { + + private final ProcessBuilder builder = new ProcessBuilder(); + + private RedirectFrom inputRedirect; + + private RedirectTo outputRedirect; + + private RedirectTo errorRedirect; + + @Override + public CompletableFuture start() throws IOException { + // TODO Auto-generated method stub + var tasks = new ArrayList>(); + + // discard stdout if not redirected + if (outputRedirect == null) + builder.redirectOutput(Redirect.DISCARD); + + // discard stderr if not redirected + if (errorRedirect == null) + builder.redirectError(Redirect.DISCARD); + + // run process + var proc = builder.start(); + + tasks.add(proc.onExit()); + + if (inputRedirect != null) + tasks.add(inputRedirect.redirect(proc.getOutputStream())); + + if (outputRedirect != null) + tasks.add(outputRedirect.redirect(proc.getInputStream())); + + if (errorRedirect != null) + tasks.add(errorRedirect.redirect(proc.getErrorStream())); + + return CompletableFuture + .allOf(tasks.toArray(new CompletableFuture[0])) + .thenApply(t -> proc.exitValue()); + } + + public void command(String... args) { + builder.command(args); + } + + public void directory(File workingDir) { + builder.directory(workingDir); + } + + public void stderr(RedirectTo to) { + errorRedirect = to; + } + + public void stdin(RedirectFrom from) { + inputRedirect = from; + } + + public void stdout(RedirectTo to) { + outputRedirect = to; + } + + @Override + public void argument(String arg) { + builder.command().add(arg); + } + +}