code: public static ProcessUtils.ProcessResult exec(String [] args)
      throws IOException {
          Process p = Runtime.getRuntime().exec(args);
          ProcessUtils pu = new ProcessUtils();
          // Gobble up any output.
          StreamGobbler err = pu.new StreamGobbler(p.getErrorStream(), "stderr");
          err.setDaemon(true);
          err.start();
          StreamGobbler out = pu.new StreamGobbler(p.getInputStream(), "stdout");
          out.setDaemon(true);
          out.start();
          int exitVal;
          try {
              exitVal = p.waitFor();
          } catch (InterruptedException e) {
              throw new IOException("Wait on process " + Arrays.toString(args) + " interrupted: "
                  + e.getMessage());
          }
          ProcessUtils.ProcessResult result =
              pu.new ProcessResult(args, exitVal, out.getSink(), err.getSink());
          if (exitVal != 0) {
              throw new IOException(result.toString());
          } else if (LOGGER.isLoggable(Level.INFO)) {
              LOGGER.info(result.toString());
          }
          return result;
      }
docs: Runs process.
  @param args List of process args.
  @return A ProcessResult data structure.
  @throws IOException If interrupted, we throw an IOException. If non-zero
  exit code, we throw an IOException (This may need to change).