com.databasesandlife.util.Executor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-common Show documentation
Show all versions of java-common Show documentation
Utility classes developed at Adrian Smith Software (A.S.S.)
package com.databasesandlife.util;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
/**
* @author This source is copyright Adrian Smith and licensed under the LGPL 3.
* @see Project on GitHub
*/
public class Executor {
/**
* @param command can be String or String[]
* @param currentDirectoryOrNull if not null, what should the 'current directory' of the new process be?
*/
protected static void run(Object command, File currentDirectoryOrNull) {
try {
final String commandForLog;
final Process p;
if (command instanceof String) {
commandForLog = (String)command;
p = Runtime.getRuntime().exec((String)command, null, currentDirectoryOrNull);
}
else if (command instanceof String[]) {
commandForLog = StringUtils.join((String[])command, " ");
p = Runtime.getRuntime().exec((String[])command, null, currentDirectoryOrNull);
}
else throw new RuntimeException("comamnd must be String or String[], is " + command.getClass());
var log = LoggerFactory.getLogger(ProcessStreamReaderRunnable.class);
var stdoutThread = spawnFor(new ProcessStreamReaderRunnable(p.getInputStream(), log::info));
var stderrThread = spawnFor(new ProcessStreamReaderRunnable(p.getErrorStream(), log::error));
stdoutThread.start();
stderrThread.start();
var returnCode = p.waitFor();
if (returnCode != 0) {
throw new ReturnCodeNotZeroException("Return code for command '" + commandForLog + "' is '" + returnCode + "'");
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
public static void run(String[] command, File currentDirectoryOrNull) { run((Object)command, currentDirectoryOrNull); }
public static void run(String command, File currentDirectoryOrNull) { run((Object)command, currentDirectoryOrNull); }
public static void run(String[] command) { run(command, null); }
public static void run(String command) { run(command, null); }
private static Thread spawnFor(Runnable r) {
var t = new Thread(r);
t.setDaemon(true);
return t;
}
public static class ProcessStreamReaderRunnable implements Runnable {
private final InputStream stream;
private final @Nonnull Consumer log;
public ProcessStreamReaderRunnable(InputStream stream, @Nonnull Consumer log) {
this.stream = stream;
this.log = log;
}
@Override
public void run() {
try (var reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
log.accept(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static class ReturnCodeNotZeroException extends RuntimeException {
public ReturnCodeNotZeroException(String message) {
super(message);
}
}
}