/*
* Sonar Cxx Plugin, open source software quality management tool.
* Copyright (C) 2010 - 2011, Neticoa SAS France - Tous droits réservés.
* Author(s) : Franck Bonin, Neticoa SAS France.
*
* Sonar Cxx Plugin 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.
*
* Sonar Cxx Plugin 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 Sonar Cxx Plugin; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.plugins.cxx.veraxx;
import java.io.File;
import java.text.ParseException;
import java.util.ArrayList;
import javax.xml.stream.XMLStreamException;
import org.apache.commons.lang.StringUtils;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.StaxParser;
import org.sonar.api.utils.XmlParserException;
import org.sonar.plugins.cxx.CxxFile;
import org.sonar.plugins.cxx.CxxPlugin;
import org.sonar.plugins.cxx.rats.CxxRatsRuleRepository;
import org.sonar.plugins.cxx.utils.ReportsHelper;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RuleRepository;
import org.sonar.api.rules.Violation;
public class CxxVeraxxSensor extends ReportsHelper implements Sensor {
private RuleFinder ruleFinder;
public CxxVeraxxSensor(RuleFinder ruleFinder)
{
this.ruleFinder = ruleFinder;
}
private static Logger logger = LoggerFactory
.getLogger(CxxVeraxxSensor.class);
public boolean shouldExecuteOnProject(Project project) {
return CxxPlugin.KEY.equals(project.getLanguageKey());
}
public static final String GROUP_ID = "org.codehaus.mojo";
public static final String ARTIFACT_ID = "cxx-maven-plugin";
public static final String SENSOR_ID = "veraxx";
public static final String DEFAULT_VERAXX_REPORTS_DIR = "vera++-reports";
public static final String DEFAULT_REPORTS_FILE_PATTERN = "**/vera++-result-*.xml";
@Override
protected String getArtifactId() {
return ARTIFACT_ID;
}
@Override
protected String getSensorId() {
return SENSOR_ID;
}
@Override
protected String getDefaultReportsDir() {
return DEFAULT_VERAXX_REPORTS_DIR;
}
@Override
protected String getDefaultReportsFilePattern() {
return DEFAULT_REPORTS_FILE_PATTERN;
}
@Override
protected String getGroupId() {
return GROUP_ID;
}
@Override
protected Logger getLogger() {
return logger;
}
public void analyse(Project project, SensorContext context) {
File reportDirectory = getReportsDirectory(project);
if (reportDirectory != null) {
File reports[] = getReports(project, reportDirectory);
for (File report : reports) {
parseReport(project, report, context);
}
}
}
private void parseReport(final Project project, File xmlFile,
final SensorContext context) {
try {
logger.info("parsing {}", xmlFile);
StaxParser parser = new StaxParser(
new StaxParser.XmlStreamHandler() {
public void stream(SMHierarchicCursor rootCursor)
throws XMLStreamException {
try {
rootCursor.advance();
collectFile(project, rootCursor.childElementCursor("file"), context);
} catch (ParseException e) {
throw new XMLStreamException(e);
}
}
});
parser.parse(xmlFile);
} catch (XMLStreamException e) {
throw new XmlParserException(e);
}
}
private void collectFile(Project project, SMInputCursor file,
SensorContext context) throws ParseException, XMLStreamException {
while (file.getNext() != null) {
//logger.info("collectError nodename = {} {}", error.getPrefixedName(), error.getAttrCount());
String fileName = file.getAttrValue("name");
if (!StringUtils.isEmpty(fileName)) {
SMInputCursor error = file.childElementCursor("error");
while (error.getNext() != null) {
String line = error.getAttrValue("line");
String severity = error.getAttrValue("severity");
String message = error.getAttrValue("message");
String source = error.getAttrValue("source");
if (!StringUtils.isEmpty(source)) {
if (StringUtils.isEmpty(line)) line = "0";
CxxFile ressource = CxxFile.fromFileName(project, fileName, getReportsIncludeSourcePath(project), false);
if (fileExist(context, ressource)) {
Rule rule = ruleFinder.findByKey(CxxVeraxxRuleRepository.REPOSITORY_KEY, source);
if (rule != null)
{
Object t[] = {source, message, line, ressource.getKey()};
logger.debug("error source={} message={} found at line {} from ressource {}", t);
Violation violation = Violation.create(rule, ressource);
violation.setMessage(message);
violation.setLineId(Integer.parseInt(line));
context.saveViolation(violation);
} else {
Object t[] = {source, message, line, fileName};
logger.warn("No rule for error source={} message={} found at line {} from file {}", t);
}
}
else
{
Object t[] = {source, message, line, fileName};
logger.warn("error id={} msg={} found at line {} from file {} has no ressource associated", t);
}
} else {
logger.warn("error no source for error");
}
}
} else {
logger.warn("error no name in file node");
}
}
}
private boolean fileExist(SensorContext context, CxxFile file) {
return context.getResource(file) != null;
}
}