private FilePath saveFullReport(FilePath workspace, File rootDir, String simulationName)
      throws IOException, InterruptedException {
    FilePath[] files = workspace.list("**/" + simulationName + "*/index.html");
    FilePath parent = files[0].getParent();

    File allSimulationsDirectory = new File(rootDir, "simulations");
    if (!allSimulationsDirectory.exists()) allSimulationsDirectory.mkdir();

    File simulationDirectory = new File(allSimulationsDirectory, simulationName);
    simulationDirectory.mkdir();

    FilePath reportDirectory = new FilePath(simulationDirectory);

    parent.copyRecursiveTo(reportDirectory);

    return reportDirectory;
  }
  @LocalData
  @Test
  public void slave() throws Exception {
    Assume.assumeFalse(
        "TimeoutException from basic",
        "https://jenkins.ci.cloudbees.com/job/core/job/jenkins_main_trunk/"
            .equals(System.getenv("JOB_URL")));
    DumbSlave s = j.createOnlineSlave();
    project.setAssignedLabel(s.getSelfLabel());

    FilePath src = new FilePath(j.jenkins.getRootPath(), "jobs/junit/workspace/");
    assertNotNull(src);
    FilePath dest = s.getWorkspaceFor(project);
    assertNotNull(dest);
    src.copyRecursiveTo("*.xml", dest);

    basic();
  }
  @Override
  public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener)
      throws InterruptedException, IOException {
    EnvVars env = build.getEnvironment(listener);
    env.overrideAll(build.getBuildVariables());

    if (Computer.currentComputer() instanceof SlaveComputer) {
      FilePath destinationFilePath;
      if (isOverrideDestinationFolder() && StringUtils.isNotBlank(getDestinationFolder())) {
        destinationFilePath = new FilePath(new File(env.expand(getDestinationFolder())));
      } else {
        destinationFilePath =
            CopyToSlaveUtils.getProjectWorkspaceOnMaster(build, listener.getLogger());
      }

      FilePath projectWorkspaceOnSlave = build.getProject().getWorkspace();

      String includes = env.expand(getIncludes());
      String excludes = env.expand(getExcludes());

      listener
          .getLogger()
          .printf(
              "[copy-to-slave] Copying '%s', excluding %s, from '%s' on '%s' to '%s' on the master.\n",
              includes,
              StringUtils.isBlank(excludes) ? "nothing" : '\'' + excludes + '\'',
              projectWorkspaceOnSlave.toURI(),
              Computer.currentComputer().getNode(),
              destinationFilePath.toURI());

      projectWorkspaceOnSlave.copyRecursiveTo(includes, excludes, destinationFilePath);
    } else if (Computer.currentComputer() instanceof MasterComputer) {
      listener
          .getLogger()
          .println(
              "[copy-to-slave] The build is taking place on the master node, no copy back to the master will take place.");
    }

    return true;
  }
  @Override
  public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
      throws IOException, InterruptedException {

    listener.getLogger().println("[CucumberReportPublisher] Compiling Cucumber Html Reports ...");

    File workspaceJsonReportDirectory = new File(build.getWorkspace().toURI().getPath());
    if (!jsonReportDirectory.isEmpty()) {
      workspaceJsonReportDirectory =
          new File(build.getWorkspace().toURI().getPath(), jsonReportDirectory);
    }
    File targetBuildDirectory = new File(build.getRootDir(), "cucumber-html-reports");

    String buildNumber = Integer.toString(build.getNumber());
    String buildProject = build.getProject().getName();

    if (!targetBuildDirectory.exists()) {
      targetBuildDirectory.mkdirs();
    }

    boolean buildResult = true;

    // if we are on a slave
    if (Computer.currentComputer() instanceof SlaveComputer) {
      listener
          .getLogger()
          .println("[CucumberReportPublisher] detected this build is running on a slave ");
      FilePath projectWorkspaceOnSlave = build.getProject().getSomeWorkspace();
      FilePath masterJsonReportDirectory = new FilePath(targetBuildDirectory);
      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] copying json from: "
                  + projectWorkspaceOnSlave.toURI()
                  + "to reports directory: "
                  + masterJsonReportDirectory.toURI());
      projectWorkspaceOnSlave.copyRecursiveTo("**/*.json", "", masterJsonReportDirectory);
    } else {
      // if we are on the master
      listener
          .getLogger()
          .println("[CucumberReportPublisher] detected this build is running on the master ");
      String[] files = findJsonFiles(workspaceJsonReportDirectory);

      if (files.length != 0) {
        listener
            .getLogger()
            .println(
                "[CucumberReportPublisher] copying json to reports directory: "
                    + targetBuildDirectory);
        for (String file : files) {
          FileUtils.copyFile(
              new File(workspaceJsonReportDirectory.getPath() + "/" + file),
              new File(targetBuildDirectory, file));
        }
      } else {
        listener
            .getLogger()
            .println(
                "[CucumberReportPublisher] there were no json results found in: "
                    + workspaceJsonReportDirectory);
      }
    }

    // generate the reports from the targetBuildDirectory
    String[] jsonReportFiles = findJsonFiles(targetBuildDirectory);
    if (jsonReportFiles.length != 0) {

      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] Found the following number of json files: "
                  + jsonReportFiles.length);
      int jsonIndex = 0;
      for (String jsonReportFile : jsonReportFiles) {
        listener
            .getLogger()
            .println(
                "[CucumberReportPublisher] "
                    + jsonIndex
                    + ". Found a json file: "
                    + jsonReportFile);
        jsonIndex++;
      }
      listener.getLogger().println("[CucumberReportPublisher] Generating HTML reports");

      try {
        ReportBuilder reportBuilder =
            new ReportBuilder(
                fullPathToJsonFiles(jsonReportFiles, targetBuildDirectory),
                targetBuildDirectory,
                pluginUrlPath,
                buildNumber,
                buildProject,
                skippedFails,
                undefinedFails,
                !noFlashCharts,
                true,
                false,
                "",
                false);
        reportBuilder.generateReports();
        buildResult = reportBuilder.getBuildStatus();
      } catch (Exception e) {
        e.printStackTrace();
        listener
            .getLogger()
            .println("[CucumberReportPublisher] there was an error generating the reports: " + e);
        for (StackTraceElement error : e.getStackTrace()) {
          listener.getLogger().println(error);
        }
      }
    } else {
      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] there were no json results found in: "
                  + targetBuildDirectory);
    }

    build.addAction(new CucumberReportBuildAction(build));
    return buildResult;
  }
  @Override
  public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
      throws InterruptedException {
    listener.getLogger().println("[htmlpublisher] Archiving HTML reports...");

    // Grab the contents of the header and footer as arrays
    ArrayList<String> headerLines;
    ArrayList<String> footerLines;
    try {
      headerLines = this.readFile("/htmlpublisher/HtmlPublisher/header.html");
      footerLines = this.readFile("/htmlpublisher/HtmlPublisher/footer.html");
    } catch (FileNotFoundException e1) {
      e1.printStackTrace();
      return false;
    } catch (IOException e1) {
      e1.printStackTrace();
      return false;
    }

    for (int i = 0; i < this.reportTargets.size(); i++) {
      // Create an array of lines we will eventually write out, initially the header.
      ArrayList<String> reportLines = new ArrayList<String>(headerLines);
      HtmlPublisherTarget reportTarget = this.reportTargets.get(i);
      boolean keepAll = reportTarget.getKeepAll();

      FilePath archiveDir =
          build
              .getWorkspace()
              .child(resolveParametersInString(build, listener, reportTarget.getReportDir()));
      FilePath targetDir = reportTarget.getArchiveTarget(build);

      String levelString = keepAll ? "BUILD" : "PROJECT";
      listener
          .getLogger()
          .println(
              "[htmlpublisher] Archiving at "
                  + levelString
                  + " level "
                  + archiveDir
                  + " to "
                  + targetDir);

      // The index name might be a comma separated list of names, so let's figure out all the pages
      // we should index.
      String[] csvReports =
          resolveParametersInString(build, listener, reportTarget.getReportFiles()).split(",");
      ArrayList<String> reports = new ArrayList<String>();
      for (int j = 0; j < csvReports.length; j++) {
        String report = csvReports[j];
        report = report.trim();

        // Ignore blank report names caused by trailing or double commas.
        if (report.equals("")) {
          continue;
        }

        reports.add(report);
        String tabNo = "tab" + (j + 1);
        // Make the report name the filename without the extension.
        int end = report.lastIndexOf(".");
        String reportName;
        if (end > 0) {
          reportName = report.substring(0, end);
        } else {
          reportName = report;
        }
        String tabItem =
            "<li id=\""
                + tabNo
                + "\" class=\"unselected\" onclick=\"updateBody('"
                + tabNo
                + "');\" value=\""
                + report
                + "\">"
                + reportName
                + "</li>";
        reportLines.add(tabItem);
      }
      // Add the JS to change the link as appropriate.
      String hudsonUrl = Hudson.getInstance().getRootUrl();
      AbstractProject job = build.getProject();
      reportLines.add(
          "<script type=\"text/javascript\">document.getElementById(\"hudson_link\").innerHTML=\"Back to "
              + job.getName()
              + "\";</script>");
      // If the URL isn't configured in Hudson, the best we can do is attempt to go Back.
      if (hudsonUrl == null) {
        reportLines.add(
            "<script type=\"text/javascript\">document.getElementById(\"hudson_link\").onclick = function() { history.go(-1); return false; };</script>");
      } else {
        String jobUrl = hudsonUrl + job.getUrl();
        reportLines.add(
            "<script type=\"text/javascript\">document.getElementById(\"hudson_link\").href=\""
                + jobUrl
                + "\";</script>");
      }

      reportLines.add(
          "<script type=\"text/javascript\">document.getElementById(\"zip_link\").href=\"*zip*/"
              + reportTarget.getSanitizedName()
              + ".zip\";</script>");

      try {
        if (!archiveDir.exists()) {
          listener.error("Specified HTML directory '" + archiveDir + "' does not exist.");
          build.setResult(Result.FAILURE);
          return true;
        } else if (!keepAll) {
          // We are only keeping one copy at the project level, so remove the old one.
          targetDir.deleteRecursive();
        }

        if (archiveDir.copyRecursiveTo("**/*", targetDir) == 0) {
          listener.error(
              "Directory '" + archiveDir + "' exists but failed copying to '" + targetDir + "'.");
          if (build.getResult().isBetterOrEqualTo(Result.UNSTABLE)) {
            // If the build failed, don't complain that there was no coverage.
            // The build probably didn't even get to the point where it produces coverage.
            listener.error("This is especially strange since your build otherwise succeeded.");
          }
          build.setResult(Result.FAILURE);
          return true;
        }
      } catch (IOException e) {
        Util.displayIOException(e, listener);
        e.printStackTrace(listener.fatalError("HTML Publisher failure"));
        build.setResult(Result.FAILURE);
        return true;
      }

      reportTarget.handleAction(build);

      // Now add the footer.
      reportLines.addAll(footerLines);
      // And write this as the index
      try {
        writeFile(reportLines, new File(targetDir.getRemote(), reportTarget.getWrapperName()));
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    return true;
  }
 public void saveSourcesFrom(FilePath dir) throws IOException, InterruptedException {
   FilePath d = new FilePath(getSourcesDir());
   d.mkdirs();
   dir.copyRecursiveTo(d);
 }
  @Override
  public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
      throws IOException, InterruptedException {

    listener.getLogger().println("[CucumberReportPublisher] Compiling Cucumber Html Reports ...");

    // source directory (possibly on slave)
    FilePath workspaceJsonReportDirectory;
    if (jsonReportDirectory.isEmpty()) {
      workspaceJsonReportDirectory = build.getWorkspace();
    } else {
      workspaceJsonReportDirectory = new FilePath(build.getWorkspace(), jsonReportDirectory);
    }

    // target directory (always on master)
    File targetBuildDirectory = new File(build.getRootDir(), "cucumber-html-reports");
    if (!targetBuildDirectory.exists()) {
      targetBuildDirectory.mkdirs();
    }

    String buildNumber = Integer.toString(build.getNumber());
    String buildProject = build.getProject().getName();

    if (Computer.currentComputer() instanceof SlaveComputer) {
      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] Copying all json files from slave: "
                  + workspaceJsonReportDirectory.getRemote()
                  + " to master reports directory: "
                  + targetBuildDirectory);
    } else {
      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] Copying all json files from: "
                  + workspaceJsonReportDirectory.getRemote()
                  + " to reports directory: "
                  + targetBuildDirectory);
    }
    workspaceJsonReportDirectory.copyRecursiveTo(
        DEFAULT_FILE_INCLUDE_PATTERN, new FilePath(targetBuildDirectory));

    // generate the reports from the targetBuildDirectory
    Result result = Result.NOT_BUILT;
    String[] jsonReportFiles =
        findJsonFiles(targetBuildDirectory, fileIncludePattern, fileExcludePattern);
    if (jsonReportFiles.length > 0) {
      listener
          .getLogger()
          .println(
              String.format(
                  "[CucumberReportPublisher] Found %d json files.", jsonReportFiles.length));
      int jsonIndex = 0;
      for (String jsonReportFile : jsonReportFiles) {
        listener
            .getLogger()
            .println(
                "[CucumberReportPublisher] "
                    + jsonIndex
                    + ". Found a json file: "
                    + jsonReportFile);
        jsonIndex++;
      }
      listener.getLogger().println("[CucumberReportPublisher] Generating HTML reports");

      try {
        ReportBuilder reportBuilder =
            new ReportBuilder(
                fullPathToJsonFiles(jsonReportFiles, targetBuildDirectory),
                targetBuildDirectory,
                pluginUrlPath,
                buildNumber,
                buildProject,
                skippedFails,
                pendingFails,
                undefinedFails,
                missingFails,
                !noFlashCharts,
                true,
                false,
                parallelTesting);
        reportBuilder.generateReports();

        boolean buildSuccess = reportBuilder.getBuildStatus();

        if (buildSuccess) {
          result = Result.SUCCESS;
        } else {
          result = ignoreFailedTests ? Result.UNSTABLE : Result.FAILURE;
        }

      } catch (Exception e) {
        e.printStackTrace();
        result = Result.FAILURE;
        listener
            .getLogger()
            .println("[CucumberReportPublisher] there was an error generating the reports: " + e);
        for (StackTraceElement error : e.getStackTrace()) {
          listener.getLogger().println(error);
        }
      }
    } else {
      result = Result.SUCCESS;
      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] there were no json results found in: "
                  + targetBuildDirectory);
    }

    build.addAction(new CucumberReportBuildAction(build));
    build.setResult(result);

    return true;
  }