Package org.intellij.sonar.analysis

Source Code of org.intellij.sonar.analysis.RunLocalAnalysisScriptTask

package org.intellij.sonar.analysis;

import com.google.common.base.*;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.psi.PsiFile;
import org.intellij.sonar.configuration.WorkingDirs;
import org.intellij.sonar.console.SonarConsole;
import org.intellij.sonar.console.StreamGobbler;
import org.intellij.sonar.index.IssuesByFileIndexer;
import org.intellij.sonar.index.SonarIssue;
import org.intellij.sonar.persistence.*;
import org.intellij.sonar.sonarreport.data.Component;
import org.intellij.sonar.sonarreport.data.SonarReport;
import org.intellij.sonar.util.SettingsUtil;
import org.intellij.sonar.util.TemplateProcessor;
import org.sonar.wsclient.services.Resource;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Set;

import static org.intellij.sonar.console.ConsoleLogLevel.ERROR;
import static org.intellij.sonar.console.ConsoleLogLevel.INFO;

public class RunLocalAnalysisScriptTask implements Runnable {
  private final String sourceCode;
  private final String pathToSonarReport;
  private final SonarQubeInspectionContext.EnrichedSettings enrichedSettings;
  private final File workingDir;
  private final SonarConsole sonarConsole;
  private final ImmutableList<PsiFile> psiFiles;

  public static Optional<RunLocalAnalysisScriptTask> from(SonarQubeInspectionContext.EnrichedSettings enrichedSettings, ImmutableList<PsiFile> psiFiles) {
    enrichedSettings.settings = SettingsUtil.process(enrichedSettings.project, enrichedSettings.settings);
    final String scripName = enrichedSettings.settings.getLocalAnalysisScripName();
    final Optional<LocalAnalysisScript> localAnalysisScript = LocalAnalysisScripts.get(scripName);
    if (!localAnalysisScript.isPresent()) return Optional.absent();
    final String sourceCodeTemplate = localAnalysisScript.get().getSourceCode();
    final String serverName = enrichedSettings.settings.getServerName();
    final Optional<SonarServerConfig> serverConfiguration = SonarServers.get(serverName);

    final TemplateProcessor sourceCodeTemplateProcessor = TemplateProcessor.of(sourceCodeTemplate);
    sourceCodeTemplateProcessor
        .withProject(enrichedSettings.project)
        .withModule(enrichedSettings.module);

    String pathToSonarReportTemplate = localAnalysisScript.get().getPathToSonarReport();
    final TemplateProcessor pathToSonarReportTemplateProcessor = TemplateProcessor.of(pathToSonarReportTemplate)
        .withProject(enrichedSettings.project)
        .withModule(enrichedSettings.module);

    if (serverConfiguration.isPresent()) {
      sourceCodeTemplateProcessor.withSonarServerConfiguration(serverConfiguration.get());
      pathToSonarReportTemplateProcessor.withSonarServerConfiguration(serverConfiguration.get());
    }

    File workingDir = WorkingDirs.computeFrom(enrichedSettings);

    sourceCodeTemplateProcessor.withWorkingDir(workingDir);
    pathToSonarReportTemplateProcessor.withWorkingDir(workingDir);

    final String sourceCode = sourceCodeTemplateProcessor.process();
    final String pathToSonarReport = pathToSonarReportTemplateProcessor.process();

    return Optional.of(new RunLocalAnalysisScriptTask(
        enrichedSettings, sourceCode, pathToSonarReport, workingDir,
        psiFiles));
  }

  public RunLocalAnalysisScriptTask(SonarQubeInspectionContext.EnrichedSettings enrichedSettings, String sourceCode, String pathToSonarReport, File workingDir, ImmutableList<PsiFile> psiFiles) {
    this.enrichedSettings = enrichedSettings;
    this.sourceCode = sourceCode;
    this.pathToSonarReport = pathToSonarReport;
    this.workingDir = workingDir;
    this.psiFiles = psiFiles;
    this.sonarConsole = SonarConsole.get(enrichedSettings.project);
  }

  public void run() {

    ProgressManager.getInstance().getProgressIndicator().setText(this.workingDir.getName());
    ProgressManager.getInstance().getProgressIndicator().setText2(this.sourceCode);
    sonarConsole.info("working dir: " + this.workingDir.getPath());
    sonarConsole.info("run: " + this.sourceCode);

    final long startTime = System.currentTimeMillis();

    final Process process;
    try {
      process = Runtime.getRuntime().exec(this.sourceCode.split("[\\s]+"), null, this.workingDir);
    } catch (IOException e) {
      sonarConsole.error(Throwables.getStackTraceAsString(e));
      return;
    }
    final StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), sonarConsole, ERROR);
    final StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), sonarConsole, INFO);
    errorGobbler.start();
    outputGobbler.start();

    final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
    indicator.setIndeterminate(true);

    while (outputGobbler.isAlive()) {
      if (indicator.isCanceled()) {
        process.destroy();
        break;
      }
    }

    try {
      int exitCode = process.exitValue();
      sonarConsole.info(String.format("finished with exit code %s in %d ms", exitCode, System.currentTimeMillis() - startTime));
      if (exitCode != 0) {
        Notifications.Bus.notify(
            new Notification(
                "SonarQube", "SonarQube",
                String.format("Local analysis failed (%d)", exitCode), NotificationType.WARNING), enrichedSettings.project);
      } else {
        readIssuesFromSonarReport();
      }
    } catch (IllegalThreadStateException ignore) {
      // do nothing, if the script execution is aborted
    }

  }

  private void readIssuesFromSonarReport() {
    sonarConsole.info("report: " + this.pathToSonarReport);
    String sonarReportContent;
    try {
      sonarReportContent = Files.toString(new File(pathToSonarReport), Charsets.UTF_8);
    } catch (IOException e) {
      sonarConsole.info(Throwables.getStackTraceAsString(e));
      return;
    }
    final SonarReport sonarReport = SonarReport.fromJson(sonarReportContent);
    final int issuesCount = sonarReport != null && sonarReport.getIssues() != null ? sonarReport.getIssues().size() : 0;
    sonarConsole.info(String.format("Found %d issues in the SonarQube report", issuesCount));

    if (enrichedSettings.settings.getResources().isEmpty()) {
      createIndexFrom(sonarReport, new Resource());
    } else {
      for (Resource resource : enrichedSettings.settings.getResources()) {
        createIndexFrom(sonarReport, resource);
      }
    }

  }

  private void createIndexFrom(SonarReport sonarReport, Resource resource) {
    final Optional<IssuesByFileIndexProjectComponent> indexComponent = IssuesByFileIndexProjectComponent.getInstance(enrichedSettings.project);
    if (!indexComponent.isPresent()) {
      return;
    }

    removeFilesAffectedByReportFromIndex(sonarReport, indexComponent);

    final Map<String, Set<SonarIssue>> index = new IssuesByFileIndexer(psiFiles)
        .withSonarReportIssues(sonarReport.getIssues())
        .create();



    if (!index.isEmpty()) {
      final int issuesCount = FluentIterable.from(index.values()).transformAndConcat(new Function<Set<SonarIssue>, Iterable<SonarIssue>>() {
        @Override
        public Iterable<SonarIssue> apply(Set<SonarIssue> sonarIssues) {
          return sonarIssues;
        }
      }).size();
      sonarConsole.info(String.format("Created index with %d issues from SonarQube report", issuesCount));
      final int newIssuesCount = FluentIterable.from(index.values()).transformAndConcat(new Function<Set<SonarIssue>, Iterable<SonarIssue>>() {
        @Override
        public Iterable<SonarIssue> apply(Set<SonarIssue> sonarIssues) {
          return sonarIssues;
        }
      }).filter(new Predicate<SonarIssue>() {
        @Override
        public boolean apply(SonarIssue sonarIssue) {
          return sonarIssue.getIsNew();
        }
      }).size();
      if (newIssuesCount > 0) sonarConsole.info(String.format("%d issues are new!", newIssuesCount));
      indexComponent.get().getIndex().putAll(index);
    }
  }

  private void removeFilesAffectedByReportFromIndex(SonarReport sonarReport, Optional<IssuesByFileIndexProjectComponent> indexComponent) {
    if (sonarReport.getComponents() != null) {
      for (Component component : sonarReport.getComponents()) {
        final String path = component.getPath();
        if (path != null) {
          final String componentFullPath = new File(workingDir, path).toString();
          indexComponent.get().getIndex().remove(componentFullPath);
        }
      }
    }
  }

  @Override
  public String toString() {
    return Objects.toStringHelper(this)
        .add("sourceCode", sourceCode)
        .add("pathToSonarReport", pathToSonarReport)
        .toString();
  }
}
TOP

Related Classes of org.intellij.sonar.analysis.RunLocalAnalysisScriptTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.