Package com.buschmais.jqassistant.sonar.plugin.sensor

Source Code of com.buschmais.jqassistant.sonar.plugin.sensor.JQAssistantSensor

package com.buschmais.jqassistant.sonar.plugin.sensor;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.config.Settings;
import org.sonar.api.issue.Issuable;
import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.ActiveRule;
import org.sonar.api.scan.filesystem.ModuleFileSystem;
import org.sonar.api.utils.SonarException;

import com.buschmais.jqassistant.core.report.schema.v1.ColumnType;
import com.buschmais.jqassistant.core.report.schema.v1.ConceptType;
import com.buschmais.jqassistant.core.report.schema.v1.ConstraintType;
import com.buschmais.jqassistant.core.report.schema.v1.ElementType;
import com.buschmais.jqassistant.core.report.schema.v1.GroupType;
import com.buschmais.jqassistant.core.report.schema.v1.JqassistantReport;
import com.buschmais.jqassistant.core.report.schema.v1.ObjectFactory;
import com.buschmais.jqassistant.core.report.schema.v1.ResultType;
import com.buschmais.jqassistant.core.report.schema.v1.RowType;
import com.buschmais.jqassistant.core.report.schema.v1.RuleType;
import com.buschmais.jqassistant.core.report.schema.v1.SourceType;
import com.buschmais.jqassistant.sonar.plugin.JQAssistant;

/**
* {@link Sensor} implementation scanning for jqassistant-report.xml files.
*/
public class JQAssistantSensor implements Sensor {

    private static final Logger LOGGER = LoggerFactory.getLogger(JQAssistantSensor.class);

    private final Settings settings;

    private final ModuleFileSystem moduleFileSystem;

    private final ResourcePerspectives perspectives;

    private final Map<String, LanguageResourceResolver> languageResourceResolvers;

    private final Map<String, ActiveRule> rules;

    private final JAXBContext reportContext;

    public JQAssistantSensor(RulesProfile profile, ResourcePerspectives perspectives, ComponentContainer componentContainerc, Settings settings,
            ModuleFileSystem moduleFileSystem) throws JAXBException {
        this.settings = settings;
        this.moduleFileSystem = moduleFileSystem;
        this.perspectives = perspectives;
        this.languageResourceResolvers = new HashMap<>();
        for (LanguageResourceResolver resolver : componentContainerc.getComponentsByType(LanguageResourceResolver.class)) {
            languageResourceResolvers.put(resolver.getLanguage(), resolver);
        }
        LOGGER.info("Found {} language resource resolvers.", languageResourceResolvers.size());
        this.rules = new HashMap<>();
        for (ActiveRule activeRule : profile.getActiveRulesByRepository(JQAssistant.KEY)) {
            rules.put(activeRule.getRule().getName(), activeRule);
        }
        this.reportContext = JAXBContext.newInstance(ObjectFactory.class);
    }

    @Override
    public void analyse(Project project, SensorContext sensorContext) {
        File reportFile = getReportFile();
        if (reportFile != null) {
            JqassistantReport report = readReport(reportFile);
            evaluateReport(project, sensorContext, report);
        }
    }

    public boolean shouldExecuteOnProject(Project project) {
        return true;
    }

    @Override
    public String toString() {
        return "jQAssistant Sensor";
    }

    private JqassistantReport readReport(File reportFile) {
        try {
            Unmarshaller unmarshaller = reportContext.createUnmarshaller();
            return unmarshaller.unmarshal(new StreamSource(reportFile), JqassistantReport.class).getValue();
        } catch (JAXBException e) {
            throw new SonarException("Cannot read jQAssistant report from file " + reportFile, e);
        }
    }

    private void evaluateReport(Project project, SensorContext sensorContext, JqassistantReport report) {
        boolean createEmptyConceptIssue = isCreateEmptyConceptIssue();
        for (GroupType groupType : report.getGroup()) {
            LOGGER.info("Processing group '{}'", groupType.getId());
            for (RuleType ruleType : groupType.getConceptOrConstraint()) {
                String id = ruleType.getId();
                ActiveRule activeRule = rules.get(id);
                if (activeRule == null) {
                    LOGGER.warn("Cannot resolve activeRule for id '{}'.", id);
                } else {
                    ResultType result = ruleType.getResult();
                    boolean hasRows = result != null && result.getRows().getCount() > 0;
                    if (ruleType instanceof ConceptType && createEmptyConceptIssue && !hasRows) {
                        createIssue(project, null, "The concept did not return a result.", activeRule, sensorContext);
                    } else if (ruleType instanceof ConstraintType && hasRows) {
                        for (RowType rowType : result.getRows().getRow()) {
                            StringBuilder message = new StringBuilder();
                            Resource<?> resource = null;
                            Integer lineNumber = null;
                            for (ColumnType column : rowType.getColumn()) {
                                String name = column.getName();
                                String value = column.getValue();
                                // if a language element element is found use it
                                // as a resource for creating an issue
                                ElementType languageElement = column.getElement();
                                if (languageElement != null) {
                                    LanguageResourceResolver resourceResolver = languageResourceResolvers.get(languageElement.getLanguage());
                                    if (resourceResolver != null) {
                                        String element = languageElement.getValue();
                                        resource = resourceResolver.resolve(element, value);
                                    }
                                }
                                SourceType source = column.getSource();
                                lineNumber = source.getLine();
                                if (message.length() > 0) {
                                    message.append(", ");
                                }
                                message.append(name);
                                message.append('=');
                                message.append(value);
                            }
                            if (resource == null) {
                                resource = project;
                            }
                            String issueDescription = ruleType.getDescription() + "\n" + message.toString();
                            createIssue(resource, lineNumber, issueDescription, activeRule, sensorContext);
                        }
                    }
                }
            }
        }

    }

    /**
     * Creates an issue.
     *
     * @param resource
     *            The project to create the issue for.
     * @param message
     *            The message to use.
     * @param rule
     *            The rule which has been violated.
     * @param sensorContext
     *            The sensor context.
     */
    private void createIssue(Resource<?> resource, Integer lineNumber, String message, ActiveRule rule, SensorContext sensorContext) {
        Issuable issuable;
        if (sensorContext.getResource(resource) != null) {
            issuable = perspectives.as(Issuable.class, resource);
            Issuable.IssueBuilder issueBuilder = issuable.newIssueBuilder().ruleKey(rule.getRule().ruleKey()).message(message);
            if (lineNumber != null) {
                issueBuilder.line(lineNumber);
            }
            issuable.addIssue(issueBuilder.build());
            LOGGER.info("Issue added for resource '{}'.", resource.getLongName());
        } else {
            LOGGER.warn("Resource '{}' not found, issue not created.", resource.getLongName());
        }
    }

    /**
     * Return the report xml file or null if not found. Checks whether
     * {@link JQAssistant#SETTINGS_KEY_REPORT_PATH} is set or not and looks up
     * the passed path or the default build directory.
     *
     * @return reportFile File object of report xml or null if not found.
     */
    private File getReportFile() {
        File reportFile;

        String configReportPath = settings.getString(JQAssistant.SETTINGS_KEY_REPORT_PATH);
        if (configReportPath != null && !configReportPath.isEmpty()) {
            LOGGER.info("Using setting '{}' = '{}' to find report file.", JQAssistant.SETTINGS_KEY_REPORT_PATH, configReportPath);
            reportFile = new File(configReportPath);
        } else {
            File buildDir = moduleFileSystem.buildDir();
            LOGGER.info("Using build directory '{}' to find report file.", buildDir);
            reportFile = new File(buildDir, JQAssistant.REPORT_FILE_NAME);
        }

        if (reportFile.exists()) {
            LOGGER.info("Report found at '{}'.", reportFile.getAbsolutePath());
            return reportFile;
        } else {
            LOGGER.info("No report found at '{}'.", reportFile.getAbsolutePath());
            return null;
        }
    }

    /**
     * Check settings whether to create issues for empty concepts or not. True
     * is default.
     *
     * @return true to create issues for empty concepts.
     */
    private boolean isCreateEmptyConceptIssue() {
        if (!settings.hasKey(JQAssistant.SETTINGS_KEY_CREATE_EMPTY_CONCEPT_ISSUE)) {
            return true;
        } else {
            return settings.getBoolean(JQAssistant.SETTINGS_KEY_CREATE_EMPTY_CONCEPT_ISSUE);
        }
    }
}
TOP

Related Classes of com.buschmais.jqassistant.sonar.plugin.sensor.JQAssistantSensor

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.