/**
   * **************************************************
   *
   * <p>private int joinWithPossibleTimeout(ProcStarter proc, final TaskListener listener,
   * StringBuffer strBuf, AbstractBuild currentBuild) throws IOException, InterruptedException
   *
   * <p>**************************************************
   */
  protected int joinWithPossibleTimeout(
      ProcStarter proc,
      final TaskListener listener,
      StringBuffer strBuf,
      AbstractBuild currentBuild,
      String stringToHide)
      throws IOException, InterruptedException {
    boolean useTimeout = configuration.isUseTimeout();
    long timeoutValue = configuration.getTimeoutValue();

    int result = -1;

    try {
      PipedInputStream pis = null;
      if (strBuf != null) {
        PipedOutputStream pos = new PipedOutputStream();
        pis = new PipedInputStream(pos, 1000000);
        proc = proc.stdout(pos);
      }

      hudson.Proc procStarted = proc.start();
      if (useTimeout) {
        result = procStarted.joinWithTimeout(timeoutValue, TimeUnit.SECONDS, listener);
      } else {
        result = procStarted.join();
      }

      if (strBuf != null) {
        byte[] stdoutDataArr = new byte[pis.available()];
        pis.read(stdoutDataArr, 0, stdoutDataArr.length);
        String stdoutStr = new String(stdoutDataArr);
        if (stringToHide != null) {
          stdoutStr = stdoutStr.replaceAll(stringToHide, "****");
        }
        strBuf.append(stdoutStr);
        PrintStream output = listener.getLogger();
        output.println(stdoutStr);
      }
    } catch (InterruptedException e) {
      throw e;
    } catch (Exception e) {
      if (listener != null) {
        listener.error("Exception caught in joinWithPossibleTimeout: " + e);
      }
    }

    return result;
  } // End: joinWithPossibleTimeout(...)
  /**
   * **************************************************
   *
   * <p>private ByteArrayOutputStream popen(ArgumentListBuilder args)
   *
   * <p>Runs the command and captures the output.
   *
   * <p>**************************************************
   */
  private ByteArrayOutputStream popen(ArgumentListBuilder args, String jazzExecutable)
      throws IOException, InterruptedException {
    try {

      // scm produces text in the platform default encoding, so we need to convert it back to UTF-8
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      WriterOutputStream o =
          new WriterOutputStream(
              new OutputStreamWriter(baos, "UTF-8"), java.nio.charset.Charset.forName("UTF-8"));

      PrintStream output = listener.getLogger();

      ForkOutputStream fos = new ForkOutputStream(o, output);
      ProcStarter pstarter = run(args, jazzExecutable);

      if (joinWithPossibleTimeout(pstarter.stdout(fos), listener, null) == 0) {
        o.flush();
        return baos;
      } else {
        String errorString = "Failed to run ";
        boolean[] maskArray = args.toMaskArray();
        String[] cmdArray = args.toCommandArray();

        for (int i = 0; i < maskArray.length; i++) {
          if (maskArray[i] == false) {
            errorString += cmdArray[i] + " ";
          } else {
            errorString += "**** ";
          }
        }

        listener.error(errorString);
        throw new AbortException();
      }
    } catch (Exception e) {
      listener.error("Exception in popen " + e);
      throw new AbortException();
    }
  }