Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

path normalization / absolutization is not allowed to use File::getCanonicalPath() #1575

Merged
merged 4 commits into from
Oct 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import javax.xml.stream.XMLStreamException;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.utils.PathUtils;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
Expand All @@ -45,14 +44,14 @@ public class BullseyeParser extends CxxCoverageParser {
private static int totalcoveredconditions;

public BullseyeParser() {
// no operation but necessary for list of coverage parsers
// no operation but necessary for list of coverage parsers
}

/**
* {@inheritDoc}
*/
@Override
public void processReport(final SensorContext context, File report, final Map<String, CoverageMeasures> coverageData)
public void processReport(File report, final Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
LOG.debug("Parsing 'Bullseye' format");
StaxParser topLevelparser = new StaxParser(new StaxParser.XmlStreamHandler() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@
package org.sonar.cxx.sensors.coverage;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.stream.XMLStreamException;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.cxx.sensors.utils.CxxUtils;
import org.sonar.cxx.sensors.utils.StaxParser;

/**
Expand All @@ -39,7 +39,7 @@
public class CoberturaParser extends CxxCoverageParser {

private static final Logger LOG = Loggers.get(CoberturaParser.class);
private String baseDir;
private Optional<Path> baseDir;
private static final Pattern conditionsPattern = Pattern.compile("\\((.*?)\\)");

public CoberturaParser() {
Expand All @@ -50,10 +50,10 @@ public CoberturaParser() {
* {@inheritDoc}
*/
@Override
public void processReport(final SensorContext context, File report, final Map<String, CoverageMeasures> coverageData)
public void processReport(File report, final Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
LOG.debug("Parsing 'Cobertura' format");
baseDir = context.fileSystem().baseDir().getAbsolutePath();
baseDir = Optional.empty();

StaxParser sourceParser = new StaxParser((SMHierarchicCursor rootCursor) -> {
rootCursor.advance();
Expand All @@ -63,7 +63,7 @@ public void processReport(final SensorContext context, File report, final Map<St

StaxParser packageParser = new StaxParser((SMHierarchicCursor rootCursor) -> {
rootCursor.advance();
collectPackageMeasures(baseDir, rootCursor.descendantElementCursor("package"), coverageData);
collectPackageMeasures(rootCursor.descendantElementCursor("package"), coverageData);
});
packageParser.parse(report);
}
Expand All @@ -72,33 +72,37 @@ private void readBaseDir(SMInputCursor source) throws XMLStreamException {
while (source.getNext() != null) {
String sourceValue = source.getElemStringValue().trim();
if (!sourceValue.isEmpty()) {
baseDir = Paths.get(baseDir).resolve(sourceValue).normalize().toString();
baseDir = Optional.of(Paths.get(sourceValue));
break;
}
}
}

private static void collectPackageMeasures(final String baseDir, SMInputCursor pack,
Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
private void collectPackageMeasures(SMInputCursor pack, Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
while (pack.getNext() != null) {
collectFileMeasures(baseDir, pack.descendantElementCursor("class"), coverageData);
collectFileMeasures(pack.descendantElementCursor("class"), coverageData);
}
}

private static void collectFileMeasures(final String baseDir, SMInputCursor clazz,
Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
private String buildPath(String filename) {
Path result = Paths.get(filename);
if (baseDir.isPresent()) {
result = baseDir.get().resolve(result);
}
return result.normalize().toString();
}

private void collectFileMeasures(SMInputCursor clazz, Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
while (clazz.getNext() != null) {
String normalPath = CxxUtils.normalizePathFull(clazz.getAttrValue("filename"), baseDir);
if (normalPath != null) {
CoverageMeasures builder = coverageData.get(normalPath);
if (builder == null) {
builder = CoverageMeasures.create();
coverageData.put(normalPath, builder);
}
collectFileData(clazz, builder);
String normalPath = buildPath(clazz.getAttrValue("filename"));
CoverageMeasures builder = coverageData.get(normalPath);
if (builder == null) {
builder = CoverageMeasures.create();
coverageData.put(normalPath, builder);
}
collectFileData(clazz, builder);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,33 @@

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

import javax.xml.stream.XMLStreamException;
import org.sonar.api.batch.sensor.SensorContext;

/**
* The interface a coverage report parser has to implement in order to be used by CxxCoverageSensor
* The interface a coverage report parser has to implement in order to be used
* by CxxCoverageSensor
*/
public interface CoverageParser {

/**
* Parses the given report and stores the results in the according builder
*
* @param context of sensor
* @param report with coverage data
* @param coverageData A Map mapping source file names to coverage measures. Has to be used to store the results into.
* @throws XMLStreamException javax.xml.stream.XMLStreamException
* @param context
* of sensor
* @param report
* with coverage data
* @param coverageData
* A Map mapping source file names to coverage measures. Has to be
* used to store the results into. Source file names might be
* relative. In such case they will be resolved against the base
* directory of SonarQube module/project.<br>
*
* <b>ATTENTION!</b> This map is shared between modules in
* multi-module projects. Don't try to resolve paths against some
* specific module!
* @throws XMLStreamException
* javax.xml.stream.XMLStreamException
*/
void processReport(final SensorContext context, File report, Map<String, CoverageMeasures> coverageData)
throws XMLStreamException;
void processReport(File report, Map<String, CoverageMeasures> coverageData) throws XMLStreamException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,20 @@ public void execute(SensorContext context) {
}

List<File> reports = getReports(context.config(), context.fileSystem().baseDir(), getReportPathKey());
coverageMeasures = processReports(context, reports, this.cache.unitCoverageCache());
coverageMeasures = processReports(reports, this.cache.unitCoverageCache());
saveMeasures(context, coverageMeasures);
}
}

private Map<String, CoverageMeasures> processReports(final SensorContext context, List<File> reports,
Map<String, Map<String, CoverageMeasures>> cacheCov) {
private Map<String, CoverageMeasures> processReports(List<File> reports,
Map<String, Map<String, CoverageMeasures>> cacheCov) {
Map<String, CoverageMeasures> measuresTotal = new HashMap<>();

for (File report : reports) {
if (!cacheCov.containsKey(report.getAbsolutePath())) {
for (CoverageParser parser : parsers) {
try {
parseCoverageReport(parser, context, report, measuresTotal);
parseCoverageReport(parser, report, measuresTotal);
if (LOG.isDebugEnabled()) {
LOG.debug("cached measures for '{}' : current cache content data = '{}'", report.getAbsolutePath(),
cacheCov.size());
Expand Down Expand Up @@ -145,11 +145,11 @@ private Map<String, CoverageMeasures> processReports(final SensorContext context
* @param measuresTotal
* @return true if report was parsed and results are available otherwise false
*/
private static void parseCoverageReport(CoverageParser parser, final SensorContext context, File report,
Map<String, CoverageMeasures> measuresTotal) {
private static void parseCoverageReport(CoverageParser parser, File report,
Map<String, CoverageMeasures> measuresTotal) {
Map<String, CoverageMeasures> measuresForReport = new HashMap<>();
try {
parser.processReport(context, report, measuresForReport);
parser.processReport(report, measuresForReport);
} catch (XMLStreamException e) {
throw new EmptyReportException("Coverage report" + report + "cannot be parsed by" + parser, e);
}
Expand All @@ -165,9 +165,8 @@ private static void parseCoverageReport(CoverageParser parser, final SensorConte
private void saveMeasures(SensorContext context,
Map<String, CoverageMeasures> coverageMeasures) {
for (Map.Entry<String, CoverageMeasures> entry : coverageMeasures.entrySet()) {
String filePath = PathUtils.sanitize(entry.getKey());
final String filePath = PathUtils.sanitize(entry.getKey());
if (filePath != null) {
filePath = CxxUtils.normalizePathFull(filePath, context.fileSystem().baseDir().getAbsolutePath());
InputFile cxxFile = context.fileSystem().inputFile(context.fileSystem().predicates().hasPath(filePath));
if (LOG.isDebugEnabled()) {
LOG.debug("save coverage measure for file: '{}' cxxFile = '{}'", filePath, cxxFile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

import org.apache.commons.io.FilenameUtils;

import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;

Expand All @@ -51,25 +50,25 @@
public class TestwellCtcTxtParser extends CxxCoverageParser {

private static final Logger LOG = Loggers.get(TestwellCtcTxtParser.class);

private Scanner scanner;

private static final int FROM_START = 0;
private static final int CONDS_FALSE = 1;
private static final int CONDS_TRUE = 2;
private static final int LINE_NR_GROUP = 3;



public TestwellCtcTxtParser() {
// no operation but necessary for list of coverage parsers
// no operation but necessary for list of coverage parsers
}

/**
* {@inheritDoc}
*/
@Override
public void processReport(final SensorContext context, File report, final Map<String, CoverageMeasures> coverageData) {
public void processReport(File report, final Map<String, CoverageMeasures> coverageData) {
LOG.debug("Parsing 'Testwell CTC++' textual format");

try (Scanner s = new Scanner(report).useDelimiter(SECTION_SEP)) {
Expand Down Expand Up @@ -122,7 +121,7 @@ private void addLines(File file, final Map<String, CoverageMeasures> coverageDat

private void parseLineSection(CoverageMeasures coverageMeasures, String nextLine) {
LOG.debug("Found line section...");

Matcher lineMatcher = LINE_RESULT.matcher(nextLine);
if (lineMatcher.find(FROM_START)) {
addEachLine(coverageMeasures, lineMatcher);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import javax.xml.stream.XMLStreamException;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.cxx.sensors.utils.StaxParser;
Expand All @@ -37,14 +36,14 @@ public class VisualStudioParser extends CxxCoverageParser {
private static final Logger LOG = Loggers.get(VisualStudioParser.class);

public VisualStudioParser() {
// no operation but necessary for list of coverage parsers
// no operation but necessary for list of coverage parsers
}

/**
* {@inheritDoc}
*/
@Override
public void processReport(final SensorContext context, File report, final Map<String, CoverageMeasures> coverageData)
public void processReport(File report, final Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
LOG.debug("Parsing 'Visual Studio' format");
StaxParser parser = new StaxParser(new StaxParser.XmlStreamHandler() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public void execute(SensorContext context) {
LOG.info("Searching reports by relative path with basedir '{}' and search prop '{}'",
context.fileSystem().baseDir(), getReportPathKey());
List<File> reports = getReports(context.config(), context.fileSystem().baseDir(), getReportPathKey());
notFoundFiles.clear();
violationsPerFileCount.clear();
violationsPerModuleCount = 0;

Expand Down Expand Up @@ -158,15 +159,14 @@ public void saveUniqueViolation(SensorContext sensorContext, CxxReportIssue issu
}

public InputFile getInputFileIfInProject(SensorContext sensorContext, String path) {
String root = sensorContext.fileSystem().baseDir().getAbsolutePath();
String normalPath = CxxUtils.normalizePathFull(path, root);
if (normalPath == null || notFoundFiles.contains(normalPath)) {
if (notFoundFiles.contains(path)) {
return null;
}
InputFile inputFile = sensorContext.fileSystem()
.inputFile(sensorContext.fileSystem().predicates().hasAbsolutePath(normalPath));
final InputFile inputFile = sensorContext.fileSystem().inputFile(sensorContext.fileSystem().predicates().hasPath(path));
if (inputFile == null) {
notFoundFiles.add(normalPath);
LOG.debug("Path '{}' couldn't be found in module '{}' base dir '{}'", path, sensorContext.module().key(),
sensorContext.fileSystem().baseDir());
notFoundFiles.add(path);
}
return inputFile;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,38 +48,6 @@ private CxxUtils() {
// only static methods
}

/**
* Normalize the given path to pass it to sonar. Return null if normalization has failed.
*
* @param filename
* @return normalized path
*/
public static String normalizePath(String filename) {
try {
return new File(filename).getCanonicalPath();
} catch (java.io.IOException e) {
LOG.error("path normalizing of '{}' failed: '{}'", filename, e);
return null;
}
}

/**
* @param filename
* @param baseDir
* @return returns case sensitive full path
*/
public static String normalizePathFull(String filename, String baseDir) {
File targetfile = new java.io.File(filename.trim());
String filePath;
if (targetfile.isAbsolute()) {
filePath = normalizePath(filename);
} else {
// RATS, CppCheck and Vera++ provide names like './file.cpp' - add input folder for index check
filePath = normalizePath(baseDir + File.separator + filename);
}
return filePath;
}

/**
* transformFile
*
Expand Down