org.sonar.server.computation.AnalysisReportService.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.server.computation.AnalysisReportService.java

Source

/*
 * SonarQube, open source software quality management tool.
 * Copyright (C) 2008-2014 SonarSource
 * mailto:contact AT sonarsource DOT com
 *
 * SonarQube is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * SonarQube is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package org.sonar.server.computation;

import com.google.common.annotations.VisibleForTesting;
import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.FieldDiffs;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.batch.protocol.GsonHelper;
import org.sonar.batch.protocol.output.issue.ReportIssue;
import org.sonar.batch.protocol.output.resource.ReportComponent;
import org.sonar.batch.protocol.output.resource.ReportComponents;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.issue.db.IssueStorage;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.db.DbClient;

import javax.annotation.Nullable;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class AnalysisReportService implements ServerComponent {
    private static final Logger LOG = LoggerFactory.getLogger(AnalysisReportService.class);
    private static final int MAX_ISSUES_SIZE = 1000;
    private final ComputeEngineIssueStorageFactory issueStorageFactory;
    private final DbClient dbClient;
    private final Gson gson;

    public AnalysisReportService(DbClient dbClient, ComputeEngineIssueStorageFactory issueStorageFactory) {
        this.issueStorageFactory = issueStorageFactory;
        this.dbClient = dbClient;
        gson = GsonHelper.create();
    }

    public void digest(DbSession session, ComputeEngineContext context) {
        decompress(session, context);
        loadResources(context);
        saveIssues(context);
    }

    @VisibleForTesting
    void loadResources(ComputeEngineContext context) {
        File file = new File(context.getReportDirectory(), "components.json");

        try {
            InputStream resourcesStream = new FileInputStream(file);
            String json = IOUtils.toString(resourcesStream);
            ReportComponents reportComponents = ReportComponents.fromJson(json);
            context.addResources(reportComponents);
        } catch (IOException e) {
            throw new IllegalStateException("Failed to read issues", e);
        }
    }

    @VisibleForTesting
    void decompress(DbSession session, ComputeEngineContext context) {
        AnalysisReportDto report = context.getReportDto();

        File decompressedDirectory = dbClient.analysisReportDao().getDecompressedReport(session, report.getId());
        context.setReportDirectory(decompressedDirectory);
    }

    @VisibleForTesting
    void saveIssues(ComputeEngineContext context) {
        IssueStorage issueStorage = issueStorageFactory.newComputeEngineIssueStorage(context.getProject());

        File issuesFile = new File(context.getReportDirectory(), "issues.json");
        List<DefaultIssue> issues = new ArrayList<>(MAX_ISSUES_SIZE);

        try {
            InputStream issuesStream = new FileInputStream(issuesFile);
            JsonReader reader = new JsonReader(new InputStreamReader(issuesStream));
            reader.beginArray();
            while (reader.hasNext()) {
                ReportIssue reportIssue = gson.fromJson(reader, ReportIssue.class);
                DefaultIssue defaultIssue = toIssue(context, reportIssue);
                issues.add(defaultIssue);
                if (shouldPersistIssues(issues, reader)) {
                    issueStorage.save(issues);
                    issues.clear();
                }
            }

            reader.endArray();
            reader.close();
        } catch (IOException e) {
            throw new IllegalStateException("Failed to read issues", e);
        }
    }

    private boolean shouldPersistIssues(List<DefaultIssue> issues, JsonReader reader) throws IOException {
        return issues.size() == MAX_ISSUES_SIZE || !reader.hasNext();
    }

    private DefaultIssue toIssue(ComputeEngineContext context, ReportIssue issue) {
        ReportComponent component = context.getComponentByBatchId(issue.componentBatchId());
        DefaultIssue defaultIssue = new DefaultIssue();
        defaultIssue.setKey(issue.key());
        defaultIssue.setComponentId(Long.valueOf(component.id()));
        defaultIssue.setRuleKey(RuleKey.of(issue.ruleRepo(), issue.ruleKey()));
        defaultIssue.setSeverity(issue.severity());
        defaultIssue.setManualSeverity(issue.isManualSeverity());
        defaultIssue.setMessage(issue.message());
        defaultIssue.setLine(issue.line());
        defaultIssue.setEffortToFix(issue.effortToFix());
        setDebt(defaultIssue, issue.debt());
        defaultIssue.setStatus(issue.status());
        defaultIssue.setResolution(issue.resolution());
        defaultIssue.setReporter(issue.reporter());
        defaultIssue.setAssignee(issue.assignee());
        defaultIssue.setChecksum(issue.checksum());
        defaultIssue.setAttributes(KeyValueFormat.parse(issue.issueAttributes()));
        defaultIssue.setAuthorLogin(issue.authorLogin());
        defaultIssue.setActionPlanKey(issue.actionPlanKey());
        defaultIssue.setCreationDate(issue.creationDate());
        defaultIssue.setUpdateDate(issue.updateDate());
        defaultIssue.setCloseDate(issue.closeDate());
        defaultIssue.setCurrentChange(FieldDiffs.parse(issue.diffFields()));
        defaultIssue.setChanged(issue.isChanged());
        defaultIssue.setNew(issue.isNew());
        defaultIssue.setSelectedAt(issue.selectedAt());
        return defaultIssue;
    }

    private DefaultIssue setDebt(DefaultIssue issue, Long debt) {
        if (debt != null) {
            issue.setDebt(Duration.create(debt));
        }

        return issue;
    }

    public void deleteDirectory(@Nullable File directory) {
        if (directory == null) {
            return;
        }

        try {
            FileUtils.deleteDirectory(directory);
        } catch (IOException e) {
            LOG.warn(String.format("Failed to delete directory '%s'", directory.getPath()), e);
        }
    }
}