package org.intellij.sonar.analysis; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import com.google.common.base.Objects; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import com.intellij.openapi.progress.ProgressManager; import com.intellij.psi.PsiFile; import org.intellij.sonar.console.SonarConsole; import org.intellij.sonar.index.IssuesByFileIndexer; import org.intellij.sonar.index.SonarIssue; import org.intellij.sonar.persistence.IssuesByFileIndexProjectComponent; import org.intellij.sonar.persistence.Settings; import org.intellij.sonar.persistence.SonarServerConfig; import org.intellij.sonar.persistence.SonarServers; import org.intellij.sonar.sonarserver.SonarServer; import org.intellij.sonar.util.DurationUtil; import org.intellij.sonar.util.SettingsUtil; import org.sonar.wsclient.issue.Issue; import org.sonar.wsclient.services.Resource; public class DownloadIssuesTask implements Runnable { private final SonarServerConfig sonarServerConfig; private final Set<String> resourceKeys; private final ImmutableList<PsiFile> psiFiles; private final Map<String,ImmutableList<Issue>> downloadedIssuesByResourceKey = Maps.newConcurrentMap(); private final SonarQubeInspectionContext.EnrichedSettings enrichedSettings; private final SonarConsole sonarConsole; public DownloadIssuesTask( SonarQubeInspectionContext.EnrichedSettings enrichedSettings, SonarServerConfig sonarServerConfig, Set<String> resourceKeys, ImmutableList<PsiFile> psiFiles ) { this.enrichedSettings = enrichedSettings; this.sonarServerConfig = sonarServerConfig; this.resourceKeys = resourceKeys; this.psiFiles = psiFiles; this.sonarConsole = SonarConsole.get(enrichedSettings.project); } public static Optional<DownloadIssuesTask> from( SonarQubeInspectionContext.EnrichedSettings enrichedSettings, ImmutableList<PsiFile> psiFiles ) { final Settings settings = SettingsUtil.process(enrichedSettings.project,enrichedSettings.settings); final String serverName = settings.getServerName(); if (serverName == null) return Optional.empty(); final Optional<SonarServerConfig> c = SonarServers.get(serverName); if (!c.isPresent()) return Optional.empty(); final Set<String> resourceKeys = settings.getResources().stream().map(Resource::getKey).collect(Collectors.toSet()); return Optional.of( new DownloadIssuesTask( enrichedSettings, c.get(), resourceKeys,psiFiles ) ); } @Override public void run() { final SonarServer sonarServer = SonarServer.create(sonarServerConfig); final long startTime = System.currentTimeMillis(); for (String resourceKey : resourceKeys) { final String downloadingIssuesMessage = String.format("Downloading issues for SonarQube resource %s",resourceKey); sonarConsole.info(downloadingIssuesMessage); final ImmutableList<Issue> issues = sonarServer.getAllIssuesFor(resourceKey); downloadedIssuesByResourceKey.put(resourceKey,issues); } onSuccess(startTime); } private void onSuccess(long downloadStartTime) { final int downloadedIssuesCount = FluentIterable.from(downloadedIssuesByResourceKey.values()) .transformAndConcat( issues -> issues ).size(); sonarConsole.info( String.format( "Downloaded %d issues in %s", downloadedIssuesCount, DurationUtil.getDurationBreakdown(System.currentTimeMillis()-downloadStartTime) ) ); for (Map.Entry<String,ImmutableList<Issue>> entry : downloadedIssuesByResourceKey.entrySet()) { if (ProgressManager.getInstance().getProgressIndicator().isCanceled()) break; sonarConsole.info(String.format("Creating index for SonarQube resource %s",entry.getKey())); long indexCreationStartTime = System.currentTimeMillis(); final ImmutableList<Issue> issues = entry.getValue(); final Map<String,Set<SonarIssue>> index = new IssuesByFileIndexer(psiFiles) .withSonarServerIssues(issues) .withSonarConsole(sonarConsole) .create(); final Optional<IssuesByFileIndexProjectComponent> indexComponent = IssuesByFileIndexProjectComponent.getInstance(enrichedSettings.project); indexComponent.ifPresent(issuesByFileIndexProjectComponent -> issuesByFileIndexProjectComponent.getIndex().putAll(index)); final int issuesCountInIndex = FluentIterable.from(index.values()).transformAndConcat( sonarIssues -> sonarIssues ).size(); sonarConsole.info( String.format( "Finished creating index with %d issues for SonarQube resource %s in %s", issuesCountInIndex, entry.getKey(), DurationUtil.getDurationBreakdown(System.currentTimeMillis()-indexCreationStartTime) ) ); } } @Override public String toString() { return Objects.toStringHelper(this) .add("sonarServerConfig",sonarServerConfig) .add("resourceKeys",resourceKeys) .add("psiFiles",psiFiles) .add("downloadedIssuesByResourceKey",downloadedIssuesByResourceKey) .toString(); } }