aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2013-10-09 18:19:01 +0200
committerSimon Brandhof <simon.brandhof@gmail.com>2013-10-09 18:21:36 +0200
commite8cbc899adb18eec17aa5df5db11eea06c46c009 (patch)
treed2f7693fcbacc03a42182b98c314dcaae3e39316
parent2557634d1700e935047ecb190681a6cd418cc2b1 (diff)
downloadsonarqube-e8cbc899adb18eec17aa5df5db11eea06c46c009.tar.gz
sonarqube-e8cbc899adb18eec17aa5df5db11eea06c46c009.zip
SONAR-3677 enhanced file system
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java48
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java87
-rw-r--r--plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectConverter.java10
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/ResourceFilters.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java19
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java8
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/UnsupportedProperties.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AttributeFilter.java41
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java218
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilter.java12
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilters.java37
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileFilterContext.java79
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileHashCache.java115
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileHashDigest.java (renamed from sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/HashBuilder.java)31
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileHashes.java (renamed from sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ChangedFileFilter.java)30
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java151
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java67
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileSystemLogger.java3
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InclusionFilter.java12
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java (renamed from sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageFilters.java)50
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageRecognizer.java61
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleFileSystemProvider.java35
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/PathPattern.java25
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapter.java (renamed from sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileSystemAdapter.java)38
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/RemoteFileHashes.java77
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/WhiteListFileFilter.java55
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/UnsupportedPropertiesTest.java27
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AttributeFilterTest.java (renamed from sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileFilterContextTest.java)24
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java498
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFilterTest.java31
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java97
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileHashDigestTest.java (renamed from sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/HashBuilderTest.java)29
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileHashesTest.java (renamed from sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileFilterWrapperTest.java)33
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileSystemLoggerTest.java3
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InclusionFilterTest.java32
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java65
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageFiltersTest.java76
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ModuleFileSystemProviderTest.java22
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapterTest.java (renamed from sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileSystemAdapterTest.java)11
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/RemoteFileHashesTest.java (renamed from sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileHashCacheTest.java)74
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/WhiteListFileFilterTest.java69
-rw-r--r--sonar-core/src/main/java/org/sonar/core/source/SnapshotDataType.java2
-rw-r--r--sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java12
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFileUtils.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileQuery.java57
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileSystemFilter.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileType.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java140
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFileFilter.java (renamed from sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileFilterWrapper.java)20
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/ModuleFileSystem.java18
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/SimpleModuleFileSystem.java10
52 files changed, 1469 insertions, 1211 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java
index df5cd76ade5..74af986d814 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java
@@ -19,39 +19,32 @@
*/
package org.sonar.plugins.core.sensors;
+import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
-import org.sonar.api.scan.filesystem.FileQuery;
-import org.sonar.api.scan.filesystem.FileType;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
-import org.sonar.api.scan.filesystem.PathResolver;
+import org.sonar.api.scan.filesystem.InputFile;
+import org.sonar.api.utils.KeyValueFormat;
import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.scan.filesystem.FileHashCache;
+import org.sonar.batch.scan.filesystem.InputFileCache;
import org.sonar.core.source.SnapshotDataType;
-import java.io.File;
-import java.util.List;
+import java.util.Map;
/**
* This sensor will retrieve hash of each file of the current module and store it in DB
* in order to compare it during next analysis and see if the file was modified.
* This is used by the incremental preview mode.
- * @see org.sonar.plugins.core.batch.IncrementalPreviewFilter
* @since 4.0
*/
public final class FileHashSensor implements Sensor {
- private ModuleFileSystem moduleFileSystem;
- private PathResolver pathResolver;
- private ComponentDataCache componentDataCache;
- private FileHashCache fileHashCache;
+ private final InputFileCache fileCache;
+ private final ComponentDataCache componentDataCache;
- public FileHashSensor(FileHashCache fileHashCache, ModuleFileSystem moduleFileSystem, PathResolver pathResolver, ComponentDataCache componentDataCache) {
- this.fileHashCache = fileHashCache;
- this.moduleFileSystem = moduleFileSystem;
- this.pathResolver = pathResolver;
+ public FileHashSensor(InputFileCache fileCache, ComponentDataCache componentDataCache) {
+ this.fileCache = fileCache;
this.componentDataCache = componentDataCache;
}
@@ -61,20 +54,17 @@ public final class FileHashSensor implements Sensor {
@Override
public void analyse(Project project, SensorContext context) {
- StringBuilder fileHashMap = new StringBuilder();
- analyse(fileHashMap, project, FileType.SOURCE);
- analyse(fileHashMap, project, FileType.TEST);
- String fileHashes = fileHashMap.toString();
- if (StringUtils.isNotBlank(fileHashes)) {
- componentDataCache.setStringData(project.getKey(), SnapshotDataType.FILE_HASH.getValue(), fileHashes);
+ Map<String, String> map = Maps.newHashMap();
+ for (InputFile inputFile : fileCache.byModule(project.key())) {
+ String baseRelativePath = inputFile.attribute(InputFile.ATTRIBUTE_BASE_RELATIVE_PATH);
+ String hash = inputFile.attribute(InputFile.ATTRIBUTE_HASH);
+ if (StringUtils.isNotEmpty(baseRelativePath) && StringUtils.isNotEmpty(hash)) {
+ map.put(baseRelativePath, hash);
+ }
}
- }
-
- private void analyse(StringBuilder fileHashMap, Project project, FileType fileType) {
- List<File> files = moduleFileSystem.files(FileQuery.on(fileType).onLanguage(project.getLanguageKey()));
- for (File file : files) {
- String hash = fileHashCache.getCurrentHash(file, moduleFileSystem.sourceCharset());
- fileHashMap.append(pathResolver.relativePath(moduleFileSystem.baseDir(), file)).append("=").append(hash).append("\n");
+ if (!map.isEmpty()) {
+ String data = KeyValueFormat.format(map);
+ componentDataCache.setStringData(project.getKey(), SnapshotDataType.FILE_HASH.getValue(), data);
}
}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java
index b46519c27d3..7e11a61698c 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java
@@ -19,96 +19,63 @@
*/
package org.sonar.plugins.core.sensors;
-import com.google.common.base.Charsets;
-import org.apache.commons.configuration.PropertiesConfiguration;
-import org.apache.commons.io.FileUtils;
-import org.junit.Before;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import edu.emory.mathcs.backport.java.util.Collections;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.SensorContext;
-import org.sonar.api.resources.Java;
import org.sonar.api.resources.Project;
-import org.sonar.api.scan.filesystem.FileQuery;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
-import org.sonar.api.scan.filesystem.PathResolver;
+import org.sonar.api.scan.filesystem.InputFile;
import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.scan.filesystem.FileHashCache;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collections;
+import org.sonar.batch.scan.filesystem.InputFileCache;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
public class FileHashSensorTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- private FileHashSensor sensor;
-
@Rule
public ExpectedException thrown = ExpectedException.none();
- private ModuleFileSystem fileSystem;
+ Project project = new Project("struts");
+ InputFileCache fileCache = mock(InputFileCache.class);
+ ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
+ FileHashSensor sensor = new FileHashSensor(fileCache, componentDataCache);
- private ComponentDataCache componentDataCache;
-
- private Project project;
+ @Test
+ public void store_file_hashes() throws Exception {
+ when(fileCache.byModule("struts")).thenReturn(Lists.<InputFile>newArrayList(
+ InputFile.create(temp.newFile(), "src/Foo.java", ImmutableMap.of(InputFile.ATTRIBUTE_HASH, "ABC")),
+ InputFile.create(temp.newFile(), "src/Bar.java", ImmutableMap.of(InputFile.ATTRIBUTE_HASH, "DEF"))
+ ));
- private FileHashCache fileHashCache;
+ SensorContext sensorContext = mock(SensorContext.class);
+ sensor.analyse(project, sensorContext);
- @Before
- public void prepare() {
- fileSystem = mock(ModuleFileSystem.class);
- when(fileSystem.sourceCharset()).thenReturn(Charsets.UTF_8);
- componentDataCache = mock(ComponentDataCache.class);
- fileHashCache = mock(FileHashCache.class);
- sensor = new FileHashSensor(fileHashCache, fileSystem, new PathResolver(), componentDataCache);
- PropertiesConfiguration conf = new PropertiesConfiguration();
- conf.setProperty("sonar.language", "java");
- project = new Project("java_project").setConfiguration(conf).setLanguage(Java.INSTANCE);
+ verify(componentDataCache).setStringData("struts", "file_hash", "src/Foo.java=ABC;src/Bar.java=DEF");
+ verifyZeroInteractions(sensorContext);
}
@Test
- public void improve_code_coverage() throws Exception {
+ public void various_tests() throws Exception {
assertThat(sensor.shouldExecuteOnProject(project)).isTrue();
assertThat(sensor.toString()).isEqualTo("FileHashSensor");
}
@Test
- public void computeHashes() throws Exception {
- File baseDir = temp.newFolder();
- File file1 = new File(baseDir, "src/com/foo/Bar.java");
- FileUtils.write(file1, "Bar", Charsets.UTF_8);
- when(fileHashCache.getCurrentHash(file1, Charsets.UTF_8)).thenReturn("barhash");
- File file2 = new File(baseDir, "src/com/foo/Foo.java");
- FileUtils.write(file2, "Foo", Charsets.UTF_8);
- when(fileHashCache.getCurrentHash(file2, Charsets.UTF_8)).thenReturn("foohash");
- when(fileSystem.baseDir()).thenReturn(baseDir);
- when(fileSystem.files(any(FileQuery.class))).thenReturn(Arrays.asList(file1, file2)).thenReturn(Collections.<File> emptyList());
- sensor.analyse(project, mock(SensorContext.class));
+ public void dont_save_hashes_if_no_files() throws Exception {
+ when(fileCache.byModule("struts")).thenReturn(Collections.<InputFile>emptyList());
- verify(componentDataCache).setStringData("java_project", "hash",
- "src/com/foo/Bar.java=barhash\n"
- + "src/com/foo/Foo.java=foohash\n");
- }
-
- @Test
- public void dont_save_hashes_if_no_file() throws Exception {
- File baseDir = temp.newFolder();
- when(fileSystem.baseDir()).thenReturn(baseDir);
- when(fileSystem.files(any(FileQuery.class))).thenReturn(Collections.<File> emptyList());
- sensor.analyse(project, mock(SensorContext.class));
+ SensorContext sensorContext = mock(SensorContext.class);
+ sensor.analyse(project, sensorContext);
- verify(componentDataCache, never()).setStringData(anyString(), anyString(), anyString());
+ verifyZeroInteractions(componentDataCache);
+ verifyZeroInteractions(sensorContext);
}
}
diff --git a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectConverter.java b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectConverter.java
index 3b877f3d479..6b883439371 100644
--- a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectConverter.java
+++ b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectConverter.java
@@ -226,11 +226,11 @@ public class MavenProjectConverter implements TaskExtension {
public static void synchronizeFileSystem(MavenProject pom, DefaultModuleFileSystem into) {
into.resetDirs(
- pom.getBasedir(),
- getBuildDir(pom),
- resolvePaths(pom.getCompileSourceRoots(), pom.getBasedir()),
- resolvePaths(pom.getTestCompileSourceRoots(), pom.getBasedir()),
- Arrays.asList(resolvePath(pom.getBuild().getOutputDirectory(), pom.getBasedir())));
+ pom.getBasedir(),
+ getBuildDir(pom),
+ resolvePaths(pom.getCompileSourceRoots(), pom.getBasedir()),
+ resolvePaths(pom.getTestCompileSourceRoots(), pom.getBasedir()),
+ Arrays.asList(resolvePath(pom.getBuild().getOutputDirectory(), pom.getBasedir())));
}
static File resolvePath(@Nullable String path, File basedir) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/ResourceFilters.java b/sonar-batch/src/main/java/org/sonar/batch/ResourceFilters.java
index 77f3f7dd31b..c32b0dbd68b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/ResourceFilters.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/ResourceFilters.java
@@ -35,7 +35,7 @@ public class ResourceFilters {
private ResourceFilter[] filters;
public ResourceFilters(ResourceFilter[] filters) {
- this.filters = (filters == null ? new ResourceFilter[0] : filters);
+ this.filters = filters == null ? new ResourceFilter[0] : filters;
}
public ResourceFilters() {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
index 37ef6fcedb4..d6ce991ec10 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
@@ -28,7 +28,6 @@ import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.resources.Languages;
import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.FileExclusions;
-import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.batch.DefaultProjectClasspath;
import org.sonar.batch.DefaultSensorContext;
import org.sonar.batch.DefaultTimeMachine;
@@ -49,12 +48,7 @@ import org.sonar.batch.issue.IssueFilters;
import org.sonar.batch.issue.ModuleIssues;
import org.sonar.batch.phases.PhaseExecutor;
import org.sonar.batch.phases.PhasesTimeProfiler;
-import org.sonar.batch.scan.filesystem.DeprecatedFileSystemAdapter;
-import org.sonar.batch.scan.filesystem.ExclusionFilters;
-import org.sonar.batch.scan.filesystem.FileHashCache;
-import org.sonar.batch.scan.filesystem.FileSystemLogger;
-import org.sonar.batch.scan.filesystem.LanguageFilters;
-import org.sonar.batch.scan.filesystem.ModuleFileSystemProvider;
+import org.sonar.batch.scan.filesystem.*;
import org.sonar.core.component.ScanPerspectives;
import org.sonar.core.measure.MeasurementFilters;
@@ -97,15 +91,16 @@ public class ModuleScanContainer extends ComponentContainer {
Languages.class,
// file system
- PathResolver.class,
FileExclusions.class,
- LanguageFilters.class,
ExclusionFilters.class,
+ FileHashes.class,
+ RemoteFileHashes.class,
+ FileIndexer.class,
+ LanguageRecognizer.class,
+ FileSystemLogger.class,
DefaultProjectClasspath.class,
new ModuleFileSystemProvider(),
- DeprecatedFileSystemAdapter.class,
- FileSystemLogger.class,
- FileHashCache.class,
+ ProjectFileSystemAdapter.class,
// the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
getComponentByType(ResourcePersister.class).getSnapshot(module),
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
index a425e6386da..4b8a82fbe4b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
@@ -28,6 +28,7 @@ import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.resources.Project;
+import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.DefaultFileLinesContextFactory;
import org.sonar.batch.DefaultResourceCreationLock;
@@ -38,7 +39,7 @@ import org.sonar.batch.index.*;
import org.sonar.batch.issue.*;
import org.sonar.batch.phases.GraphPersister;
import org.sonar.batch.profiling.PhasesSumUpTimeProfiler;
-import org.sonar.batch.scan.filesystem.HashBuilder;
+import org.sonar.batch.scan.filesystem.InputFileCache;
import org.sonar.batch.scan.maven.FakeMavenPluginExecutor;
import org.sonar.batch.scan.maven.MavenPluginExecutor;
import org.sonar.batch.source.HighlightableBuilder;
@@ -117,7 +118,10 @@ public class ProjectScanContainer extends ComponentContainer {
ResourceCache.class,
ComponentDataCache.class,
ComponentDataPersister.class,
- HashBuilder.class,
+
+ // file system
+ InputFileCache.class,
+ PathResolver.class,
// issues
IssueUpdater.class,
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/UnsupportedProperties.java b/sonar-batch/src/main/java/org/sonar/batch/scan/UnsupportedProperties.java
index 5f83ff8654f..cce1d037c06 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/UnsupportedProperties.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/UnsupportedProperties.java
@@ -20,7 +20,9 @@
package org.sonar.batch.scan;
import org.sonar.api.BatchComponent;
+import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
+import org.sonar.api.utils.MessageException;
public class UnsupportedProperties implements BatchComponent {
private final Settings settings;
@@ -31,11 +33,18 @@ public class UnsupportedProperties implements BatchComponent {
public void start() {
verify("sonar.light", "The property 'sonar.light' is no longer supported. Please use 'sonar.dynamicAnalysis'");
+ verifyIncrementalPreviewMode();
}
private void verify(String key, String message) {
if (settings.hasKey(key)) {
- throw new IllegalArgumentException(message);
+ throw MessageException.of(message);
+ }
+ }
+
+ private void verifyIncrementalPreviewMode() {
+ if (settings.getBoolean(CoreProperties.INCREMENTAL_PREVIEW) && !settings.getBoolean(CoreProperties.DRY_RUN)) {
+ throw MessageException.of("Incremental mode is only supported with preview mode");
}
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AttributeFilter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AttributeFilter.java
new file mode 100644
index 00000000000..f2565480997
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AttributeFilter.java
@@ -0,0 +1,41 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 02110-1301, USA.
+ */
+package org.sonar.batch.scan.filesystem;
+
+import org.sonar.api.scan.filesystem.InputFile;
+import org.sonar.api.scan.filesystem.InputFileFilter;
+
+import java.util.Collection;
+
+class AttributeFilter implements InputFileFilter {
+ private final String key;
+ private final Collection<String> values;
+
+ AttributeFilter(String key, Collection<String> values) {
+ this.key = key;
+ this.values = values;
+ }
+
+ @Override
+ public boolean accept(InputFile inputFile) {
+ String value = inputFile.attribute(key);
+ return values.contains(value);
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java
index 1d0c76a7bee..327a5663106 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java
@@ -22,24 +22,17 @@ package org.sonar.batch.scan.filesystem;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.filefilter.FileFilterUtils;
-import org.apache.commons.io.filefilter.HiddenFileFilter;
-import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.FileQuery;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
-import org.sonar.api.scan.filesystem.FileType;
+import org.sonar.api.scan.filesystem.InputFile;
import org.sonar.api.scan.filesystem.ModuleFileSystem;
-import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.SonarException;
+import javax.annotation.CheckForNull;
import java.io.File;
-import java.io.FileFilter;
import java.nio.charset.Charset;
-import java.util.Collection;
import java.util.List;
/**
@@ -49,42 +42,57 @@ import java.util.List;
*/
public class DefaultModuleFileSystem implements ModuleFileSystem {
- private static final IOFileFilter DIR_FILTER = FileFilterUtils.and(HiddenFileFilter.VISIBLE, FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter(".")));
+ private final String moduleKey;
+ private final InputFileCache cache;
+ private final FileIndexer indexer;
+ private final Settings settings;
- private Settings settings;
private File baseDir, workingDir, buildDir;
private List<File> sourceDirs = Lists.newArrayList();
private List<File> testDirs = Lists.newArrayList();
private List<File> binaryDirs = Lists.newArrayList();
- private PathResolver pathResolver = new PathResolver();
- private List<FileSystemFilter> fsFilters = Lists.newArrayList();
- private LanguageFilters languageFilters;
- private FileHashCache fileHashCache;
+ private List<File> additionalSourceFiles = Lists.newArrayList();
+ private List<File> additionalTestFiles = Lists.newArrayList();
- DefaultModuleFileSystem(FileHashCache fileHashCache) {
- this.fileHashCache = fileHashCache;
+ public DefaultModuleFileSystem(String moduleKey, Settings settings, InputFileCache cache, FileIndexer indexer) {
+ this.moduleKey = moduleKey;
+ this.settings = settings;
+ this.cache = cache;
+ this.indexer = indexer;
}
+ @Override
+ public String moduleKey() {
+ return moduleKey;
+ }
+
+ @Override
public File baseDir() {
return baseDir;
}
+ @Override
+ @CheckForNull
public File buildDir() {
return buildDir;
}
+ @Override
public List<File> sourceDirs() {
return sourceDirs;
}
+ @Override
public List<File> testDirs() {
return testDirs;
}
+ @Override
public List<File> binaryDirs() {
return binaryDirs;
}
+ @Override
public Charset sourceCharset() {
final Charset charset;
String encoding = settings.getString(CoreProperties.ENCODING_PROPERTY);
@@ -100,97 +108,69 @@ public class DefaultModuleFileSystem implements ModuleFileSystem {
return !settings.hasKey(CoreProperties.ENCODING_PROPERTY);
}
+ @Override
public File workingDir() {
return workingDir;
}
- List<FileSystemFilter> filters() {
- return fsFilters;
+ List<File> additionalSourceFiles() {
+ return additionalSourceFiles;
}
- LanguageFilters languageFilters() {
- return languageFilters;
+ List<File> additionalTestFiles() {
+ return additionalTestFiles;
}
- public List<File> files(FileQuery query) {
- boolean changedFilesOnly = false;
- if (settings.getBoolean(CoreProperties.INCREMENTAL_PREVIEW)) {
- if (!settings.getBoolean(CoreProperties.DRY_RUN)) {
- throw new SonarException("Incremental preview is only supported with preview mode");
- }
- changedFilesOnly = true;
- }
- return files(query, changedFilesOnly);
+ void setBaseDir(File baseDir) {
+ this.baseDir = baseDir;
}
- @Override
- public List<File> changedFiles(FileQuery query) {
- return files(query, true);
+ void setWorkingDir(File workingDir) {
+ this.workingDir = workingDir;
}
- private List<File> files(FileQuery query, boolean changedFilesOnly) {
- List<FileSystemFilter> filters = Lists.newArrayList(fsFilters);
- if (changedFilesOnly) {
- filters.add(new ChangedFileFilter(fileHashCache));
- }
- for (FileFilter fileFilter : query.filters()) {
- filters.add(new FileFilterWrapper(fileFilter));
- }
- for (String language : query.languages()) {
- filters.add(new FileFilterWrapper(languageFilters.forLang(language)));
- }
- for (String inclusion : query.inclusions()) {
- filters.add(new InclusionFilter(inclusion));
- }
- for (String exclusion : query.exclusions()) {
- filters.add(new ExclusionFilter(exclusion));
- }
- List<File> result = Lists.newLinkedList();
- FileFilterContext context = new FileFilterContext(this);
- for (FileType type : query.types()) {
- context.setType(type);
- switch (type) {
- case SOURCE:
- applyFilters(result, context, filters, sourceDirs);
- break;
- case TEST:
- applyFilters(result, context, filters, testDirs);
- break;
- default:
- throw new IllegalArgumentException("Unknown file type: " + type);
- }
- }
- return result;
+ void setBuildDir(File buildDir) {
+ this.buildDir = buildDir;
}
- private void applyFilters(List<File> result, FileFilterContext context,
- Collection<FileSystemFilter> filters, Collection<File> dirs) {
- for (File dir : dirs) {
- if (dir.exists()) {
- context.setRelativeDir(dir);
- Collection<File> files = FileUtils.listFiles(dir, HiddenFileFilter.VISIBLE, DIR_FILTER);
- for (File file : files) {
- if (accept(file, context, filters)) {
- result.add(file);
- }
- }
- }
- }
+ void addSourceDir(File d) {
+ this.sourceDirs.add(d);
}
- private boolean accept(File file, FileFilterContext context, Collection<FileSystemFilter> filters) {
- context.setRelativePath(pathResolver.relativePath(context.relativeDir(), file));
- try {
- context.setCanonicalPath(file.getCanonicalPath());
- } catch (Exception e) {
- throw new IllegalStateException("Fail to get the canonical path of: " + file);
- }
- for (FileSystemFilter filter : filters) {
- if (!filter.accept(file, context)) {
- return false;
+ void addTestDir(File d) {
+ this.testDirs.add(d);
+ }
+
+ void addBinaryDir(File d) {
+ this.binaryDirs.add(d);
+ }
+
+ void setAdditionalSourceFiles(List<File> files) {
+ this.additionalSourceFiles = files;
+ }
+
+ void setAdditionalTestFiles(List<File> files) {
+ this.additionalTestFiles = files;
+ }
+
+ /**
+ * @since 4.0
+ */
+ public Iterable<InputFile> inputFiles(FileQuery query) {
+ List<InputFile> result = Lists.newArrayList();
+
+ FileQueryFilter filter = new FileQueryFilter(settings, query);
+ for (InputFile input : cache.byModule(moduleKey)) {
+ if (filter.accept(input)) {
+ result.add(input);
}
}
- return true;
+ return result;
+ }
+
+ @Override
+ public List<File> files(FileQuery query) {
+ return InputFile.toFiles(inputFiles(query));
}
public void resetDirs(File basedir, File buildDir, List<File> sourceDirs, List<File> testDirs, List<File> binaryDirs) {
@@ -200,6 +180,11 @@ public class DefaultModuleFileSystem implements ModuleFileSystem {
this.sourceDirs = existingDirs(sourceDirs);
this.testDirs = existingDirs(testDirs);
this.binaryDirs = existingDirs(binaryDirs);
+ indexer.index(this);
+ }
+
+ void index() {
+ indexer.index(this);
}
private List<File> existingDirs(List<File> dirs) {
@@ -212,50 +197,21 @@ public class DefaultModuleFileSystem implements ModuleFileSystem {
return builder.build();
}
- DefaultModuleFileSystem setSettings(Settings settings) {
- this.settings = settings;
- return this;
- }
-
- DefaultModuleFileSystem setBaseDir(File baseDir) {
- this.baseDir = baseDir;
- return this;
- }
-
- DefaultModuleFileSystem setWorkingDir(File workingDir) {
- this.workingDir = workingDir;
- return this;
- }
- DefaultModuleFileSystem setBuildDir(File buildDir) {
- this.buildDir = buildDir;
- return this;
- }
-
- DefaultModuleFileSystem addFilters(FileSystemFilter... f) {
- for (FileSystemFilter filter : f) {
- this.fsFilters.add(filter);
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
}
- return this;
- }
-
- DefaultModuleFileSystem setLanguageFilters(LanguageFilters languageFilters) {
- this.languageFilters = languageFilters;
- return this;
- }
-
- DefaultModuleFileSystem addSourceDir(File d) {
- this.sourceDirs.add(d);
- return this;
- }
-
- DefaultModuleFileSystem addTestDir(File d) {
- this.testDirs.add(d);
- return this;
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DefaultModuleFileSystem that = (DefaultModuleFileSystem) o;
+ return moduleKey.equals(that.moduleKey);
}
- DefaultModuleFileSystem addBinaryDir(File d) {
- this.binaryDirs.add(d);
- return this;
+ @Override
+ public int hashCode() {
+ return moduleKey.hashCode();
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilter.java
index 172b58b28fa..5cbe77975fb 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilter.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilter.java
@@ -19,19 +19,19 @@
*/
package org.sonar.batch.scan.filesystem;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
+import org.sonar.api.scan.filesystem.InputFile;
+import org.sonar.api.scan.filesystem.InputFileFilter;
-import java.io.File;
-
-class ExclusionFilter implements FileSystemFilter {
+class ExclusionFilter implements InputFileFilter {
private final PathPattern pattern;
ExclusionFilter(String s) {
this.pattern = PathPattern.create(s);
}
- public boolean accept(File file, FileSystemFilter.Context context) {
- return !pattern.match(context);
+ @Override
+ public boolean accept(InputFile inputFile) {
+ return !pattern.match(inputFile);
}
@Override
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilters.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilters.java
index e8e3eab9943..2e1130d55be 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilters.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilters.java
@@ -26,12 +26,10 @@ import org.sonar.api.batch.ResourceFilter;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
import org.sonar.api.scan.filesystem.FileExclusions;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
-import org.sonar.api.scan.filesystem.FileType;
+import org.sonar.api.scan.filesystem.InputFile;
+import org.sonar.api.scan.filesystem.InputFileFilter;
-import java.io.File;
-
-public class ExclusionFilters implements FileSystemFilter, ResourceFilter, BatchComponent {
+public class ExclusionFilters implements InputFileFilter, ResourceFilter, BatchComponent {
private final FileExclusions exclusionSettings;
public ExclusionFilters(FileExclusions exclusions) {
@@ -45,7 +43,6 @@ public class ExclusionFilters implements FileSystemFilter, ResourceFilter, Batch
log("Excluded tests: ", testExclusions());
}
-
private void log(String title, PathPattern[] patterns) {
if (patterns.length > 0) {
Logger log = LoggerFactory.getLogger(ExclusionFilters.class);
@@ -56,26 +53,38 @@ public class ExclusionFilters implements FileSystemFilter, ResourceFilter, Batch
}
}
- public boolean accept(File file, Context context) {
- PathPattern[] inclusionPatterns = context.type() == FileType.TEST ? testInclusions() : sourceInclusions();
- if (inclusionPatterns.length > 0) {
+ @Override
+ public boolean accept(InputFile inputFile) {
+ String type = inputFile.attribute(InputFile.ATTRIBUTE_TYPE);
+ PathPattern[] inclusionPatterns = null;
+ PathPattern[] exclusionPatterns = null;
+ if (InputFile.TYPE_SOURCE.equals(type)) {
+ inclusionPatterns = sourceInclusions();
+ exclusionPatterns = sourceExclusions();
+ } else if (InputFile.TYPE_TEST.equals(type)) {
+ inclusionPatterns = testInclusions();
+ exclusionPatterns = testExclusions();
+ }
+ if (inclusionPatterns != null && inclusionPatterns.length > 0) {
boolean matchInclusion = false;
for (PathPattern pattern : inclusionPatterns) {
- matchInclusion |= pattern.match(context);
+ matchInclusion |= pattern.match(inputFile);
}
if (!matchInclusion) {
return false;
}
}
- PathPattern[] exclusionPatterns = context.type() == FileType.TEST ? testExclusions() : sourceExclusions();
- for (PathPattern pattern : exclusionPatterns) {
- if (pattern.match(context)) {
- return false;
+ if (exclusionPatterns != null && exclusionPatterns.length > 0) {
+ for (PathPattern pattern : exclusionPatterns) {
+ if (pattern.match(inputFile)) {
+ return false;
+ }
}
}
return true;
}
+
public boolean isIgnored(Resource resource) {
if (ResourceUtils.isFile(resource)) {
PathPattern[] inclusionPatterns = ResourceUtils.isUnitTestClass(resource) ? testInclusions() : sourceInclusions();
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileFilterContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileFilterContext.java
deleted file mode 100644
index 738291750c0..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileFilterContext.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 02110-1301, USA.
- */
-package org.sonar.batch.scan.filesystem;
-
-import org.apache.commons.io.FilenameUtils;
-import org.sonar.api.batch.FileFilter;
-import org.sonar.api.scan.filesystem.FileType;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
-
-import java.io.File;
-
-class FileFilterContext implements FileFilter.Context {
- private final ModuleFileSystem fileSystem;
- private FileType type;
- private File sourceDir;
- private String fileRelativePath;
- private String fileCanonicalPath;
-
- FileFilterContext(ModuleFileSystem fileSystem) {
- this.fileSystem = fileSystem;
- }
-
- public ModuleFileSystem fileSystem() {
- return fileSystem;
- }
-
- public FileType type() {
- return type;
- }
-
- FileFilterContext setType(FileType t) {
- this.type = t;
- return this;
- }
-
- public File relativeDir() {
- return sourceDir;
- }
-
- public String relativePath() {
- return fileRelativePath;
- }
-
- public String canonicalPath() {
- return fileCanonicalPath;
- }
-
- FileFilterContext setRelativeDir(File d) {
- this.sourceDir = d;
- return this;
- }
-
- FileFilterContext setRelativePath(String s) {
- this.fileRelativePath = s;
- return this;
- }
-
- FileFilterContext setCanonicalPath(String s) {
- this.fileCanonicalPath = FilenameUtils.separatorsToUnix(s);
- return this;
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileHashCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileHashCache.java
deleted file mode 100644
index c17733c7be9..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileHashCache.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 02110-1301, USA.
- */
-package org.sonar.batch.scan.filesystem;
-
-import com.google.common.collect.Maps;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
-import org.picocontainer.Startable;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.scan.filesystem.PathResolver;
-import org.sonar.api.utils.SonarException;
-import org.sonar.batch.components.PastSnapshot;
-import org.sonar.batch.components.PastSnapshotFinder;
-import org.sonar.core.source.SnapshotDataType;
-import org.sonar.core.source.jdbc.SnapshotDataDao;
-import org.sonar.core.source.jdbc.SnapshotDataDto;
-
-import javax.annotation.CheckForNull;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.StringReader;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-public class FileHashCache implements BatchComponent, Startable {
-
- private Map<String, String> currentHashCache = Maps.newHashMap();
- private Map<String, String> previousHashCache = Maps.newHashMap();
-
- private PathResolver pathResolver;
- private HashBuilder hashBuilder;
- private SnapshotDataDao snapshotDataDao;
- private PastSnapshotFinder pastSnapshotFinder;
- private Snapshot snapshot;
- private ProjectDefinition module;
-
- public FileHashCache(ProjectDefinition module, PathResolver pathResolver, HashBuilder hashBuilder,
- Snapshot snapshot,
- SnapshotDataDao snapshotDataDao,
- PastSnapshotFinder pastSnapshotFinder) {
- this.module = module;
- this.pathResolver = pathResolver;
- this.hashBuilder = hashBuilder;
- this.snapshot = snapshot;
- this.snapshotDataDao = snapshotDataDao;
- this.pastSnapshotFinder = pastSnapshotFinder;
- }
-
- @Override
- public void start() {
- // Extract previous checksum of all files of this module and store them in a map
- PastSnapshot pastSnapshot = pastSnapshotFinder.findPreviousAnalysis(snapshot);
- if (pastSnapshot.isRelatedToSnapshot()) {
- Collection<SnapshotDataDto> selectSnapshotData = snapshotDataDao.selectSnapshotData(pastSnapshot.getProjectSnapshot().getId().longValue(),
- Arrays.asList(SnapshotDataType.FILE_HASH.getValue()));
- if (!selectSnapshotData.isEmpty()) {
- SnapshotDataDto snapshotDataDto = selectSnapshotData.iterator().next();
- String data = snapshotDataDto.getData();
- try {
- List<String> lines = IOUtils.readLines(new StringReader(data));
- for (String line : lines) {
- String[] keyValue = StringUtils.split(line, "=");
- if (keyValue.length == 2) {
- previousHashCache.put(keyValue[0], keyValue[1]);
- }
- }
- } catch (IOException e) {
- throw new SonarException("Unable to read previous file hashes", e);
- }
- }
- }
- }
-
- public String getCurrentHash(File file, Charset sourceCharset) {
- String relativePath = pathResolver.relativePath(module.getBaseDir(), file);
- if (!currentHashCache.containsKey(relativePath)) {
- currentHashCache.put(relativePath, hashBuilder.computeHashNormalizeLineEnds(file, sourceCharset));
- }
- return currentHashCache.get(relativePath);
- }
-
- @CheckForNull
- public String getPreviousHash(File file) {
- String relativePath = pathResolver.relativePath(module.getBaseDir(), file);
- return previousHashCache.get(relativePath);
- }
-
- @Override
- public void stop() {
- // Nothing to do
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/HashBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileHashDigest.java
index 2db7946e67c..e7f5cb31827 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/HashBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileHashDigest.java
@@ -22,30 +22,29 @@ package org.sonar.batch.scan.filesystem;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
-import org.sonar.api.BatchExtension;
-import org.sonar.api.batch.InstantiationStrategy;
-import org.sonar.api.utils.SonarException;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
+import java.io.*;
import java.nio.charset.Charset;
import java.security.MessageDigest;
/**
- * @since 4.0
+ * Computes hash of files. Ends of Lines are ignored, so files with
+ * same content but different EOL encoding have the same hash.
*/
-@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
-public final class HashBuilder implements BatchExtension {
+class FileHashDigest {
+
+ // This singleton aims only to increase the coverage by allowing
+ // to test the private method !
+ static final FileHashDigest INSTANCE = new FileHashDigest();
+
+ private FileHashDigest() {
+ }
/**
* Compute hash of a file ignoring line ends differences.
* Maximum performance is needed.
*/
- public String computeHashNormalizeLineEnds(File file, Charset charset) {
+ String hash(File file, Charset charset) {
Reader reader = null;
try {
MessageDigest md5Digest = DigestUtils.getMd5Digest();
@@ -72,14 +71,14 @@ public final class HashBuilder implements BatchExtension {
}
return Hex.encodeHexString(md5Digest.digest());
} catch (IOException e) {
- throw new SonarException("Unable to compute file hash", e);
+ throw new IllegalStateException(String.format("Fail to compute hash of file %s with charset %s", file.getAbsolutePath(), charset), e);
} finally {
IOUtils.closeQuietly(reader);
}
}
- public static byte[] charToBytesUTF(char c) {
- char[] buffer = new char[] {c};
+ private byte[] charToBytesUTF(char c) {
+ char[] buffer = new char[]{c};
byte[] b = new byte[buffer.length << 1];
for (int i = 0; i < buffer.length; i++) {
int bpos = i << 1;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ChangedFileFilter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileHashes.java
index 509fb2ef08b..5ffcc11b9dc 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ChangedFileFilter.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileHashes.java
@@ -19,30 +19,30 @@
*/
package org.sonar.batch.scan.filesystem;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
+import org.sonar.api.BatchComponent;
+import javax.annotation.CheckForNull;
import java.io.File;
+import java.nio.charset.Charset;
/**
- * When enabled this filter will only allow modified files to be analyzed.
- * @since 4.0
+ * Facade for local and remote file hashes
*/
-class ChangedFileFilter implements FileSystemFilter {
+public class FileHashes implements BatchComponent {
- private FileHashCache fileHashCache;
+ private final RemoteFileHashes remoteFileHashes;
- public ChangedFileFilter(FileHashCache fileHashCache) {
- this.fileHashCache = fileHashCache;
+ public FileHashes(RemoteFileHashes remoteFileHashes) {
+ this.remoteFileHashes = remoteFileHashes;
}
- @Override
- public boolean accept(File file, Context context) {
- String previousHash = fileHashCache.getPreviousHash(file);
- if (previousHash == null) {
- return true;
- }
- String currentHash = fileHashCache.getCurrentHash(file, context.fileSystem().sourceCharset());
- return !currentHash.equals(previousHash);
+ @CheckForNull
+ public String hash(File file, Charset charset) {
+ return FileHashDigest.INSTANCE.hash(file, charset);
}
+ @CheckForNull
+ public String remoteHash(String baseRelativePath) {
+ return remoteFileHashes.remoteHash(baseRelativePath);
+ }
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
new file mode 100644
index 00000000000..4ffcb0ee37c
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
@@ -0,0 +1,151 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 02110-1301, USA.
+ */
+package org.sonar.batch.scan.filesystem;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.apache.commons.io.filefilter.HiddenFileFilter;
+import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.scan.filesystem.InputFile;
+import org.sonar.api.scan.filesystem.InputFileFilter;
+import org.sonar.api.scan.filesystem.ModuleFileSystem;
+import org.sonar.api.scan.filesystem.PathResolver;
+
+import javax.annotation.Nullable;
+import java.io.File;
+import java.nio.charset.Charset;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Index input files into {@link InputFileCache}.
+ */
+public class FileIndexer implements BatchComponent {
+
+ private static final IOFileFilter DIR_FILTER = FileFilterUtils.and(HiddenFileFilter.VISIBLE, FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter(".")));
+ private static final IOFileFilter FILE_FILTER = HiddenFileFilter.VISIBLE;
+
+ private final PathResolver pathResolver = new PathResolver();
+ private final List<InputFileFilter> filters;
+ private final LanguageRecognizer languageRecognizer;
+ private final InputFileCache cache;
+ private final FileHashes fileHashes;
+
+ // TODO support deprecated filters
+ public FileIndexer(List<InputFileFilter> filters, LanguageRecognizer languageRecognizer,
+ InputFileCache cache, FileHashes fileHashes) {
+ this.filters = filters;
+ this.languageRecognizer = languageRecognizer;
+ this.cache = cache;
+ this.fileHashes = fileHashes;
+ }
+
+ public void index(ModuleFileSystem fileSystem) {
+ Logger logger = LoggerFactory.getLogger(FileIndexer.class);
+ logger.info("Index files");
+
+ cache.removeModule(fileSystem.moduleKey());
+ int count = 0;
+ for (File sourceDir : fileSystem.sourceDirs()) {
+ count += indexDirectory(fileSystem, sourceDir, InputFile.TYPE_SOURCE);
+ }
+ for (File testDir : fileSystem.testDirs()) {
+ count += indexDirectory(fileSystem, testDir, InputFile.TYPE_TEST);
+ }
+
+ // TODO index additional sources and test files
+
+ logger.info(String.format("%d files indexed", count));
+ }
+
+ private int indexDirectory(ModuleFileSystem fileSystem, File sourceDir, String type) {
+ int count = 0;
+ Collection<File> files = FileUtils.listFiles(sourceDir, FILE_FILTER, DIR_FILTER);
+ for (File file : files) {
+ InputFile input = newInputFile(fileSystem, sourceDir, type, file);
+ if (accept(input)) {
+ cache.put(fileSystem.moduleKey(), input);
+ count++;
+ }
+ }
+ return count;
+ }
+
+ private InputFile newInputFile(ModuleFileSystem fileSystem, File sourceDir, String type, File file) {
+ try {
+ Map<String, String> attributes = Maps.newHashMap();
+
+ // paths
+ String baseRelativePath = pathResolver.relativePath(fileSystem.baseDir(), file);
+ set(attributes, InputFile.ATTRIBUTE_SOURCEDIR_PATH, FilenameUtils.normalize(sourceDir.getCanonicalPath(), true));
+ set(attributes, InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, pathResolver.relativePath(sourceDir, file));
+ set(attributes, InputFile.ATTRIBUTE_CANONICAL_PATH, FilenameUtils.normalize(file.getCanonicalPath(), true));
+
+ // other metadata
+ set(attributes, InputFile.ATTRIBUTE_TYPE, type);
+ String extension = FilenameUtils.getExtension(file.getName());
+ set(attributes, InputFile.ATTRIBUTE_EXTENSION, extension);
+ set(attributes, InputFile.ATTRIBUTE_LANGUAGE, languageRecognizer.ofExtension(extension));
+ initStatus(file, fileSystem.sourceCharset(), baseRelativePath, attributes);
+
+ return InputFile.create(file, baseRelativePath, attributes);
+
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to read file: " + file.getAbsolutePath(), e);
+ }
+ }
+
+ private void initStatus(File file, Charset charset, String baseRelativePath, Map<String, String> attributes) {
+ String hash = fileHashes.hash(file, charset);
+ set(attributes, InputFile.ATTRIBUTE_HASH, hash);
+
+ String remoteHash = fileHashes.remoteHash(baseRelativePath);
+ // currently no need to store this remote hash in attributes
+ if (StringUtils.equals(hash, remoteHash)) {
+ set(attributes, InputFile.ATTRIBUTE_STATUS, InputFile.STATUS_SAME);
+ } else if (StringUtils.isEmpty(remoteHash)) {
+ set(attributes, InputFile.ATTRIBUTE_STATUS, InputFile.STATUS_ADDED);
+ } else {
+ set(attributes, InputFile.ATTRIBUTE_STATUS, InputFile.STATUS_CHANGED);
+ }
+ }
+
+ private void set(Map<String, String> attributes, String key, @Nullable String value) {
+ if (value != null) {
+ attributes.put(key, value);
+ }
+ }
+
+ private boolean accept(InputFile inputFile) {
+ for (InputFileFilter filter : filters) {
+ if (!filter.accept(inputFile)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java
new file mode 100644
index 00000000000..b62694c3b6c
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java
@@ -0,0 +1,67 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 02110-1301, USA.
+ */
+package org.sonar.batch.scan.filesystem;
+
+import com.google.common.collect.Lists;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.scan.filesystem.FileQuery;
+import org.sonar.api.scan.filesystem.InputFile;
+import org.sonar.api.scan.filesystem.InputFileFilter;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+class FileQueryFilter {
+
+ private final List<InputFileFilter> filters;
+
+ FileQueryFilter(Settings settings, FileQuery query) {
+ filters = Lists.newArrayList();
+ for (String pattern : query.inclusions()) {
+ filters.add(new InclusionFilter(pattern));
+ }
+ for (String pattern : query.exclusions()) {
+ filters.add(new ExclusionFilter(pattern));
+ }
+ for (Map.Entry<String, Collection<String>> entry : query.attributes().entrySet()) {
+ filters.add(new AttributeFilter(entry.getKey(), entry.getValue()));
+ }
+
+ // TODO speed-up the following algorithm. Cache ?
+ if (settings.getBoolean(CoreProperties.INCREMENTAL_PREVIEW)) {
+ Collection<String> status = query.attributes().get(InputFile.ATTRIBUTE_STATUS);
+ if (status == null || status.isEmpty()) {
+ // TODO should be not(SAME) instead of is(ADDED, CHANGED)
+ filters.add(new AttributeFilter(InputFile.ATTRIBUTE_STATUS, Lists.newArrayList(InputFile.STATUS_ADDED, InputFile.STATUS_CHANGED)));
+ }
+ }
+ }
+
+ boolean accept(InputFile inputFile) {
+ for (InputFileFilter filter : filters) {
+ if (!filter.accept(inputFile)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileSystemLogger.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileSystemLogger.java
index c52b00c32df..2d402d358b0 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileSystemLogger.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileSystemLogger.java
@@ -23,13 +23,14 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
import java.io.File;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Locale;
-public class FileSystemLogger {
+public class FileSystemLogger implements BatchComponent {
private final DefaultModuleFileSystem fs;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InclusionFilter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InclusionFilter.java
index 43c776121e8..ef5d391e0cc 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InclusionFilter.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InclusionFilter.java
@@ -19,19 +19,19 @@
*/
package org.sonar.batch.scan.filesystem;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
+import org.sonar.api.scan.filesystem.InputFile;
+import org.sonar.api.scan.filesystem.InputFileFilter;
-import java.io.File;
-
-class InclusionFilter implements FileSystemFilter {
+class InclusionFilter implements InputFileFilter {
private final PathPattern pattern;
InclusionFilter(String s) {
this.pattern = PathPattern.create(s);
}
- public boolean accept(File file, FileSystemFilter.Context context) {
- return pattern.match(context);
+ @Override
+ public boolean accept(InputFile inputFile) {
+ return pattern.match(inputFile);
}
@Override
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageFilters.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java
index fcc887b7d49..f45f8088f85 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageFilters.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java
@@ -19,31 +19,39 @@
*/
package org.sonar.batch.scan.filesystem;
-import org.apache.commons.io.IOCase;
-import org.apache.commons.io.filefilter.FalseFileFilter;
-import org.apache.commons.io.filefilter.IOFileFilter;
-import org.apache.commons.io.filefilter.SuffixFileFilter;
-import org.apache.commons.io.filefilter.TrueFileFilter;
import org.sonar.api.BatchComponent;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
+import org.sonar.api.scan.filesystem.InputFile;
+import org.sonar.batch.index.Cache;
+import org.sonar.batch.index.Caches;
-public class LanguageFilters implements BatchComponent {
- private final Languages languages;
+/**
+ * Cache of all files. This cache is shared amongst all project modules. Inclusion and
+ * exclusion patterns are already applied.
+ */
+public class InputFileCache implements BatchComponent {
+
+ // module key -> path -> InputFile
+ private final Cache<String, InputFile> cache;
+
+ public InputFileCache(Caches caches) {
+ cache = caches.createCache("inputFiles");
+ }
+
+ public Iterable<InputFile> byModule(String moduleKey) {
+ return cache.values(moduleKey);
+ }
+
+ public InputFileCache removeModule(String moduleKey) {
+ cache.clear(moduleKey);
+ return this;
+ }
- public LanguageFilters(Languages languages) {
- this.languages = languages;
+ public Iterable<InputFile> all() {
+ return cache.allValues();
}
- public IOFileFilter forLang(String lang) {
- Language language = languages.get(lang);
- if (language == null) {
- return FalseFileFilter.FALSE;
- }
- String[] suffixes = language.getFileSuffixes();
- if (suffixes != null && suffixes.length>0) {
- return new SuffixFileFilter(suffixes, IOCase.SENSITIVE);
- }
- return TrueFileFilter.TRUE;
+ public InputFileCache put(String moduleKey, InputFile file) {
+ cache.put(moduleKey, file.path(), file);
+ return this;
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageRecognizer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageRecognizer.java
new file mode 100644
index 00000000000..61396830599
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageRecognizer.java
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 02110-1301, USA.
+ */
+package org.sonar.batch.scan.filesystem;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.resources.Language;
+
+import javax.annotation.CheckForNull;
+import java.util.Map;
+
+/**
+ * Based on file extensions.
+ */
+public class LanguageRecognizer implements BatchComponent {
+
+ private final Map<String, String> byExtensions = Maps.newHashMap();
+
+ public LanguageRecognizer(Language[] languages) {
+ for (Language language : languages) {
+ for (String suffix : language.getFileSuffixes()) {
+ String extension = StringUtils.removeStart(suffix, ".");
+
+ String s = byExtensions.get(extension);
+ if (s != null) {
+ throw new IllegalStateException(String.format(
+ "File extension '%s' is declared by two languages: %s and %s", extension, s, language.getKey()
+ ));
+ }
+ byExtensions.put(extension, language.getKey());
+ }
+ }
+ }
+
+ // TODO what about cobol files without extension ?
+ @CheckForNull
+ String ofExtension(String fileExtension) {
+ if (StringUtils.isNotBlank(fileExtension)) {
+ return byExtensions.get(fileExtension);
+ }
+ return null;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleFileSystemProvider.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleFileSystemProvider.java
index 3efae8a0ec0..7bd84e87ef7 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleFileSystemProvider.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleFileSystemProvider.java
@@ -19,13 +19,11 @@
*/
package org.sonar.batch.scan.filesystem;
-import com.google.common.collect.ImmutableSet;
import org.apache.commons.io.FileUtils;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.FileSystemFilter;
-import org.sonar.api.scan.filesystem.FileType;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.batch.bootstrap.TempDirectories;
@@ -37,22 +35,21 @@ import java.util.List;
*/
public class ModuleFileSystemProvider extends ProviderAdapter {
+ private PathResolver pathResolver = new PathResolver();
private DefaultModuleFileSystem singleton;
- public DefaultModuleFileSystem provide(ProjectDefinition module, PathResolver pathResolver, TempDirectories tempDirectories,
- LanguageFilters languageFilters, Settings settings, FileSystemFilter[] pluginFileFilters,
- FileHashCache fileHashCache) {
+ public DefaultModuleFileSystem provide(
+ ProjectDefinition module, TempDirectories tempDirectories,Settings settings, InputFileCache cache, FileIndexer indexer) {
+
if (singleton == null) {
- DefaultModuleFileSystem fs = new DefaultModuleFileSystem(fileHashCache);
- fs.setLanguageFilters(languageFilters);
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem(module.getKey(), settings, cache, indexer);
fs.setBaseDir(module.getBaseDir());
fs.setBuildDir(module.getBuildDir());
- fs.setSettings(settings);
fs.setWorkingDir(guessWorkingDir(module, tempDirectories));
- fs.addFilters(pluginFileFilters);
- initBinaryDirs(module, pathResolver, fs);
- initSources(module, pathResolver, fs);
- initTests(module, pathResolver, fs);
+ initBinaryDirs(module, fs);
+ initSources(module, fs);
+ initTests(module, fs);
+ fs.index();
singleton = fs;
}
return singleton;
@@ -72,7 +69,7 @@ public class ModuleFileSystemProvider extends ProviderAdapter {
return workDir;
}
- private void initSources(ProjectDefinition module, PathResolver pathResolver, DefaultModuleFileSystem fs) {
+ private void initSources(ProjectDefinition module, DefaultModuleFileSystem fs) {
for (String sourcePath : module.getSourceDirs()) {
File dir = pathResolver.relativeFile(module.getBaseDir(), sourcePath);
if (dir.isDirectory() && dir.exists()) {
@@ -80,12 +77,10 @@ public class ModuleFileSystemProvider extends ProviderAdapter {
}
}
List<File> sourceFiles = pathResolver.relativeFiles(module.getBaseDir(), module.getSourceFiles());
- if (!sourceFiles.isEmpty()) {
- fs.addFilters(new WhiteListFileFilter(FileType.SOURCE, ImmutableSet.copyOf(sourceFiles)));
- }
+ fs.setAdditionalSourceFiles(sourceFiles);
}
- private void initTests(ProjectDefinition module, PathResolver pathResolver, DefaultModuleFileSystem fs) {
+ private void initTests(ProjectDefinition module, DefaultModuleFileSystem fs) {
for (String testPath : module.getTestDirs()) {
File dir = pathResolver.relativeFile(module.getBaseDir(), testPath);
if (dir.exists() && dir.isDirectory()) {
@@ -93,12 +88,10 @@ public class ModuleFileSystemProvider extends ProviderAdapter {
}
}
List<File> testFiles = pathResolver.relativeFiles(module.getBaseDir(), module.getTestFiles());
- if (!testFiles.isEmpty()) {
- fs.addFilters(new WhiteListFileFilter(FileType.TEST, ImmutableSet.copyOf(testFiles)));
- }
+ fs.setAdditionalTestFiles(testFiles);
}
- private void initBinaryDirs(ProjectDefinition module, PathResolver pathResolver, DefaultModuleFileSystem fs) {
+ private void initBinaryDirs(ProjectDefinition module, DefaultModuleFileSystem fs) {
for (String path : module.getBinaries()) {
File dir = pathResolver.relativeFile(module.getBaseDir(), path);
fs.addBinaryDir(dir);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/PathPattern.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/PathPattern.java
index bd6eb8479e0..2df7c53e4d6 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/PathPattern.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/PathPattern.java
@@ -21,20 +21,21 @@ package org.sonar.batch.scan.filesystem;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.resources.Resource;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
+import org.sonar.api.scan.filesystem.InputFile;
import org.sonar.api.utils.WildcardPattern;
abstract class PathPattern {
+
final WildcardPattern pattern;
PathPattern(String pattern) {
this.pattern = WildcardPattern.create(pattern);
}
- abstract boolean match(FileSystemFilter.Context context);
-
abstract boolean match(Resource resource);
+ abstract boolean match(InputFile inputFile);
+
abstract boolean supportResource();
static PathPattern create(String s) {
@@ -58,14 +59,17 @@ abstract class PathPattern {
super(pattern);
}
- boolean match(FileSystemFilter.Context context) {
- return pattern.match(context.canonicalPath());
+ @Override
+ boolean match(InputFile inputFile) {
+ return pattern.match(inputFile.attribute(InputFile.ATTRIBUTE_CANONICAL_PATH));
}
+ @Override
boolean match(Resource resource) {
return false;
}
+ @Override
boolean supportResource() {
return false;
}
@@ -76,19 +80,26 @@ abstract class PathPattern {
}
}
+ /**
+ * Path relative to source directory
+ */
private static class RelativePathPattern extends PathPattern {
private RelativePathPattern(String pattern) {
super(pattern);
}
- boolean match(FileSystemFilter.Context context) {
- return pattern.match(context.relativePath());
+ @Override
+ boolean match(InputFile inputFile) {
+ String path = inputFile.attribute(InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH);
+ return path != null && pattern.match(path);
}
+ @Override
boolean match(Resource resource) {
return resource.matchFilePattern(pattern.toString());
}
+ @Override
boolean supportResource() {
return true;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileSystemAdapter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapter.java
index 4379089c86e..1f5ab333658 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileSystemAdapter.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapter.java
@@ -24,19 +24,12 @@ import com.google.common.collect.Lists;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.CharEncoding;
import org.apache.maven.project.MavenProject;
-import org.sonar.api.resources.InputFile;
-import org.sonar.api.resources.InputFileUtils;
-import org.sonar.api.resources.Java;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.ProjectFileSystem;
-import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.*;
import org.sonar.api.scan.filesystem.FileQuery;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.SonarException;
import javax.annotation.Nullable;
-
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
@@ -47,14 +40,14 @@ import java.util.List;
*
* @since 3.5
*/
-public class DeprecatedFileSystemAdapter implements ProjectFileSystem {
+public class ProjectFileSystemAdapter implements ProjectFileSystem {
private final DefaultModuleFileSystem target;
private final PathResolver pathResolver = new PathResolver();
private final MavenProject pom;
- public DeprecatedFileSystemAdapter(DefaultModuleFileSystem target, Project project, @Nullable MavenProject pom) {
+ public ProjectFileSystemAdapter(DefaultModuleFileSystem target, Project project, @Nullable MavenProject pom) {
this.target = target;
this.pom = pom;
@@ -63,7 +56,7 @@ public class DeprecatedFileSystemAdapter implements ProjectFileSystem {
project.setFileSystem(this);
}
- public DeprecatedFileSystemAdapter(DefaultModuleFileSystem target, Project project) {
+ public ProjectFileSystemAdapter(DefaultModuleFileSystem target, Project project) {
this(target, project, null);
}
@@ -192,11 +185,12 @@ public class DeprecatedFileSystemAdapter implements ProjectFileSystem {
public List<InputFile> mainFiles(String... langs) {
List<InputFile> result = Lists.newArrayList();
- List<File> files = target.files(FileQuery.onSource().onLanguage(langs));
- for (File file : files) {
- PathResolver.RelativePath relativePath = pathResolver.relativePath(getSourceDirs(), file);
- if (relativePath != null) {
- result.add(InputFileUtils.create(relativePath.dir(), relativePath.path()));
+ Iterable<org.sonar.api.scan.filesystem.InputFile> files = target.inputFiles(FileQuery.onSource().onLanguage(langs));
+ for (org.sonar.api.scan.filesystem.InputFile file : files) {
+ String sourceDir = file.attribute(org.sonar.api.scan.filesystem.InputFile.ATTRIBUTE_SOURCEDIR_PATH);
+ String sourceRelativePath = file.attribute(org.sonar.api.scan.filesystem.InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH);
+ if (sourceDir != null && sourceRelativePath != null) {
+ result.add(InputFileUtils.create(new File(sourceDir), sourceRelativePath));
}
}
return result;
@@ -204,14 +198,14 @@ public class DeprecatedFileSystemAdapter implements ProjectFileSystem {
public List<InputFile> testFiles(String... langs) {
List<InputFile> result = Lists.newArrayList();
- List<File> files = target.files(FileQuery.onTest().onLanguage(langs));
- for (File file : files) {
- PathResolver.RelativePath relativePath = pathResolver.relativePath(getTestDirs(), file);
- if (relativePath != null) {
- result.add(InputFileUtils.create(relativePath.dir(), relativePath.path()));
+ Iterable<org.sonar.api.scan.filesystem.InputFile> files = target.inputFiles(FileQuery.onTest().onLanguage(langs));
+ for (org.sonar.api.scan.filesystem.InputFile file : files) {
+ String sourceDir = file.attribute(org.sonar.api.scan.filesystem.InputFile.ATTRIBUTE_SOURCEDIR_PATH);
+ String sourceRelativePath = file.attribute(org.sonar.api.scan.filesystem.InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH);
+ if (sourceDir != null && sourceRelativePath != null) {
+ result.add(InputFileUtils.create(new File(sourceDir), sourceRelativePath));
}
}
-
return result;
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/RemoteFileHashes.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/RemoteFileHashes.java
new file mode 100644
index 00000000000..b2d8853e799
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/RemoteFileHashes.java
@@ -0,0 +1,77 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 02110-1301, USA.
+ */
+package org.sonar.batch.scan.filesystem;
+
+import com.google.common.collect.Maps;
+import org.picocontainer.Startable;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.batch.components.PastSnapshot;
+import org.sonar.batch.components.PastSnapshotFinder;
+import org.sonar.core.source.SnapshotDataType;
+import org.sonar.core.source.jdbc.SnapshotDataDao;
+import org.sonar.core.source.jdbc.SnapshotDataDto;
+
+import javax.annotation.CheckForNull;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+public class RemoteFileHashes implements BatchComponent, Startable {
+
+ private final SnapshotDataDao dao;
+ private final PastSnapshotFinder pastSnapshotFinder;
+ private final Snapshot snapshot;
+
+ private Map<String, String> pathToHash = Maps.newHashMap();
+
+ public RemoteFileHashes(Snapshot snapshot, SnapshotDataDao dao, PastSnapshotFinder pastSnapshotFinder) {
+ this.snapshot = snapshot;
+ this.dao = dao;
+ this.pastSnapshotFinder = pastSnapshotFinder;
+ }
+
+ @Override
+ public void start() {
+ // Extract previous checksum of all files of this module and store them in a map
+ PastSnapshot pastSnapshot = pastSnapshotFinder.findPreviousAnalysis(snapshot);
+ if (pastSnapshot.isRelatedToSnapshot()) {
+ Collection<SnapshotDataDto> selectSnapshotData = dao.selectSnapshotData(
+ pastSnapshot.getProjectSnapshot().getId().longValue(),
+ Arrays.asList(SnapshotDataType.FILE_HASH.getValue())
+ );
+ if (!selectSnapshotData.isEmpty()) {
+ SnapshotDataDto snapshotDataDto = selectSnapshotData.iterator().next();
+ String data = snapshotDataDto.getData();
+ pathToHash = KeyValueFormat.parse(data);
+ }
+ }
+ }
+
+ @CheckForNull
+ public String remoteHash(String baseRelativePath) {
+ return pathToHash.get(baseRelativePath);
+ }
+
+ @Override
+ public void stop() {
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/WhiteListFileFilter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/WhiteListFileFilter.java
deleted file mode 100644
index fb4cdb6b64e..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/WhiteListFileFilter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 02110-1301, USA.
- */
-package org.sonar.batch.scan.filesystem;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.SystemUtils;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
-import org.sonar.api.scan.filesystem.FileType;
-
-import java.io.File;
-import java.util.Set;
-
-/**
- * @since 3.5
- */
-class WhiteListFileFilter implements FileSystemFilter {
- private final FileType fileType;
- private final Set<File> files;
-
- WhiteListFileFilter(FileType fileType, Set<File> files) {
- Preconditions.checkNotNull(fileType);
- Preconditions.checkNotNull(files);
- this.fileType = fileType;
- this.files = files;
- }
-
- public boolean accept(File file, Context context) {
- return !context.type().equals(fileType) || files.contains(file);
- }
-
- @Override
- public String toString() {
- return StringUtils.capitalize(fileType.name().toLowerCase()) + " files: " + SystemUtils.LINE_SEPARATOR +
- Joiner.on(SystemUtils.LINE_SEPARATOR).join(files);
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/UnsupportedPropertiesTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/UnsupportedPropertiesTest.java
index 648bee96caa..f5246e64099 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/UnsupportedPropertiesTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/UnsupportedPropertiesTest.java
@@ -22,8 +22,9 @@ package org.sonar.batch.scan;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
-import org.sonar.batch.scan.UnsupportedProperties;
+import org.sonar.api.utils.MessageException;
public class UnsupportedPropertiesTest {
@@ -32,10 +33,11 @@ public class UnsupportedPropertiesTest {
@Test
public void should_fail_if_sonar_light_is_set() {
+ thrown.expect(MessageException.class);
+ thrown.expectMessage("The property 'sonar.light' is no longer supported. Please use 'sonar.dynamicAnalysis'");
+
Settings settings = new Settings();
settings.setProperty("sonar.light", true);
-
- thrown.expect(IllegalArgumentException.class);
new UnsupportedProperties(settings).start();
}
@@ -44,4 +46,23 @@ public class UnsupportedPropertiesTest {
Settings settings = new Settings();
new UnsupportedProperties(settings).start();
}
+
+ @Test
+ public void should_fail_if_incremental_but_not_preview_mode() {
+ thrown.expect(MessageException.class);
+ thrown.expectMessage("Incremental mode is only supported with preview mode");
+
+ Settings settings = new Settings();
+ settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true);
+ settings.setProperty(CoreProperties.DRY_RUN, false);
+ new UnsupportedProperties(settings).start();
+ }
+
+ @Test
+ public void should_not_fail_if_incremental_preview_mode() {
+ Settings settings = new Settings();
+ settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true);
+ settings.setProperty(CoreProperties.DRY_RUN, true);
+ new UnsupportedProperties(settings).start();
+ }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileFilterContextTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AttributeFilterTest.java
index aa74da4c145..1ce0a8a4019 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileFilterContextTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AttributeFilterTest.java
@@ -19,27 +19,27 @@
*/
package org.sonar.batch.scan.filesystem;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
-
-import java.io.File;
-import java.io.IOException;
+import org.sonar.api.scan.filesystem.InputFile;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-public class FileFilterContextTest {
+public class AttributeFilterTest {
+
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Test
- public void should_use_slash_for_canonical_path() throws IOException {
- // even on windows
- File file = temp.newFile("foo.txt");
- FileFilterContext context = new FileFilterContext(mock(ModuleFileSystem.class));
- context.setCanonicalPath(file.getCanonicalPath());
- assertThat(context.canonicalPath()).doesNotContain("\\").contains("/");
+ public void should_check_attribute_value() throws Exception {
+ AttributeFilter filter = new AttributeFilter("foo", Lists.newArrayList("one", "two"));
+
+ assertThat(filter.accept(InputFile.create(temp.newFile(), "Why.java", ImmutableMap.of("foo", "two")))).isTrue();
+ assertThat(filter.accept(InputFile.create(temp.newFile(), "Where.java", ImmutableMap.of("foo", "three")))).isFalse();
+ assertThat(filter.accept(InputFile.create(temp.newFile(), "What.java", ImmutableMap.of("bar", "one")))).isFalse();
+
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java
index 61f0ccbe5bd..c0dfddb5a7e 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java
@@ -19,286 +19,336 @@
*/
package org.sonar.batch.scan.filesystem;
-import com.google.common.base.Charsets;
-import org.apache.commons.io.filefilter.FileFilterUtils;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
-import org.sonar.api.resources.AbstractLanguage;
-import org.sonar.api.resources.Languages;
import org.sonar.api.scan.filesystem.FileQuery;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
-import org.sonar.api.utils.SonarException;
+import org.sonar.api.scan.filesystem.InputFile;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
-import java.util.Arrays;
import java.util.List;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
public class DefaultModuleFileSystemTest {
+
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Rule
public ExpectedException thrown = ExpectedException.none();
+ InputFileCache fileCache = mock(InputFileCache.class);
+ Settings settings = new Settings();
+ FileIndexer fileIndexer = mock(FileIndexer.class);
+
@Test
- public void test_new_file_system() throws IOException {
- File basedir = temp.newFolder("base");
- File workingDir = temp.newFolder("work");
- LanguageFilters languageFilters = mock(LanguageFilters.class);
- FileSystemFilter fileFilter = mock(FileSystemFilter.class);
-
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(FileHashCache.class))
- .setBaseDir(basedir)
- .setWorkingDir(workingDir)
- .addBinaryDir(new File(basedir, "target/classes"))
- .addSourceDir(new File(basedir, "src/main/java"))
- .addSourceDir(new File(basedir, "src/main/groovy"))
- .addTestDir(new File(basedir, "src/test/java"))
- .addFilters(fileFilter)
- .setLanguageFilters(languageFilters);
-
- assertThat(fileSystem).isNotNull();
- assertThat(fileSystem.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
- assertThat(fileSystem.workingDir().getCanonicalPath()).isEqualTo(workingDir.getCanonicalPath());
- assertThat(fileSystem.sourceDirs()).hasSize(2);
- assertThat(fileSystem.testDirs()).hasSize(1);
- assertThat(fileSystem.binaryDirs()).hasSize(1);
- assertThat(fileSystem.filters()).containsOnly(fileFilter);
- assertThat(fileSystem.languageFilters()).isSameAs(languageFilters);
+ public void test_equals_and_hashCode() throws Exception {
+ DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem("foo", settings, fileCache, fileIndexer);
+ DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem("foo", settings, fileCache, fileIndexer);
+ DefaultModuleFileSystem bar = new DefaultModuleFileSystem("bar", settings, fileCache, fileIndexer);
+
+ assertThat(foo1.moduleKey()).isEqualTo("foo");
+ assertThat(foo1.equals(foo1)).isTrue();
+ assertThat(foo1.equals(foo2)).isTrue();
+ assertThat(foo1.equals(bar)).isFalse();
+ assertThat(foo1.equals("foo")).isFalse();
+ assertThat(foo1.hashCode()).isEqualTo(foo1.hashCode());
+ assertThat(foo1.hashCode()).isEqualTo(foo2.hashCode());
}
@Test
public void default_source_encoding() {
- File basedir = temp.newFolder("base");
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(FileHashCache.class))
- .setBaseDir(basedir)
- .setSettings(new Settings());
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileCache, fileIndexer);
- assertThat(fileSystem.sourceCharset()).isEqualTo(Charset.defaultCharset());
- assertThat(fileSystem.isDefaultSourceCharset()).isTrue();
+ assertThat(fs.sourceCharset()).isEqualTo(Charset.defaultCharset());
+ assertThat(fs.isDefaultSourceCharset()).isTrue();
}
@Test
public void source_encoding_is_set() {
- File basedir = temp.newFolder("base");
- Settings settings = new Settings();
- settings.setProperty(CoreProperties.ENCODING_PROPERTY, "UTF-8");
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(FileHashCache.class))
- .setBaseDir(basedir)
- .setSettings(settings);
-
- assertThat(fileSystem.sourceCharset()).isEqualTo(Charset.forName("UTF-8"));
- assertThat(fileSystem.isDefaultSourceCharset()).isFalse();
- }
+ settings.setProperty(CoreProperties.ENCODING_PROPERTY, "Cp1124");
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileCache, fileIndexer);
- @Test
- public void should_exclude_dirs_starting_with_dot() throws IOException {
- File basedir = new File(resourcesDir(), "exclude_dir_starting_with_dot");
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(FileHashCache.class))
- .setBaseDir(basedir)
- .setWorkingDir(temp.newFolder())
- .addSourceDir(new File(basedir, "src"))
- .setSettings(new Settings());
-
- List<File> files = fileSystem.files(FileQuery.onSource());
- assertThat(files).hasSize(1);
- assertThat(files.get(0).getName()).isEqualTo("Included.java");
+ assertThat(fs.sourceCharset()).isEqualTo(Charset.forName("Cp1124"));
+
+ // This test fails when default Java encoding is "IBM AIX Ukraine". Sorry for that.
+ assertThat(fs.isDefaultSourceCharset()).isFalse();
}
@Test
- public void should_load_source_files_by_language() throws IOException {
- File basedir = new File(resourcesDir(), "main_and_test_files");
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(FileHashCache.class))
- .setBaseDir(basedir)
- .setWorkingDir(temp.newFolder())
- .addSourceDir(new File(basedir, "src/main/java"))
- .addTestDir(new File(basedir, "src/test/java"))
- .setLanguageFilters(new LanguageFilters(new Languages(new Java(), new Php())))
- .setSettings(new Settings());
-
- List<File> files = fileSystem.files(FileQuery.onSource().onLanguage("java"));
- assertThat(files).hasSize(2);
- for (File sourceFiles : files) {
- assertThat(sourceFiles).exists().isFile();
- assertThat(sourceFiles.getName()).isIn("Hello.java", "Foo.java");
- }
- assertThat(fileSystem.files(FileQuery.onSource().onLanguage("php"))).isEmpty();
+ public void test_dirs() throws IOException {
+ File basedir = temp.newFolder("base");
+ File buildDir = temp.newFolder("build");
+ File workingDir = temp.newFolder("work");
+
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileCache, fileIndexer);
+ fs.setBaseDir(basedir);
+ fs.setBuildDir(buildDir);
+ fs.setWorkingDir(workingDir);
+ fs.addBinaryDir(new File(basedir, "target/classes"));
+ fs.addSourceDir(new File(basedir, "src/main/java"));
+ fs.addSourceDir(new File(basedir, "src/main/groovy"));
+ fs.addTestDir(new File(basedir, "src/test/java"));
+
+ assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
+ assertThat(fs.workingDir().getCanonicalPath()).isEqualTo(workingDir.getCanonicalPath());
+ assertThat(fs.buildDir().getCanonicalPath()).isEqualTo(buildDir.getCanonicalPath());
+ assertThat(fs.sourceDirs()).hasSize(2);
+ assertThat(fs.testDirs()).hasSize(1);
+ assertThat(fs.binaryDirs()).hasSize(1);
}
@Test
- public void should_load_test_files() throws IOException {
- File basedir = new File(resourcesDir(), "main_and_test_files");
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(FileHashCache.class))
- .setBaseDir(basedir)
- .setWorkingDir(temp.newFolder())
- .addSourceDir(new File(basedir, "src/main/java"))
- .addTestDir(new File(basedir, "src/test/java"))
- .setSettings(new Settings());
-
- assertThat(fileSystem.testDirs()).hasSize(1);
- List<File> testFiles = fileSystem.files(FileQuery.onTest());
- assertThat(testFiles).hasSize(2);
- for (File testFile : testFiles) {
- assertThat(testFile).exists().isFile();
- assertThat(testFile.getName()).endsWith("Test.java");
- }
+ public void test_additional_source_files() throws IOException {
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileCache, fileIndexer);
+ assertThat(fs.additionalSourceFiles()).isEmpty();
+ assertThat(fs.additionalTestFiles()).isEmpty();
+
+ File main = temp.newFile("Main.java");
+ File test = temp.newFile("Test.java");
+ fs.setAdditionalSourceFiles(Lists.newArrayList(main));
+ fs.setAdditionalTestFiles(Lists.newArrayList(test));
+ assertThat(fs.additionalSourceFiles()).containsOnly(main);
+ assertThat(fs.additionalTestFiles()).containsOnly(test);
}
@Test
- public void should_load_test_files_by_language() throws IOException {
- File basedir = new File(resourcesDir(), "main_and_test_files");
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(FileHashCache.class))
- .setBaseDir(basedir)
- .setWorkingDir(temp.newFolder())
- .addSourceDir(new File(basedir, "src/main/java"))
- .addTestDir(new File(basedir, "src/test/java"))
- .setLanguageFilters(new LanguageFilters(new Languages(new Java(), new Php())))
- .setSettings(new Settings());
-
- List<File> testFiles = fileSystem.files(FileQuery.onTest().onLanguage("java"));
- assertThat(testFiles).hasSize(2);
- for (File testFile : testFiles) {
- assertThat(testFile).exists().isFile();
- assertThat(testFile.getName()).endsWith("Test.java");
- }
- assertThat(fileSystem.files(FileQuery.onTest().onLanguage("php"))).isEmpty();
- }
+ public void should_reset_dirs() throws IOException {
+ File basedir = temp.newFolder();
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileCache, fileIndexer);
+ fs.setBaseDir(basedir);
+ fs.setWorkingDir(basedir);
+ fs.addSourceDir(new File(basedir, "src/main/java"));
- private File resourcesDir() {
- File dir = new File("test-resources/DefaultModuleFileSystemTest");
- if (!dir.exists()) {
- dir = new File("sonar-batch/test-resources/DefaultModuleFileSystemTest");
- }
- return dir;
+ File existingDir = temp.newFolder("new_folder");
+ File notExistingDir = new File(existingDir, "not_exist");
+
+ fs.resetDirs(existingDir, existingDir,
+ Lists.newArrayList(existingDir, notExistingDir), Lists.newArrayList(existingDir, notExistingDir), Lists.newArrayList(existingDir, notExistingDir));
+
+ assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
+ assertThat(fs.buildDir().getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
+ assertThat(fs.sourceDirs()).hasSize(1);
+ assertThat(fs.sourceDirs().get(0).getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
+ assertThat(fs.testDirs()).hasSize(1);
+ assertThat(fs.testDirs().get(0).getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
+ assertThat(fs.binaryDirs()).hasSize(1);
+ assertThat(fs.binaryDirs().get(0).getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
+ verify(fileIndexer).index(fs);
}
@Test
- public void should_apply_file_filters() throws IOException {
- File basedir = new File(resourcesDir(), "main_and_test_files");
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(FileHashCache.class))
- .setBaseDir(basedir)
- .setWorkingDir(temp.newFolder())
- .addSourceDir(new File(basedir, "src/main/java"))
- .addFilters(new FileFilterWrapper(FileFilterUtils.nameFileFilter("Foo.java")))
- .setSettings(new Settings());
-
- List<File> files = fileSystem.files(FileQuery.onSource());
- assertThat(files).hasSize(1);
- assertThat(files.get(0).getName()).isEqualTo("Foo.java");
- }
+ public void should_search_input_files() throws Exception {
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileCache, fileIndexer);
- static class Php extends AbstractLanguage {
- public Php() {
- super("php");
- }
+ File mainFile = temp.newFile();
+ InputFile mainInput = InputFile.create(mainFile, "Main.java", ImmutableMap.of(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE));
+ InputFile testInput = InputFile.create(temp.newFile(), "Test.java", ImmutableMap.of(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST));
- public String[] getFileSuffixes() {
- return new String[] {"php"};
- }
- }
+ when(fileCache.byModule("foo")).thenReturn(Lists.newArrayList(mainInput, testInput));
- static class Java extends AbstractLanguage {
- public Java() {
- super("java");
- }
+ Iterable<InputFile> inputFiles = fs.inputFiles(FileQuery.onSource());
+ assertThat(inputFiles).containsOnly(mainInput);
- public String[] getFileSuffixes() {
- return new String[] {"java", "jav"};
- }
+ List<File> files = fs.files(FileQuery.onSource());
+ assertThat(files).containsOnly(mainFile);
}
@Test
- public void test_reset_dirs() throws IOException {
- File basedir = temp.newFolder();
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(FileHashCache.class))
- .setBaseDir(basedir)
- .setWorkingDir(basedir)
- .addSourceDir(new File(basedir, "src/main/java"))
- .addFilters(new FileFilterWrapper(FileFilterUtils.nameFileFilter("Foo.java")));
-
- File existingDir = temp.newFolder("new_folder");
- File notExistingDir = new File(existingDir, "not_exist");
+ public void should_index() throws Exception {
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileCache, fileIndexer);
- fileSystem.resetDirs(existingDir, existingDir,
- Arrays.asList(existingDir, notExistingDir), Arrays.asList(existingDir, notExistingDir), Arrays.asList(existingDir, notExistingDir));
-
- assertThat(fileSystem.baseDir().getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
- assertThat(fileSystem.buildDir().getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
- assertThat(fileSystem.sourceDirs()).hasSize(1);
- assertThat(fileSystem.sourceDirs().get(0).getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
- assertThat(fileSystem.testDirs()).hasSize(1);
- assertThat(fileSystem.testDirs().get(0).getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
- assertThat(fileSystem.binaryDirs()).hasSize(1);
- assertThat(fileSystem.binaryDirs().get(0).getCanonicalPath()).isEqualTo(existingDir.getCanonicalPath());
- }
+ verifyZeroInteractions(fileIndexer);
- @Test
- public void should_throw_if_incremental_mode_and_not_in_dryrun() throws Exception {
- File basedir = temp.newFolder();
- Settings settings = new Settings();
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(FileHashCache.class))
- .setBaseDir(basedir)
- .setWorkingDir(temp.newFolder())
- .addSourceDir(new File(basedir, "src/main/java"))
- .setSettings(settings);
-
- settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true);
-
- thrown.expect(SonarException.class);
- thrown.expectMessage("Incremental preview is only supported with preview mode");
- fileSystem.files(FileQuery.onSource());
+ fs.index();
+ verify(fileIndexer).index(fs);
}
- @Test
- public void should_filter_changed_files() throws Exception {
- File basedir = new File(resourcesDir(), "main_and_test_files");
- Settings settings = new Settings();
- settings.setProperty(CoreProperties.ENCODING_PROPERTY, "UTF-8");
- File mainDir = new File(basedir, "src/main/java");
- File testDir = new File(basedir, "src/test/java");
- File foo = new File(mainDir, "Foo.java");
- File hello = new File(mainDir, "Hello.java");
- File fooTest = new File(testDir, "FooTest.java");
- File helloTest = new File(testDir, "HelloTest.java");
-
- FileHashCache fileHashCache = mock(FileHashCache.class);
- when(fileHashCache.getPreviousHash(foo)).thenReturn("oldfoohash");
- when(fileHashCache.getCurrentHash(foo, Charsets.UTF_8)).thenReturn("foohash");
- when(fileHashCache.getPreviousHash(hello)).thenReturn("oldhellohash");
- when(fileHashCache.getCurrentHash(hello, Charsets.UTF_8)).thenReturn("oldhellohash");
- when(fileHashCache.getPreviousHash(fooTest)).thenReturn("oldfooTesthash");
- when(fileHashCache.getCurrentHash(fooTest, Charsets.UTF_8)).thenReturn("fooTesthash");
- when(fileHashCache.getPreviousHash(helloTest)).thenReturn("oldhelloTesthash");
- when(fileHashCache.getCurrentHash(helloTest, Charsets.UTF_8)).thenReturn("oldhelloTesthash");
-
- DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(fileHashCache)
- .setBaseDir(basedir)
- .setWorkingDir(temp.newFolder())
- .addSourceDir(mainDir)
- .addTestDir(testDir)
- .setSettings(settings);
-
- assertThat(fileSystem.files(FileQuery.onSource())).containsOnly(foo, hello);
- assertThat(fileSystem.files(FileQuery.onTest())).containsOnly(fooTest, helloTest);
-
- assertThat(fileSystem.changedFiles(FileQuery.onSource())).containsExactly(foo);
- assertThat(fileSystem.changedFiles(FileQuery.onTest())).containsExactly(fooTest);
-
- settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true);
- settings.setProperty(CoreProperties.DRY_RUN, true);
-
- assertThat(fileSystem.files(FileQuery.onSource())).containsExactly(foo);
- assertThat(fileSystem.files(FileQuery.onTest())).containsExactly(fooTest);
- }
+ //
+//
+//
+// @Test
+// public void should_exclude_dirs_starting_with_dot() throws IOException {
+// File basedir = new File(resourcesDir(), "exclude_dir_starting_with_dot");
+// DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(RemoteFileHashes.class))
+// .setBaseDir(basedir)
+// .setWorkingDir(temp.newFolder())
+// .addSourceDir(new File(basedir, "src"))
+// .setSettings(new Settings());
+//
+// List<File> files = fileSystem.files(FileQuery.onSource());
+// assertThat(files).hasSize(1);
+// assertThat(files.get(0).getName()).isEqualTo("Included.java");
+// }
+//
+// @Test
+// public void should_load_source_files_by_language() throws IOException {
+// File basedir = new File(resourcesDir(), "main_and_test_files");
+// DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(RemoteFileHashes.class))
+// .setBaseDir(basedir)
+// .setWorkingDir(temp.newFolder())
+// .addSourceDir(new File(basedir, "src/main/java"))
+// .addTestDir(new File(basedir, "src/test/java"))
+// .setSettings(new Settings());
+//
+// List<File> files = fileSystem.files(FileQuery.onSource().onLanguage("java"));
+// assertThat(files).hasSize(2);
+// for (File sourceFiles : files) {
+// assertThat(sourceFiles).exists().isFile();
+// assertThat(sourceFiles.getName()).isIn("Hello.java", "Foo.java");
+// }
+// assertThat(fileSystem.files(FileQuery.onSource().onLanguage("php"))).isEmpty();
+// }
+//
+// @Test
+// public void should_load_test_files() throws IOException {
+// File basedir = new File(resourcesDir(), "main_and_test_files");
+// DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(RemoteFileHashes.class))
+// .setBaseDir(basedir)
+// .setWorkingDir(temp.newFolder())
+// .addSourceDir(new File(basedir, "src/main/java"))
+// .addTestDir(new File(basedir, "src/test/java"))
+// .setSettings(new Settings());
+//
+// assertThat(fileSystem.testDirs()).hasSize(1);
+// List<File> testFiles = fileSystem.files(FileQuery.onTest());
+// assertThat(testFiles).hasSize(2);
+// for (File testFile : testFiles) {
+// assertThat(testFile).exists().isFile();
+// assertThat(testFile.getName()).endsWith("Test.java");
+// }
+// }
+//
+// @Test
+// public void should_load_test_files_by_language() throws IOException {
+// File basedir = new File(resourcesDir(), "main_and_test_files");
+// DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(RemoteFileHashes.class))
+// .setBaseDir(basedir)
+// .setWorkingDir(temp.newFolder())
+// .addSourceDir(new File(basedir, "src/main/java"))
+// .addTestDir(new File(basedir, "src/test/java"))
+// .setSettings(new Settings());
+//
+// List<File> testFiles = fileSystem.files(FileQuery.onTest().onLanguage("java"));
+// assertThat(testFiles).hasSize(2);
+// for (File testFile : testFiles) {
+// assertThat(testFile).exists().isFile();
+// assertThat(testFile.getName()).endsWith("Test.java");
+// }
+// assertThat(fileSystem.files(FileQuery.onTest().onLanguage("php"))).isEmpty();
+// }
+//
+// private File resourcesDir() {
+// File dir = new File("test-resources/DefaultModuleFileSystemTest");
+// if (!dir.exists()) {
+// dir = new File("sonar-batch/test-resources/DefaultModuleFileSystemTest");
+// }
+// return dir;
+// }
+//
+// @Test
+// public void should_apply_file_filters() throws IOException {
+// File basedir = new File(resourcesDir(), "main_and_test_files");
+// DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(RemoteFileHashes.class))
+// .setBaseDir(basedir)
+// .setWorkingDir(temp.newFolder())
+// .addSourceDir(new File(basedir, "src/main/java"))
+// .addFilters(new FileFilterWrapper(FileFilterUtils.nameFileFilter("Foo.java")))
+// .setSettings(new Settings());
+//
+// List<File> files = fileSystem.files(FileQuery.onSource());
+// assertThat(files).hasSize(1);
+// assertThat(files.get(0).getName()).isEqualTo("Foo.java");
+// }
+//
+// static class Php extends AbstractLanguage {
+// public Php() {
+// super("php");
+// }
+//
+// public String[] getFileSuffixes() {
+// return new String[] {"php"};
+// }
+// }
+//
+// static class Java extends AbstractLanguage {
+// public Java() {
+// super("java");
+// }
+//
+// public String[] getFileSuffixes() {
+// return new String[] {"java", "jav"};
+// }
+// }
+//
+//
+//
+// @Test
+// public void should_throw_if_incremental_mode_and_not_in_dryrun() throws Exception {
+// File basedir = temp.newFolder();
+// Settings settings = new Settings();
+// DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(mock(RemoteFileHashes.class))
+// .setBaseDir(basedir)
+// .setWorkingDir(temp.newFolder())
+// .addSourceDir(new File(basedir, "src/main/java"))
+// .setSettings(settings);
+//
+// settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true);
+//
+// thrown.expect(SonarException.class);
+// thrown.expectMessage("Incremental preview is only supported with preview mode");
+// fileSystem.files(FileQuery.onSource());
+// }
+//
+// @Test
+// public void should_filter_changed_files() throws Exception {
+// File basedir = new File(resourcesDir(), "main_and_test_files");
+// Settings settings = new Settings();
+// settings.setProperty(CoreProperties.ENCODING_PROPERTY, "UTF-8");
+// File mainDir = new File(basedir, "src/main/java");
+// File testDir = new File(basedir, "src/test/java");
+// File foo = new File(mainDir, "Foo.java");
+// File hello = new File(mainDir, "Hello.java");
+// File fooTest = new File(testDir, "FooTest.java");
+// File helloTest = new File(testDir, "HelloTest.java");
+//
+// RemoteFileHashes remoteFileHashes = mock(RemoteFileHashes.class);
+// when(remoteFileHashes.getPreviousHash(foo)).thenReturn("oldfoohash");
+// when(remoteFileHashes.getCurrentHash(foo, Charsets.UTF_8)).thenReturn("foohash");
+// when(remoteFileHashes.getPreviousHash(hello)).thenReturn("oldhellohash");
+// when(remoteFileHashes.getCurrentHash(hello, Charsets.UTF_8)).thenReturn("oldhellohash");
+// when(remoteFileHashes.getPreviousHash(fooTest)).thenReturn("oldfooTesthash");
+// when(remoteFileHashes.getCurrentHash(fooTest, Charsets.UTF_8)).thenReturn("fooTesthash");
+// when(remoteFileHashes.getPreviousHash(helloTest)).thenReturn("oldhelloTesthash");
+// when(remoteFileHashes.getCurrentHash(helloTest, Charsets.UTF_8)).thenReturn("oldhelloTesthash");
+//
+// DefaultModuleFileSystem fileSystem = new DefaultModuleFileSystem(remoteFileHashes)
+// .setBaseDir(basedir)
+// .setWorkingDir(temp.newFolder())
+// .addSourceDir(mainDir)
+// .addTestDir(testDir)
+// .setSettings(settings);
+//
+// assertThat(fileSystem.files(FileQuery.onSource())).containsOnly(foo, hello);
+// assertThat(fileSystem.files(FileQuery.onTest())).containsOnly(fooTest, helloTest);
+//
+// assertThat(fileSystem.changedFiles(FileQuery.onSource())).containsExactly(foo);
+// assertThat(fileSystem.changedFiles(FileQuery.onTest())).containsExactly(fooTest);
+//
+// settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true);
+// settings.setProperty(CoreProperties.DRY_RUN, true);
+//
+// assertThat(fileSystem.files(FileQuery.onSource())).containsExactly(foo);
+// assertThat(fileSystem.files(FileQuery.onTest())).containsExactly(fooTest);
+// }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFilterTest.java
index 269441d3ebb..9272d2cf012 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFilterTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFilterTest.java
@@ -19,35 +19,42 @@
*/
package org.sonar.batch.scan.filesystem;
+import com.google.common.collect.ImmutableMap;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
+import org.sonar.api.scan.filesystem.InputFile;
import java.io.File;
import java.io.IOException;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
public class ExclusionFilterTest {
+
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Test
- public void accept() throws IOException {
- ExclusionFilter filter = new ExclusionFilter("**/*Foo.java");
- File file = temp.newFile();
- FileFilterContext context = new FileFilterContext(mock(ModuleFileSystem.class));
+ public void accept() throws Exception {
+ ExclusionFilter sourceRelativeFilter = new ExclusionFilter("**/*Foo.java");
+ ExclusionFilter absoluteFilter = new ExclusionFilter("file:**/src/main/**Foo.java");
- context.setCanonicalPath("/absolute/path/to/MyFoo.java");
- context.setRelativePath("relative/path/to/MyFoo.java");
- assertThat(filter.accept(file, context)).isFalse();
+ File file = temp.newFile();
+ InputFile inputFile = InputFile.create(file, "src/main/java/org/MyFoo.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_CANONICAL_PATH, "/absolute/path/to/src/main/java/org/MyFoo.java",
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/MyFoo.java"
+ ));
- context.setCanonicalPath("/absolute/path/to/Other.java");
- context.setRelativePath("relative/path/to/Other.java");
+ assertThat(sourceRelativeFilter.accept(inputFile)).isFalse();
+ assertThat(absoluteFilter.accept(inputFile)).isFalse();
- assertThat(filter.accept(file, context)).isTrue();
+ inputFile = InputFile.create(file, "src/main/java/org/Other.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_CANONICAL_PATH, "/absolute/path/to/src/main/java/org/Other.java",
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/Other.java"
+ ));
+ assertThat(sourceRelativeFilter.accept(inputFile)).isTrue();
+ assertThat(absoluteFilter.accept(inputFile)).isTrue();
}
@Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java
index 0bea3c05040..05c3d065458 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.batch.scan.filesystem;
+import com.google.common.collect.ImmutableMap;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -28,15 +29,14 @@ import org.sonar.api.resources.File;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.FileExclusions;
-import org.sonar.api.scan.filesystem.FileType;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
+import org.sonar.api.scan.filesystem.InputFile;
import java.io.IOException;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
public class ExclusionFiltersTest {
+
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@@ -46,19 +46,26 @@ public class ExclusionFiltersTest {
settings.setProperty(CoreProperties.PROJECT_INCLUSIONS_PROPERTY, "**/*Dao.java");
ExclusionFilters filter = new ExclusionFilters(new FileExclusions(settings));
- FileFilterContext context = new FileFilterContext(mock(ModuleFileSystem.class));
- context.setType(FileType.SOURCE);
- context.setRelativePath("com/mycompany/Foo.java");
- assertThat(filter.accept(temp.newFile(), context)).isFalse();
+ java.io.File file = temp.newFile();
+ InputFile inputFile = InputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE,
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/Foo.java"
+ ));
+
+ assertThat(filter.accept(inputFile)).isFalse();
- context.setRelativePath("com/mycompany/FooDao.java");
- assertThat(filter.accept(temp.newFile(), context)).isTrue();
+ inputFile = InputFile.create(file, "src/main/java/com/mycompany/FooDao.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE,
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/FooDao.java"
+ ));
+ assertThat(filter.accept(inputFile)).isTrue();
// source inclusions do not apply to tests
- context = new FileFilterContext(mock(ModuleFileSystem.class));
- context.setType(FileType.TEST);
- context.setRelativePath("com/mycompany/Foo.java");
- assertThat(filter.accept(temp.newFile(), context)).isTrue();
+ inputFile = InputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST,
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/Foo.java"
+ ));
+ assertThat(filter.accept(inputFile)).isTrue();
}
@Test
@@ -67,13 +74,19 @@ public class ExclusionFiltersTest {
settings.setProperty(CoreProperties.PROJECT_INCLUSIONS_PROPERTY, "**/*Dao.java,**/*Dto.java");
ExclusionFilters filter = new ExclusionFilters(new FileExclusions(settings));
- FileFilterContext context = new FileFilterContext(mock(ModuleFileSystem.class));
- context.setType(FileType.SOURCE);
- context.setRelativePath("com/mycompany/Foo.java");
- assertThat(filter.accept(temp.newFile(), context)).isFalse();
+ java.io.File file = temp.newFile();
+ InputFile inputFile = InputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE,
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/Foo.java"
+ ));
- context.setRelativePath("com/mycompany/FooDto.java");
- assertThat(filter.accept(temp.newFile(), context)).isTrue();
+ assertThat(filter.accept(inputFile)).isFalse();
+
+ inputFile = InputFile.create(file, "src/main/java/com/mycompany/FooDto.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE,
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/FooDto.java"
+ ));
+ assertThat(filter.accept(inputFile)).isTrue();
}
@Test
@@ -82,19 +95,25 @@ public class ExclusionFiltersTest {
settings.setProperty(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, "**/*Dao.java");
ExclusionFilters filter = new ExclusionFilters(new FileExclusions(settings));
- FileFilterContext context = new FileFilterContext(mock(ModuleFileSystem.class));
- context.setType(FileType.SOURCE);
- context.setRelativePath("com/mycompany/FooDao.java");
- assertThat(filter.accept(temp.newFile(), context)).isFalse();
+ java.io.File file = temp.newFile();
+ InputFile inputFile = InputFile.create(file, "src/main/java/com/mycompany/FooDao.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE,
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/FooDao.java"
+ ));
+ assertThat(filter.accept(inputFile)).isFalse();
- context.setRelativePath("com/mycompany/Foo.java");
- assertThat(filter.accept(temp.newFile(), context)).isTrue();
+ inputFile = InputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE,
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/Foo.java"
+ ));
+ assertThat(filter.accept(inputFile)).isTrue();
// source exclusions do not apply to tests
- context = new FileFilterContext(mock(ModuleFileSystem.class));
- context.setType(FileType.TEST);
- context.setRelativePath("com/mycompany/FooDao.java");
- assertThat(filter.accept(temp.newFile(), context)).isTrue();
+ inputFile = InputFile.create(file, "src/main/java/com/mycompany/FooDao.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST,
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/FooDao.java"
+ ));
+ assertThat(filter.accept(inputFile)).isTrue();
}
@Test
@@ -106,15 +125,17 @@ public class ExclusionFiltersTest {
settings.setProperty(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, "file:" + excludedFile.getCanonicalPath());
ExclusionFilters filter = new ExclusionFilters(new FileExclusions(settings));
- FileFilterContext context = new FileFilterContext(mock(ModuleFileSystem.class));
- context.setType(FileType.SOURCE);
- context.setRelativePath("org/bar/Foo.java");
- context.setCanonicalPath(includedFile.getCanonicalPath());
- assertThat(filter.accept(includedFile, context)).isTrue();
-
- context.setRelativePath("org/bar/Bar.java");
- context.setCanonicalPath(excludedFile.getCanonicalPath());
- assertThat(filter.accept(excludedFile, context)).isFalse();
+ InputFile includedInput = InputFile.create(includedFile, "src/main/java/org/bar/Foo.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE,
+ InputFile.ATTRIBUTE_CANONICAL_PATH, includedFile.getCanonicalPath()
+ ));
+ assertThat(filter.accept(includedInput)).isTrue();
+
+ InputFile excludedInput = InputFile.create(excludedFile, "src/main/java/org/bar/Bar.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE,
+ InputFile.ATTRIBUTE_CANONICAL_PATH, excludedFile.getCanonicalPath()
+ ));
+ assertThat(filter.accept(excludedInput)).isFalse();
}
@Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/HashBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileHashDigestTest.java
index f15876f8d54..c3345c26af3 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/HashBuilderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileHashDigestTest.java
@@ -23,53 +23,60 @@ import com.google.common.base.Charsets;
import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.utils.SonarException;
import java.io.File;
import static org.fest.assertions.Assertions.assertThat;
-public class HashBuilderTest {
+public class FileHashDigestTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- private HashBuilder hashBuilder = new HashBuilder();
@Test
public void should_compute_hash() throws Exception {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "foo\r\nbar", Charsets.UTF_8, true);
- assertThat(hashBuilder.computeHashNormalizeLineEnds(tempFile, Charsets.UTF_8)).isEqualTo("daef8a22a3f12580beadf086a9e11519");
+ assertThat(FileHashDigest.INSTANCE.hash(tempFile, Charsets.UTF_8)).isEqualTo("daef8a22a3f12580beadf086a9e11519");
}
@Test
public void should_normalize_line_ends() throws Exception {
File file1 = temp.newFile();
FileUtils.write(file1, "foobar\nfofo", Charsets.UTF_8);
- String hash1 = hashBuilder.computeHashNormalizeLineEnds(file1, Charsets.UTF_8);
+ String hash1 = FileHashDigest.INSTANCE.hash(file1, Charsets.UTF_8);
File file2 = temp.newFile();
FileUtils.write(file2, "foobar\r\nfofo", Charsets.UTF_8);
- String hash2 = hashBuilder.computeHashNormalizeLineEnds(file2, Charsets.UTF_8);
+ String hash2 = FileHashDigest.INSTANCE.hash(file2, Charsets.UTF_8);
File file3 = temp.newFile();
FileUtils.write(file3, "foobar\rfofo", Charsets.UTF_8);
- String hash3 = hashBuilder.computeHashNormalizeLineEnds(file3, Charsets.UTF_8);
+ String hash3 = FileHashDigest.INSTANCE.hash(file3, Charsets.UTF_8);
File file4 = temp.newFile();
FileUtils.write(file4, "foobar\nfofo\n", Charsets.UTF_8);
- String hash4 = hashBuilder.computeHashNormalizeLineEnds(file4, Charsets.UTF_8);
+ String hash4 = FileHashDigest.INSTANCE.hash(file4, Charsets.UTF_8);
assertThat(hash1).isEqualTo(hash2);
assertThat(hash1).isEqualTo(hash3);
assertThat(hash1).isNotEqualTo(hash4);
}
- @Test(expected = SonarException.class)
- public void should_throw_on_not_existing_file() throws Exception {
+ @Test
+ public void should_throw_if_file_does_not_exist() throws Exception {
File tempFolder = temp.newFolder();
- hashBuilder.computeHashNormalizeLineEnds(new File(tempFolder, "unknowFile.txt"), Charsets.UTF_8);
+ File file = new File(tempFolder, "doesNotExist.txt");
+
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage("Fail to compute hash of file " + file.getAbsolutePath() + " with charset UTF-8");
+
+ FileHashDigest.INSTANCE.hash(file, Charsets.UTF_8);
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileFilterWrapperTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileHashesTest.java
index fbaeec9f366..98ae99d7006 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileFilterWrapperTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileHashesTest.java
@@ -19,29 +19,40 @@
*/
package org.sonar.batch.scan.filesystem;
-import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.mockito.Mockito;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
import java.io.File;
-import java.io.IOException;
+import java.nio.charset.Charset;
-public class FileFilterWrapperTest {
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class FileHashesTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- @Test
- public void should_wrap_java_io_filefilter() throws IOException {
- IOFileFilter filter = Mockito.mock(IOFileFilter.class);
- FileFilterWrapper wrapper = new FileFilterWrapper(filter);
+ RemoteFileHashes remoteFileHashes = mock(RemoteFileHashes.class);
+ @Test
+ public void hash() throws Exception {
File file = temp.newFile();
- wrapper.accept(file, Mockito.mock(FileSystemFilter.Context.class));
+ FileUtils.write(file, "fooo");
+
+ FileHashes hashes = new FileHashes(remoteFileHashes);
+ assertThat(hashes.hash(file, Charset.forName("UTF-8"))).isEqualTo("efc4470c96a94b1ff400175ef8368444");
+ verifyZeroInteractions(remoteFileHashes);
+ }
+
+ @Test
+ public void remote_hash() throws Exception {
+ String path = "src/main/java/Foo.java";
+ when(remoteFileHashes.remoteHash(path)).thenReturn("ABCDE");
- Mockito.verify(filter).accept(file);
+ FileHashes hashes = new FileHashes(remoteFileHashes);
+ assertThat(hashes.remoteHash(path)).isEqualTo("ABCDE");
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileSystemLoggerTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileSystemLoggerTest.java
index 19f2ae4c62d..f218d0bba4a 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileSystemLoggerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileSystemLoggerTest.java
@@ -38,11 +38,10 @@ public class FileSystemLoggerTest {
@Test
public void log() {
- DefaultModuleFileSystem fs = new DefaultModuleFileSystem(mock(FileHashCache.class));
+ DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", mock(Settings.class), mock(InputFileCache.class), mock(FileIndexer.class));
File src = temp.newFolder("src");
File test = temp.newFolder("test");
File base = temp.newFolder("base");
- fs.setSettings(new Settings());
fs.setBaseDir(base);
fs.addSourceDir(src);
fs.addTestDir(test);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InclusionFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InclusionFilterTest.java
index 8333c6c2286..38f391fa8ce 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InclusionFilterTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InclusionFilterTest.java
@@ -19,35 +19,41 @@
*/
package org.sonar.batch.scan.filesystem;
+import com.google.common.collect.ImmutableMap;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
+import org.sonar.api.scan.filesystem.InputFile;
import java.io.File;
-import java.io.IOException;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
public class InclusionFilterTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Test
- public void accept() throws IOException {
- InclusionFilter filter = new InclusionFilter("**/*Foo.java");
- File file = temp.newFile();
- FileFilterContext context = new FileFilterContext(mock(ModuleFileSystem.class));
+ public void accept() throws Exception {
+ InclusionFilter sourceRelativeFilter = new InclusionFilter("**/*Foo.java");
+ InclusionFilter absoluteFilter = new InclusionFilter("file:**/src/main/**Foo.java");
- context.setCanonicalPath("/absolute/path/to/MyFoo.java");
- context.setRelativePath("relative/path/to/MyFoo.java");
- assertThat(filter.accept(file, context)).isTrue();
- context.setCanonicalPath("/absolute/path/to/Other.java");
- context.setRelativePath("relative/path/to/Other.java");
+ File file = temp.newFile();
+ InputFile inputFile = InputFile.create(file, "src/main/java/org/MyFoo.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_CANONICAL_PATH, "/absolute/path/to/src/main/java/org/MyFoo.java",
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/MyFoo.java"
+ ));
+
+ assertThat(sourceRelativeFilter.accept(inputFile)).isTrue();
+ assertThat(absoluteFilter.accept(inputFile)).isTrue();
- assertThat(filter.accept(file, context)).isFalse();
+ inputFile = InputFile.create(file, "src/main/java/org/Other.java", ImmutableMap.of(
+ InputFile.ATTRIBUTE_CANONICAL_PATH, "/absolute/path/to/src/main/java/org/Other.java",
+ InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/Other.java"
+ ));
+ assertThat(sourceRelativeFilter.accept(inputFile)).isFalse();
+ assertThat(absoluteFilter.accept(inputFile)).isFalse();
}
@Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java
new file mode 100644
index 00000000000..25b82b83961
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java
@@ -0,0 +1,65 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 02110-1301, USA.
+ */
+package org.sonar.batch.scan.filesystem;
+
+import com.google.common.collect.Maps;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.scan.filesystem.InputFile;
+import org.sonar.batch.index.Caches;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class InputFileCacheTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ Caches caches = new Caches();
+
+ @Before
+ public void start() {
+ caches.start();
+ }
+
+ @After
+ public void stop() {
+ caches.stop();
+ }
+
+ @Test
+ public void should_add_input_file() throws Exception {
+ InputFileCache cache = new InputFileCache(caches);
+ cache.put("struts", InputFile.create(temp.newFile(), "src/main/java/Foo.java", Maps.<String, String>newHashMap()));
+ cache.put("struts-core", InputFile.create(temp.newFile(), "src/main/java/Foo.java", Maps.<String, String>newHashMap()));
+
+ assertThat(cache.byModule("struts")).hasSize(1);
+ assertThat(cache.byModule("struts-core")).hasSize(1);
+ assertThat(cache.all()).hasSize(2);
+
+ cache.removeModule("struts");
+ assertThat(cache.byModule("struts")).hasSize(0);
+ assertThat(cache.byModule("struts-core")).hasSize(1);
+ assertThat(cache.all()).hasSize(1);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageFiltersTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageFiltersTest.java
deleted file mode 100644
index 7e09c3d59cd..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageFiltersTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 02110-1301, USA.
- */
-package org.sonar.batch.scan.filesystem;
-
-import org.apache.commons.io.filefilter.FalseFileFilter;
-import org.apache.commons.io.filefilter.IOFileFilter;
-import org.apache.commons.io.filefilter.SuffixFileFilter;
-import org.apache.commons.io.filefilter.TrueFileFilter;
-import org.junit.Test;
-import org.sonar.api.resources.AbstractLanguage;
-import org.sonar.api.resources.Languages;
-
-import java.lang.reflect.Field;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class LanguageFiltersTest {
- @Test
- public void forLang() throws Exception {
- LanguageFilters filters = new LanguageFilters(new Languages(new Java(), new Php()));
-
- IOFileFilter filter = filters.forLang("php");
- assertThat(filter).isInstanceOf(SuffixFileFilter.class);
- assertThat(suffixes((SuffixFileFilter) filter)).containsOnly("php");
-
- filter = filters.forLang("java");
- assertThat(filter).isInstanceOf(SuffixFileFilter.class);
- assertThat(suffixes((SuffixFileFilter) filter)).containsOnly("java", "jav");
-
- assertThat(filters.forLang("unknown")).isSameAs(FalseFileFilter.FALSE);
- }
-
- private String[] suffixes(SuffixFileFilter filter) throws Exception {
- Field privateField = SuffixFileFilter.class.getDeclaredField("suffixes");
- privateField.setAccessible(true);
-
- return (String[]) privateField.get(filter);
- }
-
- static class Php extends AbstractLanguage {
- public Php() {
- super("php");
- }
-
- public String[] getFileSuffixes() {
- return new String[]{"php"};
- }
- }
-
- static class Java extends AbstractLanguage {
- public Java() {
- super("java");
- }
-
- public String[] getFileSuffixes() {
- return new String[]{"java", "jav"};
- }
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ModuleFileSystemProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ModuleFileSystemProviderTest.java
index 600fa6a4aac..d2aa69e6dc1 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ModuleFileSystemProviderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ModuleFileSystemProviderTest.java
@@ -25,13 +25,12 @@ import org.apache.commons.io.FilenameUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.FileQuery;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
import org.sonar.api.scan.filesystem.ModuleFileSystem;
-import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.batch.bootstrap.TempDirectories;
import java.io.File;
@@ -45,6 +44,10 @@ public class ModuleFileSystemProviderTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
+ InputFileCache fileCache = mock(InputFileCache.class, Mockito.RETURNS_DEEP_STUBS);
+ Settings settings = new Settings();
+ FileIndexer fileIndexer = mock(FileIndexer.class, Mockito.RETURNS_DEEP_STUBS);
+
@Test
public void test_provide() throws IOException {
ModuleFileSystemProvider provider = new ModuleFileSystemProvider();
@@ -53,8 +56,7 @@ public class ModuleFileSystemProviderTest {
ProjectDefinition module = ProjectDefinition.create()
.setBaseDir(baseDir)
.setWorkDir(workDir);
- ModuleFileSystem fs = provider.provide(module, new PathResolver(), new TempDirectories(), mock(LanguageFilters.class),
- new Settings(), new FileSystemFilter[0], mock(FileHashCache.class));
+ ModuleFileSystem fs = provider.provide(module, new TempDirectories(), settings, fileCache, fileIndexer);
assertThat(fs).isNotNull();
assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(baseDir.getCanonicalPath());
@@ -69,8 +71,8 @@ public class ModuleFileSystemProviderTest {
public void default_charset_is_platform_dependent() throws IOException {
ModuleFileSystemProvider provider = new ModuleFileSystemProvider();
- ModuleFileSystem fs = provider.provide(newSimpleModule(), new PathResolver(), new TempDirectories(), mock(LanguageFilters.class),
- new Settings(), new FileSystemFilter[0], mock(FileHashCache.class));
+ ModuleFileSystem fs = provider.provide(newSimpleModule(), new TempDirectories(),
+ new Settings(), mock(InputFileCache.class), mock(FileIndexer.class));
assertThat(fs.sourceCharset()).isEqualTo(Charset.defaultCharset());
}
@@ -82,8 +84,8 @@ public class ModuleFileSystemProviderTest {
Settings settings = new Settings();
settings.setProperty(CoreProperties.ENCODING_PROPERTY, Charsets.ISO_8859_1.name());
- ModuleFileSystem fs = provider.provide(module, new PathResolver(), new TempDirectories(), mock(LanguageFilters.class),
- settings, new FileSystemFilter[0], mock(FileHashCache.class));
+ ModuleFileSystem fs = provider.provide(module, new TempDirectories(),
+ settings, mock(InputFileCache.class), mock(FileIndexer.class));
assertThat(fs.sourceCharset()).isEqualTo(Charsets.ISO_8859_1);
}
@@ -108,8 +110,8 @@ public class ModuleFileSystemProviderTest {
.addTestDirs("src/test/java", "src/test/unknown")
.addBinaryDir("target/classes");
- ModuleFileSystem fs = provider.provide(project, new PathResolver(), new TempDirectories(), mock(LanguageFilters.class),
- new Settings(), new FileSystemFilter[0], mock(FileHashCache.class));
+ ModuleFileSystem fs = provider.provide(project, new TempDirectories(),
+ new Settings(), mock(InputFileCache.class), mock(FileIndexer.class));
assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(baseDir.getCanonicalPath());
assertThat(fs.buildDir().getCanonicalPath()).isEqualTo(buildDir.getCanonicalPath());
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileSystemAdapterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapterTest.java
index 6207a13c97c..0bdb33e03a4 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileSystemAdapterTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapterTest.java
@@ -29,18 +29,17 @@ import java.io.File;
import java.io.IOException;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
+
+public class ProjectFileSystemAdapterTest {
-public class DeprecatedFileSystemAdapterTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Test
public void should_wrap_module_file_system() {
DefaultModuleFileSystem target = mock(DefaultModuleFileSystem.class, Mockito.RETURNS_SMART_NULLS);
- DeprecatedFileSystemAdapter adapter = new DeprecatedFileSystemAdapter(target, new Project("my-project"));
+ ProjectFileSystemAdapter adapter = new ProjectFileSystemAdapter(target, new Project("my-project"));
assertThat(adapter.getBasedir()).isNotNull();
verify(target).baseDir();
@@ -63,7 +62,7 @@ public class DeprecatedFileSystemAdapterTest {
File workingDir = temp.newFile("work");
DefaultModuleFileSystem target = mock(DefaultModuleFileSystem.class);
when(target.workingDir()).thenReturn(workingDir);
- DeprecatedFileSystemAdapter adapter = new DeprecatedFileSystemAdapter(target, new Project("my-project"));
+ ProjectFileSystemAdapter adapter = new ProjectFileSystemAdapter(target, new Project("my-project"));
File buildDir = adapter.getBuildDir();
assertThat(buildDir.getParentFile().getCanonicalPath()).isEqualTo(workingDir.getCanonicalPath());
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileHashCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/RemoteFileHashesTest.java
index 1c70890ffec..91b2f5e34d1 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileHashCacheTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/RemoteFileHashesTest.java
@@ -19,24 +19,17 @@
*/
package org.sonar.batch.scan.filesystem;
-import com.google.common.base.Charsets;
-import org.apache.commons.io.FileUtils;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
-import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.batch.components.PastSnapshot;
import org.sonar.batch.components.PastSnapshotFinder;
import org.sonar.core.source.SnapshotDataType;
import org.sonar.core.source.jdbc.SnapshotDataDao;
import org.sonar.core.source.jdbc.SnapshotDataDto;
-import java.io.File;
import java.util.Arrays;
import java.util.Date;
@@ -44,7 +37,7 @@ import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class FileHashCacheTest {
+public class RemoteFileHashesTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@@ -52,76 +45,45 @@ public class FileHashCacheTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
- private FileHashCache cache;
-
- private PastSnapshotFinder pastSnapshotFinder;
-
- private Snapshot snapshot;
-
- private File baseDir;
-
- private SnapshotDataDao snapshotDataDao;
-
- private ModuleFileSystem moduleFileSystem;
-
- @Before
- public void prepare() throws Exception {
- pastSnapshotFinder = mock(PastSnapshotFinder.class);
- snapshot = mock(Snapshot.class);
- baseDir = temp.newFolder();
- snapshotDataDao = mock(SnapshotDataDao.class);
- moduleFileSystem = mock(ModuleFileSystem.class);
- cache = new FileHashCache(ProjectDefinition.create().setBaseDir(baseDir), new PathResolver(), new HashBuilder(), snapshot,
- snapshotDataDao, pastSnapshotFinder);
- }
+ PastSnapshotFinder pastSnapshotFinder = mock(PastSnapshotFinder.class);
+ Snapshot snapshot = mock(Snapshot.class);
+ SnapshotDataDao snapshotDataDao = mock(SnapshotDataDao.class);
+ RemoteFileHashes hashes = new RemoteFileHashes(snapshot, snapshotDataDao, pastSnapshotFinder);
@Test
- public void should_return_null_if_no_previous_snapshot() throws Exception {
+ public void should_return_null_if_no_remote_snapshot() throws Exception {
when(pastSnapshotFinder.findPreviousAnalysis(snapshot)).thenReturn(new PastSnapshot("foo"));
- cache.start();
- assertThat(cache.getPreviousHash(new File(baseDir, "src/main/java/foo/Bar.java"))).isNull();
+ hashes.start();
+ assertThat(hashes.remoteHash("src/main/java/foo/Bar.java")).isNull();
+ hashes.stop();
}
@Test
- public void should_return_null_if_no_previous_snapshot_data() throws Exception {
+ public void should_return_null_if_no_remote_hashes() throws Exception {
Snapshot previousSnapshot = mock(Snapshot.class);
PastSnapshot pastSnapshot = new PastSnapshot("foo", new Date(), previousSnapshot);
when(pastSnapshotFinder.findPreviousAnalysis(snapshot)).thenReturn(pastSnapshot);
- cache.start();
- assertThat(cache.getPreviousHash(new File(baseDir, "src/main/java/foo/Bar.java"))).isNull();
+ hashes.start();
+ assertThat(hashes.remoteHash("src/main/java/foo/Bar.java")).isNull();
+ hashes.stop();
}
@Test
- public void should_return_previous_hash() throws Exception {
+ public void should_return_remote_hash() throws Exception {
Snapshot previousSnapshot = mock(Snapshot.class);
when(previousSnapshot.getId()).thenReturn(123);
PastSnapshot pastSnapshot = new PastSnapshot("foo", new Date(), previousSnapshot);
when(pastSnapshotFinder.findPreviousAnalysis(snapshot)).thenReturn(pastSnapshot);
SnapshotDataDto snapshotDataDto = new SnapshotDataDto();
- snapshotDataDto.setData("src/main/java/foo/Bar.java=abcd1234\n");
+ snapshotDataDto.setData("src/main/java/foo/Bar.java=abcd1234");
when(snapshotDataDao.selectSnapshotData(123, Arrays.asList(SnapshotDataType.FILE_HASH.getValue())))
.thenReturn(Arrays.asList(snapshotDataDto));
- File file = new File(baseDir, "src/main/java/foo/Bar.java");
- FileUtils.write(file, "foo", Charsets.UTF_8);
- cache.start();
- assertThat(cache.getPreviousHash(file)).isEqualTo("abcd1234");
- }
-
- @Test
- public void should_compute_and_cache_current_hash() throws Exception {
- when(moduleFileSystem.sourceCharset()).thenReturn(Charsets.UTF_8);
-
- File file = new File(baseDir, "src/main/java/foo/Bar.java");
- FileUtils.write(file, "foo", Charsets.UTF_8);
- String hash = "9a8742076ef9ffa5591f633704c2286b";
- assertThat(cache.getCurrentHash(file, Charsets.UTF_8)).isEqualTo(hash);
-
- // Modify file
- FileUtils.write(file, "bar", Charsets.UTF_8);
- assertThat(cache.getCurrentHash(file, Charsets.UTF_8)).isEqualTo(hash);
+ hashes.start();
+ assertThat(hashes.remoteHash("src/main/java/foo/Bar.java")).isEqualTo("abcd1234");
+ hashes.stop();
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/WhiteListFileFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/WhiteListFileFilterTest.java
deleted file mode 100644
index 7d337a63f15..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/WhiteListFileFilterTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 02110-1301, USA.
- */
-package org.sonar.batch.scan.filesystem;
-
-import com.google.common.collect.Sets;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.scan.filesystem.FileType;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
-
-import java.io.File;
-import java.io.IOException;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class WhiteListFileFilterTest {
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Test
- public void should_accept() throws IOException {
- WhiteListFileFilter filter = new WhiteListFileFilter(FileType.SOURCE, Sets.newHashSet(
- new File("Foo.java"),
- new File("Bar.java")
- ));
-
- FileFilterContext context = new FileFilterContext(mock(ModuleFileSystem.class));
- context.setType(FileType.SOURCE);
- assertThat(filter.accept(new File("Foo.java"), context)).isTrue();
- assertThat(filter.accept(new File("Other.java"), context)).isFalse();
-
- context = new FileFilterContext(mock(ModuleFileSystem.class));
- context.setType(FileType.TEST);
- assertThat(filter.accept(new File("Foo.java"), context)).isTrue();
- assertThat(filter.accept(new File("Other.java"), context)).isTrue();
- }
-
- @Test
- public void test_toString() throws IOException {
- WhiteListFileFilter filter = new WhiteListFileFilter(FileType.SOURCE, Sets.newHashSet(
- new File("Foo.java"),
- new File("Bar.java")
- ));
-
- assertThat(filter.toString())
- .contains("Source files:")
- .contains("Foo.java")
- .contains("Bar.java");
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/source/SnapshotDataType.java b/sonar-core/src/main/java/org/sonar/core/source/SnapshotDataType.java
index b45eb9d32af..52fddd558cd 100644
--- a/sonar-core/src/main/java/org/sonar/core/source/SnapshotDataType.java
+++ b/sonar-core/src/main/java/org/sonar/core/source/SnapshotDataType.java
@@ -24,7 +24,7 @@ public enum SnapshotDataType {
SYNTAX_HIGHLIGHTING("highlight_syntax"),
SYMBOL_HIGHLIGHTING("symbol"),
- FILE_HASH("hash");
+ FILE_HASH("file_hash");
private SnapshotDataType(String value) {
this.value = value;
diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java
index 79c5461b892..e5389e96277 100644
--- a/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java
@@ -54,7 +54,7 @@ public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase {
}
@Test
- public void should_create_database_without_project() throws IOException, SQLException {
+ public void should_create_database_without_project() throws Exception {
setupData("should_create_database");
byte[] db = createDb(null);
@@ -71,7 +71,7 @@ public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase {
}
@Test
- public void should_create_database_with_project() throws IOException, SQLException {
+ public void should_create_database_with_project() throws Exception {
setupData("should_create_database");
byte[] database = createDb(123L);
@@ -85,7 +85,7 @@ public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase {
}
@Test
- public void should_create_database_with_issues() throws IOException, SQLException {
+ public void should_create_database_with_issues() throws Exception {
setupData("should_create_database_with_issues");
byte[] database = createDb(399L);
@@ -95,7 +95,7 @@ public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase {
}
@Test
- public void should_export_issues_of_project_tree() throws IOException, SQLException {
+ public void should_export_issues_of_project_tree() throws Exception {
setupData("multi-modules-with-issues");
// 300 : root module -> export issues of all modules
@@ -109,7 +109,7 @@ public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase {
}
@Test
- public void should_export_issues_of_sub_module() throws IOException, SQLException {
+ public void should_export_issues_of_sub_module() throws Exception {
setupData("multi-modules-with-issues");
// 301 : sub module with 1 closed issue and 1 open issue
@@ -122,7 +122,7 @@ public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase {
}
@Test
- public void should_export_issues_of_sub_module_2() throws IOException, SQLException {
+ public void should_export_issues_of_sub_module_2() throws Exception {
setupData("multi-modules-with-issues");
// 302 : sub module without any issues
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java
index 8584e22b07b..d33cd146ea4 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java
@@ -25,7 +25,9 @@ import java.io.InputStream;
/**
* @since 2.6
+ * @deprecated in 4.0. Replaced by {@link org.sonar.api.scan.filesystem.InputFile}
*/
+@Deprecated
public interface InputFile {
/**
* The source base directory, different than the project basedir.
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFileUtils.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFileUtils.java
index 576d2c18cec..9e018844b19 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFileUtils.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFileUtils.java
@@ -34,7 +34,9 @@ import java.util.List;
/**
* @since 2.8
+ * @deprecated in 4.0. Replaced by {@link org.sonar.api.scan.filesystem.InputFile}.
*/
+@Deprecated
public final class InputFileUtils {
private InputFileUtils() {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileQuery.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileQuery.java
index e69b13e92fa..3135b7c27cf 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileQuery.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileQuery.java
@@ -19,12 +19,17 @@
*/
package org.sonar.api.scan.filesystem;
-import com.google.common.collect.Lists;
+import com.google.common.base.Function;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ListMultimap;
import com.google.common.collect.Sets;
+import javax.annotation.Nullable;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Map;
import java.util.Set;
/**
@@ -32,8 +37,14 @@ import java.util.Set;
*/
public class FileQuery {
+ // TODO better builders, for example FileQuery.ALL
+
public static FileQuery on(FileType... types) {
- return new FileQuery(types);
+ FileQuery query = new FileQuery();
+ for (FileType type : types) {
+ query.on(InputFile.ATTRIBUTE_TYPE, type.name().toLowerCase());
+ }
+ return query;
}
public static FileQuery onSource() {
@@ -44,27 +55,40 @@ public class FileQuery {
return on(FileType.TEST);
}
- private final Set<FileType> types;
- private final Set<String> languages = Sets.newLinkedHashSet();
- private final Set<String> inclusions = Sets.newLinkedHashSet();
- private final Set<String> exclusions = Sets.newLinkedHashSet();
- private final Collection<FileFilter> filters = Lists.newLinkedList();
+ private final ListMultimap<String, String> attributes = ArrayListMultimap.create();
+ private final Set<String> inclusions = Sets.newHashSet();
+ private final Set<String> exclusions = Sets.newHashSet();
+
+ private FileQuery() {
+ }
+
+ private FileQuery on(String attribute, String... values) {
+ for (String value : values) {
+ attributes.put(attribute, value);
+ }
+ return this;
+ }
- private FileQuery(FileType... types) {
- this.types = Sets.newHashSet(types);
+ public Map<String, Collection<String>> attributes() {
+ return attributes.asMap();
}
+ @Deprecated
public Collection<FileType> types() {
- return types;
+ return Collections2.transform(attributes.get(InputFile.ATTRIBUTE_TYPE), new Function<String, FileType>() {
+ @Override
+ public FileType apply(@Nullable String input) {
+ return input != null ? FileType.valueOf(input) : null;
+ }
+ });
}
public Collection<String> languages() {
- return languages;
+ return attributes.get(InputFile.ATTRIBUTE_LANGUAGE);
}
public FileQuery onLanguage(String... languages) {
- this.languages.addAll(Arrays.asList(languages));
- return this;
+ return on(InputFile.ATTRIBUTE_LANGUAGE, languages);
}
public Collection<String> inclusions() {
@@ -85,13 +109,14 @@ public class FileQuery {
return this;
}
+ // TODO deprecate
public Collection<FileFilter> filters() {
- return filters;
+ throw new UnsupportedOperationException("TODO");
}
+ // TODO deprecate ?
public FileQuery withFilters(FileFilter... filters) {
- this.filters.addAll(Arrays.asList(filters));
- return this;
+ throw new UnsupportedOperationException("TODO");
}
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileSystemFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileSystemFilter.java
index 7d03441df56..3a215937d23 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileSystemFilter.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileSystemFilter.java
@@ -30,7 +30,9 @@ import java.io.File;
* <li>exclude the files which names start with Generated</li>
* </ul>
* @since 3.5
+ * @deprecated in 4.0. Replaced by {@link InputFileFilter}.
*/
+@Deprecated
public interface FileSystemFilter extends BatchExtension {
/**
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileType.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileType.java
index 6600ae2099a..31f3938da22 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileType.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileType.java
@@ -21,7 +21,9 @@ package org.sonar.api.scan.filesystem;
/**
* @since 3.5
+ * @deprecated in 4.0. Replaced by more flexible {@link InputFile} attributes.
*/
+@Deprecated
public enum FileType {
SOURCE, TEST
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java
new file mode 100644
index 00000000000..c28298ef5ae
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java
@@ -0,0 +1,140 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 02110-1301, USA.
+ */
+package org.sonar.api.scan.filesystem;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.commons.lang.StringUtils;
+
+import javax.annotation.CheckForNull;
+import java.io.File;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @since 4.0
+ */
+public class InputFile implements Serializable {
+
+ // TODO refactor attribute constants as classes or enums ?
+
+ /**
+ * Path relative to module base directory.
+ */
+ public static final String ATTRIBUTE_BASE_RELATIVE_PATH = "baseRelPath";
+
+ // TODO ambiguity of term "source" with sourceDir versus testDir properties
+ // Here it does not depend on type.
+ public static final String ATTRIBUTE_SOURCEDIR_PATH = "srcDirPath";
+ public static final String ATTRIBUTE_SOURCE_RELATIVE_PATH = "srcRelPath";
+
+ public static final String ATTRIBUTE_CANONICAL_PATH = "canonicalPath";
+ public static final String ATTRIBUTE_LANGUAGE = "lang";
+ public static final String ATTRIBUTE_TYPE = "type";
+ public static final String ATTRIBUTE_STATUS = "status";
+ public static final String STATUS_SAME = "same";
+ public static final String STATUS_CHANGED = "changed";
+ public static final String STATUS_ADDED = "added";
+ public static final String ATTRIBUTE_HASH = "checksum";
+ public static final String ATTRIBUTE_EXTENSION = "extension";
+ public static final String TYPE_SOURCE = "source";
+ public static final String TYPE_TEST = "test";
+
+ // TODO limitation of persistit -> add unit test
+ private transient File transientFile;
+ private Map<String, String> attributes;
+
+ private InputFile(File file, Map<String, String> attributes) {
+ this.transientFile = file;
+ this.attributes = attributes;
+ }
+
+ /**
+ * Plugins should not build their own instances of {@link InputFile}. This method
+ * aims to be used by unit tests.
+ * // TODO provide builder ?
+ */
+ public static InputFile create(File file, String baseRelativePath, Map<String, String> attributes) {
+ Map<String,String> copy = Maps.newHashMap(attributes);
+ copy.put(InputFile.ATTRIBUTE_BASE_RELATIVE_PATH, baseRelativePath);
+ return new InputFile(file, copy);
+ }
+
+ /**
+ * Path from module base directory. Path is unique and identifies file within given
+ * <code>{@link ModuleFileSystem}</code>. File separator is the forward slash ('/'),
+ * even on MSWindows.
+ */
+ public String path() {
+ return attribute(ATTRIBUTE_BASE_RELATIVE_PATH);
+ }
+
+ public File file() {
+ if (transientFile == null) {
+ transientFile = new File(attribute(ATTRIBUTE_CANONICAL_PATH));
+ }
+ return transientFile;
+ }
+
+ public String name() {
+ return file().getName();
+ }
+
+ public boolean has(String attribute, String value) {
+ return StringUtils.equals(attributes.get(attribute), value);
+ }
+
+ @CheckForNull
+ public String attribute(String key) {
+ return attributes.get(key);
+ }
+
+ public Map<String, String> attributes() {
+ return attributes;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ InputFile inputFile = (InputFile) o;
+ return attribute(ATTRIBUTE_CANONICAL_PATH).equals(inputFile.attribute(ATTRIBUTE_CANONICAL_PATH));
+ }
+
+ @Override
+ public int hashCode() {
+ return path().hashCode();
+ }
+
+ public static List<File> toFiles(Iterable<InputFile> inputFiles) {
+ List<File> files = Lists.newArrayList();
+ for (InputFile inputFile : inputFiles) {
+ files.add(inputFile.file());
+ }
+ return files;
+ }
+
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileFilterWrapper.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFileFilter.java
index 632aa6839d3..2b166827db8 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileFilterWrapper.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFileFilter.java
@@ -17,24 +17,16 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.batch.scan.filesystem;
+package org.sonar.api.scan.filesystem;
-import org.sonar.api.scan.filesystem.FileSystemFilter;
-
-import java.io.File;
-import java.io.FileFilter;
+import org.sonar.api.BatchExtension;
/**
- * @since 3.5
+ * TODO document lifecycle -> executed when initializing project
+ * @since 4.0
*/
-class FileFilterWrapper implements FileSystemFilter {
- private final FileFilter filter;
+public interface InputFileFilter extends BatchExtension {
- FileFilterWrapper(FileFilter filter) {
- this.filter = filter;
- }
+ boolean accept(InputFile inputFile);
- public boolean accept(File file, Context context) {
- return filter.accept(file);
- }
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/ModuleFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/ModuleFileSystem.java
index 31882d0ac28..f8c8257141f 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/ModuleFileSystem.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/ModuleFileSystem.java
@@ -20,9 +20,9 @@
package org.sonar.api.scan.filesystem;
import org.sonar.api.BatchComponent;
+import org.sonar.api.resources.InputFile;
import javax.annotation.CheckForNull;
-
import java.io.File;
import java.nio.charset.Charset;
import java.util.List;
@@ -31,6 +31,14 @@ import java.util.List;
* @since 3.5
*/
public interface ModuleFileSystem extends BatchComponent {
+
+ /**
+ * Unique module key
+ *
+ * @since 4.0
+ */
+ String moduleKey();
+
/**
* Base directory.
*/
@@ -47,12 +55,14 @@ public interface ModuleFileSystem extends BatchComponent {
* Source directories. Non-existing directories are excluded.
* Example in Maven : ${project.basedir}/src/main/java
*/
+ // TODO mark as dangerous to use
List<File> sourceDirs();
/**
* Test directories. Non-existing directories are excluded.
* Example in Maven : ${project.basedir}/src/test/java
*/
+ // TODO mark as dangerous to use
List<File> testDirs();
/**
@@ -72,12 +82,6 @@ public interface ModuleFileSystem extends BatchComponent {
List<File> files(FileQuery query);
/**
- * Search for changed files. Never return null.
- * @since 4.0
- */
- List<File> changedFiles(FileQuery query);
-
- /**
* Charset of source and test files. If it's not defined, then return the platform default charset.
*/
Charset sourceCharset();
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/SimpleModuleFileSystem.java b/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/SimpleModuleFileSystem.java
index 48bb0a3fcb0..4d821c0bf8e 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/SimpleModuleFileSystem.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/SimpleModuleFileSystem.java
@@ -42,6 +42,11 @@ public class SimpleModuleFileSystem implements ModuleFileSystem {
this.buildDir = new File(baseDir, "build");
}
+ @Override
+ public String moduleKey() {
+ return null;
+ }
+
public File baseDir() {
return baseDir;
}
@@ -81,11 +86,6 @@ public class SimpleModuleFileSystem implements ModuleFileSystem {
return Collections.emptyList();
}
- @Override
- public List<File> changedFiles(FileQuery query) {
- return Collections.emptyList();
- }
-
public Charset sourceCharset() {
return Charset.forName(CharEncoding.UTF_8);
}