From e486fe02a0a38d3d9fb70690f7870c77e2265254 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Thu, 20 Feb 2014 07:23:08 +0100 Subject: [PATCH] SONAR-926 move FS API to org.sonar.api.batch.fs --- .../core/issue/InitialOpenIssuesStack.java | 10 +- .../plugins/core/sensors/FileHashSensor.java | 9 +- .../issue/InitialOpenIssuesStackTest.java | 4 +- .../core/sensors/FileHashSensorTest.java | 15 +- .../sonar/plugins/cpd/SonarBridgeEngine.java | 38 +- .../org/sonar/plugins/cpd/SonarEngine.java | 34 +- .../cpd/index/DbDuplicationsIndex.java | 3 +- .../cpd/index/SonarDuplicationsIndex.java | 3 +- .../sonar/plugins/cpd/SonarEngineTest.java | 31 +- .../batch/DefaultFileLinesContextFactory.java | 4 +- .../org/sonar/batch/DefaultSensorContext.java | 4 +- .../java/org/sonar/batch/fs/package-info.java | 27 ++ .../java/org/sonar/batch/index/Cache.java | 378 +++++++++++++----- .../java/org/sonar/batch/index/Caches.java | 4 +- .../sonar/batch/index/ComponentDataCache.java | 4 +- .../batch/index/ComponentDataPersister.java | 4 +- .../batch/index/DefaultResourcePersister.java | 13 +- .../batch/index/ResourceKeyMigration.java | 21 +- .../sonar/batch/index/ResourcePersister.java | 2 +- .../org/sonar/batch/issue/IssueCache.java | 4 +- .../ignore/scanner/IssueExclusionsLoader.java | 20 +- .../org/sonar/batch/phases/ProfileLogger.java | 12 +- .../sonar/batch/scan/ModuleScanContainer.java | 17 +- .../scan/filesystem/ComponentIndexer.java | 40 +- .../filesystem/DefaultModuleFileSystem.java | 177 +++++--- .../filesystem/DeprecatedFileFilters.java | 19 +- .../scan/filesystem/ExclusionFilter.java | 5 +- .../scan/filesystem/ExclusionFilters.java | 9 +- .../{FileIndex.java => FileIndexer.java} | 102 +++-- .../batch/scan/filesystem/FileMetadata.java | 6 +- .../filesystem/FilePredicateAdapters.java | 79 ++++ .../scan/filesystem/FileQueryFilter.java | 71 ---- .../scan/filesystem/FileSystemLogger.java | 2 +- .../scan/filesystem/InclusionFilter.java | 5 +- .../scan/filesystem/InputFileBuilder.java | 42 +- .../filesystem/InputFileBuilderFactory.java | 7 +- .../batch/scan/filesystem/InputFileCache.java | 56 ++- .../scan/filesystem/LanguageDetection.java | 7 +- .../scan/filesystem/ModuleInputFileCache.java | 57 +++ .../filesystem/ProjectFileSystemAdapter.java | 72 ++-- .../scan/filesystem/StatusDetection.java | 10 +- .../scan/language/DefaultModuleLanguages.java | 24 +- .../batch/scan/report/ComponentSelector.java | 51 --- .../sonar/batch/scan/report/JsonReport.java | 29 +- .../java/org/sonar/batch/index/CacheTest.java | 300 +++++++------- .../org/sonar/batch/index/CachesTest.java | 6 +- .../batch/index/ResourceKeyMigrationTest.java | 16 +- .../scanner/IssueExclusionsLoaderTest.java | 90 ++--- .../sonar/batch/phases/ProfileLoggerTest.java | 52 +-- .../sonar/batch/rule/QProfileSensorTest.java | 4 +- .../scan/filesystem/AttributeFilterTest.java | 48 --- .../scan/filesystem/ComponentIndexerTest.java | 101 ++--- .../DefaultModuleFileSystemTest.java | 78 ++-- .../filesystem/DeprecatedFileFiltersTest.java | 27 +- .../scan/filesystem/ExclusionFilterTest.java | 19 +- .../scan/filesystem/ExclusionFiltersTest.java | 46 +-- .../scan/filesystem/FileMetadataTest.java | 12 +- .../scan/filesystem/FileQueryFilterTest.java | 108 ----- .../scan/filesystem/InclusionFilterTest.java | 18 +- .../InputFileBuilderFactoryTest.java | 4 +- .../scan/filesystem/InputFileBuilderTest.java | 69 ++-- .../scan/filesystem/InputFileCacheTest.java | 16 +- .../filesystem/LanguageDetectionTest.java | 7 +- .../scan/filesystem/StatusDetectionTest.java | 10 +- .../batch/scan/report/JsonReportTest.java | 31 +- .../encoding/CP1252Encoding.java | 0 .../encoding/MacRomanEncoding.java | 0 .../org/sonar/api/batch/ModuleLanguages.java | 2 - .../org/sonar/api/batch/SensorContext.java | 32 +- .../api/batch/fs/AbsolutePathPredicate.java | 39 ++ .../fs/AndPredicate.java} | 33 +- .../org/sonar/api/batch/fs/FilePredicate.java | 29 ++ .../sonar/api/batch/fs/FilePredicates.java | 152 +++++++ .../org/sonar/api/batch/fs/FileSystem.java | 92 +++++ .../org/sonar/api/batch/fs/InputFile.java | 87 ++++ .../fs}/InputFileFilter.java | 9 +- .../sonar/api/batch/fs/LanguagePredicate.java | 36 ++ .../org/sonar/api/batch/fs/NotPredicate.java | 38 ++ .../org/sonar/api/batch/fs/OrPredicate.java | 45 +++ .../api/batch/fs/PathPatternPredicate.java | 40 ++ .../api/batch/fs/RelativePathPredicate.java | 40 +- .../sonar/api/batch/fs/StatusPredicate.java | 38 ++ .../org/sonar/api/batch/fs/TypePredicate.java | 39 ++ .../api/batch/fs/UniqueIndexPredicate.java} | 17 +- .../batch/fs/internal/DefaultFileSystem.java | 225 +++++++++++ .../batch/fs/internal/DefaultInputFile.java | 252 ++++++++++++ .../api/batch/fs/internal/FileIndex.java | 39 ++ .../api/batch/fs/internal}/PathPattern.java | 66 +-- .../batch/fs/internal/RelativePathIndex.java | 39 ++ .../fs}/internal/package-info.java | 2 +- .../org/sonar/api/batch/fs/package-info.java | 23 ++ .../api/measures/FileLinesContextFactory.java | 2 +- .../sonar/api/scan/filesystem/FileQuery.java | 18 +- .../sonar/api/scan/filesystem/FileType.java | 6 +- .../sonar/api/scan/filesystem/InputFile.java | 98 ----- .../api/scan/filesystem/ModuleFileSystem.java | 21 +- .../filesystem/internal/DefaultInputFile.java | 217 ---------- .../filesystem/internal/InputFileBuilder.java | 89 ----- .../fs/internal/DefaultInputFileTest.java | 75 ++++ .../internal/DefaultInputFileTest.java | 100 ----- .../filesystem/internal/InputFilesTest.java | 48 --- .../org/sonar/server/rule/ws/RulesWs.java | 20 - .../org/sonar/server/rule/ws/RulesWsTest.java | 15 +- .../server/rule/ws/RulesWsTest/list.json | 3 - 104 files changed, 2669 insertions(+), 2050 deletions(-) create mode 100644 sonar-batch/src/main/java/org/sonar/batch/fs/package-info.java rename sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/{FileIndex.java => FileIndexer.java} (74%) create mode 100644 sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FilePredicateAdapters.java delete mode 100644 sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java create mode 100644 sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java delete mode 100644 sonar-batch/src/main/java/org/sonar/batch/scan/report/ComponentSelector.java delete mode 100644 sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AttributeFilterTest.java delete mode 100644 sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileQueryFilterTest.java rename sonar-batch/test-resources/org/sonar/batch/phases/{FileIndexerTest => ComponentIndexerTest}/encoding/CP1252Encoding.java (100%) rename sonar-batch/test-resources/org/sonar/batch/phases/{FileIndexerTest => ComponentIndexerTest}/encoding/MacRomanEncoding.java (100%) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AbsolutePathPredicate.java rename sonar-plugin-api/src/main/java/org/sonar/api/{scan/filesystem/internal/InputFiles.java => batch/fs/AndPredicate.java} (65%) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java rename sonar-plugin-api/src/main/java/org/sonar/api/{scan/filesystem => batch/fs}/InputFileFilter.java (82%) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/LanguagePredicate.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/NotPredicate.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/OrPredicate.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/PathPatternPredicate.java rename sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AttributeFilter.java => sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/RelativePathPredicate.java (56%) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/StatusPredicate.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TypePredicate.java rename sonar-plugin-api/src/{test/java/org/sonar/api/scan/filesystem/internal/InputFileBuilderTest.java => main/java/org/sonar/api/batch/fs/UniqueIndexPredicate.java} (78%) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileIndex.java rename {sonar-batch/src/main/java/org/sonar/batch/scan/filesystem => sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal}/PathPattern.java (66%) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathIndex.java rename sonar-plugin-api/src/main/java/org/sonar/api/{scan/filesystem => batch/fs}/internal/package-info.java (95%) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/DefaultInputFile.java delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/InputFileBuilder.java create mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java delete mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/DefaultInputFileTest.java delete mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/InputFilesTest.java delete mode 100644 sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsTest/list.json diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesStack.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesStack.java index 10a41111771..be0b0cea5f6 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesStack.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesStack.java @@ -36,8 +36,8 @@ import static com.google.common.collect.Lists.newArrayList; @InstantiationStrategy(InstantiationStrategy.PER_BATCH) public class InitialOpenIssuesStack implements BatchExtension { - private final Cache issuesCache; - private final Cache> issuesChangelogCache; + private final Cache issuesCache; + private final Cache> issuesChangelogCache; public InitialOpenIssuesStack(Caches caches) { issuesCache = caches.createCache("last-open-issues"); @@ -60,7 +60,7 @@ public class InitialOpenIssuesStack implements BatchExtension { } public Iterable selectAllIssues() { - return issuesCache.allValues(); + return issuesCache.values(); } public InitialOpenIssuesStack addChangelog(IssueChangeDto issueChangeDto) { @@ -79,7 +79,7 @@ public class InitialOpenIssuesStack implements BatchExtension { } public void clear() { - issuesCache.clearAll(); - issuesChangelogCache.clearAll(); + issuesCache.clear(); + issuesChangelogCache.clear(); } } 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 fd14c7b7f06..ca6d2278350 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,12 +19,11 @@ */ package org.sonar.plugins.core.sensors; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; - -import org.sonar.api.scan.filesystem.InputFile; import com.google.common.collect.Maps; import org.sonar.api.batch.Sensor; import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.resources.Project; import org.sonar.api.utils.KeyValueFormat; import org.sonar.batch.index.ComponentDataCache; @@ -60,9 +59,9 @@ public final class FileHashSensor implements Sensor { public void analyse(Project project, SensorContext context) { Map map = Maps.newHashMap(); for (InputFile inputFile : fileCache.byModule(project.key())) { - String hash = inputFile.attribute(DefaultInputFile.ATTRIBUTE_HASH); + String hash = ((DefaultInputFile) inputFile).hash(); if (hash != null) { - map.put(inputFile.path(), hash); + map.put(inputFile.relativePath(), hash); } } if (!map.isEmpty()) { diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java index a32ea0bb51d..929e7dc099e 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java @@ -60,14 +60,14 @@ public class InitialOpenIssuesStackTest { Caches caches; @Before - public void setUp() throws Exception { + public void before() throws Exception { caches = createCacheOnTemp(temp); caches.start(); stack = new InitialOpenIssuesStack(caches); } @After - public void tearDown() { + public void after() { caches.stop(); } 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 073db76b693..1b9759331e7 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,8 +19,6 @@ */ package org.sonar.plugins.core.sensors; -import org.sonar.api.scan.filesystem.InputFile; - import com.google.common.base.Charsets; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; @@ -29,8 +27,9 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.resources.Project; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; import org.sonar.batch.index.ComponentDataCache; import org.sonar.batch.scan.filesystem.InputFileCache; import org.sonar.core.source.SnapshotDataTypes; @@ -59,9 +58,8 @@ public class FileHashSensorTest { @Test public void store_file_hashes() throws Exception { when(fileCache.byModule("struts")).thenReturn(Lists.newArrayList( - DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "src/Foo.java", ImmutableMap.of(DefaultInputFile.ATTRIBUTE_HASH, "ABC")), - DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "src/Bar.java", ImmutableMap.of(DefaultInputFile.ATTRIBUTE_HASH, "DEF")) - )); + new DefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"), + new DefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF"))); SensorContext sensorContext = mock(SensorContext.class); sensor.analyse(project, sensorContext); @@ -74,9 +72,8 @@ public class FileHashSensorTest { public void store_file_hashes_for_branches() throws Exception { project = new Project("struts", "branch-2.x", "Struts 2.x"); when(fileCache.byModule("struts:branch-2.x")).thenReturn(Lists.newArrayList( - DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "src/Foo.java", ImmutableMap.of(DefaultInputFile.ATTRIBUTE_HASH, "ABC")), - DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "src/Bar.java", ImmutableMap.of(DefaultInputFile.ATTRIBUTE_HASH, "DEF")) - )); + new DefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"), + new DefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF"))); SensorContext sensorContext = mock(SensorContext.class); sensor.analyse(project, sensorContext); diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java index 9f6bb9d1f67..14b073d6711 100644 --- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java +++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java @@ -27,13 +27,13 @@ import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; import org.sonar.api.batch.CpdMapping; import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; -import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; import org.sonar.api.utils.SonarException; -import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; import org.sonar.duplications.DuplicationPredicates; import org.sonar.duplications.block.Block; import org.sonar.duplications.index.CloneGroup; @@ -42,14 +42,9 @@ import org.sonar.plugins.cpd.index.IndexFactory; import org.sonar.plugins.cpd.index.SonarDuplicationsIndex; import javax.annotation.CheckForNull; - import java.util.Collection; import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.*; public class SonarBridgeEngine extends CpdEngine { @@ -62,18 +57,18 @@ public class SonarBridgeEngine extends CpdEngine { private final IndexFactory indexFactory; private final CpdMapping[] mappings; - private final DefaultModuleFileSystem fileSystem; + private final FileSystem fs; private final Settings settings; - public SonarBridgeEngine(IndexFactory indexFactory, CpdMapping[] mappings, DefaultModuleFileSystem moduleFileSystem, Settings settings) { + public SonarBridgeEngine(IndexFactory indexFactory, CpdMapping[] mappings, FileSystem fs, Settings settings) { this.indexFactory = indexFactory; this.mappings = mappings; - this.fileSystem = moduleFileSystem; + this.fs = fs; this.settings = settings; } - public SonarBridgeEngine(IndexFactory indexFactory, DefaultModuleFileSystem moduleFileSystem, Settings settings) { - this(indexFactory, new CpdMapping[0], moduleFileSystem, settings); + public SonarBridgeEngine(IndexFactory indexFactory, FileSystem fs, Settings settings) { + this(indexFactory, new CpdMapping[0], fs, settings); } @Override @@ -85,8 +80,11 @@ public class SonarBridgeEngine extends CpdEngine { public void analyse(Project project, String languageKey, SensorContext context) { String[] cpdExclusions = settings.getStringArray(CoreProperties.CPD_EXCLUSIONS); logExclusions(cpdExclusions, LOG); - Iterable sourceFiles = fileSystem.inputFiles(FileQuery.onMain().onLanguage(languageKey) - .withExclusions(cpdExclusions)); + Iterable sourceFiles = fs.inputFiles(FilePredicates.and( + FilePredicates.hasType(InputFile.Type.MAIN), + FilePredicates.hasLanguage(languageKey), + FilePredicates.doesNotMatchPathPatterns(cpdExclusions) + )); if (!sourceFiles.iterator().hasNext()) { return; } @@ -99,10 +97,10 @@ public class SonarBridgeEngine extends CpdEngine { // Create index SonarDuplicationsIndex index = indexFactory.create(project); - TokenizerBridge bridge = new TokenizerBridge(mapping.getTokenizer(), fileSystem.sourceCharset().name(), getBlockSize(project, languageKey)); + TokenizerBridge bridge = new TokenizerBridge(mapping.getTokenizer(), fs.encoding().name(), getBlockSize(project, languageKey)); for (InputFile inputFile : sourceFiles) { LOG.debug("Populating index from {}", inputFile); - String resourceEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY); + String resourceEffectiveKey = ((DefaultInputFile) inputFile).key(); List blocks = bridge.chunk(resourceEffectiveKey, inputFile.file()); index.insert(inputFile, blocks); } @@ -114,7 +112,7 @@ public class SonarBridgeEngine extends CpdEngine { try { for (InputFile inputFile : sourceFiles) { LOG.debug("Detection of duplications for {}", inputFile); - String resourceEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY); + String resourceEffectiveKey = ((DefaultInputFile) inputFile).key(); Collection fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey); Iterable filtered; diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java index 70c2731ae45..0b340ce17c4 100644 --- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java +++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java @@ -27,17 +27,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.config.Settings; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Measure; import org.sonar.api.measures.PersistenceMode; 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.InputFile; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; import org.sonar.api.utils.SonarException; -import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; import org.sonar.duplications.block.Block; import org.sonar.duplications.block.BlockChunker; import org.sonar.duplications.detector.suffixtree.SuffixTreeCloneDetectionAlgorithm; @@ -53,7 +53,6 @@ import org.sonar.plugins.cpd.index.IndexFactory; import org.sonar.plugins.cpd.index.SonarDuplicationsIndex; import javax.annotation.Nullable; - import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStreamReader; @@ -62,12 +61,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.*; public class SonarEngine extends CpdEngine { @@ -81,12 +75,12 @@ public class SonarEngine extends CpdEngine { private static final int TIMEOUT = 5 * 60; private final IndexFactory indexFactory; - private final DefaultModuleFileSystem fileSystem; + private final FileSystem fs; private final Settings settings; - public SonarEngine(IndexFactory indexFactory, DefaultModuleFileSystem moduleFileSystem, Settings settings) { + public SonarEngine(IndexFactory indexFactory, FileSystem fs, Settings settings) { this.indexFactory = indexFactory; - this.fileSystem = moduleFileSystem; + this.fs = fs; this.settings = settings; } @@ -99,7 +93,11 @@ public class SonarEngine extends CpdEngine { public void analyse(Project project, String languageKey, SensorContext context) { String[] cpdExclusions = settings.getStringArray(CoreProperties.CPD_EXCLUSIONS); logExclusions(cpdExclusions, LOG); - Iterable sourceFiles = fileSystem.inputFiles(FileQuery.onMain().onLanguage(languageKey).withExclusions(cpdExclusions)); + Iterable sourceFiles = fs.inputFiles(FilePredicates.and( + FilePredicates.hasType(InputFile.Type.MAIN), + FilePredicates.hasLanguage(languageKey), + FilePredicates.doesNotMatchPathPatterns(cpdExclusions) + )); if (!sourceFiles.iterator().hasNext()) { return; } @@ -116,13 +114,13 @@ public class SonarEngine extends CpdEngine { for (InputFile inputFile : sourceFiles) { LOG.debug("Populating index from {}", inputFile); - String resourceEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY); + String resourceEffectiveKey = ((DefaultInputFile) inputFile).key(); List statements; Reader reader = null; try { - reader = new InputStreamReader(new FileInputStream(inputFile.file()), fileSystem.sourceCharset()); + reader = new InputStreamReader(new FileInputStream(inputFile.file()), fs.encoding()); statements = statementChunker.chunk(tokenChunker.chunk(reader)); } catch (FileNotFoundException e) { throw new SonarException("Cannot find file " + inputFile.file(), e); @@ -142,7 +140,7 @@ public class SonarEngine extends CpdEngine { try { for (InputFile inputFile : sourceFiles) { LOG.debug("Detection of duplications for {}", inputFile); - String resourceEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY); + String resourceEffectiveKey = ((DefaultInputFile) inputFile).key(); Collection fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey); diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbDuplicationsIndex.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbDuplicationsIndex.java index 83475fbb861..934f2a3fa5f 100644 --- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbDuplicationsIndex.java +++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbDuplicationsIndex.java @@ -19,10 +19,9 @@ */ package org.sonar.plugins.cpd.index; -import org.sonar.api.scan.filesystem.InputFile; - import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.database.model.Snapshot; import org.sonar.api.resources.Project; import org.sonar.batch.index.ResourcePersister; diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarDuplicationsIndex.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarDuplicationsIndex.java index 6a54af3503b..c869647e635 100644 --- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarDuplicationsIndex.java +++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarDuplicationsIndex.java @@ -19,9 +19,8 @@ */ package org.sonar.plugins.cpd.index; -import org.sonar.api.scan.filesystem.InputFile; - import com.google.common.collect.Lists; +import org.sonar.api.batch.fs.InputFile; import org.sonar.duplications.block.Block; import org.sonar.duplications.block.ByteArray; import org.sonar.duplications.index.AbstractCloneIndex; diff --git a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java index 18c80b5dcfc..5fae998b0b6 100644 --- a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java +++ b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java @@ -19,37 +19,39 @@ */ package org.sonar.plugins.cpd; -import org.sonar.api.scan.filesystem.InputFile; - -import com.google.common.base.Charsets; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.scan.filesystem.internal.InputFileBuilder; import org.sonar.api.test.IsMeasure; import org.sonar.duplications.index.CloneGroup; import org.sonar.duplications.index.ClonePart; +import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.List; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.*; public class SonarEngineTest { - private SensorContext context; - private InputFile inputFile; + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + SensorContext context = mock(SensorContext.class); + DefaultInputFile inputFile; @Before - public void setUp() { - context = mock(SensorContext.class); - inputFile = new InputFileBuilder(new java.io.File(""), Charsets.UTF_8, "src/main/java/Foo.java").build(); + public void before() throws IOException { + inputFile = new DefaultInputFile("src/main/java/Foo.java"); + inputFile.setFile(temp.newFile("Foo.java")); } @SuppressWarnings("unchecked") @@ -135,8 +137,9 @@ public class SonarEngineTest { } @Test - public void shouldEscapeXmlEntities() { - InputFile csharpFile = new InputFileBuilder(new java.io.File(""), Charsets.UTF_8, "Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs").build(); + public void shouldEscapeXmlEntities() throws IOException { + InputFile csharpFile = new DefaultInputFile("Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs") + .setFile(temp.newFile("SubsRedsDelivery.cs")); List groups = Arrays.asList(newCloneGroup( new ClonePart("Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs", 0, 5, 204), new ClonePart("Loads/File Loads/Subs & Reds/SubsRedsDelivery2.cs", 0, 15, 214))); diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContextFactory.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContextFactory.java index 5d3b49e8e9f..cc59b0bf5d7 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContextFactory.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContextFactory.java @@ -20,11 +20,11 @@ package org.sonar.batch; import org.sonar.api.batch.SonarIndex; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.measures.FileLinesContext; import org.sonar.api.measures.FileLinesContextFactory; import org.sonar.api.resources.File; import org.sonar.api.resources.Resource; -import org.sonar.api.scan.filesystem.InputFile; public class DefaultFileLinesContextFactory implements FileLinesContextFactory { @@ -43,7 +43,7 @@ public class DefaultFileLinesContextFactory implements FileLinesContextFactory { @Override public FileLinesContext createFor(InputFile inputFile) { - File sonarFile = File.create(inputFile.path()); + File sonarFile = File.create(inputFile.relativePath()); // Reload resource from index sonarFile = index.getResource(sonarFile); return new DefaultFileLinesContext(index, sonarFile); diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java index 158e9e79982..bbeb88afdb8 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java @@ -25,13 +25,13 @@ import org.slf4j.LoggerFactory; import org.sonar.api.batch.Event; import org.sonar.api.batch.SensorContext; import org.sonar.api.batch.SonarIndex; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.design.Dependency; import org.sonar.api.measures.Measure; import org.sonar.api.measures.MeasuresFilter; import org.sonar.api.measures.Metric; import org.sonar.api.resources.*; import org.sonar.api.rules.Violation; -import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.utils.SonarException; import org.sonar.core.measure.MeasurementFilters; @@ -248,6 +248,6 @@ public class DefaultSensorContext implements SensorContext { } private Resource fromInputFile(InputFile inputFile) { - return File.create(inputFile.path()); + return File.create(inputFile.relativePath()); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/fs/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/fs/package-info.java new file mode 100644 index 00000000000..9b04956ebae --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/fs/package-info.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +/** + * This package is a part of bootstrap process, so we should take care about backward compatibility. + */ +@ParametersAreNonnullByDefault +package org.sonar.batch.fs; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/Cache.java b/sonar-batch/src/main/java/org/sonar/batch/index/Cache.java index bf48d6a5c58..37749efbeb7 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/Cache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/Cache.java @@ -35,9 +35,8 @@ import java.util.Set; * This cache is not thread-safe, due to direct usage of {@link com.persistit.Exchange} *

*/ -public class Cache { +public class Cache { - private static final String DEFAULT_GROUP = "_"; private final String name; private final Exchange exchange; @@ -46,14 +45,28 @@ public class Cache { this.exchange = exchange; } - public Cache put(K key, V value) { - return put(DEFAULT_GROUP, key, value); + public Cache put(Object key, V value) { + resetKey(key); + return doPut(value); } - public Cache put(String group, K key, V value) { + public Cache put(Object firstKey, Object secondKey, V value) { + resetKey(firstKey, secondKey); + return doPut(value); + } + + public Cache put(Object firstKey, Object secondKey, Object thirdKey, V value) { + resetKey(firstKey, secondKey, thirdKey); + return doPut(value); + } + + public Cache put(Object[] key, V value) { + resetKey(key); + return doPut(value); + } + + private Cache doPut(V value) { try { - exchange.clear(); - exchange.append(group).append(key); exchange.getValue().put(value); exchange.store(); return this; @@ -63,17 +76,43 @@ public class Cache { } /** - * Implements group-based retrieval of cache elements. - * - * @param key The key. - * @param group The group. - * @return The element associated with key in the group, or null. + * Returns the value object associated with keys, or null if not found. */ - @SuppressWarnings("unchecked") - public V get(String group, K key) { + public V get(Object key) { + resetKey(key); + return doGet(); + } + + /** + * Returns the value object associated with keys, or null if not found. + */ + @CheckForNull + public V get(Object firstKey, Object secondKey) { + resetKey(firstKey, secondKey); + return doGet(); + } + + /** + * Returns the value object associated with keys, or null if not found. + */ + @CheckForNull + public V get(Object firstKey, Object secondKey, Object thirdKey) { + resetKey(firstKey, secondKey, thirdKey); + return doGet(); + } + + /** + * Returns the value object associated with keys, or null if not found. + */ + @CheckForNull + public V get(Object[] key) { + resetKey(key); + return doGet(); + } + + @CheckForNull + private V doGet() { try { - exchange.clear(); - exchange.append(group).append(key); exchange.fetch(); if (!exchange.getValue().isDefined()) { return null; @@ -85,21 +124,28 @@ public class Cache { } } - /** - * Returns the object associated with key from the cache, or null if not found. - * - * @param key The key whose associated value is to be retrieved. - * @return The value, or null if not found. - */ - @SuppressWarnings("unchecked") - public V get(K key) { - return get(DEFAULT_GROUP, key); + public boolean containsKey(Object key) { + resetKey(key); + return doContainsKey(); + } + + public boolean containsKey(Object firstKey, Object secondKey) { + resetKey(firstKey, secondKey); + return doContainsKey(); + } + + public boolean containsKey(Object firstKey, Object secondKey, Object thirdKey) { + resetKey(firstKey, secondKey, thirdKey); + return doContainsKey(); } - public boolean containsKey(String group, K key) { + public boolean containsKey(Object[] key) { + resetKey(key); + return doContainsKey(); + } + + private boolean doContainsKey() { try { - exchange.clear(); - exchange.append(group).append(key); exchange.fetch(); return exchange.isValueDefined(); } catch (Exception e) { @@ -108,10 +154,28 @@ public class Cache { } } - public boolean remove(String group, K key) { + public boolean remove(Object key) { + resetKey(key); + return doRemove(); + } + + public boolean remove(Object firstKey, Object secondKey) { + resetKey(firstKey, secondKey); + return doRemove(); + } + + public boolean remove(Object firstKey, Object secondKey, Object thirdKey) { + resetKey(firstKey, secondKey, thirdKey); + return doRemove(); + } + + public boolean remove(Object[] key) { + resetKey(key); + return doRemove(); + } + + private boolean doRemove() { try { - exchange.clear(); - exchange.append(group).append(key); return exchange.remove(); } catch (Exception e) { // TODO add parameters to message @@ -119,40 +183,47 @@ public class Cache { } } - public boolean remove(K key) { - return remove(DEFAULT_GROUP, key); - } - /** * Removes everything in the specified group. * * @param group The group name. */ - public Cache clear(String group) { + public Cache clear(Object key) { + resetKey(key); + return doClear(); + } + + public Cache clear(Object firstKey, Object secondKey) { + resetKey(firstKey, secondKey); + return doClear(); + } + + public Cache clear(Object firstKey, Object secondKey, Object thirdKey) { + resetKey(firstKey, secondKey, thirdKey); + return doClear(); + } + + public Cache clear(Object[] key) { + resetKey(key); + return doClear(); + } + + private Cache doClear() { try { - exchange.clear(); - exchange.append(group); - Key key = new Key(exchange.getKey()); - key.append(Key.AFTER); - exchange.removeKeyRange(exchange.getKey(), key); + Key to = new Key(exchange.getKey()); + to.append(Key.AFTER); + exchange.removeKeyRange(exchange.getKey(), to); return this; } catch (Exception e) { - throw new IllegalStateException("Fail to clear group '" + group + "' from cache " + name, e); + throw new IllegalStateException("Fail to clear values from cache " + name, e); } } - /** - * Removes everything in the default cache, but not any of the group caches. - */ - public Cache clear() { - return clear(DEFAULT_GROUP); - } - /** * Clears the default as well as all group caches. */ - public void clearAll() { + public void clear() { try { exchange.clear(); exchange.removeAll(); @@ -169,16 +240,15 @@ public class Cache { * @return The set of cache keys for this group. */ @SuppressWarnings("unchecked") - public Set keySet(String group) { + public Set keySet(Object key) { try { - Set keys = Sets.newLinkedHashSet(); + Set keys = Sets.newLinkedHashSet(); exchange.clear(); Exchange iteratorExchange = new Exchange(exchange); - - iteratorExchange.append(group); + iteratorExchange.append(key); iteratorExchange.append(Key.BEFORE); while (iteratorExchange.next(false)) { - keys.add((K) iteratorExchange.getKey().indexTo(-1).decode()); + keys.add(iteratorExchange.getKey().indexTo(-1).decode()); } return keys; } catch (Exception e) { @@ -186,24 +256,51 @@ public class Cache { } } + public Set keySet(Object firstKey, Object secondKey) { + try { + Set keys = Sets.newLinkedHashSet(); + exchange.clear(); + Exchange iteratorExchange = new Exchange(exchange); + iteratorExchange.append(firstKey); + iteratorExchange.append(secondKey); + iteratorExchange.append(Key.BEFORE); + while (iteratorExchange.next(false)) { + keys.add(iteratorExchange.getKey().indexTo(-1).decode()); + } + return keys; + } catch (Exception e) { + throw new IllegalStateException("Fail to get keys from cache " + name, e); + } + } /** * Returns the set of keys associated with this cache. * * @return The set containing the keys for this cache. */ - public Set keySet() { - return keySet(DEFAULT_GROUP); + public Set keySet() { + try { + Set keys = Sets.newLinkedHashSet(); + exchange.clear(); + Exchange iteratorExchange = new Exchange(exchange); + iteratorExchange.append(Key.BEFORE); + while (iteratorExchange.next(false)) { + keys.add(iteratorExchange.getKey().indexTo(-1).decode()); + } + return keys; + } catch (Exception e) { + throw new IllegalStateException("Fail to get keys from cache " + name, e); + } } /** - * Lazy-loading values for a given group + * Lazy-loading values for a given key */ - public Iterable values(String group) { + public Iterable values(Object key) { try { exchange.clear(); + exchange.append(key).append(Key.BEFORE); Exchange iteratorExchange = new Exchange(exchange); - iteratorExchange.append(group).append(Key.BEFORE); return new ValueIterable(iteratorExchange, false); } catch (Exception e) { throw new IllegalStateException("Fail to get values from cache " + name, e); @@ -214,46 +311,45 @@ public class Cache { * Lazy-loading values */ public Iterable values() { - return values(DEFAULT_GROUP); - } - - /** - * Lazy-loading values of all groups - */ - public Iterable allValues() { try { - exchange.clear(); + exchange.clear().append(Key.BEFORE); Exchange iteratorExchange = new Exchange(exchange); - iteratorExchange.append(Key.BEFORE); return new ValueIterable(iteratorExchange, true); } catch (Exception e) { throw new IllegalStateException("Fail to get values from cache " + name, e); } } - public Set groups() { - try { - Set groups = Sets.newLinkedHashSet(); - exchange.clear(); - Exchange iteratorExchange = new Exchange(exchange); - iteratorExchange.append(Key.BEFORE); - while (iteratorExchange.next(false)) { - groups.add(iteratorExchange.getKey().decodeString()); - } - return groups; - } catch (Exception e) { - throw new IllegalStateException("Fail to get values from cache " + name, e); - } - } - - public Iterable> entries() { + public Iterable> entries() { exchange.clear().to(Key.BEFORE); return new EntryIterable(new Exchange(exchange), true); } - public Iterable> entries(String group) { - exchange.clear().append(group).append(Key.BEFORE); - return new EntryIterable(new Exchange(exchange), false); + public Iterable> subEntries(Object key) { + exchange.clear().append(key).append(Key.BEFORE); + return new SubEntryIterable(new Exchange(exchange), false); + } + + private void resetKey(Object key) { + exchange.clear(); + exchange.append(key); + } + + private void resetKey(Object first, Object second) { + exchange.clear(); + exchange.append(first).append(second); + } + + private void resetKey(Object first, Object second, Object third) { + exchange.clear(); + exchange.append(first).append(second).append(third); + } + + private void resetKey(Object[] keys) { + exchange.clear(); + for (Object o : keys) { + exchange.append(o); + } } @@ -286,7 +382,7 @@ public class Cache { @Override public boolean hasNext() { try { - return exchange.next(deep); + return exchange.hasNext(deep); } catch (PersistitException e) { throw new IllegalStateException(e); } @@ -294,6 +390,11 @@ public class Cache { @Override public T next() { + try { + exchange.next(deep); + } catch (PersistitException e) { + throw new IllegalStateException(e); + } T value = null; if (exchange.getValue().isDefined()) { value = (T) exchange.getValue().get(); @@ -306,6 +407,81 @@ public class Cache { } } + private static class SubEntryIterable implements Iterable> { + private final SubEntryIterator it; + + private SubEntryIterable(Exchange exchange, boolean deep) { + it = new SubEntryIterator(exchange, deep); + } + + @Override + public Iterator> iterator() { + return it; + } + } + + private static class SubEntryIterator implements Iterator> { + private final Exchange exchange; + private final boolean deep; + + private SubEntryIterator(Exchange exchange, boolean deep) { + this.exchange = exchange; + this.deep = deep; + } + + @Override + public boolean hasNext() { + try { + return exchange.next(deep); + } catch (PersistitException e) { + throw new IllegalStateException(e); + } + } + + @Override + public SubEntry next() { + Serializable value = null; + if (exchange.getValue().isDefined()) { + value = (Serializable) exchange.getValue().get(); + } + Key key = exchange.getKey(); + return new SubEntry(key.indexTo(-1).decode(), value); + } + + @Override + public void remove() { + // nothing to do + } + } + + public static class SubEntry { + private final Object key; + private final V value; + + SubEntry(Object key, V value) { + this.key = key; + this.value = value; + } + + public Object key() { + return key; + } + + public String keyAsString() { + return (String) key; + } + + @CheckForNull + public V value() { + return value; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + } + private static class EntryIterable implements Iterable> { private final EntryIterator it; @@ -344,7 +520,11 @@ public class Cache { value = (Serializable) exchange.getValue().get(); } Key key = exchange.getKey(); - return new Entry(key.indexTo(-2).decodeString(), key.indexTo(-1).decodeString(), value); + Object[] array = new Object[key.getDepth()]; + for (int i = 0; i < key.getDepth(); i++) { + array[i] = key.indexTo(i - key.getDepth()).decode(); + } + return new Entry(array, value); } @Override @@ -353,27 +533,21 @@ public class Cache { } } - public static class Entry { - private final String group; - private final String key; - private final T value; + public static class Entry { + private final Object[] key; + private final V value; - Entry(String group, String key, T value) { - this.group = group; + Entry(Object[] key, V value) { this.key = key; this.value = value; } - public String group() { - return group; - } - - public String key() { + public Object[] key() { return key; } @CheckForNull - public T value() { + public V value() { return value; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java index 0a985e2ed5d..41c13bb682a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java @@ -77,12 +77,12 @@ public class Caches implements BatchComponent, Startable { } } - public Cache createCache(String cacheName) { + public Cache createCache(String cacheName) { Preconditions.checkState(volume != null && volume.isOpened(), "Caches are not initialized"); Preconditions.checkState(!cacheNames.contains(cacheName), "Cache is already created: " + cacheName); try { Exchange exchange = persistit.getExchange(volume, cacheName, true); - Cache cache = new Cache(cacheName, exchange); + Cache cache = new Cache(cacheName, exchange); cacheNames.add(cacheName); return cache; } catch (Exception e) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataCache.java b/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataCache.java index c4cda7dc06e..3d6f57dd099 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataCache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataCache.java @@ -46,7 +46,7 @@ public class ComponentDataCache implements BatchComponent { return data == null ? null : ((StringData) data).data(); } - public Iterable> entries(String componentKey) { - return cache.entries(componentKey); + public Iterable> entries(String componentKey) { + return cache.subEntries(componentKey); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataPersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataPersister.java index abd996f0c9f..1d63d2591ae 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataPersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataPersister.java @@ -47,13 +47,13 @@ public class ComponentDataPersister implements ScanPersister { for (Map.Entry componentEntry : snapshots.snapshots()) { String componentKey = componentEntry.getKey(); Snapshot snapshot = componentEntry.getValue(); - for (Cache.Entry dataEntry : data.entries(componentKey)) { + for (Cache.SubEntry dataEntry : data.entries(componentKey)) { Data value = dataEntry.value(); if (value != null) { SnapshotDataDto dto = new SnapshotDataDto(); dto.setSnapshotId(snapshot.getId()); dto.setResourceId(snapshot.getResourceId()); - dto.setDataType(dataEntry.key()); + dto.setDataType(dataEntry.keyAsString()); dto.setData(value.writeString()); dao.insert(session, dto); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java index c658f4bc34f..ae18f9e3fac 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java @@ -22,23 +22,16 @@ package org.sonar.batch.index; import com.google.common.collect.Maps; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.database.DatabaseSession; import org.sonar.api.database.model.ResourceModel; import org.sonar.api.database.model.Snapshot; -import org.sonar.api.resources.File; -import org.sonar.api.resources.Library; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.ResourceUtils; -import org.sonar.api.resources.Scopes; -import org.sonar.api.scan.filesystem.InputFile; +import org.sonar.api.resources.*; import org.sonar.api.security.ResourcePermissions; import org.sonar.api.utils.SonarException; import javax.persistence.NonUniqueResultException; import javax.persistence.Query; - import java.util.Date; import java.util.Iterator; import java.util.List; @@ -140,7 +133,7 @@ public final class DefaultResourcePersister implements ResourcePersister { } private Resource fromInputFile(InputFile inputFile) { - return File.create(inputFile.path()); + return File.create(inputFile.relativePath()); } /** diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java index 576af394edb..3305b627a44 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java @@ -24,18 +24,11 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.BatchComponent; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.database.DatabaseSession; import org.sonar.api.database.model.ResourceModel; -import org.sonar.api.resources.Directory; -import org.sonar.api.resources.File; -import org.sonar.api.resources.Java; -import org.sonar.api.resources.JavaFile; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.Scopes; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; +import org.sonar.api.resources.*; import org.sonar.api.utils.PathUtils; import java.util.HashMap; @@ -74,9 +67,9 @@ public class ResourceKeyMigration implements BatchComponent { Map deprecatedTestKeyMapper = new HashMap(); Map deprecatedDirectoryKeyMapper = new HashMap(); for (InputFile inputFile : inputFiles) { - String deprecatedKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_DEPRECATED_KEY); + String deprecatedKey = ((DefaultInputFile) inputFile).deprecatedKey(); if (deprecatedKey != null) { - if (InputFile.TYPE_TEST.equals(inputFile.attribute(InputFile.ATTRIBUTE_TYPE))) { + if (InputFile.Type.TEST == inputFile.type()) { deprecatedTestKeyMapper.put(deprecatedKey, inputFile); } else { deprecatedFileKeyMapper.put(deprecatedKey, inputFile); @@ -107,7 +100,7 @@ public class ResourceKeyMigration implements BatchComponent { boolean isTest = Qualifiers.UNIT_TEST_FILE.equals(resourceModel.getQualifier()); InputFile matchedFile = findInputFile(deprecatedFileKeyMapper, deprecatedTestKeyMapper, oldEffectiveKey, isTest); if (matchedFile != null) { - String newEffectiveKey = matchedFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY); + String newEffectiveKey = ((DefaultInputFile) matchedFile).key(); // Now compute migration of the parent dir String oldKey = StringUtils.substringAfterLast(oldEffectiveKey, ":"); Resource sonarFile; @@ -163,7 +156,7 @@ public class ResourceKeyMigration implements BatchComponent { } private String getParentKey(InputFile matchedFile) { - String filePath = PathUtils.sanitize(matchedFile.path()); + String filePath = PathUtils.sanitize(matchedFile.relativePath()); String parentFolderPath; if (filePath.contains(Directory.SEPARATOR)) { parentFolderPath = StringUtils.substringBeforeLast(filePath, Directory.SEPARATOR); diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java index de12c23e87c..b9b59a5676d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java @@ -19,10 +19,10 @@ */ package org.sonar.batch.index; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.database.model.Snapshot; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; -import org.sonar.api.scan.filesystem.InputFile; public interface ResourcePersister { diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java index 1b2fcb3d314..e24d72a0ac9 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java @@ -31,7 +31,7 @@ import org.sonar.batch.index.Caches; public class IssueCache implements BatchComponent { // component key -> issue key -> issue - private final Cache cache; + private final Cache cache; public IssueCache(Caches caches) { cache = caches.createCache("issues"); @@ -42,7 +42,7 @@ public class IssueCache implements BatchComponent { } public Iterable all() { - return cache.allValues(); + return cache.values(); } public IssueCache put(DefaultIssue issue) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java index fbe61421f5f..2797ccaa330 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java @@ -20,14 +20,14 @@ package org.sonar.batch.issue.ignore.scanner; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.resources.Project; -import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; import org.sonar.api.utils.SonarException; import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; -import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; import java.nio.charset.Charset; @@ -36,11 +36,11 @@ public final class IssueExclusionsLoader { private final IssueExclusionsRegexpScanner regexpScanner; private final IssueExclusionPatternInitializer exclusionPatternInitializer; private final IssueInclusionPatternInitializer inclusionPatternInitializer; - private final DefaultModuleFileSystem fileSystem; + private final FileSystem fileSystem; public IssueExclusionsLoader(IssueExclusionsRegexpScanner regexpScanner, IssueExclusionPatternInitializer exclusionPatternInitializer, IssueInclusionPatternInitializer inclusionPatternInitializer, - DefaultModuleFileSystem fileSystem) { + FileSystem fileSystem) { this.regexpScanner = regexpScanner; this.exclusionPatternInitializer = exclusionPatternInitializer; this.inclusionPatternInitializer = inclusionPatternInitializer; @@ -56,13 +56,13 @@ public final class IssueExclusionsLoader { * {@inheritDoc} */ public void execute() { - Charset sourcesEncoding = fileSystem.sourceCharset(); + Charset sourcesEncoding = fileSystem.encoding(); - for (InputFile inputFile : fileSystem.inputFiles(FileQuery.all())) { + for (InputFile inputFile : fileSystem.inputFiles(FilePredicates.all())) { try { - String componentEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY); + String componentEffectiveKey = ((DefaultInputFile) inputFile).key(); if (componentEffectiveKey != null) { - String path = inputFile.path(); + String path = inputFile.relativePath(); inclusionPatternInitializer.initializePatternsForPath(path, componentEffectiveKey); exclusionPatternInitializer.initializePatternsForPath(path, componentEffectiveKey); if (exclusionPatternInitializer.hasFileContentPattern()) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/ProfileLogger.java b/sonar-batch/src/main/java/org/sonar/batch/phases/ProfileLogger.java index ec939d8df28..96d0721420d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/ProfileLogger.java +++ b/sonar-batch/src/main/java/org/sonar/batch/phases/ProfileLogger.java @@ -26,7 +26,7 @@ import org.slf4j.LoggerFactory; import org.sonar.api.BatchComponent; import org.sonar.api.batch.ModuleLanguages; import org.sonar.api.config.Settings; -import org.sonar.api.resources.Language; +import org.sonar.api.utils.MessageException; import org.sonar.api.utils.SonarException; import org.sonar.batch.rule.ModuleQProfiles; import org.sonar.batch.rule.ModuleQProfiles.QProfile; @@ -53,15 +53,15 @@ public class ProfileLogger implements BatchComponent { void execute(Logger logger) { String defaultName = settings.getString(ModuleQProfiles.SONAR_PROFILE_PROP); boolean defaultNameUsed = StringUtils.isBlank(defaultName); - for (Language lang : languages.languages()) { - QProfile profile = profiles.findByLanguage(lang.getKey()); - logger.info("Quality profile for {}: {}", lang.getName(), profile.name()); + for (String lang : languages.keys()) { + QProfile profile = profiles.findByLanguage(lang); + logger.info("Quality profile for {}: {}", lang, profile.name()); if (StringUtils.isNotBlank(defaultName) && defaultName.equals(profile.name())) { defaultNameUsed = true; } } - if (!defaultNameUsed && !languages.languages().isEmpty()) { - throw new SonarException("sonar.profile was set to '" + defaultName + "' but didn't match any profile for any language. Please check your configuration."); + if (!defaultNameUsed && !languages.keys().isEmpty()) { + throw MessageException.of("sonar.profile was set to '" + defaultName + "' but didn't match any profile for any language. Please check your configuration."); } } 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 17c4182d137..c8ac7bb558e 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 @@ -59,18 +59,8 @@ import org.sonar.batch.rule.ActiveRulesProvider; import org.sonar.batch.rule.ModuleQProfiles; import org.sonar.batch.rule.QProfileSensor; import org.sonar.batch.rule.RulesProfileProvider; -import org.sonar.batch.scan.filesystem.ComponentIndexer; -import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; -import org.sonar.batch.scan.filesystem.DeprecatedFileFilters; -import org.sonar.batch.scan.filesystem.ExclusionFilters; -import org.sonar.batch.scan.filesystem.FileIndex; -import org.sonar.batch.scan.filesystem.FileSystemLogger; -import org.sonar.batch.scan.filesystem.InputFileBuilderFactory; -import org.sonar.batch.scan.filesystem.LanguageDetectionFactory; -import org.sonar.batch.scan.filesystem.ModuleFileSystemInitializer; -import org.sonar.batch.scan.filesystem.PreviousFileHashLoader; -import org.sonar.batch.scan.filesystem.ProjectFileSystemAdapter; -import org.sonar.batch.scan.filesystem.StatusDetectionFactory; +import org.sonar.batch.scan.filesystem.*; +import org.sonar.batch.scan.filesystem.FileIndexer; import org.sonar.batch.scan.language.DefaultModuleLanguages; import org.sonar.batch.scan.report.JsonReport; import org.sonar.core.component.ScanPerspectives; @@ -112,6 +102,7 @@ public class ModuleScanContainer extends ComponentContainer { moduleDefinition.getContainerExtensions(), // file system + ModuleInputFileCache.class, FileExclusions.class, ExclusionFilters.class, DeprecatedFileFilters.class, @@ -119,7 +110,7 @@ public class ModuleScanContainer extends ComponentContainer { StatusDetectionFactory.class, LanguageDetectionFactory.class, PreviousFileHashLoader.class, - FileIndex.class, + FileIndexer.class, ComponentIndexer.class, DefaultModuleLanguages.class, FileSystemLogger.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java index f8e374e52b8..8621fb4e9a0 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java @@ -25,16 +25,12 @@ import com.google.common.io.Files; import org.sonar.api.BatchComponent; import org.sonar.api.CoreProperties; import org.sonar.api.batch.SonarIndex; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.config.Settings; -import org.sonar.api.resources.File; -import org.sonar.api.resources.Java; -import org.sonar.api.resources.JavaFile; -import org.sonar.api.resources.Languages; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; +import org.sonar.api.resources.*; import org.sonar.api.utils.SonarException; import org.sonar.batch.index.ResourceKeyMigration; import org.sonar.batch.scan.language.DefaultModuleLanguages; @@ -64,18 +60,18 @@ public class ComponentIndexer implements BatchComponent { this.fileCache = fileCache; } - public void execute(DefaultModuleFileSystem fs) { + public void execute(FileSystem fs) { boolean shouldImportSource = settings.getBoolean(CoreProperties.CORE_IMPORT_SOURCES_PROPERTY); - Iterable inputFiles = fs.inputFiles(FileQuery.all()); + Iterable inputFiles = fs.inputFiles(FilePredicates.all()); migration.migrateIfNeeded(module, inputFiles); for (InputFile inputFile : inputFiles) { - String languageKey = inputFile.attribute(InputFile.ATTRIBUTE_LANGUAGE); - boolean unitTest = InputFile.TYPE_TEST.equals(inputFile.attribute(InputFile.ATTRIBUTE_TYPE)); - String pathFromSourceDir = inputFile.attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH); + String languageKey = inputFile.language(); + boolean unitTest = InputFile.Type.TEST == inputFile.type(); + String pathFromSourceDir = ((DefaultInputFile) inputFile).pathRelativeToSourceDir(); if (pathFromSourceDir == null) { - pathFromSourceDir = inputFile.path(); + pathFromSourceDir = inputFile.relativePath(); } - Resource sonarFile = File.create(inputFile.path(), pathFromSourceDir, languages.get(languageKey), unitTest); + Resource sonarFile = File.create(inputFile.relativePath(), pathFromSourceDir, languages.get(languageKey), unitTest); if (Java.KEY.equals(languageKey)) { sonarFile.setDeprecatedKey(JavaFile.fromRelativePath(pathFromSourceDir, false).getDeprecatedKey()); } else { @@ -84,29 +80,27 @@ public class ComponentIndexer implements BatchComponent { if (sonarFile != null) { moduleLanguages.addLanguage(languageKey); sonarIndex.index(sonarFile); - importSources(shouldImportSource, inputFile, sonarFile); + importSources(fs, shouldImportSource, inputFile, sonarFile); } } } @VisibleForTesting - void importSources(boolean shouldImportSource, InputFile inputFile, Resource sonarFile) { + void importSources(FileSystem fs, boolean shouldImportSource, InputFile inputFile, Resource sonarFile) { try { - // TODO this part deserve optimization. + // TODO this part deserves optimization. // No need to read full content in memory when shouldImportSource=false // We should try to remove BOM and count lines in a single pass - String source = Files.toString(inputFile.file(), inputFile.encoding()); + String source = Files.toString(inputFile.file(), fs.encoding()); // SONAR-3860 Remove BOM character from source source = CharMatcher.anyOf("\uFEFF").removeFrom(source); - String[] lines = source.split("(\r)?\n|\r", -1); - inputFile.attributes().put(InputFile.ATTRIBUTE_LINE_COUNT, String.valueOf(lines.length)); fileCache.put(module.getKey(), inputFile); if (shouldImportSource) { sonarIndex.setSource(sonarFile, source); } } catch (Exception e) { throw new SonarException("Unable to read and import the source file : '" + inputFile.absolutePath() + "' with the charset : '" - + inputFile.encoding() + "'.", e); + + fs.encoding() + "'.", e); } } } 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 d27c313175b..0ae6deac815 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 @@ -19,60 +19,58 @@ */ package org.sonar.batch.scan.filesystem; -import com.google.common.base.Preconditions; +import com.google.common.base.Function; +import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; +import org.sonar.api.batch.fs.FilePredicate; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.scan.filesystem.ModuleFileSystem; -import org.sonar.api.scan.filesystem.internal.InputFiles; import org.sonar.api.utils.SonarException; -import org.sonar.batch.bootstrap.AnalysisMode; import javax.annotation.CheckForNull; - +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; /** * This class can't be immutable because of execution of maven plugins that can change the project structure (see MavenPluginHandler and sonar.phase) * * @since 3.5 */ -public class DefaultModuleFileSystem implements ModuleFileSystem { - - private static final Logger LOG = LoggerFactory.getLogger(DefaultModuleFileSystem.class); +public class DefaultModuleFileSystem extends DefaultFileSystem implements ModuleFileSystem { private final String moduleKey; - private final FileIndex index; + private final FileIndexer index; private final Settings settings; - private File baseDir, workingDir, buildDir; + private File buildDir; private List sourceDirs = Lists.newArrayList(); private List testDirs = Lists.newArrayList(); private List binaryDirs = Lists.newArrayList(); private List sourceFiles = Lists.newArrayList(); private List testFiles = Lists.newArrayList(); - private AnalysisMode analysisMode; private ComponentIndexer componentIndexer; private boolean initialized; - public DefaultModuleFileSystem(Project module, Settings settings, FileIndex index, ModuleFileSystemInitializer initializer, AnalysisMode analysisMode, - ComponentIndexer componentIndexer) { + public DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, Project module, Settings settings, FileIndexer index, ModuleFileSystemInitializer initializer, + ComponentIndexer componentIndexer) { + super(moduleInputFileCache); this.componentIndexer = componentIndexer; this.moduleKey = module.getKey(); this.settings = settings; this.index = index; - this.analysisMode = analysisMode; - this.baseDir = initializer.baseDir(); - this.workingDir = initializer.workingDir(); + setBaseDir(initializer.baseDir()); + setWorkDir(initializer.workingDir()); this.buildDir = initializer.buildDir(); this.sourceDirs = initializer.sourceDirs(); this.testDirs = initializer.testDirs(); @@ -89,11 +87,6 @@ public class DefaultModuleFileSystem implements ModuleFileSystem { return moduleKey; } - @Override - public File baseDir() { - return baseDir; - } - @Override @CheckForNull public File buildDir() { @@ -115,11 +108,6 @@ public class DefaultModuleFileSystem implements ModuleFileSystem { return binaryDirs; } - @Override - public File workingDir() { - return workingDir; - } - List sourceFiles() { return sourceFiles; } @@ -128,6 +116,23 @@ public class DefaultModuleFileSystem implements ModuleFileSystem { return testFiles; } + @Override + public Charset encoding() { + final Charset charset; + String encoding = settings.getString(CoreProperties.ENCODING_PROPERTY); + if (StringUtils.isNotEmpty(encoding)) { + charset = Charset.forName(StringUtils.trim(encoding)); + } else { + charset = Charset.defaultCharset(); + } + return charset; + } + + @Override + public boolean isDefaultJvmEncoding() { + return !settings.hasKey(CoreProperties.ENCODING_PROPERTY); + } + /** * Should not be used - only for old plugins * @deprecated since 4.0 @@ -146,60 +151,39 @@ public class DefaultModuleFileSystem implements ModuleFileSystem { throw new UnsupportedOperationException("Modifications of the file system are not permitted"); } + /** + * @return + * @deprecated in 4.2. Replaced by {@link #encoding()} + */ @Override + @Deprecated public Charset sourceCharset() { - final Charset charset; - String encoding = settings.getString(CoreProperties.ENCODING_PROPERTY); - if (StringUtils.isNotEmpty(encoding)) { - charset = Charset.forName(StringUtils.trim(encoding)); - } else { - charset = Charset.defaultCharset(); - } - return charset; - } - - boolean isDefaultSourceCharset() { - return !settings.hasKey(CoreProperties.ENCODING_PROPERTY); + return encoding(); } /** - * @since 4.0 + * @deprecated in 4.2. Replaced by {@link #workDir()} */ + @Deprecated @Override - public Iterable inputFiles(FileQuery query) { - if (!initialized) { - LOG.warn("Accessing the filesystem before the Sensor phase is deprecated and will not be supported in the future. Please update your plugin."); - index.index(this); - } - List result = Lists.newArrayList(); - FileQueryFilter filter = new FileQueryFilter(analysisMode, query); - for (InputFile input : index.inputFiles(moduleKey)) { - if (filter.accept(input)) { - result.add(input); - } - } - return result; - } - - @Override - public InputFile inputFile(File ioFile) { - if (!ioFile.isFile()) { - throw new SonarException(ioFile.getAbsolutePath() + "is not a file"); - } - return index.inputFile(this, ioFile); + public File workingDir() { + return workDir(); } @Override public List files(FileQuery query) { - return InputFiles.toFiles(inputFiles(query)); + Collection predicates = Lists.newArrayList(); + for (Map.Entry> entry : query.attributes().entrySet()) { + predicates.add(fromDeprecatedAttribute(entry.getKey(), entry.getValue())); + } + return ImmutableList.copyOf(files(FilePredicates.and(predicates))); } public void resetDirs(File basedir, File buildDir, List sourceDirs, List testDirs, List binaryDirs) { if (initialized) { throw new SonarException("Module filesystem is already initialized. Modification of the filesystem are only allowed during Initializer phase."); } - Preconditions.checkNotNull(basedir, "Basedir can't be null"); - this.baseDir = basedir; + setBaseDir(basedir); this.buildDir = buildDir; this.sourceDirs = existingDirs(sourceDirs); this.testDirs = existingDirs(testDirs); @@ -210,9 +194,9 @@ public class DefaultModuleFileSystem implements ModuleFileSystem { if (initialized) { throw new SonarException("Module filesystem can only be indexed once"); } - initialized = true; index.index(this); componentIndexer.execute(this); + initialized = true; } private List existingDirs(List dirs) { @@ -225,6 +209,67 @@ public class DefaultModuleFileSystem implements ModuleFileSystem { return builder.build(); } + static FilePredicate fromDeprecatedAttribute(String key, Collection value) { + if ("TYPE".equals(key)) { + return FilePredicates.or(Collections2.transform(value, new Function() { + @Override + public FilePredicate apply(@Nullable String s) { + return FilePredicates.hasType(org.sonar.api.batch.fs.InputFile.Type.valueOf(s)); + } + })); + } + if ("STATUS".equals(key)) { + return FilePredicates.or(Collections2.transform(value, new Function() { + @Override + public FilePredicate apply(@Nullable String s) { + return FilePredicates.hasStatus(org.sonar.api.batch.fs.InputFile.Status.valueOf(s)); + } + })); + } + if ("LANG".equals(key)) { + return FilePredicates.or(Collections2.transform(value, new Function() { + @Override + public FilePredicate apply(@Nullable String s) { + return FilePredicates.hasLanguage(s); + } + })); + } + if ("CMP_KEY".equals(key)) { + return FilePredicates.or(Collections2.transform(value, new Function() { + @Override + public FilePredicate apply(@Nullable String s) { + return new FilePredicateAdapters.KeyPredicate(s); + } + })); + } + if ("CMP_DEPRECATED_KEY".equals(key)) { + return FilePredicates.or(Collections2.transform(value, new Function() { + @Override + public FilePredicate apply(@Nullable String s) { + return new FilePredicateAdapters.DeprecatedKeyPredicate(s); + } + })); + } + if ("SRC_REL_PATH".equals(key)) { + return FilePredicates.or(Collections2.transform(value, new Function() { + @Override + public FilePredicate apply(@Nullable String s) { + return new FilePredicateAdapters.SourceRelativePathPredicate(s); + } + })); + } + if ("SRC_DIR_PATH".equals(key)) { + return FilePredicates.or(Collections2.transform(value, new Function() { + @Override + public FilePredicate apply(@Nullable String s) { + return new FilePredicateAdapters.SourceDirPredicate(s); + } + })); + } + throw new IllegalArgumentException("Unsupported file attribute: " + key); + } + + @Override public boolean equals(Object o) { if (this == o) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileFilters.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileFilters.java index 146d309268e..9ca77131d92 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileFilters.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileFilters.java @@ -19,10 +19,12 @@ */ package org.sonar.batch.scan.filesystem; -import org.sonar.api.scan.filesystem.InputFileFilter; - -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; -import org.sonar.api.scan.filesystem.*; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputFileFilter; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.scan.filesystem.FileSystemFilter; +import org.sonar.api.scan.filesystem.FileType; +import org.sonar.api.scan.filesystem.ModuleFileSystem; import java.io.File; @@ -64,19 +66,18 @@ public class DeprecatedFileFilters implements InputFileFilter { @Override public FileType type() { - String type = inputFile.attribute(InputFile.ATTRIBUTE_TYPE); - return type == null ? null : FileType.valueOf(type.toUpperCase()); + String type = inputFile.type().name(); + return FileType.valueOf(type); } @Override public File relativeDir() { - String path = inputFile.attribute(DefaultInputFile.ATTRIBUTE_SOURCEDIR_PATH); - return path != null ? new File(path) : null; + return new File(((DefaultInputFile)inputFile).sourceDirAbsolutePath()); } @Override public String relativePath() { - return inputFile.attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH); + return ((DefaultInputFile)inputFile).pathRelativeToSourceDir(); } @Override 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 27ec3f53f7b..e9ec3793260 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,9 +19,10 @@ */ package org.sonar.batch.scan.filesystem; -import org.sonar.api.scan.filesystem.InputFileFilter; -import org.sonar.api.scan.filesystem.InputFile; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputFileFilter; +import org.sonar.api.batch.fs.internal.PathPattern; class ExclusionFilter implements InputFileFilter { private final PathPattern pattern; 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 d2fb4acf9c5..50acca5c074 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 @@ -22,8 +22,9 @@ package org.sonar.batch.scan.filesystem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.BatchComponent; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.PathPattern; import org.sonar.api.scan.filesystem.FileExclusions; -import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.scan.filesystem.ModuleFileSystem; import org.sonar.api.scan.filesystem.PathResolver; @@ -64,13 +65,13 @@ public class ExclusionFilters implements BatchComponent { } } - public boolean accept(File ioFile, String relativePathFromBasedir, String type) { + public boolean accept(File ioFile, String relativePathFromBasedir, InputFile.Type type) { PathPattern[] inclusionPatterns = null; PathPattern[] exclusionPatterns = null; - if (InputFile.TYPE_MAIN.equals(type)) { + if (InputFile.Type.MAIN==type) { inclusionPatterns = sourceInclusions; exclusionPatterns = sourceExclusions; - } else if (InputFile.TYPE_TEST.equals(type)) { + } else if (InputFile.Type.TEST==type) { inclusionPatterns = testInclusions; exclusionPatterns = testExclusions; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndex.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java similarity index 74% rename from sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndex.java rename to sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java index 31adc80346e..7ad6bc13143 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndex.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java @@ -19,6 +19,7 @@ */ package org.sonar.batch.scan.filesystem; +import com.google.common.collect.Sets; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.HiddenFileFilter; @@ -26,9 +27,9 @@ import org.apache.commons.io.filefilter.IOFileFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.BatchComponent; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputFileFilter; import org.sonar.api.resources.Project; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.InputFileFilter; import org.sonar.api.scan.filesystem.PathResolver; import org.sonar.api.utils.SonarException; @@ -41,33 +42,9 @@ import java.util.Set; /** * Index input files into {@link InputFileCache}. */ -public class FileIndex implements BatchComponent { +public class FileIndexer implements BatchComponent { private static final String FILE_IS_NOT_DECLARED_IN_MODULE_BASEDIR = "File '%s' is not declared in module basedir %s"; - - private static class Progress { - private final Set removedPaths; - private final Set indexed; - - Progress(Set removedPaths) { - this.removedPaths = removedPaths; - this.indexed = new HashSet(); - } - - void markAsIndexed(String relativePath) { - if (indexed.contains(relativePath)) { - throw new SonarException("File " + relativePath + " can't be indexed twice. Please check that inclusion/exclusion patterns produce " - + "disjoint sets for main and test files"); - } - removedPaths.remove(relativePath); - indexed.add(relativePath); - } - - int count() { - return indexed.size(); - } - } - private static final IOFileFilter DIR_FILTER = FileFilterUtils.and(HiddenFileFilter.VISIBLE, FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter("."))); private static final IOFileFilter FILE_FILTER = HiddenFileFilter.VISIBLE; @@ -78,18 +55,18 @@ public class FileIndex implements BatchComponent { private final ExclusionFilters exclusionFilters; private final InputFileBuilderFactory inputFileBuilderFactory; - public FileIndex(List filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory, - InputFileCache cache, PathResolver pathResolver, Project project) { + public FileIndexer(List filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory, + InputFileCache cache, PathResolver pathResolver, Project module) { this.filters = filters; this.exclusionFilters = exclusionFilters; this.inputFileBuilderFactory = inputFileBuilderFactory; this.fileCache = cache; this.pathResolver = pathResolver; - this.module = project; + this.module = module; } void index(DefaultModuleFileSystem fileSystem) { - Logger logger = LoggerFactory.getLogger(FileIndex.class); + Logger logger = LoggerFactory.getLogger(FileIndexer.class); if (!module.getModules().isEmpty()) { // No indexing for an aggregator module return; @@ -98,28 +75,28 @@ public class FileIndex implements BatchComponent { exclusionFilters.prepare(fileSystem); // TODO log configuration too (replace FileSystemLogger) - Progress progress = new Progress(fileCache.fileRelativePaths(fileSystem.moduleKey())); + Progress progress = new Progress(fileCache.byModule(fileSystem.moduleKey())); InputFileBuilder inputFileBuilder = inputFileBuilderFactory.create(fileSystem); if (!fileSystem.sourceFiles().isEmpty() || !fileSystem.testFiles().isEmpty()) { // Index only provided files - indexFiles(inputFileBuilder, fileSystem, progress, fileSystem.sourceFiles(), InputFile.TYPE_MAIN); - indexFiles(inputFileBuilder, fileSystem, progress, fileSystem.testFiles(), InputFile.TYPE_TEST); + indexFiles(inputFileBuilder, fileSystem, progress, fileSystem.sourceFiles(), InputFile.Type.MAIN); + indexFiles(inputFileBuilder, fileSystem, progress, fileSystem.testFiles(), InputFile.Type.TEST); } else if (fileSystem.baseDir() != null) { // index from basedir indexDirectory(inputFileBuilder, fileSystem, progress, fileSystem.baseDir()); } // Remove files that have been removed since previous indexation - for (String path : progress.removedPaths) { - fileCache.remove(fileSystem.moduleKey(), path); + for (InputFile removed : progress.removed) { + fileCache.remove(fileSystem.moduleKey(), removed); } logger.info(String.format("%d files indexed", progress.count())); } - private void indexFiles(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress progress, List sourceFiles, String type) { + private void indexFiles(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress progress, List sourceFiles, InputFile.Type type) { for (File sourceFile : sourceFiles) { String path = pathResolver.relativePath(fileSystem.baseDir(), sourceFile); if (path == null) { @@ -134,15 +111,6 @@ public class FileIndex implements BatchComponent { } } - Iterable inputFiles(String moduleKey) { - return fileCache.byModule(moduleKey); - } - - InputFile inputFile(DefaultModuleFileSystem fileSystem, File ioFile) { - String path = computeFilePath(fileSystem, ioFile); - return fileCache.byPath(fileSystem.moduleKey(), path); - } - private void indexDirectory(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress status, File dirToIndex) { Collection files = FileUtils.listFiles(dirToIndex, FILE_FILTER, DIR_FILTER); for (File sourceFile : files) { @@ -152,28 +120,24 @@ public class FileIndex implements BatchComponent { FILE_IS_NOT_DECLARED_IN_MODULE_BASEDIR, sourceFile.getAbsoluteFile(), fileSystem.baseDir() )); } else { - if (exclusionFilters.accept(sourceFile, path, InputFile.TYPE_MAIN)) { - indexFile(inputFileBuilder, fileSystem, status, sourceFile, path, InputFile.TYPE_MAIN); + if (exclusionFilters.accept(sourceFile, path, InputFile.Type.MAIN)) { + indexFile(inputFileBuilder, fileSystem, status, sourceFile, path, InputFile.Type.MAIN); } - if (exclusionFilters.accept(sourceFile, path, InputFile.TYPE_TEST)) { - indexFile(inputFileBuilder, fileSystem, status, sourceFile, path, InputFile.TYPE_TEST); + if (exclusionFilters.accept(sourceFile, path, InputFile.Type.TEST)) { + indexFile(inputFileBuilder, fileSystem, status, sourceFile, path, InputFile.Type.TEST); } } } } - private void indexFile(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fs, Progress status, File file, String path, String type) { + private void indexFile(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fs, Progress status, File file, String path, InputFile.Type type) { InputFile inputFile = inputFileBuilder.create(file, type); if (inputFile != null && accept(inputFile)) { - fileCache.put(fs.moduleKey(), inputFile); - status.markAsIndexed(path); + fs.add(inputFile); + status.markAsIndexed(inputFile); } } - private String computeFilePath(DefaultModuleFileSystem fileSystem, File file) { - return pathResolver.relativePath(fileSystem.baseDir(), file); - } - private boolean accept(InputFile inputFile) { // InputFileFilter extensions for (InputFileFilter filter : filters) { @@ -183,4 +147,28 @@ public class FileIndex implements BatchComponent { } return true; } + + private static class Progress { + private final Set removed; + private final Set indexed; + + Progress(Iterable removed) { + this.removed = Sets.newHashSet(removed); + this.indexed = new HashSet(); + } + + void markAsIndexed(InputFile inputFile) { + if (indexed.contains(inputFile)) { + throw new SonarException("File " + inputFile + " can't be indexed twice. Please check that inclusion/exclusion patterns produce " + + "disjoint sets for main and test files"); + } + removed.remove(inputFile); + indexed.add(inputFile); + } + + int count() { + return indexed.size(); + } + } + } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileMetadata.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileMetadata.java index 298eeef3654..166db70aecc 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileMetadata.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileMetadata.java @@ -49,7 +49,7 @@ class FileMetadata { */ Metadata read(File file, Charset encoding) { Reader reader = null; - long lines = 0L; + int lines = 0; char c = (char)-1; try { MessageDigest md5Digest = DigestUtils.getMd5Digest(); @@ -102,10 +102,10 @@ class FileMetadata { } static class Metadata { - long lines; + int lines; String hash; - private Metadata(long lines, String hash) { + private Metadata(int lines, String hash) { this.lines = lines; this.hash = hash; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FilePredicateAdapters.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FilePredicateAdapters.java new file mode 100644 index 00000000000..beb959fa65f --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FilePredicateAdapters.java @@ -0,0 +1,79 @@ +/* + * 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.fs.FilePredicate; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; + +class FilePredicateAdapters { + static class KeyPredicate implements FilePredicate { + private final String key; + + KeyPredicate(String key) { + this.key = key; + } + + @Override + public boolean apply(InputFile f) { + return key.equals(((DefaultInputFile) f).key()); + } + } + + static class DeprecatedKeyPredicate implements FilePredicate { + private final String key; + + DeprecatedKeyPredicate(String key) { + this.key = key; + } + + @Override + public boolean apply(InputFile f) { + return key.equals(((DefaultInputFile) f).deprecatedKey()); + } + } + + static class SourceRelativePathPredicate implements FilePredicate { + private final String path; + + SourceRelativePathPredicate(String s) { + this.path = FilenameUtils.normalize(s, true); + } + + @Override + public boolean apply(InputFile f) { + return path.equals(((DefaultInputFile) f).pathRelativeToSourceDir()); + } + } + + static class SourceDirPredicate implements FilePredicate { + private final String path; + + SourceDirPredicate(String s) { + this.path = FilenameUtils.normalize(s, true); + } + + @Override + public boolean apply(InputFile f) { + return path.equals(((DefaultInputFile) f).sourceDirAbsolutePath()); + } + } +} 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 deleted file mode 100644 index e7e5a07396c..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java +++ /dev/null @@ -1,71 +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.sonar.api.scan.filesystem.InputFileFilter; - -import org.sonar.api.scan.filesystem.InputFile; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.batch.bootstrap.AnalysisMode; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -class FileQueryFilter { - - private final List filters; - - FileQueryFilter(AnalysisMode analysisMode, 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> entry : query.attributes().entrySet()) { - filters.add(new AttributeFilter(entry.getKey(), entry.getValue())); - } - - if (analysisMode.isIncremental()) { - Collection status = query.attributes().get(InputFile.ATTRIBUTE_STATUS); - if (status == null || status.isEmpty()) { - filters.add(new AttributeFilter(InputFile.ATTRIBUTE_STATUS, Lists.newArrayList(InputFile.STATUS_ADDED, InputFile.STATUS_CHANGED))); - } - } - } - - @VisibleForTesting - List filters() { - return filters; - } - - 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 2d402d358b0..f2967d5a1fb 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 @@ -53,7 +53,7 @@ public class FileSystemLogger implements BatchComponent { } private void logEncoding(Logger logger, Charset charset) { - if (!fs.isDefaultSourceCharset()) { + if (!fs.isDefaultJvmEncoding()) { logger.info("Source encoding: " + charset.displayName() + ", default locale: " + Locale.getDefault()); } else { logger.warn("Source encoding is platform dependent (" + charset.displayName() + "), default locale: " + Locale.getDefault()); 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 38b56313cc4..6464f151968 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,9 +19,10 @@ */ package org.sonar.batch.scan.filesystem; -import org.sonar.api.scan.filesystem.InputFileFilter; -import org.sonar.api.scan.filesystem.InputFile; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputFileFilter; +import org.sonar.api.batch.fs.internal.PathPattern; class InclusionFilter implements InputFileFilter { private final PathPattern pattern; diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java index 9f0af6a2d6d..9f8f79f7dd7 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java @@ -19,17 +19,17 @@ */ package org.sonar.batch.scan.filesystem; -import com.google.common.collect.Maps; import org.apache.commons.io.FilenameUtils; import org.slf4j.LoggerFactory; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.resources.Java; import org.sonar.api.resources.JavaFile; -import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.scan.filesystem.PathResolver; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; +import org.sonar.batch.bootstrap.AnalysisMode; import javax.annotation.CheckForNull; - import java.io.File; import java.util.List; @@ -40,14 +40,16 @@ class InputFileBuilder { private final LanguageDetection langDetection; private final StatusDetection statusDetection; private final DefaultModuleFileSystem fs; + private final AnalysisMode analysisMode; InputFileBuilder(String moduleKey, PathResolver pathResolver, LanguageDetection langDetection, - StatusDetection statusDetection, DefaultModuleFileSystem fs) { + StatusDetection statusDetection, DefaultModuleFileSystem fs, AnalysisMode analysisMode) { this.moduleKey = moduleKey; this.pathResolver = pathResolver; this.langDetection = langDetection; this.statusDetection = statusDetection; this.fs = fs; + this.analysisMode = analysisMode; } String moduleKey() { @@ -66,37 +68,42 @@ class InputFileBuilder { return statusDetection; } - DefaultModuleFileSystem fs() { + FileSystem fs() { return fs; } @CheckForNull - DefaultInputFile create(File file, String type) { + DefaultInputFile create(File file, InputFile.Type type) { String relativePath = pathResolver.relativePath(fs.baseDir(), file); if (relativePath == null) { LoggerFactory.getLogger(getClass()).warn( "File '%s' is ignored. It is not in module basedir '%s'.", file.getAbsolutePath(), fs.baseDir()); return null; } - DefaultInputFile inputFile = DefaultInputFile.create(file, fs.sourceCharset(), relativePath, Maps.newHashMap()); + DefaultInputFile inputFile = new DefaultInputFile(relativePath); inputFile.setType(type); - inputFile.setKey(moduleKey + ":" + inputFile.path()); + inputFile.setKey(new StringBuilder().append(moduleKey).append(":").append(inputFile.relativePath()).toString()); + inputFile.setBasedir(fs.baseDir()); + inputFile.setAbsolutePath(file.getAbsolutePath()); + inputFile.setFile(file); + FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(inputFile.file(), fs.encoding()); + inputFile.setLines(metadata.lines); + inputFile.setHash(metadata.hash); + inputFile.setStatus(statusDetection.status(inputFile.relativePath(), metadata.hash)); + if (analysisMode.isIncremental() && inputFile.status() == InputFile.Status.SAME) { + return null; + } String lang = langDetection.language(inputFile); if (lang == null) { - // TODO use a default plain-text language ? return null; } inputFile.setLanguage(lang); - FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(inputFile.file(), fs.sourceCharset()); - inputFile.setLines(metadata.lines); - inputFile.setHash(metadata.hash); - inputFile.setStatus(statusDetection.status(inputFile.path(), metadata.hash)); fillDeprecatedData(inputFile); return inputFile; } private void fillDeprecatedData(DefaultInputFile inputFile) { - List sourceDirs = InputFile.TYPE_MAIN.equals(inputFile.type()) ? fs.sourceDirs() : fs.testDirs(); + List sourceDirs = InputFile.Type.MAIN == inputFile.type() ? fs.sourceDirs() : fs.testDirs(); for (File sourceDir : sourceDirs) { String sourceRelativePath = pathResolver.relativePath(sourceDir, inputFile.file()); if (sourceRelativePath != null) { @@ -104,9 +111,10 @@ class InputFileBuilder { inputFile.setSourceDirAbsolutePath(FilenameUtils.normalize(sourceDir.getAbsolutePath(), true)); if (Java.KEY.equals(inputFile.language())) { - inputFile.setDeprecatedKey(moduleKey + ":" + JavaFile.fromRelativePath(sourceRelativePath, false).getDeprecatedKey()); + inputFile.setDeprecatedKey(new StringBuilder() + .append(moduleKey).append(":").append(JavaFile.fromRelativePath(sourceRelativePath, false).getDeprecatedKey()).toString()); } else { - inputFile.setDeprecatedKey(moduleKey + ":" + sourceRelativePath); + inputFile.setDeprecatedKey(new StringBuilder().append(moduleKey).append(":").append(sourceRelativePath).toString()); } } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java index ce24330fd42..ae0143353e4 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java @@ -22,6 +22,7 @@ package org.sonar.batch.scan.filesystem; import org.sonar.api.BatchComponent; import org.sonar.api.resources.Project; import org.sonar.api.scan.filesystem.PathResolver; +import org.sonar.batch.bootstrap.AnalysisMode; public class InputFileBuilderFactory implements BatchComponent { @@ -29,16 +30,18 @@ public class InputFileBuilderFactory implements BatchComponent { private final PathResolver pathResolver; private final LanguageDetectionFactory langDetectionFactory; private final StatusDetectionFactory statusDetectionFactory; + private final AnalysisMode analysisMode; public InputFileBuilderFactory(Project moduleDef, PathResolver pathResolver, LanguageDetectionFactory langDetectionFactory, - StatusDetectionFactory statusDetectionFactory) { + StatusDetectionFactory statusDetectionFactory, AnalysisMode analysisMode) { this.moduleKey = moduleDef.getEffectiveKey(); this.pathResolver = pathResolver; this.langDetectionFactory = langDetectionFactory; this.statusDetectionFactory = statusDetectionFactory; + this.analysisMode = analysisMode; } InputFileBuilder create(DefaultModuleFileSystem fs) { - return new InputFileBuilder(moduleKey, pathResolver, langDetectionFactory.create(), statusDetectionFactory.create(), fs); + return new InputFileBuilder(moduleKey, pathResolver, langDetectionFactory.create(), statusDetectionFactory.create(), fs, analysisMode); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java index 7ab06aec59b..0a4dde8fd60 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java @@ -20,34 +20,38 @@ package org.sonar.batch.scan.filesystem; import org.sonar.api.BatchComponent; -import org.sonar.api.scan.filesystem.InputFile; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.FileIndex; +import org.sonar.api.batch.fs.internal.RelativePathIndex; import org.sonar.batch.index.Cache; import org.sonar.batch.index.Caches; import javax.annotation.CheckForNull; -import java.util.Set; - /** * 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 cache; + // [path type | module key | path] -> InputFile + // For example: + // [rel | struts-core | src/main/java/Action.java] -> InputFile + // [rel | struts-core | src/main/java/Filter.java] -> InputFile + // [abs | struts-core | /absolute/path/to/src/main/java/Action.java] -> InputFile + // [abs | struts-core | /absolute/path/to/src/main/java/Filter.java] -> InputFile + private final Cache cache; public InputFileCache(Caches caches) { cache = caches.createCache("inputFiles"); } - public Iterable byModule(String moduleKey) { - return cache.values(moduleKey); + public Iterable all() { + return cache.values(); } - @CheckForNull - public InputFile byPath(String moduleKey, String path) { - return cache.get(moduleKey, path); + public Iterable byModule(String moduleKey) { + return cache.values(moduleKey); } public InputFileCache removeModule(String moduleKey) { @@ -55,25 +59,33 @@ public class InputFileCache implements BatchComponent { return this; } - public InputFileCache remove(String moduleKey, String relativePath) { - cache.remove(moduleKey, relativePath); + public InputFileCache remove(String moduleKey, InputFile inputFile) { + cache.remove(moduleKey, inputFile.relativePath()); return this; } - public Iterable all() { - return cache.allValues(); + public InputFileCache put(String moduleKey, InputFile inputFile) { + cache.put(moduleKey, inputFile.relativePath(), inputFile); + return this; } - public Set fileRelativePaths(String moduleKey) { - return cache.keySet(moduleKey); - } - public boolean containsFile(String moduleKey, String relativePath) { - return cache.containsKey(moduleKey, relativePath); + public void index(String moduleKey, String indexId, Object indexValue, InputFile inputFile) { + // already indexed by relative path is already used + if (!indexId.equals(RelativePathIndex.ID)) { + // See limitation of org.sonar.batch.index.Cache -> fail + // to traverse a sub-tree, for example in order to + // have the following structure in InputFileCache : + // [index id|module key|index value] + throw new UnsupportedOperationException("Only relative path index is supported yet"); + } } - public InputFileCache put(String moduleKey, InputFile file) { - cache.put(moduleKey, file.path(), file); - return this; + @CheckForNull + public InputFile get(String moduleKey, String indexId, Object indexValue) { + if (!indexId.equals(RelativePathIndex.ID)) { + throw new UnsupportedOperationException("Only relative path index is supported yet"); + } + return cache.get(moduleKey, indexValue); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetection.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetection.java index f4f876905a7..c34e0d42184 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetection.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetection.java @@ -26,10 +26,11 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.PathPattern; import org.sonar.api.config.Settings; import org.sonar.api.resources.Language; import org.sonar.api.resources.Languages; -import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.utils.MessageException; import javax.annotation.CheckForNull; @@ -100,7 +101,7 @@ class LanguageDetection { break; } else { // Language was already forced by another pattern - throw MessageException.of("Language of file '" + inputFile.path() + "' can not be decided as the file matches patterns of both " + getDetails(detectedLanguage) + throw MessageException.of("Language of file '" + inputFile.relativePath() + "' can not be decided as the file matches patterns of both " + getDetails(detectedLanguage) + " and " + getDetails(languageKey)); } } @@ -108,7 +109,7 @@ class LanguageDetection { } } if (detectedLanguage != null) { - LOG.debug("Language of file '" + inputFile.path() + "' was detected to be '" + detectedLanguage + "'"); + LOG.debug("Language of file '" + inputFile.relativePath() + "' was detected to be '" + detectedLanguage + "'"); return detectedLanguage; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java new file mode 100644 index 00000000000..90d885eedc5 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java @@ -0,0 +1,57 @@ +/* + * 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.BatchComponent; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.UniqueIndexPredicate; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.resources.Project; + +public class ModuleInputFileCache extends DefaultFileSystem.Cache implements BatchComponent { + + private final String moduleKey; + private final InputFileCache projectCache; + + public ModuleInputFileCache(Project module, InputFileCache projectCache) { + this.moduleKey = module.getKey(); + this.projectCache = projectCache; + } + + @Override + protected Iterable inputFiles() { + return projectCache.byModule(moduleKey); + } + + @Override + protected InputFile inputFile(UniqueIndexPredicate predicate) { + return projectCache.get(moduleKey, predicate.indexId(), predicate.value()); + } + + @Override + protected void doAdd(InputFile inputFile) { + projectCache.put(moduleKey, inputFile); + } + + @Override + protected void doIndex(String indexId, Object value, InputFile inputFile) { + projectCache.index(moduleKey, indexId, value, inputFile); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapter.java index 30f6b5c6fb6..373a582dec2 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapter.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapter.java @@ -21,22 +21,17 @@ package org.sonar.batch.scan.filesystem; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import java.util.Arrays; 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.scan.filesystem.FileQuery; +import org.sonar.api.batch.fs.FilePredicate; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.resources.*; 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; @@ -140,11 +135,9 @@ public class ProjectFileSystemAdapter implements ProjectFileSystem { } public List getSourceFiles(Language... langs) { - List result = Lists.newArrayList(); - for (Language lang : langs) { - result.addAll(target.files(FileQuery.onMain().onLanguage(lang.getKey()))); - } - return result; + return Lists.newArrayList(target.files(FilePredicates.and( + FilePredicates.hasType(org.sonar.api.batch.fs.InputFile.Type.MAIN), + newHasLanguagesPredicate(langs)))); } public List getJavaSourceFiles() { @@ -156,15 +149,15 @@ public class ProjectFileSystemAdapter implements ProjectFileSystem { } public List getTestFiles(Language... langs) { - List result = Lists.newArrayList(); - for (Language lang : langs) { - result.addAll(target.files(FileQuery.onTest().onLanguage(lang.getKey()))); - } - return result; + return Lists.newArrayList(target.files(FilePredicates.and( + FilePredicates.hasType(org.sonar.api.batch.fs.InputFile.Type.TEST), + newHasLanguagesPredicate(langs)))); } public boolean hasTestFiles(Language lang) { - return !getTestFiles(lang).isEmpty(); + return target.hasFiles(FilePredicates.and( + FilePredicates.hasType(org.sonar.api.batch.fs.InputFile.Type.TEST), + FilePredicates.hasLanguage(lang.getKey()))); } public File writeToWorkingDirectory(String content, String fileName) throws IOException { @@ -190,32 +183,25 @@ public class ProjectFileSystemAdapter implements ProjectFileSystem { } public List mainFiles(String... langs) { - List result = Lists.newArrayList(); - Iterable files = target.inputFiles(FileQuery.onMain().onLanguage(langs)); - for (org.sonar.api.scan.filesystem.InputFile file : files) { - String sourceDir = file.attribute(org.sonar.api.scan.filesystem.internal.DefaultInputFile.ATTRIBUTE_SOURCEDIR_PATH); - String sourceRelativePath = file.attribute(org.sonar.api.scan.filesystem.internal.DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH); - if (sourceDir != null && sourceRelativePath != null) { - result.add(InputFileUtils.create(new File(sourceDir), sourceRelativePath)); - } else { - result.add(InputFileUtils.create(target.baseDir(), file.path())); - } - } - return result; + return Lists.newArrayList((Iterable) target.inputFiles(FilePredicates.and( + FilePredicates.hasType(org.sonar.api.batch.fs.InputFile.Type.MAIN), + FilePredicates.hasLanguages(Arrays.asList(langs)) + ))); + } public List testFiles(String... langs) { - List result = Lists.newArrayList(); - Iterable 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.internal.DefaultInputFile.ATTRIBUTE_SOURCEDIR_PATH); - String sourceRelativePath = file.attribute(org.sonar.api.scan.filesystem.internal.DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH); - if (sourceDir != null && sourceRelativePath != null) { - result.add(InputFileUtils.create(new File(sourceDir), sourceRelativePath)); - } else { - result.add(InputFileUtils.create(target.baseDir(), file.path())); - } + return Lists.newArrayList((Iterable) target.inputFiles(FilePredicates.and( + FilePredicates.hasType(org.sonar.api.batch.fs.InputFile.Type.TEST), + FilePredicates.hasLanguages(Arrays.asList(langs)) + ))); + } + + private static FilePredicate newHasLanguagesPredicate(Language... languages) { + List list = Lists.newArrayList(); + for (Language language : languages) { + list.add(FilePredicates.hasLanguage(language.getKey())); } - return result; + return FilePredicates.or(list); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java index adadcdf391b..03402929c1f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java @@ -20,7 +20,7 @@ package org.sonar.batch.scan.filesystem; import org.apache.commons.lang.StringUtils; -import org.sonar.api.scan.filesystem.InputFile; +import org.sonar.api.batch.fs.InputFile; import java.util.Map; @@ -32,15 +32,15 @@ class StatusDetection { this.previousHashByRelativePath = previousHashByRelativePath; } - String status(String relativePath, String hash) { + InputFile.Status status(String relativePath, String hash) { String previousHash = previousHashByRelativePath.get(relativePath); if (StringUtils.equals(hash, previousHash)) { - return InputFile.STATUS_SAME; + return InputFile.Status.SAME; } if (StringUtils.isEmpty(previousHash)) { - return InputFile.STATUS_ADDED; + return InputFile.Status.ADDED; } - return InputFile.STATUS_CHANGED; + return InputFile.Status.CHANGED; } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/language/DefaultModuleLanguages.java b/sonar-batch/src/main/java/org/sonar/batch/scan/language/DefaultModuleLanguages.java index fecede739bb..3922924a7fc 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/language/DefaultModuleLanguages.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/language/DefaultModuleLanguages.java @@ -19,6 +19,7 @@ */ package org.sonar.batch.scan.language; +import com.google.common.collect.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; @@ -27,26 +28,22 @@ import org.sonar.api.config.Settings; import org.sonar.api.resources.Language; import org.sonar.api.resources.Languages; import org.sonar.api.utils.MessageException; -import org.sonar.api.utils.SonarException; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.List; /** * Give access to all languages detected on the current module + * * @since 4.2 */ public class DefaultModuleLanguages implements ModuleLanguages { private static final Logger LOG = LoggerFactory.getLogger(DefaultModuleLanguages.class); - private Map moduleLanguages = new HashMap(); - - private Languages languages; + private final List moduleLanguages = Lists.newArrayList(); public DefaultModuleLanguages(Settings settings, Languages languages) { - this.languages = languages; if (settings.hasKey(CoreProperties.PROJECT_LANGUAGE_PROPERTY)) { String languageKey = settings.getString(CoreProperties.PROJECT_LANGUAGE_PROPERTY); LOG.info("Language is forced to {}", languageKey); @@ -59,18 +56,11 @@ public class DefaultModuleLanguages implements ModuleLanguages { } public void addLanguage(String languageKey) { - Language language = languages.get(languageKey); - if (language == null) { - throw new SonarException("Language with key '" + languageKey + "' not found"); - } - moduleLanguages.put(languageKey, language); + moduleLanguages.add(languageKey); } + @Override public Collection keys() { - return moduleLanguages.keySet(); - } - - public Collection languages() { - return moduleLanguages.values(); + return moduleLanguages; } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/report/ComponentSelector.java b/sonar-batch/src/main/java/org/sonar/batch/scan/report/ComponentSelector.java deleted file mode 100644 index 277b9c41f69..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/report/ComponentSelector.java +++ /dev/null @@ -1,51 +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.report; - -import org.sonar.api.issue.Issue; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.batch.scan.filesystem.InputFileCache; - -import java.util.Set; - -abstract class ComponentSelector { - - private final InputFileCache cache; - - ComponentSelector(InputFileCache cache) { - this.cache = cache; - } - - public InputFileCache getCache() { - return cache; - } - - abstract void init(); - - abstract boolean register(Issue issue); - - abstract Set componentKeys(); - - InputFile component(String componentKey) { - String moduleKey = org.apache.commons.lang.StringUtils.substringBeforeLast(componentKey, ":"); - String path = org.apache.commons.lang.StringUtils.substringAfterLast(componentKey, ":"); - return cache.byPath(moduleKey, path); - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java b/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java index 7c835ecce71..2c55eb11621 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java @@ -25,6 +25,9 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.BatchComponent; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.config.Settings; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.platform.Server; @@ -32,9 +35,6 @@ import org.sonar.api.resources.Project; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.ModuleFileSystem; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; import org.sonar.api.user.User; import org.sonar.api.user.UserFinder; import org.sonar.api.utils.SonarException; @@ -45,11 +45,7 @@ import org.sonar.batch.events.EventBus; import org.sonar.batch.issue.IssueCache; import org.sonar.batch.scan.filesystem.InputFileCache; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; +import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -64,7 +60,7 @@ public class JsonReport implements BatchComponent { private static final Logger LOG = LoggerFactory.getLogger(JsonReport.class); private final Settings settings; - private final ModuleFileSystem fileSystem; + private final FileSystem fileSystem; private final Server server; private final RuleFinder ruleFinder; private final IssueCache issueCache; @@ -74,8 +70,8 @@ public class JsonReport implements BatchComponent { private final InputFileCache fileCache; private final Project rootModule; - public JsonReport(Settings settings, ModuleFileSystem fileSystem, Server server, RuleFinder ruleFinder, IssueCache issueCache, - EventBus eventBus, AnalysisMode analysisMode, UserFinder userFinder, Project rootModule, InputFileCache fileCache) { + public JsonReport(Settings settings, FileSystem fileSystem, Server server, RuleFinder ruleFinder, IssueCache issueCache, + EventBus eventBus, AnalysisMode analysisMode, UserFinder userFinder, Project rootModule, InputFileCache fileCache) { this.settings = settings; this.fileSystem = fileSystem; this.server = server; @@ -97,7 +93,7 @@ public class JsonReport implements BatchComponent { } private void exportResults() { - File exportFile = new File(fileSystem.workingDir(), settings.getString("sonar.report.export.path")); + File exportFile = new File(fileSystem.workDir(), settings.getString("sonar.report.export.path")); LOG.info("Export results to " + exportFile.getAbsolutePath()); Writer output = null; @@ -173,12 +169,13 @@ public class JsonReport implements BatchComponent { writeJsonModuleComponents(json, rootModule); // TODO we need to dump directories for (InputFile inputFile : fileCache.all()) { + String key = ((DefaultInputFile) inputFile).key(); json .beginObject() - .prop("key", inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY)) - .prop("path", inputFile.path()) - .prop("moduleKey", StringUtils.substringBeforeLast(inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY), ":")) - .prop("status", inputFile.attribute(InputFile.ATTRIBUTE_STATUS)) + .prop("key", key) + .prop("path", inputFile.relativePath()) + .prop("moduleKey", StringUtils.substringBeforeLast(key, ":")) + .prop("status", inputFile.status().name()) .endObject(); } json.endArray(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java index a888e5eb6bb..83ed6836110 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java @@ -20,10 +20,9 @@ package org.sonar.batch.index; import com.google.common.collect.Iterables; -import com.persistit.exception.PersistitException; import org.junit.After; import org.junit.Before; -import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -31,8 +30,8 @@ import static org.fest.assertions.Assertions.assertThat; public class CacheTest { - @ClassRule - public static TemporaryFolder temp = new TemporaryFolder(); + @Rule + public TemporaryFolder temp = new TemporaryFolder(); Caches caches; @@ -48,20 +47,42 @@ public class CacheTest { } @Test - public void test_put_get_remove() throws Exception { - Cache cache = caches.createCache("issues"); - assertThat(cache.get("foo")).isNull(); - cache.put("foo", "bar"); - assertThat(cache.get("foo")).isEqualTo("bar"); - assertThat(cache.keySet()).containsOnly("foo"); - cache.remove("foo"); - assertThat(cache.get("foo")).isNull(); - assertThat(cache.keySet()).isEmpty(); + public void one_part_key() throws Exception { + Cache cache = caches.createCache("capitals"); + + assertThat(cache.get("france")).isNull(); + + cache.put("france", "paris"); + cache.put("italy", "rome"); + assertThat(cache.get("france")).isEqualTo("paris"); + assertThat(cache.keySet()).containsOnly("france", "italy"); + assertThat(cache.keySet("france")).isEmpty(); + assertThat(cache.values()).containsOnly("paris", "rome"); + assertThat(cache.containsKey("france")).isTrue(); + + Cache.Entry[] entries = Iterables.toArray(cache.entries(), Cache.Entry.class); + assertThat(entries).hasSize(2); + assertThat(entries[0].key()[0]).isEqualTo("france"); + assertThat(entries[0].value()).isEqualTo("paris"); + assertThat(entries[1].key()[0]).isEqualTo("italy"); + assertThat(entries[1].value()).isEqualTo("rome"); + + cache.remove("france"); + assertThat(cache.get("france")).isNull(); + assertThat(cache.get("italy")).isEqualTo("rome"); + assertThat(cache.keySet()).containsOnly("italy"); + assertThat(cache.keySet("france")).isEmpty(); + assertThat(cache.containsKey("france")).isFalse(); + assertThat(cache.containsKey("italy")).isTrue(); + assertThat(cache.values()).containsOnly("rome"); + + cache.clear(); + assertThat(cache.values()).isEmpty(); } @Test public void test_key_being_prefix_of_another_key() throws Exception { - Cache cache = caches.createCache("components"); + Cache cache = caches.createCache("components"); cache.put("struts-el:org.apache.strutsel.taglib.html.ELButtonTag", "the Tag"); cache.put("struts-el:org.apache.strutsel.taglib.html.ELButtonTagBeanInfo", "the BeanInfo"); @@ -71,147 +92,142 @@ public class CacheTest { } @Test - public void test_put_get_remove_on_groups() throws Exception { - Cache cache = caches.createCache("measures"); - String group = "org/apache/struts/Action.java"; - assertThat(cache.get(group, "ncloc")).isNull(); - cache.put(group, "ncloc", 123f); - assertThat(cache.get(group, "ncloc")).isEqualTo(123f); - assertThat(cache.keySet(group)).containsOnly("ncloc"); - assertThat(cache.containsKey(group, "ncloc")).isTrue(); - assertThat(cache.get("ncloc")).isNull(); - assertThat(cache.get(group)).isNull(); - cache.remove(group, "ncloc"); - assertThat(cache.get(group, "ncloc")).isNull(); - assertThat(cache.keySet(group)).isEmpty(); - assertThat(cache.containsKey(group, "ncloc")).isFalse(); - } - - @Test - public void test_clear_group() throws Exception { - Cache cache = caches.createCache("measures"); - String group = "org/apache/struts/Action.java"; - cache.put(group, "ncloc", 123f); - cache.put(group, "lines", 200f); - cache.put("otherGroup", "lines", 400f); - assertThat(cache.get(group, "lines")).isNotNull(); - assertThat(cache.get("otherGroup", "lines")).isNotNull(); - - cache.clear(group); - assertThat(cache.get(group, "lines")).isNull(); - assertThat(cache.get("otherGroup", "lines")).isNotNull(); - } - - @Test - public void test_operations_on_empty_cache() throws Exception { - Cache cache = caches.createCache("issues"); - assertThat(cache.get("foo")).isNull(); - assertThat(cache.get("group", "foo")).isNull(); + public void two_parts_key() throws Exception { + Cache cache = caches.createCache("capitals"); + + assertThat(cache.get("europe", "france")).isNull(); + + cache.put("europe", "france", "paris"); + cache.put("europe", "italy", "rome"); + assertThat(cache.get("europe")).isNull(); + assertThat(cache.get("europe", "france")).isEqualTo("paris"); + assertThat(cache.get("europe", "italy")).isEqualTo("rome"); + assertThat(cache.get("europe")).isNull(); + assertThat(cache.keySet("europe")).containsOnly("france", "italy"); + assertThat(cache.keySet()).containsOnly("europe"); + assertThat(cache.containsKey("europe")).isFalse(); + assertThat(cache.containsKey("europe", "france")).isTrue(); + assertThat(cache.containsKey("europe", "spain")).isFalse(); + assertThat(cache.values()).containsOnly("paris", "rome"); + assertThat(cache.values("america")).isEmpty(); + assertThat(cache.values("europe")).containsOnly("paris", "rome"); + assertThat(cache.values("oceania")).isEmpty(); + + Cache.Entry[] allEntries = Iterables.toArray(cache.entries(), Cache.Entry.class); + assertThat(allEntries).hasSize(2); + assertThat(allEntries[0].key()).isEqualTo(new String[]{"europe", "france"}); + assertThat(allEntries[0].value()).isEqualTo("paris"); + assertThat(allEntries[1].key()).isEqualTo(new String[]{"europe", "italy"}); + assertThat(allEntries[1].value()).isEqualTo("rome"); + + Cache.SubEntry[] subEntries = Iterables.toArray(cache.subEntries("europe"), Cache.SubEntry.class); + assertThat(subEntries).hasSize(2); + assertThat(subEntries[0].keyAsString()).isEqualTo("france"); + assertThat(subEntries[0].value()).isEqualTo("paris"); + assertThat(subEntries[1].keyAsString()).isEqualTo("italy"); + assertThat(subEntries[1].value()).isEqualTo("rome"); + + cache.remove("europe", "france"); + assertThat(cache.values()).containsOnly("rome"); + assertThat(cache.get("europe", "france")).isNull(); + assertThat(cache.get("europe", "italy")).isEqualTo("rome"); + assertThat(cache.containsKey("europe", "france")).isFalse(); + assertThat(cache.keySet("europe")).containsOnly("italy"); + + cache.clear("america"); + assertThat(cache.keySet()).containsOnly("europe"); + cache.clear("europe"); assertThat(cache.keySet()).isEmpty(); - assertThat(cache.keySet("group")).isEmpty(); - assertThat(cache.values()).isEmpty(); - assertThat(cache.values("group")).isEmpty(); - - // do not fail - cache.remove("foo"); - cache.remove("group", "foo"); - cache.clear(); - cache.clear("group"); - cache.clearAll(); } @Test - public void test_get_missing_key() { - Cache cache = caches.createCache("issues"); - assertThat(cache.get("foo")).isNull(); - } - - @Test - public void test_keyset_of_group() { - Cache cache = caches.createCache("measures"); - cache.put("org/apache/struts/Action.java", "ncloc", 123f); - cache.put("org/apache/struts/Action.java", "lines", 200f); - cache.put("org/apache/struts/Filter.java", "coverage", 500f); - assertThat(cache.keySet("org/apache/struts/Action.java")).containsOnly("ncloc", "lines"); - assertThat(cache.keySet("org/apache/struts/Filter.java")).containsOnly("coverage"); - } - - @Test - public void test_values_of_group() { - Cache cache = caches.createCache("measures"); - cache.put("org/apache/struts/Action.java", "ncloc", 123f); - cache.put("org/apache/struts/Action.java", "lines", 200f); - cache.put("org/apache/struts/Filter.java", "lines", 500f); - assertThat(cache.values("org/apache/struts/Action.java")).containsOnly(123f, 200f); - assertThat(cache.values("org/apache/struts/Filter.java")).containsOnly(500f); - assertThat(cache.values("other")).isEmpty(); - } - - @Test - public void test_values() { - Cache cache = caches.createCache("measures"); - cache.put("ncloc", 123f); - cache.put("lines", 200f); - assertThat(cache.values()).containsOnly(123f, 200f); - } - - @Test - public void test_all_values() { - Cache cache = caches.createCache("measures"); - cache.put("org/apache/struts/Action.java", "ncloc", 123f); - cache.put("org/apache/struts/Action.java", "lines", 200f); - cache.put("org/apache/struts/Filter.java", "ncloc", 400f); - cache.put("org/apache/struts/Filter.java", "lines", 500f); - - assertThat(cache.allValues()).containsOnly(123f, 200f, 400f, 500f); + public void three_parts_key() throws Exception { + Cache cache = caches.createCache("places"); + assertThat(cache.get("europe", "france", "paris")).isNull(); + + cache.put("europe", "france", "paris", "eiffel tower"); + cache.put("europe", "france", "annecy", "lake"); + cache.put("europe", "italy", "rome", "colosseum"); + assertThat(cache.get("europe")).isNull(); + assertThat(cache.get("europe", "france")).isNull(); + assertThat(cache.get("europe", "france", "paris")).isEqualTo("eiffel tower"); + assertThat(cache.get("europe", "france", "annecy")).isEqualTo("lake"); + assertThat(cache.get("europe", "italy", "rome")).isEqualTo("colosseum"); + assertThat(cache.keySet()).containsOnly("europe"); + assertThat(cache.keySet("europe")).containsOnly("france", "italy"); + assertThat(cache.keySet("europe", "france")).containsOnly("annecy", "paris"); + assertThat(cache.containsKey("europe")).isFalse(); + assertThat(cache.containsKey("europe", "france")).isFalse(); + assertThat(cache.containsKey("europe", "france", "annecy")).isTrue(); + assertThat(cache.containsKey("europe", "france", "biarritz")).isFalse(); + assertThat(cache.values()).containsOnly("eiffel tower", "lake", "colosseum"); + + Cache.Entry[] allEntries = Iterables.toArray(cache.entries(), Cache.Entry.class); + assertThat(allEntries).hasSize(3); + assertThat(allEntries[0].key()).isEqualTo(new String[]{"europe", "france", "annecy"}); + assertThat(allEntries[0].value()).isEqualTo("lake"); + assertThat(allEntries[1].key()).isEqualTo(new String[]{"europe", "france", "paris"}); + assertThat(allEntries[1].value()).isEqualTo("eiffel tower"); + assertThat(allEntries[2].key()).isEqualTo(new String[]{"europe", "italy", "rome"}); + assertThat(allEntries[2].value()).isEqualTo("colosseum"); + + Cache.SubEntry[] subEntries = Iterables.toArray(cache.subEntries("europe"), Cache.SubEntry.class); + assertThat(subEntries).hasSize(2); + assertThat(subEntries[0].keyAsString()).isEqualTo("france"); + assertThat(subEntries[0].value()).isNull(); + assertThat(subEntries[1].keyAsString()).isEqualTo("italy"); + assertThat(subEntries[1].value()).isNull(); + + cache.remove("europe", "france", "annecy"); + assertThat(cache.values()).containsOnly("eiffel tower", "colosseum"); + assertThat(cache.get("europe", "france", "annecy")).isNull(); + assertThat(cache.get("europe", "italy", "rome")).isEqualTo("colosseum"); + assertThat(cache.containsKey("europe", "france")).isFalse(); + + cache.clear("europe", "italy"); + assertThat(cache.values()).containsOnly("eiffel tower"); + + cache.clear("europe"); + assertThat(cache.values()).isEmpty(); } @Test - public void test_groups() { - Cache cache = caches.createCache("issues"); - assertThat(cache.groups()).isEmpty(); + public void remove_versus_clear() throws Exception { + Cache cache = caches.createCache("capitals"); + cache.put("europe", "france", "paris"); + cache.put("europe", "italy", "rome"); - cache.put("org/apache/struts/Action.java", "ncloc", 123f); - cache.put("org/apache/struts/Action.java", "lines", 200f); - cache.put("org/apache/struts/Filter.java", "ncloc", 400f); + // remove("europe") does not remove sub-keys + cache.remove("europe"); + assertThat(cache.values()).containsOnly("paris", "rome"); - assertThat(cache.groups()).containsOnly("org/apache/struts/Action.java", "org/apache/struts/Filter.java"); + // clear("europe") removes sub-keys + cache.clear("europe"); + assertThat(cache.values()).isEmpty(); } @Test - public void test_entries() throws PersistitException { - Cache cache = caches.createCache("issues"); - cache.put("org/apache/struts/Action.java", "ncloc", 123f); - cache.put("org/apache/struts/Action.java", "lines", 200f); - cache.put("org/apache/struts/Filter.java", "ncloc", 400f); - - Cache.Entry[] entries = Iterables.toArray(cache.entries(), Cache.Entry.class); - assertThat(entries).hasSize(3); - assertThat(entries[0].group()).isEqualTo("org/apache/struts/Action.java"); - assertThat(entries[0].key()).isEqualTo("lines"); - assertThat(entries[0].value()).isEqualTo(200f); - assertThat(entries[1].group()).isEqualTo("org/apache/struts/Action.java"); - assertThat(entries[1].key()).isEqualTo("ncloc"); - assertThat(entries[1].value()).isEqualTo(123f); - assertThat(entries[2].group()).isEqualTo("org/apache/struts/Filter.java"); - assertThat(entries[2].key()).isEqualTo("ncloc"); - assertThat(entries[2].value()).isEqualTo(400f); - } + public void empty_cache() throws Exception { + Cache cache = caches.createCache("empty"); - @Test - public void test_entries_of_group() throws PersistitException { - Cache cache = caches.createCache("issues"); - cache.put("org/apache/struts/Action.java", "ncloc", 123f); - cache.put("org/apache/struts/Action.java", "lines", 200f); - cache.put("org/apache/struts/Filter.java", "ncloc", 400f); + assertThat(cache.get("foo")).isNull(); + assertThat(cache.get("foo", "bar")).isNull(); + assertThat(cache.get("foo", "bar", "baz")).isNull(); + assertThat(cache.keySet()).isEmpty(); + assertThat(cache.keySet("foo")).isEmpty(); + assertThat(cache.containsKey("foo")).isFalse(); + assertThat(cache.containsKey("foo", "bar")).isFalse(); + assertThat(cache.containsKey("foo", "bar", "baz")).isFalse(); + assertThat(cache.values()).isEmpty(); + assertThat(cache.values("foo")).isEmpty(); - Cache.Entry[] entries = Iterables.toArray(cache.entries("org/apache/struts/Action.java"), Cache.Entry.class); - assertThat(entries).hasSize(2); - assertThat(entries[0].group()).isEqualTo("org/apache/struts/Action.java"); - assertThat(entries[0].key()).isEqualTo("lines"); - assertThat(entries[0].value()).isEqualTo(200f); - assertThat(entries[1].group()).isEqualTo("org/apache/struts/Action.java"); - assertThat(entries[1].key()).isEqualTo("ncloc"); - assertThat(entries[1].value()).isEqualTo(123f); + // do not fail + cache.remove("foo"); + cache.remove("foo", "bar"); + cache.remove("foo", "bar", "baz"); + cache.clear("foo"); + cache.clear("foo", "bar"); + cache.clear("foo", "bar", "baz"); + cache.clear(); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java index 2e206f93071..df166adad95 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java @@ -83,16 +83,16 @@ public class CachesTest { @Test public void should_create_cache() throws Exception { caches.start(); - Cache cache = caches.createCache("foo"); + Cache cache = caches.createCache("foo"); assertThat(cache).isNotNull(); } @Test public void should_not_create_cache_twice() throws Exception { caches.start(); - caches.createCache("foo"); + caches.createCache("foo"); try { - caches.createCache("foo"); + caches.createCache("foo"); fail(); } catch (IllegalStateException e) { // ok diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java index f669da66c7e..776f9b4a4b7 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java @@ -19,7 +19,6 @@ */ package org.sonar.batch.index; -import com.google.common.base.Charsets; import org.apache.commons.configuration.PropertiesConfiguration; import org.junit.Before; import org.junit.Rule; @@ -27,10 +26,9 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.slf4j.Logger; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.resources.Project; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; -import org.sonar.api.scan.filesystem.internal.InputFileBuilder; import org.sonar.jpa.test.AbstractDbUnitTestCase; import java.io.File; @@ -89,10 +87,10 @@ public class ResourceKeyMigrationTest extends AbstractDbUnitTestCase { File file = new File(baseDir, path); String effectiveKey = module.getKey() + ":" + path; String deprecatedEffectiveKey = module.getKey() + ":" + deprecatedKey; - return new InputFileBuilder(file, Charsets.UTF_8, path) - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, effectiveKey) - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_DEPRECATED_KEY, deprecatedEffectiveKey) - .attribute(InputFile.ATTRIBUTE_TYPE, isTest ? InputFile.TYPE_TEST : InputFile.TYPE_MAIN).build(); + return new DefaultInputFile(path).setFile(file) + .setKey(effectiveKey) + .setDeprecatedKey(deprecatedEffectiveKey) + .setType(isTest ? InputFile.Type.TEST : InputFile.Type.MAIN); } @Test @@ -114,7 +112,7 @@ public class ResourceKeyMigrationTest extends AbstractDbUnitTestCase { verify(logger).info("Migrated resource {} to {}", "b:org/foo", "b:src/main/java/org/foo"); verify(logger).info("Migrated resource {} to {}", "b:[root]", "b:src/main/java"); - checkTables("shouldMigrateResourceKeys", new String[] {"build_date", "created_at"}, "projects"); + checkTables("shouldMigrateResourceKeys", new String[]{"build_date", "created_at"}, "projects"); } private static Project newProject(String key, String language) { diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java index 8f8eba536f7..31001bc9843 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java @@ -20,13 +20,6 @@ package org.sonar.batch.issue.ignore.scanner; -import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; -import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; -import org.sonar.batch.issue.ignore.pattern.PatternMatcher; -import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader; -import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner; - -import com.google.common.base.Charsets; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -34,53 +27,49 @@ import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; -import org.sonar.api.scan.filesystem.internal.InputFileBuilder; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.utils.SonarException; -import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; +import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; +import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; +import org.sonar.batch.issue.ignore.pattern.PatternMatcher; import java.io.File; import java.io.IOException; -import java.util.Arrays; import static com.google.common.base.Charsets.UTF_8; import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; public class IssueExclusionsLoaderTest { - private IssueExclusionsLoader scanner; + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); @Mock private IssueExclusionsRegexpScanner regexpScanner; + @Mock private IssueInclusionPatternInitializer inclusionPatternInitializer; + @Mock private IssueExclusionPatternInitializer exclusionPatternInitializer; + @Mock private PatternMatcher patternMatcher; - @Mock - private DefaultModuleFileSystem fs; - - @Rule - public ExpectedException thrown = ExpectedException.none(); - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - private File baseDir; + DefaultFileSystem fs = new DefaultFileSystem().setEncoding(UTF_8); + IssueExclusionsLoader scanner; + File baseDir; @Before - public void init() throws IOException { + public void before() throws IOException { baseDir = temp.newFolder(); MockitoAnnotations.initMocks(this); - - when(fs.sourceCharset()).thenReturn(UTF_8); - scanner = new IssueExclusionsLoader(regexpScanner, exclusionPatternInitializer, inclusionPatternInitializer, fs); } @@ -110,16 +99,17 @@ public class IssueExclusionsLoaderTest { } @Test - public void shouldAnalyseProject() throws IOException { + public void shouldAnalyzeProject() throws IOException { File javaFile1 = new File(baseDir, "src/main/java/Foo.java"); + fs.add(new DefaultInputFile("src/main/java/Foo.java") + .setFile(javaFile1) + .setType(InputFile.Type.MAIN) + .setKey("polop:src/main/java/Foo.java")); File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java"); - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( - new InputFileBuilder(javaFile1, Charsets.UTF_8, "src/main/java/Foo.java") - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/main/java/Foo.java") - .build(), - new InputFileBuilder(javaTestFile1, Charsets.UTF_8, "src/test/java/FooTest.java") - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/test/java/FooTest.java") - .build())); + fs.add(new DefaultInputFile("src/test/java/FooTest.java") + .setFile(javaTestFile1) + .setType(InputFile.Type.TEST) + .setKey("polop:src/test/java/FooTest.java")); when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true); @@ -136,15 +126,15 @@ public class IssueExclusionsLoaderTest { @Test public void shouldAnalyseFilesOnlyWhenRegexConfigured() throws IOException { File javaFile1 = new File(baseDir, "src/main/java/Foo.java"); + fs.add(new DefaultInputFile("src/main/java/Foo.java") + .setFile(javaFile1) + .setType(InputFile.Type.MAIN) + .setKey("polop:src/main/java/Foo.java")); File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java"); - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( - new InputFileBuilder(javaFile1, Charsets.UTF_8, "src/main/java/Foo.java") - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/main/java/Foo.java") - .build(), - new InputFileBuilder(javaTestFile1, Charsets.UTF_8, "src/test/java/FooTest.java") - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/test/java/FooTest.java") - .build())); - + fs.add(new DefaultInputFile("src/test/java/FooTest.java") + .setFile(javaTestFile1) + .setType(InputFile.Type.TEST) + .setKey("polop:src/test/java/FooTest.java")); when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(false); scanner.execute(); @@ -159,10 +149,10 @@ public class IssueExclusionsLoaderTest { @Test public void shouldReportFailure() throws IOException { File phpFile1 = new File(baseDir, "src/Foo.php"); - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( - new InputFileBuilder(phpFile1, Charsets.UTF_8, "src/Foo.php") - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/Foo.php") - .build())); + fs.add(new DefaultInputFile("src/Foo.php") + .setFile(phpFile1) + .setType(InputFile.Type.MAIN) + .setKey("polop:src/Foo.php")); when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true); doThrow(new IOException("BUG")).when(regexpScanner).scan("polop:src/Foo.php", phpFile1, UTF_8); diff --git a/sonar-batch/src/test/java/org/sonar/batch/phases/ProfileLoggerTest.java b/sonar-batch/src/test/java/org/sonar/batch/phases/ProfileLoggerTest.java index 22ec32b6e22..68d1cde8c4a 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/phases/ProfileLoggerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/phases/ProfileLoggerTest.java @@ -27,47 +27,27 @@ import org.junit.rules.ExpectedException; import org.slf4j.Logger; import org.sonar.api.batch.ModuleLanguages; import org.sonar.api.config.Settings; -import org.sonar.api.resources.AbstractLanguage; -import org.sonar.api.resources.Language; -import org.sonar.api.utils.SonarException; +import org.sonar.api.utils.MessageException; import org.sonar.batch.rule.ModuleQProfiles; import org.sonar.batch.rule.ModuleQProfiles.QProfile; import java.util.Collections; -import java.util.List; -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 ProfileLoggerTest { @Rule public ExpectedException thrown = ExpectedException.none(); - private ModuleLanguages languages; - private ModuleQProfiles profiles; - private Settings settings; + ModuleLanguages languages; + ModuleQProfiles profiles; + Settings settings = new Settings(); @Before - public void prepare() { + public void before() { languages = mock(ModuleLanguages.class); - List languageList = Lists.newArrayList(); - languageList.add(new AbstractLanguage("java", "Java") { - - @Override - public String[] getFileSuffixes() { - return null; - } - }); - languageList.add(new AbstractLanguage("cobol", "Cobol") { - - @Override - public String[] getFileSuffixes() { - return null; - } - }); - when(languages.languages()).thenReturn(languageList); + when(languages.keys()).thenReturn(Lists.newArrayList("java", "cobol")); profiles = mock(ModuleQProfiles.class); QProfile javaProfile = mock(QProfile.class); @@ -76,38 +56,34 @@ public class ProfileLoggerTest { QProfile cobolProfile = mock(QProfile.class); when(cobolProfile.name()).thenReturn("My Cobol profile"); when(profiles.findByLanguage("cobol")).thenReturn(cobolProfile); - - settings = new Settings(); } @Test public void should_log_all_used_profiles() { - ProfileLogger profileLogger = new ProfileLogger(settings, languages, profiles); Logger logger = mock(Logger.class); profileLogger.execute(logger); - verify(logger).info("Quality profile for {}: {}", "Java", "My Java profile"); - verify(logger).info("Quality profile for {}: {}", "Cobol", "My Cobol profile"); + verify(logger).info("Quality profile for {}: {}", "java", "My Java profile"); + verify(logger).info("Quality profile for {}: {}", "cobol", "My Cobol profile"); } @Test public void should_fail_if_default_profile_not_used() { - settings.setProperty("sonar.profile", "Unknow"); + settings.setProperty("sonar.profile", "Unknown"); ProfileLogger profileLogger = new ProfileLogger(settings, languages, profiles); - thrown.expect(SonarException.class); - thrown.expectMessage("sonar.profile was set to 'Unknow' but didn't match any profile for any language. Please check your configuration."); + thrown.expect(MessageException.class); + thrown.expectMessage("sonar.profile was set to 'Unknown' but didn't match any profile for any language. Please check your configuration."); profileLogger.execute(); - } @Test public void should_not_fail_if_no_language_on_project() { - settings.setProperty("sonar.profile", "Unknow"); - when(languages.languages()).thenReturn(Collections.emptyList()); + settings.setProperty("sonar.profile", "Unknown"); + when(languages.keys()).thenReturn(Collections.emptyList()); ProfileLogger profileLogger = new ProfileLogger(settings, languages, profiles); diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java index 8d4bdbda1ca..bda70b4e5ee 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java @@ -19,7 +19,7 @@ */ package org.sonar.batch.rule; -import edu.emory.mathcs.backport.java.util.Collections; +import java.util.Collections; import org.junit.Test; import org.sonar.api.batch.ModuleLanguages; import org.sonar.api.batch.SensorContext; @@ -52,7 +52,7 @@ public class QProfileSensorTest extends AbstractDaoTestCase { public void no_qprofiles() throws Exception { setupData("shared"); QualityProfileDao dao = new QualityProfileDao(getMyBatis()); - when(moduleQProfiles.findAll()).thenReturn(Collections.emptyList()); + when(moduleQProfiles.findAll()).thenReturn(Collections.emptyList()); QProfileSensor sensor = new QProfileSensor(moduleQProfiles, moduleLanguages, dao); assertThat(sensor.shouldExecuteOnProject(project)).isTrue(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AttributeFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AttributeFilterTest.java deleted file mode 100644 index c5abdd3f9fb..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AttributeFilterTest.java +++ /dev/null @@ -1,48 +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.Charsets; -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.internal.DefaultInputFile; - -import static org.fest.assertions.Assertions.assertThat; - -public class AttributeFilterTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - @Test - public void should_check_attribute_value() throws Exception { - AttributeFilter filter = new AttributeFilter("foo", Lists.newArrayList("one", "two")); - - assertThat(filter.key()).isEqualTo("foo"); - assertThat(filter.values()).containsOnly("one", "two"); - assertThat(filter.accept(DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "Why.java", ImmutableMap.of("foo", "two")))).isTrue(); - assertThat(filter.accept(DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "Where.java", ImmutableMap.of("foo", "three")))).isFalse(); - assertThat(filter.accept(DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "What.java", ImmutableMap.of("bar", "one")))).isFalse(); - - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java index 3bd5f2dbbdc..1744309ea1d 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java @@ -30,50 +30,40 @@ import org.mockito.ArgumentMatcher; import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent; import org.sonar.api.CoreProperties; import org.sonar.api.batch.SonarIndex; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.config.Settings; -import org.sonar.api.resources.AbstractLanguage; -import org.sonar.api.resources.Java; -import org.sonar.api.resources.Languages; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; -import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; -import org.sonar.api.scan.filesystem.internal.InputFileBuilder; +import org.sonar.api.resources.*; import org.sonar.batch.index.ResourceKeyMigration; import org.sonar.batch.scan.language.DefaultModuleLanguages; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; -import java.util.Arrays; -import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; public class ComponentIndexerTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); - private File baseDir; - private DefaultModuleFileSystem fs; - private SonarIndex sonarIndex; - private AbstractLanguage cobolLanguage; - private Project project; - private Settings settings; + File baseDir; + DefaultFileSystem fs = new DefaultFileSystem(); + SonarIndex sonarIndex; + AbstractLanguage cobolLanguage; + Project project; + Settings settings; - private String aClaess; - private String explicacao; + String aClaess; + String explicacao; @Before public void prepare() throws IOException { baseDir = temp.newFolder(); - fs = mock(DefaultModuleFileSystem.class); sonarIndex = mock(SonarIndex.class); project = mock(Project.class); settings = new Settings(); @@ -90,10 +80,9 @@ public class ComponentIndexerTest { @Test public void should_index_java_files() throws IOException { - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( - newInputFile("src/main/java/foo/bar/Foo.java", "", "foo/bar/Foo.java", "java", false), - newInputFile("src/main/java2/foo/bar/Foo.java", "", "foo/bar/Foo.java", "java", false), - newInputFile("src/test/java/foo/bar/FooTest.java", "", "foo/bar/FooTest.java", "java", true))); + fs.add(newInputFile("src/main/java/foo/bar/Foo.java", "", "foo/bar/Foo.java", "java", false)); + fs.add(newInputFile("src/main/java2/foo/bar/Foo.java", "", "foo/bar/Foo.java", "java", false)); + fs.add(newInputFile("src/test/java/foo/bar/FooTest.java", "", "foo/bar/FooTest.java", "java", true)); Languages languages = new Languages(Java.INSTANCE); ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages), mock(InputFileCache.class)); @@ -114,10 +103,9 @@ public class ComponentIndexerTest { @Test public void should_index_cobol_files() throws IOException { - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( - newInputFile("src/foo/bar/Foo.cbl", "", "foo/bar/Foo.cbl", "cobol", false), - newInputFile("src2/foo/bar/Foo.cbl", "", "foo/bar/Foo.cbl", "cobol", false), - newInputFile("src/test/foo/bar/FooTest.cbl", "", "foo/bar/FooTest.cbl", "cobol", true))); + fs.add(newInputFile("src/foo/bar/Foo.cbl", "", "foo/bar/Foo.cbl", "cobol", false)); + fs.add(newInputFile("src2/foo/bar/Foo.cbl", "", "foo/bar/Foo.cbl", "cobol", false)); + fs.add(newInputFile("src/test/foo/bar/FooTest.cbl", "", "foo/bar/FooTest.cbl", "cobol", true)); Languages languages = new Languages(cobolLanguage); ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages), @@ -133,8 +121,7 @@ public class ComponentIndexerTest { public void shouldImportSource() throws IOException { settings.setProperty(CoreProperties.CORE_IMPORT_SOURCES_PROPERTY, "true"); - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( - newInputFile("src/main/java/foo/bar/Foo.java", "sample code", "foo/bar/Foo.java", "java", false))); + fs.add(newInputFile("src/main/java/foo/bar/Foo.java", "sample code", "foo/bar/Foo.java", "java", false)); Languages languages = new Languages(Java.INSTANCE); ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages), mock(InputFileCache.class)); @@ -167,16 +154,14 @@ public class ComponentIndexerTest { } @Test - public void should_remove_byte_order_mark_character() throws Exception { + public void remove_byte_order_mark_character() throws Exception { settings.setProperty(CoreProperties.CORE_IMPORT_SOURCES_PROPERTY, "true"); File javaFile1 = new File(baseDir, "src/main/java/foo/bar/Foo.java"); FileUtils.write(javaFile1, "\uFEFFpublic class Test", Charsets.UTF_8); - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( - new InputFileBuilder(javaFile1, Charset.forName("UTF-8"), "src/main/java/foo/bar/Foo.java") - .attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "foo/bar/Foo.java") - .attribute(InputFile.ATTRIBUTE_LANGUAGE, "java") - .build())); + fs.add(new DefaultInputFile("src/main/java/foo/bar/Foo.java").setFile(javaFile1) + .setPathRelativeToSourceDir("foo/bar/Foo.java") + .setLanguage("java")); Languages languages = new Languages(Java.INSTANCE); ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages), mock(InputFileCache.class)); @@ -195,16 +180,14 @@ public class ComponentIndexerTest { private void fileEncodingTest(String encoding, String testFile) throws Exception { settings.setProperty(CoreProperties.CORE_IMPORT_SOURCES_PROPERTY, "true"); + fs.setEncoding(Charset.forName(encoding)); File javaFile1 = new File(baseDir, "src/main/java/foo/bar/Foo.java"); FileUtils.copyFile(getFile(testFile), javaFile1); - when(fs.inputFiles(FileQuery.all())) - .thenReturn( - (Iterable) Arrays.asList( - new InputFileBuilder(javaFile1, Charset.forName(encoding), "src/main/java/foo/bar/Foo.java") - .attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "foo/bar/Foo.java") - .attribute(InputFile.ATTRIBUTE_LANGUAGE, "java") - .build())); + fs.add(new DefaultInputFile("src/main/java/foo/bar/Foo.java") + .setFile(javaFile1) + .setPathRelativeToSourceDir("foo/bar/Foo.java") + .setLanguage("java")); Languages languages = new Languages(Java.INSTANCE); ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages), mock(InputFileCache.class)); @@ -221,36 +204,18 @@ public class ComponentIndexerTest { })); } - @Test - public void should_compute_line_count() throws IOException { - DefaultInputFile inputFile3lines = newInputFile("src/main/java/foo/bar/Foo1.java", "line1\nline2\nline3", "foo/bar/Foo1.java", "java", false); - DefaultInputFile inputFileEmpty = newInputFile("src/main/java/foo/bar/Foo2.java", "", "foo/bar/Foo2.java", "java", false); - DefaultInputFile inputFileEndsWithNewLine = newInputFile("src/main/java/foo/bar/Foo3.java", "line1\nline2\nline3\n", "foo/bar/Foo3.java", "java", false); - DefaultInputFile inputFileMixedLineEnds = newInputFile("src/main/java/foo/bar/Foo4.java", "line1\r\r\nline3\r\n\nline5\r", "foo/bar/Foo4.java", "java", false); - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList(inputFile3lines, inputFileEmpty, inputFileEndsWithNewLine, inputFileMixedLineEnds)); - Languages languages = new Languages(Java.INSTANCE); - ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages), - mock(InputFileCache.class)); - indexer.execute(fs); - - assertThat(inputFile3lines.attribute(InputFile.ATTRIBUTE_LINE_COUNT)).isEqualTo("3"); - assertThat(inputFileEmpty.attribute(InputFile.ATTRIBUTE_LINE_COUNT)).isEqualTo("1"); - assertThat(inputFileEndsWithNewLine.attribute(InputFile.ATTRIBUTE_LINE_COUNT)).isEqualTo("4"); - assertThat(inputFileMixedLineEnds.attribute(InputFile.ATTRIBUTE_LINE_COUNT)).isEqualTo("6"); - } private File getFile(String testFile) { - return new File("test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/" + testFile); + return new File("test-resources/org/sonar/batch/phases/ComponentIndexerTest/encoding/" + testFile); } private DefaultInputFile newInputFile(String path, String content, String sourceRelativePath, String languageKey, boolean unitTest) throws IOException { File file = new File(baseDir, path); FileUtils.write(file, content); - return new InputFileBuilder(file, Charsets.UTF_8, path) - .attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, sourceRelativePath) - .attribute(InputFile.ATTRIBUTE_LANGUAGE, languageKey) - .attribute(InputFile.ATTRIBUTE_TYPE, unitTest ? InputFile.TYPE_TEST : InputFile.TYPE_MAIN) - .build(); + return new DefaultInputFile(path).setFile(file) + .setPathRelativeToSourceDir(sourceRelativePath) + .setLanguage(languageKey) + .setType(unitTest ? InputFile.Type.TEST : InputFile.Type.MAIN); } } 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 4041895dff4..cccc194e107 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,34 +19,26 @@ */ package org.sonar.batch.scan.filesystem; -import com.google.common.base.Charsets; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; import org.sonar.api.CoreProperties; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; -import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; -import org.sonar.batch.bootstrap.AnalysisMode; 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.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; public class DefaultModuleFileSystemTest { @@ -57,23 +49,21 @@ public class DefaultModuleFileSystemTest { public ExpectedException thrown = ExpectedException.none(); Settings settings = new Settings(); - FileIndex fileIndex = mock(FileIndex.class); + FileIndexer fileIndexer = mock(FileIndexer.class); ModuleFileSystemInitializer initializer = mock(ModuleFileSystemInitializer.class, Mockito.RETURNS_DEEP_STUBS); - private AnalysisMode mode; - private ComponentIndexer componentIndexer; - - @Before - public void before() { - mode = mock(AnalysisMode.class); - componentIndexer = mock(ComponentIndexer.class); - } + ComponentIndexer componentIndexer = mock(ComponentIndexer.class); + ModuleInputFileCache moduleInputFileCache = mock(ModuleInputFileCache.class); @Test public void test_equals_and_hashCode() throws Exception { - DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem(new Project("foo"), settings, fileIndex, initializer, mode, componentIndexer); - DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem(new Project("foo"), settings, fileIndex, initializer, mode, componentIndexer); - DefaultModuleFileSystem bar = new DefaultModuleFileSystem(new Project("bar"), settings, fileIndex, initializer, mode, componentIndexer); - DefaultModuleFileSystem branch = new DefaultModuleFileSystem(new Project("bar", "branch", "My project"), settings, fileIndex, initializer, mode, componentIndexer); + DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem(moduleInputFileCache, + new Project("foo"), settings, fileIndexer, initializer, componentIndexer); + DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem(moduleInputFileCache, + new Project("foo"), settings, fileIndexer, initializer, componentIndexer); + DefaultModuleFileSystem bar = new DefaultModuleFileSystem(moduleInputFileCache, + new Project("bar"), settings, fileIndexer, initializer, componentIndexer); + DefaultModuleFileSystem branch = new DefaultModuleFileSystem(moduleInputFileCache, + new Project("bar", "branch", "My project"), settings, fileIndexer, initializer, componentIndexer); assertThat(foo1.moduleKey()).isEqualTo("foo"); assertThat(branch.moduleKey()).isEqualTo("bar:branch"); @@ -87,21 +77,24 @@ public class DefaultModuleFileSystemTest { @Test public void default_source_encoding() { - DefaultModuleFileSystem fs = new DefaultModuleFileSystem(new Project("foo"), settings, fileIndex, initializer, mode, componentIndexer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, + new Project("foo"), settings, fileIndexer, initializer, componentIndexer); assertThat(fs.sourceCharset()).isEqualTo(Charset.defaultCharset()); - assertThat(fs.isDefaultSourceCharset()).isTrue(); + assertThat(fs.isDefaultJvmEncoding()).isTrue(); } @Test public void source_encoding_is_set() { settings.setProperty(CoreProperties.ENCODING_PROPERTY, "Cp1124"); - DefaultModuleFileSystem fs = new DefaultModuleFileSystem(new Project("foo"), settings, fileIndex, initializer, mode, componentIndexer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, + new Project("foo"), settings, fileIndexer, initializer, componentIndexer); + assertThat(fs.encoding()).isEqualTo(Charset.forName("Cp1124")); 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(); + assertThat(fs.isDefaultJvmEncoding()).isFalse(); } @Test @@ -120,7 +113,8 @@ public class DefaultModuleFileSystemTest { when(initializer.additionalSourceFiles()).thenReturn(Arrays.asList(additionalFile)); when(initializer.additionalTestFiles()).thenReturn(Arrays.asList(additionalTest)); - DefaultModuleFileSystem fs = new DefaultModuleFileSystem(new Project("foo"), settings, fileIndex, initializer, mode, componentIndexer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, + new Project("foo"), settings, fileIndexer, initializer, componentIndexer); assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath()); assertThat(fs.workingDir().getCanonicalPath()).isEqualTo(workingDir.getCanonicalPath()); @@ -139,7 +133,8 @@ public class DefaultModuleFileSystemTest { when(initializer.workingDir()).thenReturn(basedir); when(initializer.sourceDirs()).thenReturn(Arrays.asList(new File(basedir, "src/main/java"))); - DefaultModuleFileSystem fs = new DefaultModuleFileSystem(new Project("foo"), settings, fileIndex, initializer, mode, componentIndexer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, + new Project("foo"), settings, fileIndexer, initializer, componentIndexer); File existingDir = temp.newFolder("new_folder"); File notExistingDir = new File(existingDir, "not_exist"); @@ -159,30 +154,31 @@ public class DefaultModuleFileSystemTest { @Test public void should_search_input_files() throws Exception { - DefaultModuleFileSystem fs = new DefaultModuleFileSystem(new Project("foo"), settings, fileIndex, initializer, mode, componentIndexer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, + new Project("foo"), settings, fileIndexer, initializer, componentIndexer); File mainFile = temp.newFile(); - InputFile mainInput = DefaultInputFile.create(mainFile, Charsets.UTF_8, "Main.java", ImmutableMap.of(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_MAIN)); - InputFile testInput = DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "Test.java", ImmutableMap.of(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST)); - - when(fileIndex.inputFiles("foo")).thenReturn(Lists.newArrayList(mainInput, testInput)); + InputFile mainInput = new DefaultInputFile("Main.java").setFile(mainFile).setType(InputFile.Type.MAIN); + InputFile testInput = new DefaultInputFile("Test.java").setFile(temp.newFile()).setType(InputFile.Type.TEST); + when(moduleInputFileCache.inputFiles()).thenReturn(Lists.newArrayList(mainInput, testInput)); fs.index(); - Iterable inputFiles = fs.inputFiles(FileQuery.onSource()); + Iterable inputFiles = fs.inputFiles(FilePredicates.hasType(InputFile.Type.MAIN)); assertThat(inputFiles).containsOnly(mainInput); - List files = fs.files(FileQuery.onSource()); + Iterable files = fs.files(FilePredicates.hasType(InputFile.Type.MAIN)); assertThat(files).containsOnly(mainFile); } @Test public void should_index() throws Exception { - DefaultModuleFileSystem fs = new DefaultModuleFileSystem(new Project("foo"), settings, fileIndex, initializer, mode, componentIndexer); + DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, + new Project("foo"), settings, fileIndexer, initializer, componentIndexer); - verifyZeroInteractions(fileIndex); + verifyZeroInteractions(fileIndexer); fs.index(); - verify(fileIndex).index(fs); + verify(fileIndexer).index(fs); verify(componentIndexer).execute(fs); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java index 6fafbb57e20..5592ecfa204 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java @@ -19,28 +19,22 @@ */ package org.sonar.batch.scan.filesystem; -import org.sonar.api.scan.filesystem.InputFile; - -import com.google.common.base.Charsets; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import org.apache.commons.io.FilenameUtils; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.mockito.ArgumentCaptor; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.scan.filesystem.FileSystemFilter; import org.sonar.api.scan.filesystem.FileType; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; import java.io.File; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; -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 DeprecatedFileFiltersTest { @@ -53,7 +47,7 @@ public class DeprecatedFileFiltersTest { public void no_filters() throws Exception { DeprecatedFileFilters filters = new DeprecatedFileFilters(); - InputFile inputFile = DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "src/main/java/Foo.java", Maps.newHashMap()); + InputFile inputFile = new DefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile()); assertThat(filters.accept(inputFile)).isTrue(); } @@ -63,12 +57,11 @@ public class DeprecatedFileFiltersTest { File basedir = temp.newFolder(); File file = temp.newFile(); - InputFile inputFile = DefaultInputFile.create(file, Charsets.UTF_8, "src/main/java/Foo.java", ImmutableMap.of( - DefaultInputFile.ATTRIBUTE_SOURCEDIR_PATH, new File(basedir, "src/main/java").getAbsolutePath(), - DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "Foo.java", - InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST - - )); + InputFile inputFile = new DefaultInputFile("src/main/java/Foo.java") + .setFile(file) + .setType(InputFile.Type.MAIN) + .setSourceDirAbsolutePath(new File(basedir, "src/main/java").getAbsolutePath()) + .setPathRelativeToSourceDir("Foo.java"); when(filter.accept(eq(file), any(DeprecatedFileFilters.DeprecatedContext.class))).thenReturn(false); assertThat(filters.accept(inputFile)).isFalse(); @@ -80,6 +73,6 @@ public class DeprecatedFileFiltersTest { assertThat(context.canonicalPath()).isEqualTo(FilenameUtils.separatorsToUnix(file.getAbsolutePath())); assertThat(context.relativeDir()).isEqualTo(new File(basedir, "src/main/java")); assertThat(context.relativePath()).isEqualTo("Foo.java"); - assertThat(context.type()).isEqualTo(FileType.TEST); + assertThat(context.type()).isEqualTo(FileType.MAIN); } } 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 1f2551a119c..c08dbe3b1c4 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,14 +19,11 @@ */ package org.sonar.batch.scan.filesystem; -import org.sonar.api.scan.filesystem.InputFile; - -import com.google.common.base.Charsets; -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.internal.DefaultInputFile; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import java.io.File; @@ -43,17 +40,17 @@ public class ExclusionFilterTest { ExclusionFilter absoluteFilter = new ExclusionFilter("file:**/src/main/**Foo.java"); File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java"); - InputFile inputFile = DefaultInputFile.create(file, Charsets.UTF_8, "src/main/java/org/MyFoo.java", ImmutableMap.of( - DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/MyFoo.java" - )); + InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java") + .setFile(file) + .setPathRelativeToSourceDir("org/MyFoo.java"); assertThat(sourceRelativeFilter.accept(inputFile)).isFalse(); assertThat(absoluteFilter.accept(inputFile)).isFalse(); file = new File(temp.newFolder(), "src/main/java/org/Other.java"); - inputFile = DefaultInputFile.create(file, Charsets.UTF_8, "src/main/java/org/Other.java", ImmutableMap.of( - DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/Other.java" - )); + inputFile = new DefaultInputFile("src/main/java/org/Other.java") + .setFile(file) + .setPathRelativeToSourceDir("org/Other.java"); assertThat(sourceRelativeFilter.accept(inputFile)).isTrue(); assertThat(absoluteFilter.accept(inputFile)).isTrue(); } 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 70f00226796..6083f224a5c 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 @@ -24,9 +24,9 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.CoreProperties; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.config.Settings; import org.sonar.api.scan.filesystem.FileExclusions; -import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.scan.filesystem.ModuleFileSystem; import java.io.File; @@ -60,12 +60,12 @@ public class ExclusionFiltersTest { java.io.File file = temp.newFile(); - assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.TYPE_MAIN)).isFalse(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.Type.MAIN)).isFalse(); - assertThat(filter.accept(file, "src/main/java/com/mycompany/FooDao.java", InputFile.TYPE_MAIN)).isTrue(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/FooDao.java", InputFile.Type.MAIN)).isTrue(); // test are excluded by default if no sonar.tests nor sonar.test.inclusions - assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.TYPE_TEST)).isFalse(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.Type.TEST)).isFalse(); } @Test @@ -78,12 +78,12 @@ public class ExclusionFiltersTest { java.io.File file = temp.newFile(); - assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.TYPE_MAIN)).isTrue(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.Type.MAIN)).isTrue(); - assertThat(filter.accept(file, "src/main/java2/com/mycompany/FooDao.java", InputFile.TYPE_MAIN)).isFalse(); + assertThat(filter.accept(file, "src/main/java2/com/mycompany/FooDao.java", InputFile.Type.MAIN)).isFalse(); // source inclusions do not apply to tests - assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.TYPE_TEST)).isFalse(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.Type.TEST)).isFalse(); } @Test @@ -97,11 +97,11 @@ public class ExclusionFiltersTest { java.io.File file = temp.newFile(); - assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.TYPE_MAIN)).isTrue(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.Type.MAIN)).isTrue(); - assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.TYPE_TEST)).isFalse(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.Type.TEST)).isFalse(); - assertThat(filter.accept(file, "src/test/java/com/mycompany/Foo.java", InputFile.TYPE_TEST)).isTrue(); + assertThat(filter.accept(file, "src/test/java/com/mycompany/Foo.java", InputFile.Type.TEST)).isTrue(); } @Test @@ -115,12 +115,12 @@ public class ExclusionFiltersTest { java.io.File file = temp.newFile(); - assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.TYPE_MAIN)).isFalse(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.Type.MAIN)).isFalse(); - assertThat(filter.accept(file, "src/main/java2/com/mycompany/FooDao.java", InputFile.TYPE_MAIN)).isTrue(); + assertThat(filter.accept(file, "src/main/java2/com/mycompany/FooDao.java", InputFile.Type.MAIN)).isTrue(); // source inclusions do not apply to tests - assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.TYPE_TEST)).isFalse(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.Type.TEST)).isFalse(); } @Test @@ -134,11 +134,11 @@ public class ExclusionFiltersTest { java.io.File file = temp.newFile(); // test inclusions do not apply to main code - assertThat(filter.accept(file, "src/test/java/com/mycompany/Foo.java", InputFile.TYPE_MAIN)).isFalse(); + assertThat(filter.accept(file, "src/test/java/com/mycompany/Foo.java", InputFile.Type.MAIN)).isFalse(); - assertThat(filter.accept(file, "src/test2/java/com/mycompany/FooTest.java", InputFile.TYPE_TEST)).isFalse(); + assertThat(filter.accept(file, "src/test2/java/com/mycompany/FooTest.java", InputFile.Type.TEST)).isFalse(); - assertThat(filter.accept(file, "src/test/java/com/mycompany/Foo.java", InputFile.TYPE_TEST)).isTrue(); + assertThat(filter.accept(file, "src/test/java/com/mycompany/Foo.java", InputFile.Type.TEST)).isTrue(); } @Test @@ -151,9 +151,9 @@ public class ExclusionFiltersTest { java.io.File file = temp.newFile(); - assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.TYPE_MAIN)).isFalse(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.Type.MAIN)).isFalse(); - assertThat(filter.accept(file, "src/main/java/com/mycompany/FooDto.java", InputFile.TYPE_MAIN)).isTrue(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/FooDto.java", InputFile.Type.MAIN)).isTrue(); } @Test @@ -167,12 +167,12 @@ public class ExclusionFiltersTest { filter.prepare(fs); java.io.File file = temp.newFile(); - assertThat(filter.accept(file, "src/main/java/com/mycompany/FooDao.java", InputFile.TYPE_MAIN)).isFalse(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/FooDao.java", InputFile.Type.MAIN)).isFalse(); - assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.TYPE_MAIN)).isTrue(); + assertThat(filter.accept(file, "src/main/java/com/mycompany/Foo.java", InputFile.Type.MAIN)).isTrue(); // source exclusions do not apply to tests - assertThat(filter.accept(file, "src/test/java/com/mycompany/FooDao.java", InputFile.TYPE_TEST)).isTrue(); + assertThat(filter.accept(file, "src/test/java/com/mycompany/FooDao.java", InputFile.Type.TEST)).isTrue(); } @Test @@ -187,9 +187,9 @@ public class ExclusionFiltersTest { filter.prepare(fs); - assertThat(filter.accept(includedFile, "src/main/java/org/bar/Foo.java", InputFile.TYPE_MAIN)).isTrue(); + assertThat(filter.accept(includedFile, "src/main/java/org/bar/Foo.java", InputFile.Type.MAIN)).isTrue(); - assertThat(filter.accept(excludedFile, "src/main/java/org/bar/Bar.java", InputFile.TYPE_MAIN)).isFalse(); + assertThat(filter.accept(excludedFile, "src/main/java/org/bar/Bar.java", InputFile.Type.MAIN)).isFalse(); } @Test diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java index b0a4703d773..2a92f70d84a 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java @@ -47,7 +47,7 @@ public class FileMetadataTest { FileUtils.write(tempFile, "foo\r\nbar\r\nbaz", Charsets.UTF_8, true); FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(tempFile, Charsets.UTF_8); - assertThat(metadata.lines).isEqualTo(3L); + assertThat(metadata.lines).isEqualTo(3); assertThat(metadata.hash).isEqualTo(EXPECTED_HASH_WITHOUT_LATEST_EOL); } @@ -57,7 +57,7 @@ public class FileMetadataTest { FileUtils.write(tempFile, "foo\r\nbar\r\nbaz\r\n", Charsets.UTF_8, true); FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(tempFile, Charsets.UTF_8); - assertThat(metadata.lines).isEqualTo(3L); + assertThat(metadata.lines).isEqualTo(3); assertThat(metadata.hash).isEqualTo(EXPECTED_HASH_WITH_LATEST_EOL); } @@ -67,7 +67,7 @@ public class FileMetadataTest { FileUtils.write(tempFile, "foo\nbar\nbaz", Charsets.UTF_8, true); FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(tempFile, Charsets.UTF_8); - assertThat(metadata.lines).isEqualTo(3L); + assertThat(metadata.lines).isEqualTo(3); assertThat(metadata.hash).isEqualTo(EXPECTED_HASH_WITHOUT_LATEST_EOL); } @@ -77,7 +77,7 @@ public class FileMetadataTest { FileUtils.write(tempFile, "foo\nbar\nbaz\n", Charsets.UTF_8, true); FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(tempFile, Charsets.UTF_8); - assertThat(metadata.lines).isEqualTo(3L); + assertThat(metadata.lines).isEqualTo(3); assertThat(metadata.hash).isEqualTo(EXPECTED_HASH_WITH_LATEST_EOL); } @@ -87,7 +87,7 @@ public class FileMetadataTest { FileUtils.write(tempFile, "foo\nbar\r\nbaz\n", Charsets.UTF_8, true); FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(tempFile, Charsets.UTF_8); - assertThat(metadata.lines).isEqualTo(3L); + assertThat(metadata.lines).isEqualTo(3); assertThat(metadata.hash).isEqualTo(EXPECTED_HASH_WITH_LATEST_EOL); } @@ -97,7 +97,7 @@ public class FileMetadataTest { FileUtils.write(tempFile, "foo\nbar\r\nbaz", Charsets.UTF_8, true); FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(tempFile, Charsets.UTF_8); - assertThat(metadata.lines).isEqualTo(3L); + assertThat(metadata.lines).isEqualTo(3); assertThat(metadata.hash).isEqualTo(EXPECTED_HASH_WITHOUT_LATEST_EOL); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileQueryFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileQueryFilterTest.java deleted file mode 100644 index 443f7061f44..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileQueryFilterTest.java +++ /dev/null @@ -1,108 +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.sonar.api.scan.filesystem.InputFileFilter; - -import org.sonar.api.scan.filesystem.InputFile; -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.batch.bootstrap.AnalysisMode; -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class FileQueryFilterTest { - - private AnalysisMode mode; - - @Before - public void before() { - mode = mock(AnalysisMode.class); - } - - @Test - public void wrap_query_on_attributes() throws Exception { - FileQuery query = FileQuery.onSource(); - FileQueryFilter filter = new FileQueryFilter(mode, query); - - assertThat(filter.filters()).hasSize(1); - InputFileFilter typeFilter = filter.filters().get(0); - assertThat(typeFilter).isInstanceOf(AttributeFilter.class); - assertThat(((AttributeFilter) typeFilter).key()).isEqualTo(InputFile.ATTRIBUTE_TYPE); - assertThat(((AttributeFilter) typeFilter).values()).containsOnly(InputFile.TYPE_MAIN); - } - - @Test - public void wrap_query_on_inclusions() throws Exception { - FileQuery query = FileQuery.on().withInclusions("Foo*.java"); - FileQueryFilter filter = new FileQueryFilter(mode, query); - - assertThat(filter.filters()).hasSize(1); - InputFileFilter inclusionFilter = filter.filters().get(0); - assertThat(inclusionFilter).isInstanceOf(InclusionFilter.class); - assertThat(inclusionFilter.toString()).isEqualTo("Includes: Foo*.java"); - } - - @Test - public void wrap_query_on_exclusions() throws Exception { - FileQuery query = FileQuery.on().withExclusions("Foo*.java"); - FileQueryFilter filter = new FileQueryFilter(mode, query); - - assertThat(filter.filters()).hasSize(1); - InputFileFilter exclusionFilter = filter.filters().get(0); - assertThat(exclusionFilter).isInstanceOf(ExclusionFilter.class); - assertThat(exclusionFilter.toString()).isEqualTo("Excludes: Foo*.java"); - } - - @Test - public void all_files_by_default() throws Exception { - FileQuery query = FileQuery.on(); - FileQueryFilter filter = new FileQueryFilter(mode, query); - assertThat(filter.filters()).isEmpty(); - } - - @Test - public void only_changed_files_by_default_if_incremental_mode() throws Exception { - when(mode.isIncremental()).thenReturn(true); - - FileQuery query = FileQuery.on(); - FileQueryFilter filter = new FileQueryFilter(mode, query); - - assertThat(filter.filters()).hasSize(1); - AttributeFilter statusFilter = (AttributeFilter) filter.filters().get(0); - assertThat(statusFilter.key()).isEqualTo(InputFile.ATTRIBUTE_STATUS); - assertThat(statusFilter.values()).containsOnly(InputFile.STATUS_ADDED, InputFile.STATUS_CHANGED); - } - - @Test - public void get_all_files_even_if_incremental_mode() throws Exception { - when(mode.isIncremental()).thenReturn(true); - - FileQuery query = FileQuery.on().on(InputFile.ATTRIBUTE_STATUS, InputFile.STATUS_SAME); - FileQueryFilter filter = new FileQueryFilter(mode, query); - - assertThat(filter.filters()).hasSize(1); - AttributeFilter statusFilter = (AttributeFilter) filter.filters().get(0); - assertThat(statusFilter.key()).isEqualTo(InputFile.ATTRIBUTE_STATUS); - assertThat(statusFilter.values()).containsOnly(InputFile.STATUS_SAME); - } -} 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 a8ce2a9194d..21afc18791c 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,14 +19,12 @@ */ package org.sonar.batch.scan.filesystem; -import org.sonar.api.scan.filesystem.InputFile; -import com.google.common.base.Charsets; -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.internal.DefaultInputFile; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import java.io.File; @@ -42,17 +40,17 @@ public class InclusionFilterTest { InclusionFilter absoluteFilter = new InclusionFilter("file:**/src/main/**Foo.java"); File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java"); - InputFile inputFile = DefaultInputFile.create(file, Charsets.UTF_8, "src/main/java/org/MyFoo.java", ImmutableMap.of( - DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/MyFoo.java" - )); + InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java") + .setFile(file) + .setPathRelativeToSourceDir("org/MyFoo.java"); assertThat(sourceRelativeFilter.accept(inputFile)).isTrue(); assertThat(absoluteFilter.accept(inputFile)).isTrue(); file = new File(temp.newFolder(), "src/main/java/org/Other.java"); - inputFile = DefaultInputFile.create(file, Charsets.UTF_8, "src/main/java/org/Other.java", ImmutableMap.of( - DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/Other.java" - )); + inputFile = new DefaultInputFile("src/main/java/org/Other.java") + .setFile(file) + .setPathRelativeToSourceDir("org/Other.java"); assertThat(sourceRelativeFilter.accept(inputFile)).isFalse(); assertThat(absoluteFilter.accept(inputFile)).isFalse(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java index 5eba1db2260..c5ee1254df2 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java @@ -23,6 +23,7 @@ import org.junit.Test; import org.mockito.Mockito; import org.sonar.api.resources.Project; import org.sonar.api.scan.filesystem.PathResolver; +import org.sonar.batch.bootstrap.AnalysisMode; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -35,10 +36,11 @@ public class InputFileBuilderFactoryTest { LanguageDetectionFactory langDetectionFactory = mock(LanguageDetectionFactory.class, Mockito.RETURNS_MOCKS); StatusDetectionFactory statusDetectionFactory = mock(StatusDetectionFactory.class, Mockito.RETURNS_MOCKS); DefaultModuleFileSystem fs = mock(DefaultModuleFileSystem.class); + AnalysisMode analysisMode = mock(AnalysisMode.class); InputFileBuilderFactory factory = new InputFileBuilderFactory( project, pathResolver, langDetectionFactory, - statusDetectionFactory); + statusDetectionFactory, analysisMode); InputFileBuilder builder = factory.create(fs); assertThat(builder.langDetection()).isNotNull(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java index 4e19c94bd1b..fadd7426a0c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java @@ -24,10 +24,11 @@ import org.apache.commons.io.FileUtils; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import org.sonar.api.scan.filesystem.InputFile; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.scan.filesystem.PathResolver; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; import org.sonar.api.utils.PathUtils; +import org.sonar.batch.bootstrap.AnalysisMode; import java.io.File; import java.util.Arrays; @@ -45,6 +46,7 @@ public class InputFileBuilderTest { LanguageDetection langDetection = mock(LanguageDetection.class); StatusDetection statusDetection = mock(StatusDetection.class); DefaultModuleFileSystem fs = mock(DefaultModuleFileSystem.class); + AnalysisMode analysisMode = mock(AnalysisMode.class); @Test public void create_input_file() throws Exception { @@ -54,29 +56,28 @@ public class InputFileBuilderTest { FileUtils.touch(srcFile); FileUtils.write(srcFile, "single line"); when(fs.baseDir()).thenReturn(basedir); - when(fs.sourceCharset()).thenReturn(Charsets.UTF_8); + when(fs.encoding()).thenReturn(Charsets.UTF_8); // lang when(langDetection.language(any(InputFile.class))).thenReturn("java"); // status - when(statusDetection.status("src/main/java/foo/Bar.java", "6c1d64c0b3555892fe7273e954f6fb5a")).thenReturn(InputFile.STATUS_ADDED); + when(statusDetection.status("src/main/java/foo/Bar.java", "6c1d64c0b3555892fe7273e954f6fb5a")) + .thenReturn(InputFile.Status.ADDED); InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(), - langDetection, statusDetection, fs); - DefaultInputFile inputFile = builder.create(srcFile, InputFile.TYPE_MAIN); + langDetection, statusDetection, fs, analysisMode); + DefaultInputFile inputFile = builder.create(srcFile, InputFile.Type.MAIN); - assertThat(inputFile.name()).isEqualTo("Bar.java"); assertThat(inputFile.file()).isEqualTo(srcFile.getAbsoluteFile()); assertThat(inputFile.absolutePath()).isEqualTo(PathUtils.sanitize(srcFile.getAbsolutePath())); assertThat(inputFile.language()).isEqualTo("java"); - assertThat(inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY)).isEqualTo("struts:src/main/java/foo/Bar.java"); - assertThat(inputFile.path()).isEqualTo("src/main/java/foo/Bar.java"); - - assertThat(inputFile.attribute(InputFile.ATTRIBUTE_LINE_COUNT)).isEqualTo("1"); - assertThat(inputFile.attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH)).isNull(); - assertThat(inputFile.attribute(DefaultInputFile.ATTRIBUTE_SOURCEDIR_PATH)).isNull(); - assertThat(inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_DEPRECATED_KEY)).isNull(); + assertThat(inputFile.key()).isEqualTo("struts:src/main/java/foo/Bar.java"); + assertThat(inputFile.relativePath()).isEqualTo("src/main/java/foo/Bar.java"); + assertThat(inputFile.lines()).isEqualTo(1); + assertThat(inputFile.sourceDirAbsolutePath()).isNull(); + assertThat(inputFile.pathRelativeToSourceDir()).isNull(); + assertThat(inputFile.deprecatedKey()).isNull(); } @Test @@ -89,8 +90,8 @@ public class InputFileBuilderTest { when(fs.baseDir()).thenReturn(basedir); InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(), - langDetection, statusDetection, fs); - DefaultInputFile inputFile = builder.create(srcFile, InputFile.TYPE_MAIN); + langDetection, statusDetection, fs, analysisMode); + DefaultInputFile inputFile = builder.create(srcFile, InputFile.Type.MAIN); assertThat(inputFile).isNull(); } @@ -103,14 +104,14 @@ public class InputFileBuilderTest { FileUtils.touch(srcFile); FileUtils.write(srcFile, "single line"); when(fs.baseDir()).thenReturn(basedir); - when(fs.sourceCharset()).thenReturn(Charsets.UTF_8); + when(fs.encoding()).thenReturn(Charsets.UTF_8); // lang when(langDetection.language(any(InputFile.class))).thenReturn(null); InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(), - langDetection, statusDetection, fs); - DefaultInputFile inputFile = builder.create(srcFile, InputFile.TYPE_MAIN); + langDetection, statusDetection, fs, analysisMode); + DefaultInputFile inputFile = builder.create(srcFile, InputFile.Type.MAIN); assertThat(inputFile).isNull(); } @@ -123,7 +124,7 @@ public class InputFileBuilderTest { FileUtils.touch(srcFile); FileUtils.write(srcFile, "single line"); when(fs.baseDir()).thenReturn(basedir); - when(fs.sourceCharset()).thenReturn(Charsets.UTF_8); + when(fs.encoding()).thenReturn(Charsets.UTF_8); File sourceDir = new File(basedir, "src/main/java"); when(fs.sourceDirs()).thenReturn(Arrays.asList(sourceDir)); @@ -131,15 +132,16 @@ public class InputFileBuilderTest { when(langDetection.language(any(InputFile.class))).thenReturn("java"); // status - when(statusDetection.status("src/main/java/foo/Bar.java", "6c1d64c0b3555892fe7273e954f6fb5a")).thenReturn(InputFile.STATUS_ADDED); + when(statusDetection.status("src/main/java/foo/Bar.java", "6c1d64c0b3555892fe7273e954f6fb5a")) + .thenReturn(InputFile.Status.ADDED); InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(), - langDetection, statusDetection, fs); - DefaultInputFile inputFile = builder.create(srcFile, InputFile.TYPE_MAIN); + langDetection, statusDetection, fs, analysisMode); + DefaultInputFile inputFile = builder.create(srcFile, InputFile.Type.MAIN); - assertThat(inputFile.attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH)).isEqualTo("foo/Bar.java"); - assertThat(inputFile.attribute(DefaultInputFile.ATTRIBUTE_SOURCEDIR_PATH)).isEqualTo(PathUtils.sanitize(sourceDir.getAbsolutePath())); - assertThat(inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_DEPRECATED_KEY)).isEqualTo("struts:foo.Bar"); + assertThat(inputFile.pathRelativeToSourceDir()).isEqualTo("foo/Bar.java"); + assertThat(inputFile.sourceDirAbsolutePath()).isEqualTo(PathUtils.sanitize(sourceDir.getAbsolutePath())); + assertThat(inputFile.deprecatedKey()).isEqualTo("struts:foo.Bar"); } @Test @@ -150,7 +152,7 @@ public class InputFileBuilderTest { FileUtils.touch(srcFile); FileUtils.write(srcFile, "single line"); when(fs.baseDir()).thenReturn(basedir); - when(fs.sourceCharset()).thenReturn(Charsets.UTF_8); + when(fs.encoding()).thenReturn(Charsets.UTF_8); File sourceDir = new File(basedir, "src"); when(fs.sourceDirs()).thenReturn(Arrays.asList(sourceDir)); @@ -158,15 +160,16 @@ public class InputFileBuilderTest { when(langDetection.language(any(InputFile.class))).thenReturn("php"); // status - when(statusDetection.status("src/Bar.php", "6c1d64c0b3555892fe7273e954f6fb5a")).thenReturn(InputFile.STATUS_ADDED); + when(statusDetection.status("src/Bar.php", "6c1d64c0b3555892fe7273e954f6fb5a")) + .thenReturn(InputFile.Status.ADDED); InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(), - langDetection, statusDetection, fs); - DefaultInputFile inputFile = builder.create(srcFile, InputFile.TYPE_MAIN); + langDetection, statusDetection, fs, analysisMode); + DefaultInputFile inputFile = builder.create(srcFile, InputFile.Type.MAIN); - assertThat(inputFile.attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH)).isEqualTo("foo/Bar.php"); - assertThat(inputFile.attribute(DefaultInputFile.ATTRIBUTE_SOURCEDIR_PATH)).isEqualTo(PathUtils.sanitize(sourceDir.getAbsolutePath())); - assertThat(inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_DEPRECATED_KEY)).isEqualTo("struts:foo/Bar.php"); + assertThat(inputFile.pathRelativeToSourceDir()).isEqualTo("foo/Bar.php"); + assertThat(inputFile.sourceDirAbsolutePath()).isEqualTo(PathUtils.sanitize(sourceDir.getAbsolutePath())); + assertThat(inputFile.deprecatedKey()).isEqualTo("struts:foo/Bar.php"); } } 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 index a829e350f3c..3cfbb4bd64d 100644 --- 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 @@ -19,18 +19,16 @@ */ package org.sonar.batch.scan.filesystem; -import org.sonar.api.scan.filesystem.InputFile; - -import com.google.common.base.Charsets; -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.internal.DefaultInputFile; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.batch.index.Caches; import org.sonar.batch.index.CachesTest; + import static org.fest.assertions.Assertions.assertThat; public class InputFileCacheTest { @@ -54,17 +52,15 @@ public class InputFileCacheTest { @Test public void should_add_input_file() throws Exception { InputFileCache cache = new InputFileCache(caches); - cache.put("struts", DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "src/main/java/Foo.java", Maps.newHashMap())); - cache.put("struts-core", DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "src/main/java/Foo.java", Maps.newHashMap())); + cache.put("struts", new DefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile("Foo.java"))); + cache.put("struts-core", new DefaultInputFile("src/main/java/Bar.java").setFile(temp.newFile("Bar.java"))); assertThat(cache.byModule("struts")).hasSize(1); assertThat(cache.byModule("struts-core")).hasSize(1); assertThat(cache.all()).hasSize(2); for (InputFile inputFile : cache.all()) { - assertThat(inputFile.path()).startsWith("src/main/java"); + assertThat(inputFile.relativePath()).startsWith("src/main/java/"); } - assertThat(cache.fileRelativePaths("struts-core")).containsOnly("src/main/java/Foo.java"); - cache.removeModule("struts"); assertThat(cache.byModule("struts")).hasSize(0); assertThat(cache.byModule("struts-core")).hasSize(1); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java index 4f455152512..308604508c7 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java @@ -19,17 +19,16 @@ */ package org.sonar.batch.scan.filesystem; -import com.google.common.base.Charsets; 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.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.config.Settings; import org.sonar.api.resources.Language; import org.sonar.api.resources.Languages; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.internal.InputFileBuilder; import org.sonar.api.utils.MessageException; import java.io.File; @@ -182,7 +181,7 @@ public class LanguageDetectionTest { private InputFile newInputFile(String path) throws IOException { File basedir = temp.newFolder(); - return new InputFileBuilder(new File(basedir, path), Charsets.UTF_8, path).build(); + return new DefaultInputFile(path).setFile(new File(basedir, path)); } static class MockLanguage implements Language { diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java index 79404404f8f..3c99e842b89 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java @@ -21,20 +21,20 @@ package org.sonar.batch.scan.filesystem; import com.google.common.collect.ImmutableMap; import org.junit.Test; -import org.sonar.api.scan.filesystem.InputFile; +import org.sonar.api.batch.fs.InputFile; import static org.fest.assertions.Assertions.assertThat; public class StatusDetectionTest { @Test public void detect_status() throws Exception { - StatusDetection statusDetection = new StatusDetection(ImmutableMap.of( + StatusDetection statusDetection = new StatusDetection(ImmutableMap.of( "src/Foo.java", "ABCDE", "src/Bar.java", "FGHIJ" )); - assertThat(statusDetection.status("src/Foo.java", "ABCDE")).isEqualTo(InputFile.STATUS_SAME); - assertThat(statusDetection.status("src/Foo.java", "XXXXX")).isEqualTo(InputFile.STATUS_CHANGED); - assertThat(statusDetection.status("src/Other.java", "QWERT")).isEqualTo(InputFile.STATUS_ADDED); + assertThat(statusDetection.status("src/Foo.java", "ABCDE")).isEqualTo(InputFile.Status.SAME); + assertThat(statusDetection.status("src/Foo.java", "XXXXX")).isEqualTo(InputFile.Status.CHANGED); + assertThat(statusDetection.status("src/Other.java", "QWERT")).isEqualTo(InputFile.Status.ADDED); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java index e4b8a348509..8ea696629fc 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java @@ -25,6 +25,9 @@ import org.junit.Before; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.skyscreamer.jsonassert.JSONAssert; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.config.Settings; import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.DefaultIssue; @@ -34,9 +37,6 @@ import org.sonar.api.resources.Resource; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.ModuleFileSystem; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; import org.sonar.api.user.User; import org.sonar.api.user.UserFinder; import org.sonar.batch.bootstrap.AnalysisMode; @@ -68,36 +68,33 @@ public class JsonReportTest { JsonReport jsonReport; Resource resource = mock(Resource.class); - ModuleFileSystem fileSystem = mock(ModuleFileSystem.class); + DefaultFileSystem fs = new DefaultFileSystem(); Server server = mock(Server.class); RuleFinder ruleFinder = mock(RuleFinder.class); - Settings settings; + Settings settings = new Settings(); IssueCache issueCache = mock(IssueCache.class); private AnalysisMode mode; private UserFinder userFinder; @Before - public void setUp() { + public void before() { SIMPLE_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+02:00")); when(resource.getEffectiveKey()).thenReturn("Action.java"); when(server.getVersion()).thenReturn("3.6"); - - settings = new Settings(); mode = mock(AnalysisMode.class); when(mode.isPreview()).thenReturn(true); userFinder = mock(UserFinder.class); - InputFile inputFile = mock(InputFile.class); - when(inputFile.path()).thenReturn("src/main/java/org/apache/struts/Action.java"); - when(inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY)).thenReturn("struts:src/main/java/org/apache/struts/Action.java"); - when(inputFile.attribute(InputFile.ATTRIBUTE_STATUS)).thenReturn(InputFile.STATUS_CHANGED); + DefaultInputFile inputFile = new DefaultInputFile("src/main/java/org/apache/struts/Action.java"); + inputFile.setKey("struts:src/main/java/org/apache/struts/Action.java"); + inputFile.setStatus(InputFile.Status.CHANGED); InputFileCache fileCache = mock(InputFileCache.class); - when(fileCache.all()).thenReturn(Arrays.asList(inputFile)); + when(fileCache.all()).thenReturn(Arrays.asList(inputFile)); Project rootModule = new Project("struts"); Project moduleA = new Project("struts-core"); moduleA.setParent(rootModule).setPath("core"); Project moduleB = new Project("struts-ui"); moduleB.setParent(rootModule).setPath("ui"); - jsonReport = new JsonReport(settings, fileSystem, server, ruleFinder, issueCache, mock(EventBus.class), + jsonReport = new JsonReport(settings, fs, server, ruleFinder, issueCache, mock(EventBus.class), mode, userFinder, rootModule, fileCache); } @@ -166,18 +163,18 @@ public class JsonReportTest { @Test public void should_export_issues_to_file() throws IOException { - File sonarDirectory = temporaryFolder.newFolder("sonar"); + File workDir = temporaryFolder.newFolder("sonar"); + fs.setWorkDir(workDir); Rule rule = Rule.create("squid", "AvoidCycles").setName("Avoid Cycles"); when(ruleFinder.findByKey(RuleKey.of("squid", "AvoidCycles"))).thenReturn(rule); when(jsonReport.getIssues()).thenReturn(Collections.emptyList()); settings.setProperty("sonar.report.export.path", "output.json"); - when(fileSystem.workingDir()).thenReturn(sonarDirectory); jsonReport.execute(); - assertThat(new File(sonarDirectory, "output.json")).exists(); + assertThat(new File(workDir, "output.json")).exists(); } } diff --git a/sonar-batch/test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/CP1252Encoding.java b/sonar-batch/test-resources/org/sonar/batch/phases/ComponentIndexerTest/encoding/CP1252Encoding.java similarity index 100% rename from sonar-batch/test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/CP1252Encoding.java rename to sonar-batch/test-resources/org/sonar/batch/phases/ComponentIndexerTest/encoding/CP1252Encoding.java diff --git a/sonar-batch/test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/MacRomanEncoding.java b/sonar-batch/test-resources/org/sonar/batch/phases/ComponentIndexerTest/encoding/MacRomanEncoding.java similarity index 100% rename from sonar-batch/test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/MacRomanEncoding.java rename to sonar-batch/test-resources/org/sonar/batch/phases/ComponentIndexerTest/encoding/MacRomanEncoding.java diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/ModuleLanguages.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/ModuleLanguages.java index 730a62e14f1..e91b9d76739 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/ModuleLanguages.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/ModuleLanguages.java @@ -33,6 +33,4 @@ public interface ModuleLanguages extends BatchComponent { Collection keys(); - Collection languages(); - } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java index 42cb48fac6d..da1dcccfe49 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java @@ -19,6 +19,7 @@ */ package org.sonar.api.batch; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.design.Dependency; import org.sonar.api.measures.Measure; import org.sonar.api.measures.MeasuresFilter; @@ -26,7 +27,6 @@ import org.sonar.api.measures.Metric; import org.sonar.api.resources.ProjectLink; import org.sonar.api.resources.Resource; import org.sonar.api.rules.Violation; -import org.sonar.api.scan.filesystem.InputFile; import java.util.Collection; import java.util.Date; @@ -42,7 +42,6 @@ public interface SensorContext { * Indexes a resource as a direct child of project. This method does nothing and returns true if the resource already indexed. * * @return false if the resource is excluded - * @since 2.6 * @since 4.2 Resource indexing is done by the platform for all physical resources. This method should only be used to index methods/paragraphs (see SONAR-5006) */ boolean index(Resource resource); @@ -53,19 +52,20 @@ public interface SensorContext { * @param resource the resource to index. Not nullable * @param parentReference a reference to the parent. If null, the the resource is indexed as a direct child of project. * @return false if the parent is not indexed or if the resource is excluded - * @since 2.6 * @since 4.2 Resource indexing is done by the platform for all physical resources. This method should only be used to index methods/paragraphs (see SONAR-5006) */ boolean index(Resource resource, Resource parentReference); /** * Returns true if the referenced resource is indexed and excluded. + * * @since 2.6 */ boolean isExcluded(Resource reference); /** * Returns true if the referenced resource is indexed. + * * @since 2.6 */ boolean isIndexed(Resource reference, boolean acceptExcluded); @@ -142,13 +142,6 @@ public interface SensorContext { */ Measure saveMeasure(Resource resource, Metric metric, Double value); - /** - * Experimental. - * Add or update a measure on an InputFile. - * @since 4.2 - */ - Measure saveMeasure(InputFile inputFile, Metric metric, Double value); - /** * Add or update a measure. *

@@ -158,13 +151,6 @@ public interface SensorContext { */ Measure saveMeasure(Resource resource, Measure measure); - /** - * Experimental. - * Add or update a measure on an InputFile. - * @since 4.2 - */ - Measure saveMeasure(InputFile inputFile, Measure measure); - // ----------- RULE VIOLATIONS -------------- /** @@ -203,8 +189,7 @@ public interface SensorContext { /** * Save the source code of a file. The file must be have been indexed before. * - * @throws org.sonar.api.resources.DuplicatedSourceException - * if the source has already been set on this resource + * @throws org.sonar.api.resources.DuplicatedSourceException if the source has already been set on this resource * @since 1.10. Returns a boolean since 2.6. * @deprecated since 4.2 Source import is done by the platform */ @@ -249,4 +234,13 @@ public interface SensorContext { */ void deleteEvent(Event event); + /** + * @since 4.2 + */ + Measure saveMeasure(InputFile inputFile, Metric metric, Double value); + + /** + * @since 4.2 + */ + Measure saveMeasure(InputFile inputFile, Measure measure); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AbsolutePathPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AbsolutePathPredicate.java new file mode 100644 index 00000000000..a659ad27f10 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AbsolutePathPredicate.java @@ -0,0 +1,39 @@ +/* + * 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.batch.fs; + +import org.apache.commons.io.FilenameUtils; + +/** + * @since 4.2 + */ +class AbsolutePathPredicate implements FilePredicate { + + private final String path; + + AbsolutePathPredicate(String path) { + this.path = FilenameUtils.normalize(path, true); + } + + @Override + public boolean apply(InputFile f) { + return path.equals(f.absolutePath()); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/InputFiles.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AndPredicate.java similarity index 65% rename from sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/InputFiles.java rename to sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AndPredicate.java index 923cd32b133..f1221c1fe2c 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/InputFiles.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AndPredicate.java @@ -17,28 +17,29 @@ * 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.internal; +package org.sonar.api.batch.fs; -import org.sonar.api.scan.filesystem.InputFile; - -import com.google.common.collect.Lists; - -import java.io.File; -import java.util.List; +import javax.annotation.Nullable; /** - * @since 4.0 + * @since 4.2 */ -public class InputFiles { - InputFiles() { - // static methods only +class AndPredicate implements FilePredicate { + + private final Iterable predicates; + + AndPredicate(@Nullable Iterable predicates) { + this.predicates = predicates; } - public static List toFiles(Iterable inputFiles) { - List files = Lists.newArrayList(); - for (InputFile inputFile : inputFiles) { - files.add(inputFile.file()); + @Override + public boolean apply(InputFile f) { + for (FilePredicate predicate : predicates) { + if (!predicate.apply(f)) { + return false; + } } - return files; + return true; } + } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java new file mode 100644 index 00000000000..5cc7b7ae9e1 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java @@ -0,0 +1,29 @@ +/* + * 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.batch.fs; + +/** + * Determines if a file must be kept in search results. See {@link org.sonar.api.batch.fs.FileSystem} + * and {@link org.sonar.api.batch.fs.FilePredicates}. + * @since 4.2 + */ +public interface FilePredicate { + boolean apply(InputFile inputFile); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java new file mode 100644 index 00000000000..877666c733b --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java @@ -0,0 +1,152 @@ +/* + * 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.batch.fs; + +import com.google.common.collect.Lists; +import org.sonar.api.batch.fs.internal.PathPattern; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Factory of {@link org.sonar.api.batch.fs.FilePredicate} + * + * @since 4.2 + */ +public class FilePredicates { + private static final FilePredicate ALWAYS_TRUE = new AlwaysTruePredicate(); + + private FilePredicates() { + // only static stuff + } + + /** + * Returns a predicate that always evaluates to true + */ + public static FilePredicate all() { + return ALWAYS_TRUE; + } + + /** + * Warning - not efficient because absolute path is not indexed yet. + */ + public static FilePredicate hasAbsolutePath(String s) { + return new AbsolutePathPredicate(s); + } + + /** + * TODO document that non-normalized path and Windows-style path are supported + */ + public static FilePredicate hasRelativePath(String s) { + return new RelativePathPredicate(s); + } + + public static FilePredicate matchesPathPattern(String inclusionPattern) { + return new PathPatternPredicate(PathPattern.create(inclusionPattern)); + } + + public static FilePredicate matchesPathPatterns(String[] inclusionPatterns) { + FilePredicate[] predicates = new FilePredicate[inclusionPatterns.length]; + for (int i = 0; i < inclusionPatterns.length; i++) { + predicates[i] = new PathPatternPredicate(PathPattern.create(inclusionPatterns[i])); + } + return and(predicates); + } + + public static FilePredicate doesNotMatchPathPattern(String exclusionPattern) { + return not(matchesPathPattern(exclusionPattern)); + } + + public static FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns) { + return not(matchesPathPatterns(exclusionPatterns)); + } + + public static FilePredicate hasPath(String s) { + File file = new File(s); + if (file.isAbsolute()) { + return hasAbsolutePath(s); + } + return hasRelativePath(s); + } + + public static FilePredicate is(File ioFile) { + if (ioFile.isAbsolute()) { + return hasAbsolutePath(ioFile.getAbsolutePath()); + } + return hasRelativePath(ioFile.getPath()); + } + + public static FilePredicate hasLanguage(String language) { + return new LanguagePredicate(language); + } + + public static FilePredicate hasLanguages(Collection languages) { + List list = Lists.newArrayList(); + for (String language : languages) { + list.add(hasLanguage(language)); + } + return or(list); + } + + public static FilePredicate hasStatus(InputFile.Status status) { + return new StatusPredicate(status); + } + + public static FilePredicate hasType(InputFile.Type type) { + return new TypePredicate(type); + } + + public static FilePredicate not(FilePredicate p) { + return new NotPredicate(p); + } + + public static FilePredicate or(Iterable or) { + return new OrPredicate(or); + } + + public static FilePredicate or(FilePredicate... or) { + return new OrPredicate(Arrays.asList(or)); + } + + public static FilePredicate or(FilePredicate first, FilePredicate second) { + return new OrPredicate(Arrays.asList(first, second)); + } + + public static FilePredicate and(Iterable and) { + return new AndPredicate(and); + } + + public static FilePredicate and(FilePredicate... and) { + return new AndPredicate(Arrays.asList(and)); + } + + public static FilePredicate and(FilePredicate first, FilePredicate second) { + return new AndPredicate(Arrays.asList(first, second)); + } + + private static class AlwaysTruePredicate implements FilePredicate { + @Override + public boolean apply(InputFile inputFile) { + return true; + } + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java new file mode 100644 index 00000000000..7d285af934f --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java @@ -0,0 +1,92 @@ +/* + * 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.batch.fs; + +import org.sonar.api.BatchComponent; + +import javax.annotation.CheckForNull; +import java.io.File; +import java.nio.charset.Charset; +import java.util.Set; + +/** + *

The unit tests needing an instance of FileSystem can use the implementation + * {@link org.sonar.api.batch.fs.internal.DefaultFileSystem} and the related {@link org.sonar.api.scan.filesystem.internal.DefaultInputFile}:

+ *
+ *   FileSystem fs = new DefaultFileSystem();
+ *   fs.add(new DefaultInputFile("src/foo/bar.php"));
+ * 
+ * + * @since 4.2 + */ +public interface FileSystem extends BatchComponent { + + /** + * Absolute base directory of module + */ + File baseDir(); + + /** + * Default encoding of input files. If it's not defined, then + * the platform default encoding is returned + */ + Charset encoding(); + + /** + * Absolute work directory. It can be used to + * store third-party analysis reports. + *

+ * The work directory can be located outside {@link #baseDir()}. + */ + File workDir(); + + /** + * @see org.sonar.api.batch.fs.FilePredicates + */ + @CheckForNull + InputFile inputFile(FilePredicate predicate); + + /** + * Input files matching the given attributes. Return all the files if the parameter + * attributes is empty. + * @see org.sonar.api.batch.fs.FilePredicates + */ + Iterable inputFiles(FilePredicate predicate); + + /** + * Returns true if at least one {@link org.sonar.api.batch.fs.InputFile} matches + * the given attributes. This method can be faster than checking if {@link #inputFiles(org.sonar.api.batch.fs.FilePredicate...)} + * has elements. If the parameter attributes is empty, then returns true + * if at least one input file exists. + * @see org.sonar.api.batch.fs.FilePredicates + */ + boolean hasFiles(FilePredicate predicate); + + /** + * Files matching the given attributes. + * @see org.sonar.api.batch.fs.FilePredicates + */ + Iterable files(FilePredicate predicate); + + /** + * Languages detected in all the files, whatever their type (main code or test) + */ + Set languages(); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java new file mode 100644 index 00000000000..fb37090325d --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java @@ -0,0 +1,87 @@ +/* + * 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.batch.fs; + +import java.io.File; +import java.io.Serializable; + +/** + * This layer over {@link java.io.File} adds information useful for code analyzers. + * + * @since 4.2 + */ +public interface InputFile extends Serializable { + + enum Type { + MAIN, TEST + } + + /** + * Status regarding previous analysis + */ + enum Status { + SAME, CHANGED, ADDED + } + + /** + * Path relative to module base directory. Path is unique and identifies file + * within given {@link FileSystem}. + * File separator is the forward slash ('/'), even on Microsoft Windows. + *

+ * Returns src/main/java/com/Foo.java if module base dir is + * /absolute/path/to/module and if file is + * /absolute/path/to/module/src/main/java/com/Foo.java. + *

+ * Relative path is not null and is normalized ('foo/../foo' is replaced by 'foo'). + */ + String relativePath(); + + /** + * Normalized absolute path. File separator is forward slash ('/'), even on Microsoft Windows. + *

+ * This is not canonical path. Symbolic links are not resolved. For example if /project/src links + * to /tmp/src and basedir is /project, then this method returns /project/src/index.php. Use + * {@code file().getCanonicalPath()} to resolve symbolic link. + */ + String absolutePath(); + + /** + * The underlying absolute {@link java.io.File} + */ + File file(); + + /** + * Language, for example "java" or "php". It's automatically guessed when it is not + * set by project configuration. + */ + String language(); + + /** + * Does it contain main or test code ? + */ + Type type(); + + /** + * Status regarding previous analysis + */ + Status status(); + + int lines(); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFileFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java similarity index 82% rename from sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFileFilter.java rename to sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java index 7c58519f9e9..d9bdac27857 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFileFilter.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java @@ -17,18 +17,17 @@ * 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; +package org.sonar.api.batch.fs; import org.sonar.api.BatchExtension; /** - * Implement this extension to limit the set of files to be analyzed. Global file inclusion/exclusion patterns - * are already applied. - * + * Extension point to complete the list of files to ignore during inspection * @since 4.2 */ public interface InputFileFilter extends BatchExtension { - boolean accept(InputFile inputFile); + // TODO requires a context (FileSystem) ? + boolean accept(InputFile f); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/LanguagePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/LanguagePredicate.java new file mode 100644 index 00000000000..9ab1578b33a --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/LanguagePredicate.java @@ -0,0 +1,36 @@ +/* + * 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.batch.fs; + +/** + * @since 4.2 + */ +class LanguagePredicate implements FilePredicate { + private final String language; + + LanguagePredicate(String language) { + this.language = language; + } + + @Override + public boolean apply(InputFile f) { + return language.equals(f.language()); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/NotPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/NotPredicate.java new file mode 100644 index 00000000000..5a83803bab0 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/NotPredicate.java @@ -0,0 +1,38 @@ +/* + * 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.batch.fs; + +/** + * @since 4.2 + */ +class NotPredicate implements FilePredicate { + + private final FilePredicate predicate; + + NotPredicate(FilePredicate predicate) { + this.predicate = predicate; + } + + @Override + public boolean apply(InputFile f) { + return !predicate.apply(f); + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/OrPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/OrPredicate.java new file mode 100644 index 00000000000..af364527a2a --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/OrPredicate.java @@ -0,0 +1,45 @@ +/* + * 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.batch.fs; + +import javax.annotation.Nullable; + +/** + * @since 4.2 + */ +class OrPredicate implements FilePredicate { + + private final Iterable predicates; + + OrPredicate(@Nullable Iterable predicates) { + this.predicates = predicates; + } + + @Override + public boolean apply(InputFile f) { + for (FilePredicate predicate : predicates) { + if (predicate.apply(f)) { + return true; + } + } + return false; + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/PathPatternPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/PathPatternPredicate.java new file mode 100644 index 00000000000..2a342026352 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/PathPatternPredicate.java @@ -0,0 +1,40 @@ +/* + * 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.batch.fs; + +import org.sonar.api.batch.fs.internal.PathPattern; + +/** + * @since 4.2 + */ +class PathPatternPredicate implements FilePredicate { + + private final PathPattern pattern; + + PathPatternPredicate(PathPattern pattern) { + this.pattern = pattern; + } + + @Override + public boolean apply(InputFile f) { + return pattern.match(f); + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AttributeFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/RelativePathPredicate.java similarity index 56% rename from sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AttributeFilter.java rename to sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/RelativePathPredicate.java index 1e5e37cae09..98453eb4a58 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AttributeFilter.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/RelativePathPredicate.java @@ -17,37 +17,35 @@ * 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.batch.fs; -import org.sonar.api.scan.filesystem.InputFileFilter; +import org.apache.commons.io.FilenameUtils; +import org.sonar.api.batch.fs.internal.RelativePathIndex; -import org.sonar.api.scan.filesystem.InputFile; -import com.google.common.annotations.VisibleForTesting; - -import java.util.Collection; +/** + * @since 4.2 + */ +class RelativePathPredicate implements FilePredicate, UniqueIndexPredicate { -class AttributeFilter implements InputFileFilter { - private final String key; - private final Collection values; + private final String path; - AttributeFilter(String key, Collection values) { - this.key = key; - this.values = values; + RelativePathPredicate(String path) { + this.path = FilenameUtils.normalize(path, true); } @Override - public boolean accept(InputFile inputFile) { - String value = inputFile.attribute(key); - return values.contains(value); + public boolean apply(InputFile f) { + return path.equals(f.relativePath()); } - @VisibleForTesting - String key() { - return key; + @Override + public Object value() { + return path; } - @VisibleForTesting - Collection values() { - return values; + @Override + public String indexId() { + return RelativePathIndex.ID; } + } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/StatusPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/StatusPredicate.java new file mode 100644 index 00000000000..c80b4830f7b --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/StatusPredicate.java @@ -0,0 +1,38 @@ +/* + * 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.batch.fs; + +/** + * @since 4.2 + */ +class StatusPredicate implements FilePredicate { + + private final InputFile.Status status; + + StatusPredicate(InputFile.Status status) { + this.status = status; + } + + @Override + public boolean apply(InputFile f) { + return status == f.status(); + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TypePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TypePredicate.java new file mode 100644 index 00000000000..84be0a29e15 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TypePredicate.java @@ -0,0 +1,39 @@ +/* + * 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.batch.fs; + +/** + * @since 4.2 + */ +class TypePredicate implements FilePredicate { + + private final InputFile.Type type; + + TypePredicate(InputFile.Type type) { + this.type = type; + } + + @Override + public boolean apply(InputFile f) { + return type == f.type(); + } + +} + diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/InputFileBuilderTest.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/UniqueIndexPredicate.java similarity index 78% rename from sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/InputFileBuilderTest.java rename to sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/UniqueIndexPredicate.java index 6e70f14fa1d..693722d101f 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/InputFileBuilderTest.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/UniqueIndexPredicate.java @@ -17,14 +17,15 @@ * 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.internal; +package org.sonar.api.batch.fs; -import org.junit.Test; +/** + * @since 4.2 + */ +public interface UniqueIndexPredicate { + + String indexId(); + + Object value(); -public class InputFileBuilderTest { - @Test - public void just_for_coverage() throws Exception { - InputFileBuilder._FOR_UNIT_TESTING_ONLY_(); - // do not fail - } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java new file mode 100644 index 00000000000..4754c1aebb1 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java @@ -0,0 +1,225 @@ +/* + * 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.batch.fs.internal; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.apache.commons.io.Charsets; +import org.sonar.api.batch.fs.FilePredicate; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.UniqueIndexPredicate; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import java.io.File; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * @since 4.2 + */ +public class DefaultFileSystem implements FileSystem { + + private final Cache cache; + private final Set languages = Sets.newTreeSet(); + private File baseDir, workDir; + private Charset encoding = Charsets.UTF_8; + private boolean isDefaultJvmEncoding = false; + + /** + * Only for testing + */ + public DefaultFileSystem() { + this.cache = new MapCache(); + } + + protected DefaultFileSystem(Cache cache) { + this.cache = cache; + } + + public DefaultFileSystem setBaseDir(File d) { + Preconditions.checkNotNull(d, "Base directory can't be null"); + this.baseDir = d.getAbsoluteFile(); + return this; + } + + /** + * Marked as nullable only for the tests that do not call {@link #setBaseDir(java.io.File)} + */ + @Override + @CheckForNull + public File baseDir() { + return baseDir; + } + + public DefaultFileSystem setEncoding(Charset e) { + this.encoding = e; + return this; + } + + @Override + public Charset encoding() { + return encoding; + } + + public boolean isDefaultJvmEncoding() { + return isDefaultJvmEncoding; + } + + public void setIsDefaultJvmEncoding(boolean b) { + this.isDefaultJvmEncoding = b; + } + + public DefaultFileSystem setWorkDir(File d) { + this.workDir = d.getAbsoluteFile(); + return this; + } + + /** + * Marked as nullable only for the tests that do not call {@link #setWorkDir(java.io.File)} + */ + @Override + @CheckForNull + public File workDir() { + return workDir; + } + + @Override + public InputFile inputFile(FilePredicate predicate) { + if (predicate instanceof UniqueIndexPredicate) { + return cache.inputFile((UniqueIndexPredicate) predicate); + } + try { + Iterable files = inputFiles(predicate); + return Iterables.getOnlyElement(files); + } catch (NoSuchElementException e) { + return null; + } + } + + @Override + public Iterable inputFiles(FilePredicate predicate) { + return Iterables.filter(cache.inputFiles(), new GuavaPredicate(predicate)); + } + + @Override + public boolean hasFiles(FilePredicate predicate) { + return Iterables.indexOf(cache.inputFiles(), new GuavaPredicate(predicate)) >= 0; + } + + @Override + public Iterable files(FilePredicate predicate) { + return Iterables.transform(inputFiles(predicate), new Function() { + @Override + public File apply(@Nullable InputFile input) { + return input == null ? null : input.file(); + } + }); + } + + public void add(InputFile inputFile) { + cache.add(inputFile); + if (inputFile.language() != null) { + languages.add(inputFile.language()); + } + } + + @Override + public Set languages() { + return languages; + } + + public static abstract class Cache { + protected abstract Iterable inputFiles(); + + @CheckForNull + protected abstract InputFile inputFile(UniqueIndexPredicate predicate); + + protected abstract void doAdd(InputFile inputFile); + + protected abstract void doIndex(String indexId, Object value, InputFile inputFile); + + final void add(InputFile inputFile) { + doAdd(inputFile); + for (FileIndex index : FileIndex.ALL) { + doIndex(index.id(), index.valueOf(inputFile), inputFile); + } + } + } + + /** + * Used only for testing + */ + private static class MapCache extends Cache { + private final List files = Lists.newArrayList(); + private final Map> fileMap = Maps.newHashMap(); + + @Override + public Iterable inputFiles() { + return Lists.newArrayList(files); + } + + @Override + public InputFile inputFile(UniqueIndexPredicate predicate) { + Map byAttr = fileMap.get(predicate.indexId()); + if (byAttr != null) { + return byAttr.get(predicate.value()); + } + return null; + } + + @Override + protected void doAdd(InputFile inputFile) { + files.add(inputFile); + } + + @Override + protected void doIndex(String indexId, Object value, InputFile inputFile) { + Map attrValues = fileMap.get(indexId); + if (attrValues == null) { + attrValues = Maps.newHashMap(); + fileMap.put(indexId, attrValues); + } + attrValues.put(value, inputFile); + } + } + + private static class GuavaPredicate implements Predicate { + private final FilePredicate predicate; + + private GuavaPredicate(FilePredicate predicate) { + this.predicate = predicate; + } + + @Override + public boolean apply(@Nullable InputFile input) { + return input != null && predicate.apply(input); + } + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java new file mode 100644 index 00000000000..fa3f49d0c0a --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java @@ -0,0 +1,252 @@ +/* + * 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.batch.fs.internal; + +import org.apache.commons.io.FilenameUtils; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.utils.PathUtils; + +import javax.annotation.CheckForNull; +import java.io.*; + +/** + * @since 4.2 + */ +public class DefaultInputFile implements InputFile, org.sonar.api.resources.InputFile, Serializable { + + private final String relativePath; + private String absolutePath; + private String language; + private Type type = Type.MAIN; + private Status status; + private String hash; + private int lines; + private String key; + private String deprecatedKey; + private String sourceDirAbsolutePath; + private String pathRelativeToSourceDir; + private String basedir; + + public DefaultInputFile(String relativePath) { + this.relativePath = FilenameUtils.normalize(relativePath, true); + } + + @Override + public String relativePath() { + return relativePath; + } + + /** + * Marked as nullable just for the unit tests that do not call {@link #setFile(java.io.File)} + * previously. + */ + @Override + @CheckForNull + public String absolutePath() { + return absolutePath; + } + + @Override + public File file() { + return new File(absolutePath); + } + + /** + * Marked as nullable just for the unit tests that do not call {@link #setLanguage(String)} + * previously. + */ + @CheckForNull + @Override + public String language() { + return language; + } + + @Override + public Type type() { + return type; + } + + /** + * Marked as nullable just for the unit tests that do not previously call + * {@link #setStatus(org.sonar.api.batch.fs.InputFile.Status)} + */ + @CheckForNull + @Override + public Status status() { + return status; + } + + /** + * Marked as nullable just for the unit tests that do not previously call + * {@link #setHash(String)} + */ + @CheckForNull + public String hash() { + return hash; + } + + @Override + public int lines() { + return lines; + } + + /** + * Marked as nullable just for the unit tests that do not previously call + * {@link #setKey(String)}. + */ + @CheckForNull + public String key() { + return key; + } + + public DefaultInputFile setAbsolutePath(String s) { + this.absolutePath = FilenameUtils.normalize(s, true); + return this; + } + + public DefaultInputFile setLanguage(String language) { + this.language = language; + return this; + } + + public DefaultInputFile setFile(File file) { + setAbsolutePath(file.getAbsolutePath()); + return this; + } + + public DefaultInputFile setType(Type type) { + this.type = type; + return this; + } + + public DefaultInputFile setStatus(Status status) { + this.status = status; + return this; + } + + public DefaultInputFile setHash(String hash) { + this.hash = hash; + return this; + } + + public DefaultInputFile setLines(int lines) { + this.lines = lines; + return this; + } + + public DefaultInputFile setKey(String s) { + this.key = s; + return this; + } + + /** + * Key used before version 4.2. It's different than {@link #key} on Java files. + */ + public String deprecatedKey() { + return deprecatedKey; + } + + public DefaultInputFile setDeprecatedKey(String s) { + this.deprecatedKey = s; + return this; + } + + /** + * Used only for backward-compatibility. Meaningless since version 4.2. + */ + public String sourceDirAbsolutePath() { + return sourceDirAbsolutePath; + } + + public DefaultInputFile setSourceDirAbsolutePath(String s) { + this.sourceDirAbsolutePath = FilenameUtils.normalize(s, true); + return this; + } + + /** + * Used only for backward-compatibility. Meaningless since version 4.2. + */ + + public String pathRelativeToSourceDir() { + return pathRelativeToSourceDir; + } + + public DefaultInputFile setPathRelativeToSourceDir(String s) { + this.pathRelativeToSourceDir = FilenameUtils.normalize(s, true); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultInputFile that = (DefaultInputFile) o; + return relativePath.equals(that.relativePath); + } + + @Override + public int hashCode() { + return relativePath.hashCode(); + } + + /** + * @deprecated in 4.2. Use {@link org.sonar.api.batch.fs.FileSystem#baseDir()} + */ + @Deprecated + @Override + public File getFileBaseDir() { + return new File(basedir); + } + + public void setBasedir(File basedir) { + this.basedir = PathUtils.sanitize(basedir.getAbsolutePath()); + } + + /** + * @deprecated in 4.2. Use {@link #file()} + */ + @Deprecated + @Override + public File getFile() { + return file(); + } + + /** + * @deprecated in 4.2. Use {@link #relativePath()} + */ + @Deprecated + @Override + public String getRelativePath() { + return relativePath(); + } + + @Override + public InputStream getInputStream() throws FileNotFoundException { + return new BufferedInputStream(new FileInputStream(file())); + } +} + + + diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileIndex.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileIndex.java new file mode 100644 index 00000000000..a6a6d45e470 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileIndex.java @@ -0,0 +1,39 @@ +/* + * 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.batch.fs.internal; + +import com.google.common.collect.ImmutableList; +import org.sonar.api.batch.fs.InputFile; + +import javax.annotation.CheckForNull; +import java.util.List; + +// Accepted to support both InputFile and InputDir as long as indexes are on the same attributes +public interface FileIndex { + + // Currently only a single index is supported + List ALL = ImmutableList.of(new RelativePathIndex()); + + @CheckForNull + Object valueOf(InputFile f); + + String id(); + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/PathPattern.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java similarity index 66% rename from sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/PathPattern.java rename to sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java index 9c9d00afaf7..186226fb47b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/PathPattern.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java @@ -17,22 +17,17 @@ * 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.batch.fs.internal; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.resources.Resource; -import org.sonar.api.scan.filesystem.InputFile; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.utils.PathUtils; import org.sonar.api.utils.WildcardPattern; import java.io.File; -abstract class PathPattern { - - private static final Logger LOG = LoggerFactory.getLogger(PathPattern.class); +public abstract class PathPattern { final WildcardPattern pattern; @@ -40,26 +35,21 @@ abstract class PathPattern { this.pattern = WildcardPattern.create(pattern); } - abstract boolean match(Resource resource); - - abstract boolean match(InputFile inputFile); - - abstract boolean match(File ioFile, String relativePathFromBasedir); + public abstract boolean match(InputFile inputFile); - abstract boolean match(InputFile inputFile, boolean caseSensitiveFileExtension); + public abstract boolean match(File ioFile, String relativePathFromBasedir); - abstract boolean supportResource(); + public abstract boolean match(InputFile inputFile, boolean caseSensitiveFileExtension); - static PathPattern create(String s) { + public static PathPattern create(String s) { String trimmed = StringUtils.trim(s); if (StringUtils.startsWithIgnoreCase(trimmed, "file:")) { - LOG.warn("Absolute path patterns are deprecated. Please replace {} by a path pattern relative to the basedir of the module.", trimmed); return new AbsolutePathPattern(StringUtils.substring(trimmed, "file:".length())); } return new RelativePathPattern(trimmed); } - static PathPattern[] create(String[] s) { + public static PathPattern[] create(String[] s) { PathPattern[] result = new PathPattern[s.length]; for (int i = 0; i < s.length; i++) { result[i] = create(s[i]); @@ -67,28 +57,24 @@ abstract class PathPattern { return result; } - /** - * @deprecated since 4.2 - */ - @Deprecated private static class AbsolutePathPattern extends PathPattern { private AbsolutePathPattern(String pattern) { super(pattern); } @Override - boolean match(File ioFile, String relativePathFromBasedir) { - String path = PathUtils.canonicalPath(ioFile); + public boolean match(File ioFile, String relativePathFromBasedir) { + String path = PathUtils.sanitize(ioFile.getAbsolutePath()); return pattern.match(path); } @Override - boolean match(InputFile inputFile) { + public boolean match(InputFile inputFile) { return match(inputFile, true); } @Override - boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) { + public boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) { String path = inputFile.absolutePath(); if (!caseSensitiveFileExtension) { String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName())); @@ -100,16 +86,6 @@ abstract class PathPattern { return pattern.match(path); } - @Override - boolean match(Resource resource) { - return false; - } - - @Override - boolean supportResource() { - return false; - } - @Override public String toString() { return "file:" + pattern.toString(); @@ -125,18 +101,18 @@ abstract class PathPattern { } @Override - boolean match(File ioFile, String relativePathFromBasedir) { + public boolean match(File ioFile, String relativePathFromBasedir) { return relativePathFromBasedir != null && pattern.match(relativePathFromBasedir); } @Override - boolean match(InputFile inputFile) { + public boolean match(InputFile inputFile) { return match(inputFile, true); } @Override - boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) { - String path = inputFile.path(); + public boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) { + String path = inputFile.relativePath(); if (!caseSensitiveFileExtension) { String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName())); if (StringUtils.isNotBlank(extension)) { @@ -147,16 +123,6 @@ abstract class PathPattern { return path != null && pattern.match(path); } - @Override - boolean match(Resource resource) { - return resource.matchFilePattern(pattern.toString()); - } - - @Override - boolean supportResource() { - return true; - } - @Override public String toString() { return pattern.toString(); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathIndex.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathIndex.java new file mode 100644 index 00000000000..dc52ed7bf49 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathIndex.java @@ -0,0 +1,39 @@ +/* + * 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.batch.fs.internal; + +import org.sonar.api.batch.fs.InputFile; + +/** + * @since 4.2 + */ +public class RelativePathIndex implements FileIndex { + public static final String ID = "rel"; + + @Override + public Object valueOf(InputFile f) { + return f.relativePath(); + } + + @Override + public String id() { + return ID; + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java similarity index 95% rename from sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/package-info.java rename to sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java index 2018417ac1c..80283a000fb 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/package-info.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java @@ -18,6 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @ParametersAreNonnullByDefault -package org.sonar.api.scan.filesystem.internal; +package org.sonar.api.batch.fs.internal; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java new file mode 100644 index 00000000000..02490a199b8 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.api.batch.fs; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContextFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContextFactory.java index d9908d4583b..f7af0d48af5 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContextFactory.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContextFactory.java @@ -21,8 +21,8 @@ package org.sonar.api.measures; import com.google.common.annotations.Beta; import org.sonar.api.BatchComponent; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.resources.Resource; -import org.sonar.api.scan.filesystem.InputFile; /** *

This interface is not intended to be implemented by clients.

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 e8d05fe14d0..f1adc52953f 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 @@ -50,7 +50,7 @@ public class FileQuery { public static FileQuery on(FileType... types) { FileQuery query = new FileQuery(); for (FileType type : types) { - query.on(InputFile.ATTRIBUTE_TYPE, type.typeValue()); + query.on("TYPE", type.typeValue()); } return query; } @@ -75,12 +75,12 @@ public class FileQuery { */ public static FileQuery onMain() { FileQuery query = new FileQuery(); - return query.on(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_MAIN); + return query.on("TYPE", "MAIN"); } public static FileQuery onTest() { FileQuery query = new FileQuery(); - return query.on(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST); + return query.on("TYPE", "TEST"); } private FileQuery() { @@ -102,7 +102,7 @@ public class FileQuery { */ @Deprecated public Collection types() { - return Collections2.transform(attributes.get(InputFile.ATTRIBUTE_TYPE), new Function() { + return Collections2.transform(attributes.get("TYPE"), new Function() { @Override public FileType apply(@Nullable String input) { return input != null ? FileType.valueOf(input) : null; @@ -111,15 +111,15 @@ public class FileQuery { } public Collection typeAttributes() { - return attributes.get(InputFile.ATTRIBUTE_TYPE); + return attributes.get("TYPE"); } public Collection languages() { - return attributes.get(InputFile.ATTRIBUTE_LANGUAGE); + return attributes.get("LANG"); } public FileQuery onLanguage(String... languages) { - return on(InputFile.ATTRIBUTE_LANGUAGE, languages); + return on("LANG", languages); } public Collection inclusions() { @@ -144,10 +144,6 @@ public class FileQuery { throw new UnsupportedOperationException("TODO"); } - public FileQuery withFilters(FileFilter... filters) { - throw new UnsupportedOperationException("TODO"); - } - @Override public boolean equals(Object obj) { if (obj == null) { 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 6754503a9f8..bf296dc8ad2 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,11 +21,11 @@ package org.sonar.api.scan.filesystem; /** * @since 3.5 - * @deprecated since 4.2 use {@link InputFile#TYPE_MAIN} or {@link InputFile#TYPE_TEST} + * @deprecated in 4.2 */ @Deprecated public enum FileType { - SOURCE(InputFile.TYPE_MAIN), TEST(InputFile.TYPE_TEST); + SOURCE("MAIN"), TEST("TEST"), MAIN("MAIN"); private String typeValue; @@ -33,7 +33,7 @@ public enum FileType { this.typeValue = typeValue; } - String typeValue() { + public String typeValue() { return typeValue; } } 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 deleted file mode 100644 index e811576ec2e..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java +++ /dev/null @@ -1,98 +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.api.scan.filesystem; - -import javax.annotation.CheckForNull; - -import java.io.File; -import java.io.Serializable; -import java.nio.charset.Charset; -import java.util.Map; - -public interface InputFile extends Serializable { - - /** - * Detected language - */ - String ATTRIBUTE_LANGUAGE = "LANG"; - - /** - * Number of lines in the file. - */ - String ATTRIBUTE_LINE_COUNT = "LINE_COUNT"; - - /** - * Type of source file. For now only possible values are {@link #TYPE_MAIN} or {@link #TYPE_TEST} - */ - String ATTRIBUTE_TYPE = "TYPE"; - String TYPE_MAIN = "MAIN"; - String TYPE_TEST = "TEST"; - - String ATTRIBUTE_STATUS = "STATUS"; - String STATUS_SAME = "SAME"; - String STATUS_CHANGED = "CHANGED"; - String STATUS_ADDED = "ADDED"; - - /** - * Path is relative from module base directory. Path is unique and identifies file - * within given {@link org.sonar.api.scan.filesystem.ModuleFileSystem}. - * File separator is the forward slash ('/'), even on MSWindows. - *

- * Returns src/main/java/com/Foo.java if module base dir is - * /absolute/path/to/module and if file is - * /absolute/path/to/module/src/main/java/com/Foo.java. - *

- * Returned path is never null. - */ - String path(); - - /** - * Not-null canonical path. File separator is forward slash ('/'), even on MSWindows. - */ - String absolutePath(); - - File file(); - - Charset encoding(); - - /** - * Not-null filename, including extension - */ - String name(); - - /** - * Not-null type (is it a main file or a unit test file?). - * See constant values prefixed by TYPE_, for example {@link #TYPE_MAIN}. - */ - String type(); - - /** - * Does the given attribute have the given value ? - */ - boolean has(String attribute, String value); - - /** - * See list of attribute keys in constants starting with ATTRIBUTE_. - */ - @CheckForNull - String attribute(String key); - - Map attributes(); -} 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 9ea6ec091e9..89d721d27ec 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 @@ -22,14 +22,15 @@ package org.sonar.api.scan.filesystem; import org.sonar.api.BatchComponent; import javax.annotation.CheckForNull; - import java.io.File; import java.nio.charset.Charset; import java.util.List; /** * @since 3.5 + * @deprecated in 4.2. Replaced by {@link org.sonar.api.batch.fs.FileSystem} */ +@Deprecated public interface ModuleFileSystem extends BatchComponent { /** @@ -49,7 +50,6 @@ public interface ModuleFileSystem extends BatchComponent { * Example in Maven : ${project.basedir}/src/main/java * @deprecated since 4.2 will always return {@link #baseDir()} */ - @Deprecated List sourceDirs(); /** @@ -57,7 +57,6 @@ public interface ModuleFileSystem extends BatchComponent { * Example in Maven : ${project.basedir}/src/test/java * @deprecated since 4.2 will always return {@link #baseDir()} */ - @Deprecated List testDirs(); /** @@ -70,29 +69,13 @@ public interface ModuleFileSystem extends BatchComponent { * * @deprecated since 4.2 sonar.binaries should be converted to language specific property */ - @Deprecated List binaryDirs(); /** * Search for files. Never return null. - * @deprecated since 4.2 use {@link #inputFiles(FileQuery)} */ - @Deprecated List files(FileQuery query); - /** - * Search for input files. Never return null. - * @since 4.2 - */ - Iterable inputFiles(FileQuery query); - - /** - * Search for input file corresponding to the given java.io.File. - * @since 4.2 - */ - @CheckForNull - InputFile inputFile(File ioFile); - /** * Default charset for files of the module. If it's not defined, then * return the platform default charset. When trying to read an input file it is better to rely on diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/DefaultInputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/DefaultInputFile.java deleted file mode 100644 index 9f75219c86d..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/DefaultInputFile.java +++ /dev/null @@ -1,217 +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.api.scan.filesystem.internal; - -import org.apache.commons.codec.Charsets; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.utils.PathUtils; - -import javax.annotation.CheckForNull; -import java.io.File; -import java.nio.charset.Charset; -import java.util.Map; - -/** - * PLUGINS MUST NOT USE THIS CLASS, EVEN FOR UNIT TESTING. - * - * @since 4.0 - */ -public class DefaultInputFile implements InputFile { - - /** - * We're not sure that this is the correct way, so not in API yet. - */ - public static final String ATTRIBUTE_COMPONENT_KEY = "CMP_KEY"; - - public static final String ATTRIBUTE_COMPONENT_DEPRECATED_KEY = "CMP_DEPRECATED_KEY"; - - public static final String ATTRIBUTE_HASH = "HASH"; - - /** - * Relative path from source directory. File separator is the forward slash ('/'), - * even on MSWindows. - * @deprecated since 4.2 No more sonar.sources - */ - @Deprecated - public static final String ATTRIBUTE_SOURCE_RELATIVE_PATH = "SRC_REL_PATH"; - - /** - * Canonical path of source directory. - * Example: /path/to/module/src/main/java or C:\path\to\module\src\main\java - * @deprecated since 4.2 No more sonar.sources - */ - @Deprecated - public static final String ATTRIBUTE_SOURCEDIR_PATH = "SRC_DIR_PATH"; - - private final String absolutePath; - private final String path; - private final Map attributes; - private final String encoding; - - private DefaultInputFile(File file, Charset encoding, String path, Map attributes) { - this.encoding = encoding.name(); - this.absolutePath = PathUtils.canonicalPath(file); - this.path = FilenameUtils.separatorsToUnix(path); - this.attributes = attributes; - } - - /** - * Plugins must not build their own instances of {@link InputFile}. - * {@link org.sonar.api.scan.filesystem.ModuleFileSystem} must be used to search for files to scan. - *

- * Usage: InputFile.create(file, "src/main/java/com/Foo.java", attributes) - */ - public static DefaultInputFile create(File file, Charset encoding, String path, Map attributes) { - return new DefaultInputFile(file, encoding, path, attributes); - } - - @Override - public String path() { - return path; - } - - @Override - public String absolutePath() { - return absolutePath; - } - - @Override - public File file() { - return new File(absolutePath); - } - - @Override - public Charset encoding() { - return Charsets.toCharset(encoding); - } - - @Override - public String name() { - return file().getName(); - } - - @Override - public String type() { - return attribute(ATTRIBUTE_TYPE); - } - - @Override - public boolean has(String attribute, String value) { - return StringUtils.equals(attributes.get(attribute), value); - } - - @Override - @CheckForNull - public String attribute(String key) { - return attributes.get(key); - } - - @Override - public Map attributes() { - return attributes; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DefaultInputFile other = (DefaultInputFile) o; - return absolutePath.equals(other.absolutePath); - } - - @Override - public int hashCode() { - return absolutePath.hashCode(); - } - - public DefaultInputFile setLines(long l) { - attributes.put(ATTRIBUTE_LINE_COUNT, String.valueOf(l)); - return this; - } - - public String language() { - return attributes.get(ATTRIBUTE_LANGUAGE); - } - - public DefaultInputFile setLanguage(String s) { - attributes.put(ATTRIBUTE_LANGUAGE, s); - return this; - } - - public DefaultInputFile setHash(String s) { - attributes.put(ATTRIBUTE_HASH, s); - return this; - } - - public DefaultInputFile setStatus(String s) { - attributes.put(ATTRIBUTE_STATUS, s); - return this; - } - - public DefaultInputFile setKey(String s) { - attributes.put(ATTRIBUTE_COMPONENT_KEY, s); - return this; - } - - public DefaultInputFile setDeprecatedKey(String s) { - attributes.put(ATTRIBUTE_COMPONENT_DEPRECATED_KEY, s); - return this; - } - - public DefaultInputFile setType(String s) { - attributes.put(ATTRIBUTE_TYPE, s); - return this; - } - - /** - * Used only for backward-compatibility. Meaningless since version 4.2. - */ - public String sourceDirAbsolutePath() { - return attributes.get(ATTRIBUTE_SOURCEDIR_PATH); - } - - public DefaultInputFile setSourceDirAbsolutePath(String s) { - attributes.put(ATTRIBUTE_SOURCEDIR_PATH, FilenameUtils.normalize(s, true)); - return this; - } - - /** - * Used only for backward-compatibility. Meaningless since version 4.2. - */ - public String pathRelativeToSourceDir() { - return attributes.get(ATTRIBUTE_SOURCE_RELATIVE_PATH); - } - - public DefaultInputFile setPathRelativeToSourceDir(String s) { - attributes.put(ATTRIBUTE_SOURCE_RELATIVE_PATH, FilenameUtils.normalize(s, true)); - return this; - } - - @Override - public String toString() { - return String.format("[%s,%s]", path, type()); - } -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/InputFileBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/InputFileBuilder.java deleted file mode 100644 index d7e2d730fbe..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/InputFileBuilder.java +++ /dev/null @@ -1,89 +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.api.scan.filesystem.internal; - -import org.sonar.api.scan.filesystem.InputFile; - -import org.sonar.api.utils.PathUtils; - -import javax.annotation.Nullable; - -import java.io.File; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.Map; - -/** - * FOR UNIT-TESTING ONLY - * - * @since 4.0 - */ -public class InputFileBuilder { - - private final Map attributes = new HashMap(); - private final File file; - private final String relativePath; - private Charset encoding; - - public static void _FOR_UNIT_TESTING_ONLY_() { - // For those who don't read javadoc - } - - public InputFileBuilder(File file, Charset encoding, String relativePath) { - this.file = file; - this.encoding = encoding; - this.relativePath = relativePath; - } - - public InputFileBuilder attribute(String key, @Nullable String value) { - if (value != null) { - attributes.put(key, value); - } - return this; - } - - public InputFileBuilder type(@Nullable String type) { - return attribute(InputFile.ATTRIBUTE_TYPE, type); - } - - public InputFileBuilder language(@Nullable String language) { - return attribute(InputFile.ATTRIBUTE_LANGUAGE, language); - } - - public InputFileBuilder hash(@Nullable String hash) { - return attribute(DefaultInputFile.ATTRIBUTE_HASH, hash); - } - - public InputFileBuilder status(@Nullable String status) { - return attribute(InputFile.ATTRIBUTE_STATUS, status); - } - - public InputFileBuilder sourceDir(File dir) { - return attribute(DefaultInputFile.ATTRIBUTE_SOURCEDIR_PATH, PathUtils.canonicalPath(dir)); - } - - public InputFileBuilder sourceDir(@Nullable String path) { - return attribute(DefaultInputFile.ATTRIBUTE_SOURCEDIR_PATH, PathUtils.sanitize(path)); - } - - public DefaultInputFile build() { - return DefaultInputFile.create(file, encoding, relativePath, attributes); - } -} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java new file mode 100644 index 00000000000..afbc74f2928 --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java @@ -0,0 +1,75 @@ +/* + * 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.batch.fs.internal; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.batch.fs.InputFile; + +import java.io.File; + +import static org.fest.assertions.Assertions.assertThat; + +public class DefaultInputFileTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Test + public void test() throws Exception { + DefaultInputFile inputFile = new DefaultInputFile("src/Foo.php") + .setFile(temp.newFile("Foo.php")) + .setDeprecatedKey("deprecated") + .setKey("ABCDE") + .setHash("1234") + .setLines(42) + .setLanguage("php") + .setStatus(InputFile.Status.ADDED) + .setType(InputFile.Type.TEST); + + assertThat(inputFile.relativePath()).isEqualTo("src/Foo.php"); + assertThat(inputFile.getRelativePath()).isEqualTo("src/Foo.php"); + assertThat(new File(inputFile.relativePath())).isRelative(); + assertThat(inputFile.absolutePath()).endsWith("Foo.php"); + assertThat(new File(inputFile.absolutePath())).isAbsolute(); + assertThat(inputFile.language()).isEqualTo("php"); + assertThat(inputFile.status()).isEqualTo(InputFile.Status.ADDED); + assertThat(inputFile.type()).isEqualTo(InputFile.Type.TEST); + assertThat(inputFile.lines()).isEqualTo(42); + assertThat(inputFile.hash()).isEqualTo("1234"); + } + + @Test + public void test_equals_and_hashcode() throws Exception { + DefaultInputFile f1 = new DefaultInputFile("src/Foo.php"); + DefaultInputFile f1a = new DefaultInputFile("src/Foo.php"); + DefaultInputFile f2 = new DefaultInputFile("src/Bar.php"); + + assertThat(f1).isEqualTo(f1); + assertThat(f1).isEqualTo(f1a); + assertThat(f1).isNotEqualTo(f2); + assertThat(f1.equals("foo")).isFalse(); + assertThat(f1.equals(null)).isFalse(); + + assertThat(f1.hashCode()).isEqualTo(f1.hashCode()); + assertThat(f1.hashCode()).isEqualTo(f1a.hashCode()); + } +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/DefaultInputFileTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/DefaultInputFileTest.java deleted file mode 100644 index a8346a0ccd3..00000000000 --- a/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/DefaultInputFileTest.java +++ /dev/null @@ -1,100 +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.api.scan.filesystem.internal; - -import org.sonar.api.scan.filesystem.InputFile; - -import com.google.common.base.Charsets; -import org.apache.commons.io.FilenameUtils; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.utils.PathUtils; - -import java.io.File; -import java.io.IOException; - -import static org.fest.assertions.Assertions.assertThat; - -public class DefaultInputFileTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - @Test - public void test_attributes() throws IOException { - File file = temp.newFile(); - InputFile input = new InputFileBuilder(file, Charsets.UTF_8, "src/main/java/Foo.java") - .attribute("foo", "bar") - .type(InputFile.TYPE_TEST) - .hash("ABC") - .status(InputFile.STATUS_ADDED) - .language("java") - .build(); - - assertThat(input.attributes()).hasSize(5); - assertThat(input.attribute("unknown")).isNull(); - assertThat(input.attribute("foo")).isEqualTo("bar"); - assertThat(input.attribute(InputFile.ATTRIBUTE_TYPE)).isEqualTo(InputFile.TYPE_TEST); - assertThat(input.attribute(DefaultInputFile.ATTRIBUTE_HASH)).isEqualTo("ABC"); - assertThat(input.attribute(InputFile.ATTRIBUTE_LANGUAGE)).isEqualTo("java"); - assertThat(input.attribute(InputFile.ATTRIBUTE_STATUS)).isEqualTo(InputFile.STATUS_ADDED); - - assertThat(input.has(InputFile.ATTRIBUTE_LANGUAGE, "java")).isTrue(); - assertThat(input.has(InputFile.ATTRIBUTE_LANGUAGE, "php")).isFalse(); - assertThat(input.has("unknown", "xxx")).isFalse(); - } - - @Test - public void test_file() throws Exception { - File sourceDir = temp.newFolder(); - File file = temp.newFile("Foo.java"); - InputFile input = new InputFileBuilder(file, Charsets.UTF_8, "src/main/java/Foo.java") - .sourceDir(sourceDir) - .build(); - - assertThat(input.name()).isEqualTo("Foo.java"); - assertThat(input.file()).isEqualTo(file); - assertThat(input.attribute(DefaultInputFile.ATTRIBUTE_SOURCEDIR_PATH)).isEqualTo(FilenameUtils.separatorsToUnix(sourceDir.getAbsolutePath())); - assertThat(input.path()).isEqualTo("src/main/java/Foo.java"); - assertThat(input.absolutePath()).isEqualTo(PathUtils.canonicalPath(file)); - } - - @Test - public void test_equals_and_hashCode() throws Exception { - File file1 = temp.newFile(); - InputFile input1 = new InputFileBuilder(file1, Charsets.UTF_8, "src/main/java/Foo.java").build(); - InputFile input1a = new InputFileBuilder(file1, Charsets.UTF_8, "src/main/java/Foo.java").build(); - InputFile input2 = new InputFileBuilder(temp.newFile(), Charsets.UTF_8, "src/main/java/Bar.java").build(); - - assertThat(input1.equals(input1)).isTrue(); - assertThat(input1.equals(input1a)).isTrue(); - assertThat(input1.equals(input2)).isFalse(); - assertThat(input1.hashCode()).isEqualTo(input1.hashCode()); - assertThat(input1.hashCode()).isEqualTo(input1a.hashCode()); - } - - @Test - public void test_toString() throws Exception { - File file1 = temp.newFile(); - InputFile input = new InputFileBuilder(file1, Charsets.UTF_8, "src/main/java/Foo.java").type(InputFile.TYPE_TEST).build(); - assertThat(input.toString()).isEqualTo("[src/main/java/Foo.java,TEST]"); - } -} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/InputFilesTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/InputFilesTest.java deleted file mode 100644 index f0b522be7c5..00000000000 --- a/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/InputFilesTest.java +++ /dev/null @@ -1,48 +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.api.scan.filesystem.internal; - -import org.sonar.api.scan.filesystem.InputFile; - -import com.google.common.base.Charsets; -import com.google.common.collect.Lists; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import java.io.File; - -import static org.fest.assertions.Assertions.assertThat; - -public class InputFilesTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - @Test - public void test_toFiles() throws Exception { - File file1 = temp.newFile(); - File file2 = temp.newFile(); - InputFile input1 = new InputFileBuilder(file1, Charsets.UTF_8, "src/main/java/Foo.java").build(); - InputFile input2 = new InputFileBuilder(file2, Charsets.UTF_8, "src/main/java/Bar.java").build(); - - assertThat(InputFiles.toFiles(Lists.newArrayList(input1, input2))).containsOnly(file1, file2); - } -} diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWs.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWs.java index 26f9ad15676..d7b35b3f6b6 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWs.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWs.java @@ -19,9 +19,6 @@ */ package org.sonar.server.rule.ws; -import org.sonar.api.server.ws.Request; -import org.sonar.api.server.ws.RequestHandler; -import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; public class RulesWs implements WebService { @@ -41,16 +38,6 @@ public class RulesWs implements WebService { NewController controller = context.newController("api/rules") .setDescription("Coding rules"); - controller.newAction("list") - .setDescription("List coding rules") - .setSince("4.2") - .setHandler(new RequestHandler() { - @Override - public void handle(Request request, Response response) { - list(request, response); - } - }); - controller.newAction("show") .setDescription("Detail of rule") .setSince("4.2") @@ -71,13 +58,6 @@ public class RulesWs implements WebService { controller.done(); } - void list(Request request, Response response) { - response.newJsonWriter().beginObject() - .prop("TODO", true) - .endObject() - .close(); - } - private void addTagParams(final NewAction action) { action.newParam("key", "Full key of the rule"); action.newParam("tags", "Comma separated list of tags"); diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsTest.java index 17c8b893cfa..bfa4bf55207 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsTest.java @@ -54,14 +54,7 @@ public class RulesWsTest { assertThat(controller).isNotNull(); assertThat(controller.path()).isEqualTo("api/rules"); assertThat(controller.description()).isNotEmpty(); - assertThat(controller.actions()).hasSize(4); - - WebService.Action search = controller.action("list"); - assertThat(search).isNotNull(); - assertThat(search.handler()).isNotNull(); - assertThat(search.since()).isEqualTo("4.2"); - assertThat(search.isPost()).isFalse(); - assertThat(search.isPrivate()).isFalse(); + assertThat(controller.actions()).hasSize(3); WebService.Action show = controller.action("show"); assertThat(show).isNotNull(); @@ -86,10 +79,4 @@ public class RulesWsTest { assertThat(removeTags.isPrivate()).isFalse(); assertThat(removeTags.params()).hasSize(2); } - - @Test - public void search_for_rules() throws Exception { - tester.newRequest("list").execute().assertJson(getClass(), "list.json"); - } - } diff --git a/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsTest/list.json b/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsTest/list.json deleted file mode 100644 index a3a00e8e344..00000000000 --- a/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsTest/list.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "TODO": true -} -- 2.39.5