1
0
mirror of https://github.com/mitb-archive/filebot synced 2024-08-13 17:03:45 -04:00

Refactor system exec

This commit is contained in:
Reinhard Pointner 2019-03-15 14:19:00 +07:00
parent 45528ef212
commit 3fa0530da9
6 changed files with 124 additions and 74 deletions

View File

@ -0,0 +1,85 @@
package net.filebot;
import static java.nio.charset.StandardCharsets.*;
import static java.util.Arrays.*;
import static java.util.stream.Collectors.*;
import static net.filebot.Logging.*;
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.util.List;
import net.filebot.util.ByteBufferOutputStream;
public class Execute {
private static final int BUFFER_SIZE = 8 * 1024;
public static CharSequence execute(String... command) throws IOException {
return execute(asList(command), null);
}
public static CharSequence execute(String[] command, File directory) throws IOException {
return execute(asList(command), directory);
}
public static CharSequence execute(String[]... command) throws IOException {
return execute(stream(command).flatMap(a -> stream(a)).collect(toList()), null);
}
public static CharSequence execute(List<String> command, File directory) throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectError(Redirect.INHERIT);
if (directory != null) {
processBuilder.directory(directory);
}
Process process = processBuilder.start();
try (ByteBufferOutputStream bb = new ByteBufferOutputStream(BUFFER_SIZE)) {
bb.transferFully(process.getInputStream());
int exitCode = process.waitFor();
CharSequence output = UTF_8.decode(bb.getByteBuffer());
// DEBUG
debug.finest(format("Execute %s%n%s", command, output));
if (exitCode != 0) {
throw new ExecuteException(command, exitCode);
}
return output;
} catch (InterruptedException e) {
throw new IOException(String.format("%s timed out", command), e);
}
}
public static void system(String[] command, File directory) throws IOException {
system(asList(command), directory);
}
public static void system(List<String> command, File directory) throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.inheritIO();
if (directory != null) {
processBuilder.directory(directory);
}
// DEBUG
debug.finest(format("Execute %s", command));
try {
int exitCode = processBuilder.start().waitFor();
if (exitCode != 0) {
throw new ExecuteException(command, exitCode);
}
} catch (InterruptedException e) {
throw new IOException(String.format("%s timed out", command), e);
}
}
}

View File

@ -0,0 +1,23 @@
package net.filebot;
import java.io.IOException;
import java.util.List;
public class ExecuteException extends IOException {
private int exitCode;
public ExecuteException(String message, int exitCode) {
super(message);
this.exitCode = exitCode;
}
public ExecuteException(List<String> command, int exitCode) {
this(String.format("%s failed with exit code %d", command, exitCode), exitCode);
}
public int getExitCode() {
return exitCode;
}
}

View File

@ -1,20 +1,16 @@
package net.filebot.archive;
import static java.nio.charset.StandardCharsets.*;
import static java.util.Arrays.*;
import static java.util.stream.Collectors.*;
import static net.filebot.Logging.*;
import static net.filebot.Execute.*;
import static net.filebot.util.RegularExpressions.*;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.util.List;
import java.util.regex.Pattern;
import net.filebot.util.ByteBufferOutputStream;
import net.filebot.util.FileUtilities.ExtensionFileFilter;
import net.filebot.vfs.FileInfo;
import net.filebot.vfs.SimpleFileInfo;
@ -48,37 +44,10 @@ public class ShellExecutables implements ArchiveExtractor {
command.extract(archive, outputFolder.getCanonicalFile(), filter);
}
protected static Command getCommand(File archive) {
protected Command getCommand(File archive) {
return RAR_FILES.accept(archive) ? Command.unrar : Command.p7zip;
}
protected static CharSequence execute(String[]... command) throws IOException {
return execute(stream(command).flatMap(a -> stream(a)).toArray(String[]::new));
}
protected static CharSequence execute(String... command) throws IOException {
Process process = new ProcessBuilder(command).redirectError(Redirect.INHERIT).start();
try (ByteBufferOutputStream bb = new ByteBufferOutputStream(8 * 1024)) {
bb.transferFully(process.getInputStream());
int returnCode = process.waitFor();
String output = UTF_8.decode(bb.getByteBuffer()).toString();
// DEBUG
debug.fine(format("Execute: %s", asList(command)));
debug.finest(output);
if (returnCode == 0) {
return output;
} else {
throw new IOException(String.format("%s failed with exit code %d: %s", asList(command), returnCode, output.trim()));
}
} catch (InterruptedException e) {
throw new IOException(String.format("%s timed out", asList(command)), e);
}
}
public enum Command {
p7zip {

View File

@ -1,6 +1,7 @@
package net.filebot.cli;
import static java.util.stream.Collectors.*;
import static net.filebot.Execute.*;
import static net.filebot.Logging.*;
import java.io.File;
@ -28,7 +29,7 @@ public class ExecCommand {
this.directory = directory;
}
public void execute(MediaBindingBean... group) throws IOException, InterruptedException {
public void execute(MediaBindingBean... group) throws IOException {
if (parallel) {
executeParallel(group);
} else {
@ -36,7 +37,7 @@ public class ExecCommand {
}
}
private void executeSequence(MediaBindingBean... group) throws IOException, InterruptedException {
private void executeSequence(MediaBindingBean... group) throws IOException {
// collect unique commands
List<List<String>> commands = Stream.of(group).map(v -> {
return template.stream().map(t -> getArgumentValue(t, v)).filter(Objects::nonNull).collect(toList());
@ -44,18 +45,18 @@ public class ExecCommand {
// execute unique commands
for (List<String> command : commands) {
execute(command);
system(command, directory);
}
}
private void executeParallel(MediaBindingBean... group) throws IOException, InterruptedException {
private void executeParallel(MediaBindingBean... group) throws IOException {
// collect single command
List<String> command = template.stream().flatMap(t -> {
return Stream.of(group).map(v -> getArgumentValue(t, v)).filter(Objects::nonNull).distinct();
}).collect(toList());
// execute single command
execute(command);
system(command, directory);
}
private String getArgumentValue(ExpressionFormat template, MediaBindingBean variables) {
@ -67,19 +68,6 @@ public class ExecCommand {
return null;
}
private void execute(List<String> command) throws IOException, InterruptedException {
ProcessBuilder process = new ProcessBuilder(command);
process.directory(directory);
process.inheritIO();
debug.finest(format("Execute %s", command));
int exitCode = process.start().waitFor();
if (exitCode != 0) {
throw new IOException(String.format("%s failed with exit code %d", command, exitCode));
}
}
public static ExecCommand parse(List<String> args, File directory) throws ScriptException {
// execute one command per file or one command with many file arguments
boolean parallel = args.lastIndexOf("+") == args.size() - 1;

View File

@ -1,7 +1,8 @@
package net.filebot.cli;
import static net.filebot.Execute.*;
import java.io.File;
import java.io.IOException;
import net.filebot.RenameAction;
@ -17,14 +18,9 @@ public class ExecutableRenameAction implements RenameAction {
@Override
public File rename(File from, File to) throws Exception {
ProcessBuilder process = new ProcessBuilder(executable, from.getCanonicalPath(), getRelativePath(directory, to));
process.directory(directory);
process.inheritIO();
String[] command = { executable, from.getCanonicalPath(), getRelativePath(directory, to) };
int exitCode = process.start().waitFor();
if (exitCode != 0) {
throw new IOException(String.format("%s failed with exit code %d", process.command(), exitCode));
}
system(command, directory);
return null;
}

View File

@ -3,10 +3,10 @@ package net.filebot.media;
import static java.util.Arrays.*;
import static java.util.Collections.*;
import static java.util.stream.Collectors.*;
import static net.filebot.Execute.*;
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
@ -25,23 +25,12 @@ public class FFProbe implements MediaCharacteristics {
}
protected Map<String, Object> parse(File file) throws IOException, InterruptedException {
ProcessBuilder processBuilder = new ProcessBuilder(getFFProbeCommand(), "-show_streams", "-show_format", "-print_format", "json", "-v", "error", file.getCanonicalPath());
String[] command = { getFFProbeCommand(), "-show_streams", "-show_format", "-print_format", "json", "-v", "error", file.getCanonicalPath() };
processBuilder.directory(file.getParentFile());
processBuilder.redirectError(Redirect.INHERIT);
Process process = processBuilder.start();
CharSequence output = execute(command, file.getParentFile());
// parse process standard output
Map<String, Object> json = (Map) JsonReader.jsonToJava(process.getInputStream(), singletonMap(JsonReader.USE_MAPS, true));
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new IOException(String.format("%s failed with exit code %d", processBuilder.command(), exitCode));
}
// group video / audio / subtitle streams together
return json;
return (Map) JsonReader.jsonToJava(output.toString(), singletonMap(JsonReader.USE_MAPS, true));
}
private Map<String, Object> json;