From 9be830786c74f8a1207064476bec728fb8d38cdf Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 27 Oct 2015 01:44:49 +0100 Subject: [PATCH] Cleaned up process std i/o. Changed where/how flushing runs when finished. Added better docs. Added getOutput() to safely convert baos to string --- .../dorkbox/util/process/ProcessProxy.java | 27 ++++---- .../util/process/ShellProcessBuilder.java | 67 ++++++++++++++++--- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/Dorkbox-Util/src/dorkbox/util/process/ProcessProxy.java b/Dorkbox-Util/src/dorkbox/util/process/ProcessProxy.java index b389a89..c3a35b8 100644 --- a/Dorkbox-Util/src/dorkbox/util/process/ProcessProxy.java +++ b/Dorkbox-Util/src/dorkbox/util/process/ProcessProxy.java @@ -38,6 +38,9 @@ class ProcessProxy extends Thread { public void close() { try { + if (os != null) { + os.flush(); // this goes to the console, so we don't want to close it! + } this.is.close(); } catch (IOException e) { } @@ -46,33 +49,29 @@ class ProcessProxy extends Thread { @Override public void run() { + final OutputStream os = this.os; + try { // this thread will read until there is no more data to read. (this is generally what you want) // the stream will be closed when the process closes it (usually on exit) int readInt; - if (this.os == null) { + if (os == null) { // just read so it won't block. while ((readInt = this.is.read()) != -1) { } } else { while ((readInt = this.is.read()) != -1) { - this.os.write(readInt); - // always flush - this.os.flush(); + os.write(readInt); + + // flush the output on new line. + if (readInt == '\n') { + os.flush(); + } } } - } catch (IOException ignore) { - } catch (IllegalArgumentException e) { - } finally { - try { - if (this.os != null) { - this.os.flush(); // this goes to the console, so we don't want to close it! - } - this.is.close(); - } catch (IOException ignore) { - } + } catch (Exception ignore) { } } } diff --git a/Dorkbox-Util/src/dorkbox/util/process/ShellProcessBuilder.java b/Dorkbox-Util/src/dorkbox/util/process/ShellProcessBuilder.java index f3428d3..064b769 100644 --- a/Dorkbox-Util/src/dorkbox/util/process/ShellProcessBuilder.java +++ b/Dorkbox-Util/src/dorkbox/util/process/ShellProcessBuilder.java @@ -17,6 +17,7 @@ package dorkbox.util.process; import dorkbox.util.OS; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.InputStream; import java.io.PrintStream; @@ -26,10 +27,14 @@ import java.util.List; /** * If you want to save off the output from the process, set a PrintStream to the following: + *
 {@code
+ *
  * ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(8196);
  * PrintStream outputStream = new PrintStream(byteArrayOutputStream);
  * ...
- * String output = byteArrayOutputStream.toString();
+ *
+ * String output = ShellProcessBuilder.getOutput(byteArrayOutputStream);
+ * }
*/ public class ShellProcessBuilder { @@ -37,6 +42,7 @@ class ShellProcessBuilder { private final PrintStream outputStream; private final PrintStream errorStream; private final InputStream inputStream; + protected List arguments = new ArrayList(); private String workingDirectory = null; private String executableName = null; @@ -66,9 +72,9 @@ class ShellProcessBuilder { public ShellProcessBuilder(InputStream in, PrintStream out, PrintStream err) { + this.inputStream = in; this.outputStream = out; this.errorStream = err; - this.inputStream = in; } /** @@ -188,16 +194,33 @@ class ShellProcessBuilder { } if (this.debugInfo) { - this.errorStream.print("Executing: "); + if (errorStream != null) { + this.errorStream.print("Executing: "); + } else { + System.err.println("Executing: "); + } Iterator iterator = argumentsList.iterator(); while (iterator.hasNext()) { String s = iterator.next(); - this.errorStream.print(s); + if (errorStream != null) { + this.errorStream.print(s); + } else { + System.err.print(s); + } if (iterator.hasNext()) { - this.errorStream.print(" "); + if (errorStream != null) { + this.errorStream.print(" "); + } else { + System.err.print(" "); + } } } - this.errorStream.print(OS.LINE_SEPARATOR); + + if (errorStream != null) { + this.errorStream.print(OS.LINE_SEPARATOR); + } else { + System.err.print(OS.LINE_SEPARATOR); + } } ProcessBuilder processBuilder = new ProcessBuilder(argumentsList); @@ -213,7 +236,11 @@ class ShellProcessBuilder { try { this.process = processBuilder.start(); } catch (Exception ex) { - this.errorStream.println("There was a problem executing the program. Details:\n"); + if (errorStream != null) { + this.errorStream.println("There was a problem executing the program. Details:"); + } else { + System.err.println("There was a problem executing the program. Details:"); + } ex.printStackTrace(this.errorStream); if (this.process != null) { @@ -221,7 +248,11 @@ class ShellProcessBuilder { this.process.destroy(); this.process = null; } catch (Exception e) { - this.errorStream.println("Error destroying process: \n"); + if (errorStream != null) { + this.errorStream.println("Error destroying process:"); + } else { + System.err.println("Error destroying process:"); + } e.printStackTrace(this.errorStream); } } @@ -255,6 +286,7 @@ class ShellProcessBuilder { readFromProcess_output = new ProcessProxy("Process Reader: " + this.executableName, this.process.getInputStream(), this.outputStream); + if (this.errorStream != this.outputStream) { readFromProcess_error = new ProcessProxy("Process Reader: " + this.executableName, this.process.getErrorStream(), @@ -338,4 +370,23 @@ class ShellProcessBuilder { .removeShutdownHook(hook); } } + + /** + * Converts the baos to a string in a safe way. There might be a trailing newline character at the end of this output. + * + * @param byteArrayOutputStream the baos that is used in the {@link ShellProcessBuilder#ShellProcessBuilder(PrintStream)} (or similar + * calls) + * + * @return A string representing the output of the process + */ + public static + String getOutput(final ByteArrayOutputStream byteArrayOutputStream) { + String s; + synchronized (byteArrayOutputStream) { + s = byteArrayOutputStream.toString(); + byteArrayOutputStream.reset(); + } + + return s; + } }