- closing _all_ process streams

- allowing multiple accesses to stdout / stderr in O(1)
This commit is contained in:
Sebastian Stenzel
2014-12-16 20:46:48 +01:00
parent 6b45d62aa1
commit 3cdda99c67
3 changed files with 41 additions and 28 deletions

View File

@@ -10,12 +10,10 @@
package org.cryptomator.ui.util.command;
import static java.lang.String.format;
import static org.apache.commons.io.IOUtils.copy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.cryptomator.ui.util.mount.CommandFailedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,59 +23,75 @@ public final class CommandResult {
private static final Logger LOG = LoggerFactory.getLogger(CommandResult.class);
private final Process process;
private final String stdout;
private final String stderr;
private final CommandFailedException exception;
/**
* Constructs a CommandResult from a terminated process and closes all its streams.
* @param process An <strong>already finished</strong> process.
*/
CommandResult(Process process) {
this.process = process;
String out = null;
String err = null;
CommandFailedException ex = null;
try {
out = IOUtils.toString(process.getInputStream());
err = IOUtils.toString(process.getErrorStream());
} catch (IOException e) {
ex = new CommandFailedException(e);
} finally {
this.process = process;
this.stdout = out;
this.stderr = err;
this.exception = ex;
IOUtils.closeQuietly(process.getInputStream());
IOUtils.closeQuietly(process.getOutputStream());
IOUtils.closeQuietly(process.getErrorStream());
logDebugInfo();
}
}
/**
* @return Data written to STDOUT
*/
public String getOutput() throws CommandFailedException {
try (InputStream in = process.getInputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
copy(in, out);
return new String(out.toByteArray());
} catch (IOException e) {
throw new CommandFailedException(e);
}
public String getStdOut() throws CommandFailedException {
assertNoException();
return stdout;
}
/**
* @return Data written to STDERR
*/
public String getError() throws CommandFailedException {
try (InputStream in = process.getErrorStream(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
copy(in, out);
return new String(out.toByteArray());
} catch (IOException e) {
throw new CommandFailedException(e);
}
public String getStdErr() throws CommandFailedException {
assertNoException();
return stderr;
}
/**
* @return Exit value of the process
*/
public int getExitValue() throws CommandFailedException {
public int getExitValue() {
return process.exitValue();
}
void logDebugInfo() {
private void logDebugInfo() {
if (LOG.isDebugEnabled()) {
try {
LOG.debug("Command execution finished. Exit code: {}\n" + "Output:\n" + "{}\n" + "Error:\n" + "{}\n", process.exitValue(), getOutput(), getError());
} catch (CommandFailedException e) {
LOG.debug("Command execution finished. Exit code: {}\n", process.exitValue());
}
LOG.debug("Command execution finished. Exit code: {}\n" + "Output:\n" + "{}\n" + "Error:\n" + "{}\n", process.exitValue(), stdout, stderr);
}
}
void assertOk() throws CommandFailedException {
assertNoException();
int exitValue = getExitValue();
if (exitValue != 0) {
throw new CommandFailedException(format("Command execution failed. Exit code: %d\n" + "# Output:\n" + "%s\n" + "# Error:\n" + "%s", exitValue, getOutput(), getError()));
throw new CommandFailedException(format("Command execution failed. Exit code: %d\n" + "# Output:\n" + "%s\n" + "# Error:\n" + "%s", exitValue, stdout, stderr));
}
}
private void assertNoException() throws CommandFailedException {
if (exception != null) {
throw exception;
}
}

View File

@@ -66,7 +66,6 @@ final class CommandRunner {
final String[] cmds = ArrayUtils.add(determineCli(), line);
final Process proc = Runtime.getRuntime().exec(cmds, env.toArray(new String[0]));
result = run(proc, timeout, unit);
result.logDebugInfo();
result.assertOk();
}
return result;

View File

@@ -39,7 +39,7 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy {
public WebDavMount mount(int localPort) throws CommandFailedException {
final Script mountScript = fromLines("net use * http://0--1.ipv6-literal.net:%PORT% /persistent:no").addEnv("PORT", String.valueOf(localPort));
final CommandResult mountResult = mountScript.execute(30, TimeUnit.SECONDS);
final String driveLetter = getDriveLetter(mountResult.getOutput());
final String driveLetter = getDriveLetter(mountResult.getStdOut());
final Script unmountScript = fromLines("net use " + driveLetter + " /delete").addEnv("DRIVE_LETTER", driveLetter);
return new WebDavMount() {
@Override