/* * Sonar C# Plugin :: StyleCop * Copyright (C) 2010 Jose Chillan, Alexandre Victoor and SonarSource * dev@sonar.codehaus.org * * This program 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. * * This program 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 02 */ package org.sonar.plugins.csharp.stylecop; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStreamReader; import javax.xml.stream.XMLStreamException; import org.apache.commons.io.IOUtils; import org.codehaus.staxmate.SMInputFactory; import org.codehaus.staxmate.in.SMHierarchicCursor; import org.codehaus.staxmate.in.SMInputCursor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.BatchExtension; import org.sonar.api.batch.SensorContext; import org.sonar.api.resources.Project; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RuleQuery; import org.sonar.api.rules.Violation; import org.sonar.api.utils.SonarException; import org.sonar.dotnet.tools.commons.utils.AbstractStaxParser; /** * Parses the reports generated by a StyleCop analysis. */ public class StyleCopResultParser extends AbstractStaxParser implements BatchExtension { private static final Logger LOG = LoggerFactory.getLogger(StyleCopResultParser.class); private Project project; private SensorContext context; private RuleFinder ruleFinder; /** * Constructs a @link{StyleCopResultParser}. * * @param project * @param context * @param rulesManager * @param profile */ public StyleCopResultParser(Project project, SensorContext context, RuleFinder ruleFinder) { super(); this.project = project; this.context = context; this.ruleFinder = ruleFinder; } /** * Parses a processed violation file. * * @param file * the file to parse */ public void parse(File file) { SMInputFactory inputFactory = initStax(); FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(file); SMHierarchicCursor cursor = inputFactory.rootElementCursor(new InputStreamReader(fileInputStream, getEncoding())); SMInputCursor mainCursor = cursor.advance().childElementCursor(); parseStyleCopViolationsBloc(mainCursor); cursor.getStreamReader().closeCompletely(); } catch (XMLStreamException e) { throw new SonarException("Error while reading StyleCop result file: " + file.getAbsolutePath(), e); } catch (FileNotFoundException e) { throw new SonarException("Cannot find StyleCop result file: " + file.getAbsolutePath(), e); } finally { IOUtils.closeQuietly(fileInputStream); } } private void parseStyleCopViolationsBloc(SMInputCursor violationsCursor) throws XMLStreamException { // Cursor in on <Violations> StringBuffer configKey = new StringBuffer(); RuleQuery ruleQuery = RuleQuery.create().withRepositoryKey(StyleCopConstants.REPOSITORY_KEY); while (violationsCursor.getNext() != null) { configKey.setLength(0); configKey.append(violationsCursor.getAttrValue("RuleNamespace")); configKey.append("#"); configKey.append(violationsCursor.getAttrValue("Rule")); Rule currentRule = ruleFinder.find(ruleQuery.withConfigKey(configKey.toString())); if (currentRule != null) { createViolation(violationsCursor, currentRule); } else { LOG.warn("Could not find the following rule in the StyleCop rule repository: " + configKey.toString()); } } } private void createViolation(SMInputCursor violationsCursor, Rule currentRule) throws XMLStreamException { org.sonar.api.resources.File sonarFile = org.sonar.api.resources.File.fromIOFile(new File(violationsCursor.getAttrValue("Source")), project); if (context.isIndexed(sonarFile, false)) { Violation violation = Violation.create(currentRule, sonarFile); String lineNumber = violationsCursor.getAttrValue("LineNumber"); if (lineNumber != null) { violation.setLineId(Integer.parseInt(lineNumber)); } violation.setMessage(violationsCursor.collectDescendantText().trim()); violation.setSeverity(currentRule.getSeverity()); context.saveViolation(violation); } } }