/** {@inheritDoc} */
  public boolean perform(Build<?, ?> build, Launcher launcher, BuildListener listener)
      throws InterruptedException, IOException {
    if (coverageReportPattern == null) {
      listener.getLogger().println("Skipping coverage reports as coverageReportPattern is null");
      return false;
    }
    if (!Result.SUCCESS.equals(build.getResult())) {
      listener.getLogger().println("Skipping coverage reports as the build was not successful...");
      return true;
    }

    listener.getLogger().println("Publishing PureCoverage reports...");
    FilePath buildTarget = new FilePath(build.getRootDir());

    FilePath[] reports = new FilePath[0];
    final FilePath moduleRoot = build.getParent().getWorkspace();
    try {
      reports = moduleRoot.list(coverageReportPattern);
    } catch (IOException e) {
      Util.displayIOException(e, listener);
      e.printStackTrace(listener.fatalError("Unable to find PureCoverage results"));
      build.setResult(Result.FAILURE);
    }

    if (reports.length == 0) {
      listener
          .getLogger()
          .println(
              "No coverage results were found using the pattern '"
                  + coverageReportPattern
                  + "'.  Did you generate the report(s)?");
      build.setResult(Result.FAILURE);
      return true;
    }

    if (reports.length > 1) {
      listener
          .getLogger()
          .println(
              "PureCoverage publisher found more than one report that match the pattern. "
                  + "Currently, accumulating PureCoverage results is not implemented!");
      build.setResult(Result.FAILURE);
      return true;
    }

    FilePath singleReport = reports[0];
    final FilePath targetPath = new FilePath(buildTarget, CoverageReportsFinder.COVERAGE_PREFIX);
    try {
      singleReport.copyTo(targetPath);
    } catch (IOException e) {
      Util.displayIOException(e, listener);
      e.printStackTrace(
          listener.fatalError(
              "Unable to copy coverage from " + singleReport + " to " + buildTarget));
      build.setResult(Result.FAILURE);
    }

    listener.getLogger().println("Parsing PureCoverage results...");
    ProjectCoverage projectCoverage = null;
    CoverageReportsFinder finder = new CoverageReportsFinder();
    for (File coverageResult : finder.findReports(build)) {
      try {
        CoverageParser coverageParser = new PureCoverageParser();
        projectCoverage = coverageParser.parse(coverageResult);
      } catch (IOException e) {
        Util.displayIOException(e, listener);
        e.printStackTrace(listener.fatalError("Unable to parse " + coverageResult));
        build.setResult(Result.FAILURE);
        return false;
      }
    }

    CoverageResult coverageResult = new CoverageResult(build, projectCoverage);
    build.getActions().add(new CoverageBuildAction(build, coverageResult));

    return true;
  }