aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-scanner-engine/src/main/java/org/sonar/scanner
diff options
context:
space:
mode:
authorDimitris Kavvathas <dimitris.kavvathas@sonarsource.com>2022-12-07 11:10:47 +0100
committersonartech <sonartech@sonarsource.com>2022-12-12 20:04:02 +0000
commit978818983042dcad1e997cc81c8a98c9724bfb80 (patch)
treec79e3792119850141e6c0f9c4326adbedab39410 /sonar-scanner-engine/src/main/java/org/sonar/scanner
parent133d15e977d3d2a71413578ac5b8c72d918b8b7d (diff)
downloadsonarqube-978818983042dcad1e997cc81c8a98c9724bfb80.tar.gz
sonarqube-978818983042dcad1e997cc81c8a98c9724bfb80.zip
SONAR-17518 Ignore AccessDeniedException of directory, if it is excluded.
Diffstat (limited to 'sonar-scanner-engine/src/main/java/org/sonar/scanner')
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AbstractExclusionFilters.java27
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java54
2 files changed, 75 insertions, 6 deletions
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AbstractExclusionFilters.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AbstractExclusionFilters.java
index 2d808175dd0..545d653fbf1 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AbstractExclusionFilters.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AbstractExclusionFilters.java
@@ -45,7 +45,7 @@ public abstract class AbstractExclusionFilters {
private PathPattern[] testInclusionsPattern;
private PathPattern[] testExclusionsPattern;
- public AbstractExclusionFilters(Function<String, String[]> configProvider) {
+ protected AbstractExclusionFilters(Function<String, String[]> configProvider) {
this.sourceInclusions = inclusions(configProvider, CoreProperties.PROJECT_INCLUSIONS_PROPERTY);
this.testInclusions = inclusions(configProvider, CoreProperties.PROJECT_TEST_INCLUSIONS_PROPERTY);
this.sourceExclusions = exclusions(configProvider, CoreProperties.GLOBAL_EXCLUSIONS_PROPERTY, CoreProperties.PROJECT_EXCLUSIONS_PROPERTY);
@@ -138,10 +138,6 @@ public abstract class AbstractExclusionFilters {
public boolean isExcluded(Path absolutePath, Path relativePath, InputFile.Type type) {
PathPattern[] exclusionPatterns = InputFile.Type.MAIN == type ? mainExclusionsPattern : testExclusionsPattern;
- if (exclusionPatterns.length == 0) {
- return false;
- }
-
for (PathPattern pattern : exclusionPatterns) {
if (pattern.match(absolutePath, relativePath)) {
return true;
@@ -150,4 +146,25 @@ public abstract class AbstractExclusionFilters {
return false;
}
+
+ /**
+ * <p>Checks if the file should be excluded as a parent directory of excluded files and subdirectories.</p>
+ *
+ * @param absolutePath The full path of the file.
+ * @param relativePath The relative path of the file.
+ * @param baseDir The base directory of the project.
+ * @param type The file type.
+ * @return True if the file should be excluded, false otherwise.
+ */
+ public boolean isExcludedAsParentDirectoryOfExcludedChildren(Path absolutePath, Path relativePath, Path baseDir, InputFile.Type type) {
+ PathPattern[] exclusionPatterns = InputFile.Type.MAIN == type ? mainExclusionsPattern : testExclusionsPattern;
+
+ return Stream.of(exclusionPatterns)
+ .map(PathPattern::toString)
+ .filter(ps -> ps.endsWith("/**/*"))
+ .map(ps -> ps.substring(0, ps.length() - 5))
+ .map(baseDir::resolve)
+ .anyMatch(exclusionRootPath -> absolutePath.startsWith(exclusionRootPath)
+ || PathPattern.create(exclusionRootPath.toString()).match(absolutePath, relativePath));
+ }
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java
index 1219428a305..0c7b24d235c 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java
@@ -20,6 +20,7 @@
package org.sonar.scanner.scan.filesystem;
import java.io.IOException;
+import java.nio.file.AccessDeniedException;
import java.nio.file.FileSystemLoopException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
@@ -38,6 +39,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
+import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.scm.IgnoreCommand;
@@ -216,6 +218,27 @@ public class ProjectFileIndexer {
new IndexFileVisitor(module, moduleExclusionFilters, moduleCoverageAndDuplicationExclusions, type, exclusionCounter));
}
+
+ /**
+ * <p>Checks if the path is a directory that is excluded.</p>
+ *
+ * <p>Exclusions patterns are checked both at project and module level.</p>
+ *
+ * @param moduleExclusionFilters The exclusion filters.
+ * @param realAbsoluteFile The path to be checked.
+ * @param projectBaseDir The project base directory.
+ * @param moduleBaseDir The module base directory.
+ * @param type The input file type.
+ * @return True if path is an excluded directory, false otherwise.
+ */
+ private static boolean isExcludedDirectory(ModuleExclusionFilters moduleExclusionFilters, Path realAbsoluteFile, Path projectBaseDir, Path moduleBaseDir,
+ InputFile.Type type) {
+ Path projectRelativePath = projectBaseDir.relativize(realAbsoluteFile);
+ Path moduleRelativePath = moduleBaseDir.relativize(realAbsoluteFile);
+ return moduleExclusionFilters.isExcludedAsParentDirectoryOfExcludedChildren(realAbsoluteFile, projectRelativePath, projectBaseDir, type)
+ || moduleExclusionFilters.isExcludedAsParentDirectoryOfExcludedChildren(realAbsoluteFile, moduleRelativePath, moduleBaseDir, type);
+ }
+
private class IndexFileVisitor implements FileVisitor<Path> {
private final DefaultInputModule module;
private final ModuleExclusionFilters moduleExclusionFilters;
@@ -249,16 +272,45 @@ public class ProjectFileIndexer {
return FileVisitResult.CONTINUE;
}
+ /**
+ * <p>Overridden method to handle exceptions while visiting files in the analysis.</p>
+ *
+ * <p>
+ * <ul>
+ * <li>FileSystemLoopException - We show a warning that a symlink loop exists and we skip the file.</li>
+ * <li>AccessDeniedException for excluded files/directories - We skip the file, as files excluded from the analysis, shouldn't throw access exceptions.</li>
+ * </ul>
+ * </p>
+ *
+ * @param file a reference to the file
+ * @param exc the I/O exception that prevented the file from being visited
+ *
+ * @throws IOException
+ */
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
if (exc instanceof FileSystemLoopException) {
LOG.warn("Not indexing due to symlink loop: {}", file.toFile());
return FileVisitResult.CONTINUE;
+ } else if (exc instanceof AccessDeniedException && isExcluded(file)) {
+ return FileVisitResult.CONTINUE;
}
-
throw exc;
}
+ /**
+ * <p>Checks if the directory is excluded in the analysis or not. Only the exclusions are checked.</p>
+ *
+ * <p>The inclusions cannot be checked for directories, since the current implementation of pattern matching is intended only for files.</p>
+ *
+ * @param path The file or directory.
+ * @return True if file/directory is excluded from the analysis, false otherwise.
+ */
+ private boolean isExcluded(Path path) throws IOException {
+ Path realAbsoluteFile = path.toRealPath(LinkOption.NOFOLLOW_LINKS).toAbsolutePath().normalize();
+ return isExcludedDirectory(moduleExclusionFilters, realAbsoluteFile, inputModuleHierarchy.root().getBaseDir(), module.getBaseDir(), type);
+ }
+
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
return FileVisitResult.CONTINUE;