@Override
  public Reader diffbl(
      EnumSet<DiffBlOptions> type, String baseline1, String baseline2, String viewPath)
      throws IOException {
    ArgumentListBuilder cmd = new ArgumentListBuilder();
    cmd.add("diffbl");
    if (type != null) {
      for (DiffBlOptions t : type) {
        cmd.add(getOption(t));
      }
    }
    cmd.add(baseline1);
    cmd.add(baseline2);

    // Output to a temporary file since the output can become quite large
    File tmpFile = null;
    try {
      tmpFile = File.createTempFile("cleartool-diffbl", null);
    } catch (IOException e) {
      throw new IOException("Couldn't create a temporary file", e);
    }
    OutputStream out = new FileOutputStream(tmpFile);

    FilePath workingDirectory = launcher.getWorkspace();
    if (viewPath != null) {
      workingDirectory = workingDirectory.child(viewPath);
    }
    try {
      launcher.run(cmd.toCommandArray(), null, out, workingDirectory);
    } catch (IOException e) {
    } catch (InterruptedException e) {
    }
    out.close();
    return new InputStreamReader(new FileInputStream(tmpFile));
  }
  protected String runAndProcessOutput(
      ArgumentListBuilder cmd,
      InputStream in,
      FilePath workFolder,
      boolean catchExceptions,
      List<IOException> exceptions)
      throws IOException, InterruptedException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
      launcher.run(cmd.toCommandArray(), in, baos, workFolder);
    } catch (IOException e) {
      if (!catchExceptions) {
        throw e;
      } else {
        exceptions.add(e);
      }
    }

    BufferedReader reader =
        new BufferedReader(new InputStreamReader(new ByteArrayInputStream(baos.toByteArray())));
    baos.close();
    String line = reader.readLine();
    StringBuilder builder = new StringBuilder();
    while (line != null) {
      if (builder.length() > 0) {
        builder.append("\n");
      }
      builder.append(line);
      line = reader.readLine();
    }
    reader.close();
    return builder.toString();
  }
  public void mkview(String viewPath, String viewTag, String streamSelector)
      throws IOException, InterruptedException {
    Validate.notEmpty(viewPath);
    boolean isOptionalParamContainsHost = false;
    ArgumentListBuilder cmd = new ArgumentListBuilder();
    cmd.add("mkview");
    cmd.add("-snapshot");
    if (streamSelector != null) {
      cmd.add("-stream");
      cmd.add(streamSelector);
    }
    cmd.add("-tag");
    cmd.add(viewTag);

    if ((optionalMkviewParameters != null) && (optionalMkviewParameters.length() > 0)) {
      String variabledResolvedParams =
          Util.replaceMacro(optionalMkviewParameters, this.variableResolver);
      cmd.addTokenized(variabledResolvedParams);
      isOptionalParamContainsHost = optionalMkviewParameters.contains("-host");
    }

    if (!isOptionalParamContainsHost) {
      cmd.add(viewPath);
    }

    launcher.run(cmd.toCommandArray(), null, null, null);
  }
 public void recommendBaseline(String streamSelector) throws IOException, InterruptedException {
   ArgumentListBuilder cmd = new ArgumentListBuilder();
   cmd.add("chstream");
   cmd.add("-rec");
   cmd.add("-def");
   cmd.add(streamSelector);
   launcher.run(cmd.toCommandArray(), null, null, null);
 }
  public void unlock(String comment, String objectSelector)
      throws IOException, InterruptedException {
    ArgumentListBuilder cmd = new ArgumentListBuilder();

    cmd.add("unlock");
    cmd.add(objectSelector);

    launcher.run(cmd.toCommandArray(), null, null, null);
  }
 public void rebaseDynamic(String viewTag, String baseline)
     throws IOException, InterruptedException {
   ArgumentListBuilder cmd = new ArgumentListBuilder();
   cmd.add("rebase");
   cmd.add("-baseline", baseline);
   cmd.add("-view", viewTag);
   cmd.add("-complete");
   cmd.add("-force");
   launcher.run(cmd.toCommandArray(), null, null, null);
 }
  private void setcs(String viewTag, String viewPath, SetcsOption option, String configSpec)
      throws IOException, InterruptedException {
    if (option == SetcsOption.CONFIGSPEC) {
      Validate.notNull(
          configSpec, "Using option CONFIGSPEC, you must provide a non-null config spec");
    } else {
      Validate.isTrue(
          configSpec == null, "Not using option CONFIGSPEC, you must provide a null config spec");
    }
    ArgumentListBuilder cmd = new ArgumentListBuilder();
    cmd.add("setcs");
    if (viewTag != null) {
      cmd.add("-tag");
      cmd.add(viewTag);
    }
    String optionStr = getOption(option);
    if (optionStr != null) {
      cmd.add(optionStr);
    }
    FilePath configSpecFile = null;
    if (option == SetcsOption.CONFIGSPEC) {
      configSpecFile = launcher.getWorkspace().createTextTempFile("configspec", ".txt", configSpec);
      cmd.add(
          PathUtil.convertPathForOS(
              configSpecFile.absolutize().getRemote(), launcher.getLauncher().isUnix()));
    }
    FilePath workingDirectory = null;
    if (viewPath != null) {
      workingDirectory = new FilePath(getRootViewPath(launcher), viewPath);
    }
    String output =
        runAndProcessOutput(
            cmd, new ByteArrayInputStream("yes".getBytes()), workingDirectory, false, null);
    if (configSpecFile != null) {
      configSpecFile.delete();
    }

    if (output.contains("cleartool: Warning: An update is already in progress for view")) {
      throw new IOException("View update failed: " + output);
    }
  }
  public boolean doesViewExist(String viewTag) throws IOException, InterruptedException {
    ArgumentListBuilder cmd = new ArgumentListBuilder();
    cmd.add("lsview");
    cmd.add(viewTag);

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
      return launcher.run(cmd.toCommandArray(), null, baos, null);
    } catch (IOException e) {
      return false;
    }
  }
  public List<String> lsvob(boolean onlyMounted) throws IOException, InterruptedException {
    viewListPattern = getListPattern();
    ArgumentListBuilder cmd = new ArgumentListBuilder();
    cmd.add("lsvob");

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    if (launcher.run(cmd.toCommandArray(), null, baos, null)) {
      return parseListOutput(
          new InputStreamReader(new ByteArrayInputStream(baos.toByteArray())), onlyMounted);
    }
    return new ArrayList<String>();
  }
  public void rmview(String viewPath) throws IOException, InterruptedException {
    ArgumentListBuilder cmd = new ArgumentListBuilder();
    cmd.add("rmview");
    cmd.add("-force");
    cmd.add(viewPath);

    FilePath workspace = launcher.getWorkspace();
    String output = runAndProcessOutput(cmd, null, workspace, false, null);

    if (output.contains("cleartool: Error")) {
      throw new IOException("Failed to remove view: " + output);
    }

    FilePath viewFilePath = workspace.child(viewPath);
    if (viewFilePath.exists()) {
      launcher
          .getListener()
          .getLogger()
          .println("Removing view folder as it was not removed when the view was removed.");
      viewFilePath.deleteRecursive();
    }
  }
  public void mkstream(String parentStream, String stream)
      throws IOException, InterruptedException {
    ArgumentListBuilder cmd = new ArgumentListBuilder();

    cmd.add("mkstream");
    cmd.add("-in");
    cmd.add(parentStream);
    cmd.add(stream);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    launcher.run(cmd.toCommandArray(), null, baos, null);
    baos.close();
  }
  @Override
  public Reader lshistory(
      String format,
      Date lastBuildDate,
      String viewPath,
      String branch,
      String[] pathsInView,
      boolean getMinor)
      throws IOException, InterruptedException {
    Validate.notNull(pathsInView);
    Validate.notNull(viewPath);
    SimpleDateFormat formatter = new SimpleDateFormat("d-MMM-yy.HH:mm:ss'UTC'Z", Locale.US);
    formatter.setTimeZone(TimeZone.getTimeZone("UTC"));

    ArgumentListBuilder cmd = new ArgumentListBuilder();
    cmd.add("lshistory");
    cmd.add("-all");
    cmd.add("-since", formatter.format(lastBuildDate).toLowerCase());
    cmd.add("-fmt", format);
    // cmd.addQuoted(format);
    if (StringUtils.isNotEmpty(branch)) {
      cmd.add("-branch", "brtype:" + branch);
    }
    if (getMinor) {
      cmd.add("-minor");
    }
    cmd.add("-nco");

    FilePath filePath = getRootViewPath(launcher).child(viewPath);

    for (String path : pathsInView) {
      path = path.replace("\n", "").replace("\r", "");
      if (path.matches(".*\\s.*")) {
        cmd.addQuoted(path);
      } else {
        cmd.add(path);
      }
    }
    Reader returnReader = null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
      launcher.run(cmd.toCommandArray(), null, baos, filePath);
    } catch (IOException e) {
      // We don't care if Clearcase returns an error code, we will process it afterwards
    }
    returnReader = new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()));
    baos.close();

    return returnReader;
  }
  public void mountVobs() throws IOException, InterruptedException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ArgumentListBuilder cmd = new ArgumentListBuilder();
    cmd.add("mount");
    cmd.add("-all");

    try {
      launcher.run(cmd.toCommandArray(), null, baos, null);
    } catch (IOException ex) {
      logRedundantCleartoolError(cmd.toCommandArray(), ex);
    } finally {
      baos.close();
    }
  }
 @Override
 public Reader describe(String format, String objectSelectors)
     throws IOException, InterruptedException {
   Validate.notNull(objectSelectors);
   ArgumentListBuilder cmd = new ArgumentListBuilder();
   cmd.add("desc");
   if (StringUtils.isNotBlank(format)) {
     cmd.add("-fmt", format);
   }
   cmd.addTokenized(objectSelectors);
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   launcher.run(cmd.toCommandArray(), null, baos, null);
   Reader reader = new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()));
   baos.close();
   return reader;
 }
  public Reader lsactivity(String activity, String commandFormat, String viewPath)
      throws IOException, InterruptedException {
    ArgumentListBuilder cmd = new ArgumentListBuilder();
    cmd.add("lsactivity");
    cmd.add("-fmt", commandFormat);
    cmd.add(activity);

    // changed the path from workspace to getRootViewPath to make Dynamic UCM work
    FilePath filePath = getRootViewPath(launcher).child(viewPath);

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    launcher.run(cmd.toCommandArray(), null, baos, filePath);
    InputStreamReader reader = new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()));
    baos.close();
    return reader;
  }
  public boolean lock(String comment, String objectSelector)
      throws IOException, InterruptedException {
    ArgumentListBuilder cmd = new ArgumentListBuilder();

    cmd.add("lock");
    cmd.add(objectSelector);

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    launcher.run(cmd.toCommandArray(), null, baos, null);
    String cleartoolResult = baos.toString();
    if (cleartoolResult.contains("cleartool: Error")) {
      return false;
    }
    baos.close();
    return true;
  }
  @Override
  public boolean doesStreamExist(String streamSelector) throws IOException, InterruptedException {
    ArgumentListBuilder cmd = new ArgumentListBuilder();

    cmd.add("lsstream");
    cmd.add("-short");
    cmd.add(streamSelector);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    try {
      launcher.run(cmd.toCommandArray(), null, baos, null);
    } catch (Exception e) {
      // empty by design
    }
    baos.close();
    String cleartoolResult = baos.toString();
    return !(cleartoolResult.contains("stream not found"));
  }
  public String lsproject(String viewTag, String format) throws InterruptedException, IOException {
    ArgumentListBuilder cmd = new ArgumentListBuilder();
    cmd.add("lsproject");
    cmd.add("-view");
    cmd.add(viewTag);
    if (StringUtils.isNotEmpty(format)) {
      cmd.add("-fmt");
      cmd.add(format);
    }
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
      launcher.run(cmd.toCommandArray(), null, baos, null);
    } catch (IOException e) {
      // We don't care if Clearcase returns an error code, we will process it afterwards
    }
    String output = baos.toString();
    baos.close();

    return output;
  }
  /** for dynamic views : viewPath == viewTag */
  public void mkview(
      String viewPath, String viewTag, String streamSelector, String defaultStorageDir)
      throws IOException, InterruptedException {
    ArgumentListBuilder cmd = new ArgumentListBuilder();

    cmd.add("mkview");
    if (streamSelector != null) {
      cmd.add("-stream");
      cmd.add(streamSelector);
    }
    cmd.add("-tag");
    cmd.add(viewTag);

    boolean isOptionalParamContainsHost = false;
    if (StringUtils.isNotEmpty(optionalMkviewParameters)) {
      String variabledResolvedParams =
          Util.replaceMacro(optionalMkviewParameters, this.variableResolver);
      cmd.addTokenized(variabledResolvedParams);
      isOptionalParamContainsHost = optionalMkviewParameters.contains("-host");
    }

    // add the default storage directory only if gpath/hpath are not set (only for windows)
    if (!isOptionalParamContainsHost && StringUtils.isNotEmpty(defaultStorageDir)) {
      String separator = PathUtil.fileSepForOS(getLauncher().getLauncher().isUnix());
      String viewStorageDir = defaultStorageDir + separator + viewTag;
      String base = viewStorageDir;
      FilePath fp = new FilePath(getLauncher().getLauncher().getChannel(), viewStorageDir);
      int i = 1;
      while (fp.exists()) {
        viewStorageDir = base + "." + i++;
        fp = new FilePath(getLauncher().getLauncher().getChannel(), viewStorageDir);
        if (i == Integer.MAX_VALUE) {
          throw new IOException("Cannot determine a view storage dir.");
        }
      }
      cmd.add(viewStorageDir);
    }

    launcher.run(cmd.toCommandArray(), null, null, null);
  }
 @Override
 protected FilePath getRootViewPath(ClearToolLauncher launcher) {
   return new FilePath(launcher.getWorkspace().getChannel(), viewDrive);
 }
 public void startView(String viewTags) throws IOException, InterruptedException {
   ArgumentListBuilder cmd = new ArgumentListBuilder();
   cmd.add("startview");
   cmd.addTokenized(viewTags);
   launcher.run(cmd.toCommandArray(), null, null, null);
 }