package org.sonar.scanner.externalissue.sarif;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
+import java.util.concurrent.TimeUnit;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+import org.jetbrains.annotations.NotNull;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.predicates.AbstractFilePredicate;
import org.sonar.api.batch.sensor.SensorContext;
@ScannerSide
public class LocationMapper {
+ private static final int CACHE_SIZE = 500;
+ private static final int CACHE_EXPIRY = 60;
private final SensorContext sensorContext;
private final RegionMapper regionMapper;
+ LoadingCache<String, Optional<InputFile>> inputFileCache = CacheBuilder.newBuilder()
+ .maximumSize(CACHE_SIZE)
+ .expireAfterAccess(CACHE_EXPIRY, TimeUnit.SECONDS)
+ .concurrencyLevel(Runtime.getRuntime().availableProcessors())
+ .build(getCacheLoader());
+
LocationMapper(SensorContext sensorContext, RegionMapper regionMapper) {
this.sensorContext = sensorContext;
this.regionMapper = regionMapper;
PhysicalLocation physicalLocation = location.getPhysicalLocation();
String fileUri = getFileUriOrThrow(location);
- InputFile file = findFile(sensorContext, fileUri);
- if (file == null) {
+ Optional<InputFile> file = findFile(fileUri);
+ if (file.isEmpty()) {
return null;
}
- newIssueLocation.on(file);
- regionMapper.mapRegion(physicalLocation.getRegion(), file).ifPresent(newIssueLocation::at);
+ InputFile inputFile = file.get();
+ newIssueLocation.on(inputFile);
+ regionMapper.mapRegion(physicalLocation.getRegion(), inputFile).ifPresent(newIssueLocation::at);
return newIssueLocation;
}
return Optional.ofNullable(location).map(PhysicalLocation::getArtifactLocation).map(ArtifactLocation::getUri).isPresent();
}
- @CheckForNull
- private static InputFile findFile(SensorContext context, String filePath) {
+ private Optional<InputFile> findFile(String filePath) {
+ return inputFileCache.getUnchecked(filePath);
+ }
+
+ private CacheLoader<String, Optional<InputFile>> getCacheLoader() {
+ return new CacheLoader<>() {
+ @NotNull
+ @Override
+ public Optional<InputFile> load(final String filePath) {
+ return computeInputFile(filePath);
+ }
+ };
+ }
+
+ private Optional<InputFile> computeInputFile(String key) {
// we use a custom predicate (which is not optimized) because fileSystem().predicates().is() doesn't handle symlinks correctly
- return context.fileSystem().inputFile(new IsPredicate(getFileFromAbsoluteUriOrPath(filePath).toPath()));
+ return Optional.ofNullable(sensorContext.fileSystem().inputFile(new LocationMapper.IsPredicate(getFileFromAbsoluteUriOrPath(key).toPath())));
}
private static File getFileFromAbsoluteUriOrPath(String filePath) {
}
}
}
+
}