]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-926 move FS API to org.sonar.api.batch.fs
authorSimon Brandhof <simon.brandhof@gmail.com>
Thu, 20 Feb 2014 06:23:08 +0000 (07:23 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Thu, 20 Feb 2014 06:23:13 +0000 (07:23 +0100)
113 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesStack.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java
plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java
plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java
plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbDuplicationsIndex.java
plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarDuplicationsIndex.java
plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java
sonar-batch/src/main/java/org/sonar/batch/DefaultFileLinesContextFactory.java
sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
sonar-batch/src/main/java/org/sonar/batch/fs/package-info.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/index/Cache.java
sonar-batch/src/main/java/org/sonar/batch/index/Caches.java
sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataCache.java
sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataPersister.java
sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java
sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java
sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java
sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java
sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java
sonar-batch/src/main/java/org/sonar/batch/phases/ProfileLogger.java
sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AttributeFilter.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileFilters.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilter.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ExclusionFilters.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndex.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileMetadata.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FilePredicateAdapters.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileQueryFilter.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileSystemLogger.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InclusionFilter.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetection.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/PathPattern.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ProjectFileSystemAdapter.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java
sonar-batch/src/main/java/org/sonar/batch/scan/language/DefaultModuleLanguages.java
sonar-batch/src/main/java/org/sonar/batch/scan/report/ComponentSelector.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java
sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java
sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java
sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java
sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java
sonar-batch/src/test/java/org/sonar/batch/phases/ProfileLoggerTest.java
sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AttributeFilterTest.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFilterTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileQueryFilterTest.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InclusionFilterTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java
sonar-batch/test-resources/org/sonar/batch/phases/ComponentIndexerTest/encoding/CP1252Encoding.java [new file with mode: 0644]
sonar-batch/test-resources/org/sonar/batch/phases/ComponentIndexerTest/encoding/MacRomanEncoding.java [new file with mode: 0644]
sonar-batch/test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/CP1252Encoding.java [deleted file]
sonar-batch/test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/MacRomanEncoding.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/ModuleLanguages.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AbsolutePathPredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AndPredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/LanguagePredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/NotPredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/OrPredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/PathPatternPredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/RelativePathPredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/StatusPredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TypePredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/UniqueIndexPredicate.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileIndex.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathIndex.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/measures/FileLinesContextFactory.java
sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileQuery.java
sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileType.java
sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFileFilter.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/ModuleFileSystem.java
sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/DefaultInputFile.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/InputFileBuilder.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/InputFiles.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/package-info.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/DefaultInputFileTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/InputFileBuilderTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/InputFilesTest.java [deleted file]
sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWs.java
sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsTest.java
sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsTest/list.json [deleted file]

index 10a41111771b1a27ad6305f3c647850614173b94..be0b0cea5f6872fbc6ae82370d4d6370523083ce 100644 (file)
@@ -36,8 +36,8 @@ import static com.google.common.collect.Lists.newArrayList;
 @InstantiationStrategy(InstantiationStrategy.PER_BATCH)
 public class InitialOpenIssuesStack implements BatchExtension {
 
-  private final Cache<String, IssueDto> issuesCache;
-  private final Cache<String, ArrayList<IssueChangeDto>> issuesChangelogCache;
+  private final Cache<IssueDto> issuesCache;
+  private final Cache<ArrayList<IssueChangeDto>> issuesChangelogCache;
 
   public InitialOpenIssuesStack(Caches caches) {
     issuesCache = caches.createCache("last-open-issues");
@@ -60,7 +60,7 @@ public class InitialOpenIssuesStack implements BatchExtension {
   }
 
   public Iterable<IssueDto> 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();
   }
 }
index fd14c7b7f06ac9f33333e3da557981edfd69495f..ca6d2278350b1f5677d21e773c85352d6c37df3a 100644 (file)
  */
 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<String, String> 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()) {
index a32ea0bb51dc72b00d03192958d8b32722ae5736..929e7dc099e5ac9932cadc3340a53ebd3cd1415c 100644 (file)
@@ -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();
   }
 
index 073db76b693affeb1544b6b1397d8373e3a48f32..1b9759331e79ee7d26d0223d02ec994f1388178f 100644 (file)
@@ -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.<InputFile>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.<InputFile>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);
index 9f6bb9d1f67db5d5941284d7c31cff961dd647ac..14b073d671129464492f6f8e714b9bbbda0655c3 100644 (file)
@@ -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<InputFile> sourceFiles = fileSystem.inputFiles(FileQuery.onMain().onLanguage(languageKey)
-      .withExclusions(cpdExclusions));
+    Iterable<InputFile> 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<Block> 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<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
 
         Iterable<CloneGroup> filtered;
index 70c2731ae450484c76ef3814350f47eb3cdad575..0b340ce17c4020558f90669d6eb8d41657e94318 100644 (file)
@@ -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<InputFile> sourceFiles = fileSystem.inputFiles(FileQuery.onMain().onLanguage(languageKey).withExclusions(cpdExclusions));
+    Iterable<InputFile> 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<Statement> 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<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
 
index 83475fbb86152895c2138a80fbcdf20826fdfaf2..934f2a3fa5f9cbb03a4d242e7fb5f7a8cf2164ad 100644 (file)
  */
 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;
index 6a54af3503ba4e05070150671b8a2674594e0ce7..c869647e63538e2214fa8297cf6c6c2dcb63a668 100644 (file)
@@ -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;
index 18c80b5dcfc5455457b161861b84b6bd35ba6e3a..5fae998b0b6089cf8bbc8a45cd0e725d25427cf3 100644 (file)
  */
 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<CloneGroup> 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)));
index 5d3b49e8e9faa16a812b72bb689a12dcacd87217..cc59b0bf5d7bac562690fcfd56e3569cc4f77a13 100644 (file)
 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);
index 158e9e79982c9fc5f6c99cfeb350b7906dc0636e..bbeb88afdb8a779e28fbb70d920524a761c88f76 100644 (file)
@@ -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 (file)
index 0000000..9b04956
--- /dev/null
@@ -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;
index bf48d6a5c58fe373fc0365723143d8808e985138..37749efbeb7ab0878b03aae380514c9f9c31c809 100644 (file)
@@ -35,9 +35,8 @@ import java.util.Set;
  * This cache is not thread-safe, due to direct usage of {@link com.persistit.Exchange}
  * </p>
  */
-public class Cache<K, V extends Serializable> {
+public class Cache<V extends Serializable> {
 
-  private static final String DEFAULT_GROUP = "_";
   private final String name;
   private final Exchange exchange;
 
@@ -46,14 +45,28 @@ public class Cache<K, V extends Serializable> {
     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<K, V extends Serializable> {
   }
 
   /**
-   * 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<K, V extends Serializable> {
     }
   }
 
-  /**
-   * 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<K, V extends Serializable> {
     }
   }
 
-  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<K, V extends Serializable> {
     }
   }
 
-  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<K, V extends Serializable> {
    * @return The set of cache keys for this group.
    */
   @SuppressWarnings("unchecked")
-  public Set<K> keySet(String group) {
+  public Set keySet(Object key) {
     try {
-      Set<K> keys = Sets.newLinkedHashSet();
+      Set<Object> 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<K, V extends Serializable> {
     }
   }
 
+  public Set keySet(Object firstKey, Object secondKey) {
+    try {
+      Set<Object> 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<K> keySet() {
-    return keySet(DEFAULT_GROUP);
+  public Set<Object> keySet() {
+    try {
+      Set<Object> 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<V> values(String group) {
+  public Iterable<V> 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<V>(iteratorExchange, false);
     } catch (Exception e) {
       throw new IllegalStateException("Fail to get values from cache " + name, e);
@@ -214,46 +311,45 @@ public class Cache<K, V extends Serializable> {
    * Lazy-loading values
    */
   public Iterable<V> values() {
-    return values(DEFAULT_GROUP);
-  }
-
-  /**
-   * Lazy-loading values of all groups
-   */
-  public Iterable<V> allValues() {
     try {
-      exchange.clear();
+      exchange.clear().append(Key.BEFORE);
       Exchange iteratorExchange = new Exchange(exchange);
-      iteratorExchange.append(Key.BEFORE);
       return new ValueIterable<V>(iteratorExchange, true);
     } catch (Exception e) {
       throw new IllegalStateException("Fail to get values from cache " + name, e);
     }
   }
 
-  public Set<String> groups() {
-    try {
-      Set<String> 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 <T extends Serializable> Iterable<Entry<T>> entries() {
+  public Iterable<Entry<V>> entries() {
     exchange.clear().to(Key.BEFORE);
     return new EntryIterable(new Exchange(exchange), true);
   }
 
-  public <T extends Serializable> Iterable<Entry<T>> entries(String group) {
-    exchange.clear().append(group).append(Key.BEFORE);
-    return new EntryIterable(new Exchange(exchange), false);
+  public Iterable<SubEntry<V>> 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<K, V extends Serializable> {
     @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<K, V extends Serializable> {
 
     @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<K, V extends Serializable> {
     }
   }
 
+  private static class SubEntryIterable<T extends Serializable> implements Iterable<SubEntry<T>> {
+    private final SubEntryIterator<T> it;
+
+    private SubEntryIterable(Exchange exchange, boolean deep) {
+      it = new SubEntryIterator<T>(exchange, deep);
+    }
+
+    @Override
+    public Iterator<SubEntry<T>> iterator() {
+      return it;
+    }
+  }
+
+  private static class SubEntryIterator<T extends Serializable> implements Iterator<SubEntry<T>> {
+    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<V extends Serializable> {
+    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<T extends Serializable> implements Iterable<Entry<T>> {
     private final EntryIterator<T> it;
 
@@ -344,7 +520,11 @@ public class Cache<K, V extends Serializable> {
         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<K, V extends Serializable> {
     }
   }
 
-  public static class Entry<T extends Serializable> {
-    private final String group;
-    private final String key;
-    private final T value;
+  public static class Entry<V extends Serializable> {
+    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;
     }
 
index 0a985e2ed5db05d93c57dfc07f2dc3f81cf3a158..41c13bb682a262acc3b028f1d353c1aed5988915 100644 (file)
@@ -77,12 +77,12 @@ public class Caches implements BatchComponent, Startable {
     }
   }
 
-  public <K extends Serializable, V extends Serializable> Cache<K, V> createCache(String cacheName) {
+  public <V extends Serializable> Cache<V> 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<K, V> cache = new Cache<K, V>(cacheName, exchange);
+      Cache<V> cache = new Cache<V>(cacheName, exchange);
       cacheNames.add(cacheName);
       return cache;
     } catch (Exception e) {
index c4cda7dc06e9ad7d6a208b5b3b78c68c6eef8b2e..3d6f57dd099525ae05b8c1c30ca317aa1fb1ebab 100644 (file)
@@ -46,7 +46,7 @@ public class ComponentDataCache implements BatchComponent {
     return data == null ? null : ((StringData) data).data();
   }
 
-  public <D extends Data> Iterable<Cache.Entry<D>> entries(String componentKey) {
-    return cache.entries(componentKey);
+  public <D extends Data> Iterable<Cache.SubEntry<D>> entries(String componentKey) {
+    return cache.subEntries(componentKey);
   }
 }
index abd996f0c9fc14abecfcfce40295e81bf5c8d3f4..1d63d2591ae510f8c782bfa3d6bd06951848f298 100644 (file)
@@ -47,13 +47,13 @@ public class ComponentDataPersister implements ScanPersister {
     for (Map.Entry<String, Snapshot> componentEntry : snapshots.snapshots()) {
       String componentKey = componentEntry.getKey();
       Snapshot snapshot = componentEntry.getValue();
-      for (Cache.Entry<Data> dataEntry : data.entries(componentKey)) {
+      for (Cache.SubEntry<Data> 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);
         }
index c658f4bc34f0b32a7c3ac45c3f5227b52cfd2759..ae18f9e3faca9259858e32a73f6ee0bbcdb346c0 100644 (file)
@@ -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());
   }
 
   /**
index 576af394edbf03ecfc1e2c00120cb50ca2b0b33d..3305b627a44a88426c6ac84a3ec9e743c56e492c 100644 (file)
@@ -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<String, InputFile> deprecatedTestKeyMapper = new HashMap<String, InputFile>();
       Map<String, String> deprecatedDirectoryKeyMapper = new HashMap<String, String>();
       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);
index de12c23e87c454448db7b434f5c51e74ed385e10..b9b59a5676d65f485158d06dc18d0186898a612a 100644 (file)
  */
 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 {
 
index 1b2fcb3d31492efb51169f0ab9f983ec9e997cf6..e24d72a0ac91f9b64c5b0fa05106561f5ab81fd9 100644 (file)
@@ -31,7 +31,7 @@ import org.sonar.batch.index.Caches;
 public class IssueCache implements BatchComponent {
 
   // component key -> issue key -> issue
-  private final Cache<String, DefaultIssue> cache;
+  private final Cache<DefaultIssue> cache;
 
   public IssueCache(Caches caches) {
     cache = caches.createCache("issues");
@@ -42,7 +42,7 @@ public class IssueCache implements BatchComponent {
   }
 
   public Iterable<DefaultIssue> all() {
-    return cache.allValues();
+    return cache.values();
   }
 
   public IssueCache put(DefaultIssue issue) {
index fbe61421f5f8868d419d9b28b002295f80d0a5f4..2797ccaa330685d2629eb621d346b0ed5d27406c 100644 (file)
 
 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()) {
index ec939d8df28a8ffa1e49ecce8ff94262ae66b189..96d0721420d9d35ca5070e2ab4d01ea8e5c475b7 100644 (file)
@@ -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.");
     }
   }
 
index 17c4182d137bed09d0fb34daa48329e401603d6f..c8ac7bb558e668a02ff2eca048c064369b1476a8 100644 (file)
@@ -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/AttributeFilter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AttributeFilter.java
deleted file mode 100644 (file)
index 1e5e37c..0000000
+++ /dev/null
@@ -1,53 +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 java.util.Collection;
-
-class AttributeFilter implements InputFileFilter {
-  private final String key;
-  private final Collection<String> values;
-
-  AttributeFilter(String key, Collection<String> values) {
-    this.key = key;
-    this.values = values;
-  }
-
-  @Override
-  public boolean accept(InputFile inputFile) {
-    String value = inputFile.attribute(key);
-    return values.contains(value);
-  }
-
-  @VisibleForTesting
-  String key() {
-    return key;
-  }
-
-  @VisibleForTesting
-  Collection<String> values() {
-    return values;
-  }
-}
index f8e374e52b86ded4b942c6b15d1bae46307f9504..8621fb4e9a0556a2239f60cc169e805d441aadac 100644 (file)
@@ -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<InputFile> inputFiles = fs.inputFiles(FileQuery.all());
+    Iterable<InputFile> 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);
     }
   }
 }
index d27c313175b8c8351b0a0a7f80edb39a7715626f..0ae6deac8153285b5c34635b89431018af3ea0e8 100644 (file)
  */
 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<File> sourceDirs = Lists.newArrayList();
   private List<File> testDirs = Lists.newArrayList();
   private List<File> binaryDirs = Lists.newArrayList();
   private List<File> sourceFiles = Lists.newArrayList();
   private List<File> 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<File> 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<InputFile> 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<InputFile> 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<File> files(FileQuery query) {
-    return InputFiles.toFiles(inputFiles(query));
+    Collection<FilePredicate> predicates = Lists.newArrayList();
+    for (Map.Entry<String, Collection<String>> 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<File> sourceDirs, List<File> testDirs, List<File> 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<File> existingDirs(List<File> dirs) {
@@ -225,6 +209,67 @@ public class DefaultModuleFileSystem implements ModuleFileSystem {
     return builder.build();
   }
 
+  static FilePredicate fromDeprecatedAttribute(String key, Collection<String> value) {
+    if ("TYPE".equals(key)) {
+      return FilePredicates.or(Collections2.transform(value, new Function<String, FilePredicate>() {
+        @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<String, FilePredicate>() {
+        @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<String, FilePredicate>() {
+        @Override
+        public FilePredicate apply(@Nullable String s) {
+          return FilePredicates.hasLanguage(s);
+        }
+      }));
+    }
+    if ("CMP_KEY".equals(key)) {
+      return FilePredicates.or(Collections2.transform(value, new Function<String, FilePredicate>() {
+        @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<String, FilePredicate>() {
+        @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<String, FilePredicate>() {
+        @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<String, FilePredicate>() {
+        @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) {
index 146d309268ea46ee8d9429e02539945839f47217..9ca77131d9284dd42d459606f01c2e0d04621e69 100644 (file)
  */
 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
index 27ec3f53f7b7253ac810ce07e694c01a63caf714..e9ec3793260d633db849eda9c1fc51ea0d06372d 100644 (file)
  */
 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;
index d2fb4acf9c5feac633460bfe2a725773a3398d1c..50acca5c07499bd64963038c11f81830b94168ee 100644 (file)
@@ -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/FileIndex.java
deleted file mode 100644 (file)
index 31adc80..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.batch.scan.filesystem;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.filefilter.FileFilterUtils;
-import org.apache.commons.io.filefilter.HiddenFileFilter;
-import org.apache.commons.io.filefilter.IOFileFilter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.BatchComponent;
-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;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Index input files into {@link InputFileCache}.
- */
-public class FileIndex 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<String> removedPaths;
-    private final Set<String> indexed;
-
-    Progress(Set<String> removedPaths) {
-      this.removedPaths = removedPaths;
-      this.indexed = new HashSet<String>();
-    }
-
-    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;
-
-  private final PathResolver pathResolver;
-  private final List<InputFileFilter> filters;
-  private final InputFileCache fileCache;
-  private final Project module;
-  private final ExclusionFilters exclusionFilters;
-  private final InputFileBuilderFactory inputFileBuilderFactory;
-
-  public FileIndex(List<InputFileFilter> filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory,
-    InputFileCache cache, PathResolver pathResolver, Project project) {
-    this.filters = filters;
-    this.exclusionFilters = exclusionFilters;
-    this.inputFileBuilderFactory = inputFileBuilderFactory;
-    this.fileCache = cache;
-    this.pathResolver = pathResolver;
-    this.module = project;
-  }
-
-  void index(DefaultModuleFileSystem fileSystem) {
-    Logger logger = LoggerFactory.getLogger(FileIndex.class);
-    if (!module.getModules().isEmpty()) {
-      // No indexing for an aggregator module
-      return;
-    }
-    logger.info("Index files");
-    exclusionFilters.prepare(fileSystem);
-    // TODO log configuration too (replace FileSystemLogger)
-
-    Progress progress = new Progress(fileCache.fileRelativePaths(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);
-    } 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);
-    }
-
-    logger.info(String.format("%d files indexed", progress.count()));
-
-  }
-
-  private void indexFiles(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress progress, List<File> sourceFiles, String type) {
-    for (File sourceFile : sourceFiles) {
-      String path = pathResolver.relativePath(fileSystem.baseDir(), sourceFile);
-      if (path == null) {
-        LoggerFactory.getLogger(getClass()).warn(String.format(
-          FILE_IS_NOT_DECLARED_IN_MODULE_BASEDIR, sourceFile.getAbsoluteFile(), fileSystem.baseDir()
-          ));
-      } else {
-        if (exclusionFilters.accept(sourceFile, path, type)) {
-          indexFile(inputFileBuilder, fileSystem, progress, sourceFile, path, type);
-        }
-      }
-    }
-  }
-
-  Iterable<InputFile> 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<File> files = FileUtils.listFiles(dirToIndex, FILE_FILTER, DIR_FILTER);
-    for (File sourceFile : files) {
-      String path = pathResolver.relativePath(fileSystem.baseDir(), sourceFile);
-      if (path == null) {
-        LoggerFactory.getLogger(getClass()).warn(String.format(
-          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_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) {
-    InputFile inputFile = inputFileBuilder.create(file, type);
-    if (inputFile != null && accept(inputFile)) {
-      fileCache.put(fs.moduleKey(), inputFile);
-      status.markAsIndexed(path);
-    }
-  }
-
-  private String computeFilePath(DefaultModuleFileSystem fileSystem, File file) {
-    return pathResolver.relativePath(fileSystem.baseDir(), file);
-  }
-
-  private boolean accept(InputFile inputFile) {
-    // InputFileFilter extensions
-    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/FileIndexer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
new file mode 100644 (file)
index 0000000..7ad6bc1
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.scan.filesystem;
+
+import com.google.common.collect.Sets;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.apache.commons.io.filefilter.HiddenFileFilter;
+import org.apache.commons.io.filefilter.IOFileFilter;
+import org.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.PathResolver;
+import org.sonar.api.utils.SonarException;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Index input files into {@link InputFileCache}.
+ */
+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 final IOFileFilter DIR_FILTER = FileFilterUtils.and(HiddenFileFilter.VISIBLE, FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter(".")));
+  private static final IOFileFilter FILE_FILTER = HiddenFileFilter.VISIBLE;
+
+  private final PathResolver pathResolver;
+  private final List<InputFileFilter> filters;
+  private final InputFileCache fileCache;
+  private final Project module;
+  private final ExclusionFilters exclusionFilters;
+  private final InputFileBuilderFactory inputFileBuilderFactory;
+
+  public FileIndexer(List<InputFileFilter> 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 = module;
+  }
+
+  void index(DefaultModuleFileSystem fileSystem) {
+    Logger logger = LoggerFactory.getLogger(FileIndexer.class);
+    if (!module.getModules().isEmpty()) {
+      // No indexing for an aggregator module
+      return;
+    }
+    logger.info("Index files");
+    exclusionFilters.prepare(fileSystem);
+    // TODO log configuration too (replace FileSystemLogger)
+
+    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);
+    } else if (fileSystem.baseDir() != null) {
+      // index from basedir
+      indexDirectory(inputFileBuilder, fileSystem, progress, fileSystem.baseDir());
+    }
+
+    // Remove files that have been removed since previous indexation
+    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<File> sourceFiles, InputFile.Type type) {
+    for (File sourceFile : sourceFiles) {
+      String path = pathResolver.relativePath(fileSystem.baseDir(), sourceFile);
+      if (path == null) {
+        LoggerFactory.getLogger(getClass()).warn(String.format(
+          FILE_IS_NOT_DECLARED_IN_MODULE_BASEDIR, sourceFile.getAbsoluteFile(), fileSystem.baseDir()
+          ));
+      } else {
+        if (exclusionFilters.accept(sourceFile, path, type)) {
+          indexFile(inputFileBuilder, fileSystem, progress, sourceFile, path, type);
+        }
+      }
+    }
+  }
+
+  private void indexDirectory(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress status, File dirToIndex) {
+    Collection<File> files = FileUtils.listFiles(dirToIndex, FILE_FILTER, DIR_FILTER);
+    for (File sourceFile : files) {
+      String path = pathResolver.relativePath(fileSystem.baseDir(), sourceFile);
+      if (path == null) {
+        LoggerFactory.getLogger(getClass()).warn(String.format(
+          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.TEST)) {
+          indexFile(inputFileBuilder, fileSystem, status, sourceFile, path, InputFile.Type.TEST);
+        }
+      }
+    }
+  }
+
+  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)) {
+      fs.add(inputFile);
+      status.markAsIndexed(inputFile);
+    }
+  }
+
+  private boolean accept(InputFile inputFile) {
+    // InputFileFilter extensions
+    for (InputFileFilter filter : filters) {
+      if (!filter.accept(inputFile)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  private static class Progress {
+    private final Set<InputFile> removed;
+    private final Set<InputFile> indexed;
+
+    Progress(Iterable<InputFile> removed) {
+      this.removed = Sets.newHashSet(removed);
+      this.indexed = new HashSet<InputFile>();
+    }
+
+    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();
+    }
+  }
+
+}
index 298eeef36542d36842ece94323db8e523a434e65..166db70aecc7affe7c3c8f46db83f657a709c6c2 100644 (file)
@@ -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 (file)
index 0000000..beb959f
--- /dev/null
@@ -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 (file)
index e7e5a07..0000000
+++ /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<InputFileFilter> 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<String, Collection<String>> entry : query.attributes().entrySet()) {
-      filters.add(new AttributeFilter(entry.getKey(), entry.getValue()));
-    }
-
-    if (analysisMode.isIncremental()) {
-      Collection<String> 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<InputFileFilter> filters() {
-    return filters;
-  }
-
-  boolean accept(InputFile inputFile) {
-    for (InputFileFilter filter : filters) {
-      if (!filter.accept(inputFile)) {
-        return false;
-      }
-    }
-    return true;
-  }
-}
index 2d402d358b0d570146bccaf6f4dc27d10727022e..f2967d5a1fb577d3ddb3308fb61178fc2cf82498 100644 (file)
@@ -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());
index 38b56313cc4aff75606a0fd47b711d5b20052e97..6464f1519689d650d945e63e4c0aba9fbde5a769 100644 (file)
  */
 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;
index 9f0af6a2d6d2d26a14f2c0dd0c39646561313faa..9f8f79f7dd733f204132a85cb7e55d6f02b6593f 100644 (file)
  */
 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.<String, String>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<File> sourceDirs = InputFile.TYPE_MAIN.equals(inputFile.type()) ? fs.sourceDirs() : fs.testDirs();
+    List<File> 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());
         }
       }
     }
index ce24330fd421b9b0964cbadb8eaa4caa4e33b216..ae0143353e4b34709d3deea6d1f06f3eef4f0d4e 100644 (file)
@@ -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);
   }
 }
index 7ab06aec59b76397b945d23c0e0f78761117ab1c..0a4dde8fd60d258204d6752ba5e6cbfc73ffe176 100644 (file)
 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<String, InputFile> 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<InputFile> cache;
 
   public InputFileCache(Caches caches) {
     cache = caches.createCache("inputFiles");
   }
 
-  public Iterable<InputFile> byModule(String moduleKey) {
-    return cache.values(moduleKey);
+  public Iterable<InputFile> all() {
+    return cache.values();
   }
 
-  @CheckForNull
-  public InputFile byPath(String moduleKey, String path) {
-    return cache.get(moduleKey, path);
+  public Iterable<InputFile> 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<InputFile> all() {
-    return cache.allValues();
+  public InputFileCache put(String moduleKey, InputFile inputFile) {
+    cache.put(moduleKey, inputFile.relativePath(), inputFile);
+    return this;
   }
 
-  public Set<String> 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);
   }
 }
index f4f876905a775bcae0af6fd8fc3da129f433f008..c34e0d421846e1afb2d8d0b40fb7a0c81d460991 100644 (file)
@@ -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 (file)
index 0000000..90d885e
--- /dev/null
@@ -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<InputFile> 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/PathPattern.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/PathPattern.java
deleted file mode 100644 (file)
index 9c9d00a..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.batch.scan.filesystem;
-
-import org.apache.commons.io.FilenameUtils;
-import org.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.utils.PathUtils;
-import org.sonar.api.utils.WildcardPattern;
-
-import java.io.File;
-
-abstract class PathPattern {
-
-  private static final Logger LOG = LoggerFactory.getLogger(PathPattern.class);
-
-  final WildcardPattern pattern;
-
-  PathPattern(String pattern) {
-    this.pattern = WildcardPattern.create(pattern);
-  }
-
-  abstract boolean match(Resource resource);
-
-  abstract boolean match(InputFile inputFile);
-
-  abstract boolean match(File ioFile, String relativePathFromBasedir);
-
-  abstract boolean match(InputFile inputFile, boolean caseSensitiveFileExtension);
-
-  abstract boolean supportResource();
-
-  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) {
-    PathPattern[] result = new PathPattern[s.length];
-    for (int i = 0; i < s.length; i++) {
-      result[i] = create(s[i]);
-    }
-    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);
-      return pattern.match(path);
-    }
-
-    @Override
-    boolean match(InputFile inputFile) {
-      return match(inputFile, true);
-    }
-
-    @Override
-    boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) {
-      String path = inputFile.absolutePath();
-      if (!caseSensitiveFileExtension) {
-        String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName()));
-        if (StringUtils.isNotBlank(extension)) {
-          StringUtils.removeEndIgnoreCase(path, extension);
-          path = path + extension;
-        }
-      }
-      return pattern.match(path);
-    }
-
-    @Override
-    boolean match(Resource resource) {
-      return false;
-    }
-
-    @Override
-    boolean supportResource() {
-      return false;
-    }
-
-    @Override
-    public String toString() {
-      return "file:" + pattern.toString();
-    }
-  }
-
-  /**
-   * Path relative to module basedir
-   */
-  private static class RelativePathPattern extends PathPattern {
-    private RelativePathPattern(String pattern) {
-      super(pattern);
-    }
-
-    @Override
-    boolean match(File ioFile, String relativePathFromBasedir) {
-      return relativePathFromBasedir != null && pattern.match(relativePathFromBasedir);
-    }
-
-    @Override
-    boolean match(InputFile inputFile) {
-      return match(inputFile, true);
-    }
-
-    @Override
-    boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) {
-      String path = inputFile.path();
-      if (!caseSensitiveFileExtension) {
-        String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName()));
-        if (StringUtils.isNotBlank(extension)) {
-          path = StringUtils.removeEndIgnoreCase(path, extension);
-          path = path + extension;
-        }
-      }
-      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();
-    }
-  }
-
-  static String sanitizeExtension(String suffix) {
-    return StringUtils.lowerCase(StringUtils.removeStart(suffix, "."));
-  }
-}
index 30f6b5c6fb6129341503aed07d3a10ccd025c22a..373a582dec29cd644ef8cddda8046979f70b584a 100644 (file)
@@ -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<File> getSourceFiles(Language... langs) {
-    List<File> 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<File> getJavaSourceFiles() {
@@ -156,15 +149,15 @@ public class ProjectFileSystemAdapter implements ProjectFileSystem {
   }
 
   public List<File> getTestFiles(Language... langs) {
-    List<File> 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<InputFile> mainFiles(String... langs) {
-    List<InputFile> result = Lists.newArrayList();
-    Iterable<org.sonar.api.scan.filesystem.InputFile> 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<InputFile> testFiles(String... langs) {
-    List<InputFile> result = Lists.newArrayList();
-    Iterable<org.sonar.api.scan.filesystem.InputFile> files = target.inputFiles(FileQuery.onTest().onLanguage(langs));
-    for (org.sonar.api.scan.filesystem.InputFile file : files) {
-      String sourceDir = file.attribute(org.sonar.api.scan.filesystem.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<FilePredicate> list = Lists.newArrayList();
+    for (Language language : languages) {
+      list.add(FilePredicates.hasLanguage(language.getKey()));
     }
-    return result;
+    return FilePredicates.or(list);
   }
 }
index adadcdf391b1001c2e710bf63c2e70b58a2afb9a..03402929c1f568fee2da0db658983e466fd8b1ac 100644 (file)
@@ -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;
   }
 }
index fecede739bb2947997f0d651b252e420528f46cf..3922924a7fc0fac87e221b1bf4a01c89b111e8ff 100644 (file)
@@ -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<String, Language> moduleLanguages = new HashMap<String, Language>();
-
-  private Languages languages;
+  private final List<String> 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<String> keys() {
-    return moduleLanguages.keySet();
-  }
-
-  public Collection<Language> 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 (file)
index 277b9c4..0000000
+++ /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<String> 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);
-  }
-}
index 7c835ecce71b3d5bcb2fbe1a306d1ab8fef9c381..2c55eb1162141826e5da7ad39a97f92ca9ccf592 100644 (file)
@@ -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();
index a888e5eb6bb50c63b47f626412718f6be8f11447..83ed6836110e20f0da52ffcfdaa77c0b1530bd1d 100644 (file)
 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<String, String> 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<String> 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.<String>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<String, String> cache = caches.createCache("components");
+    Cache<String> 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<String, Float> 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<String, Float> 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<String, String> cache = caches.createCache("issues");
-    assertThat(cache.get("foo")).isNull();
-    assertThat(cache.get("group", "foo")).isNull();
+  public void two_parts_key() throws Exception {
+    Cache<String> 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.<String>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.<String>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<String, String> cache = caches.createCache("issues");
-    assertThat(cache.get("foo")).isNull();
-  }
-
-  @Test
-  public void test_keyset_of_group() {
-    Cache<String, Float> 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<String, Float> 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<String, Float> 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<String, Float> 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<String> 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.<String>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.<String>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<String, Float> cache = caches.createCache("issues");
-    assertThat(cache.groups()).isEmpty();
+  public void remove_versus_clear() throws Exception {
+    Cache<String> 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<String, Float> 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.<Float>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<String> cache = caches.createCache("empty");
 
-  @Test
-  public void test_entries_of_group() throws PersistitException {
-    Cache<String, Float> 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.<Float>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();
   }
 }
index 2e206f93071a4e1d55caafbcfc44f7309bbd3460..df166adad957569a317914535464b13507d857b8 100644 (file)
@@ -83,16 +83,16 @@ public class CachesTest {
   @Test
   public void should_create_cache() throws Exception {
     caches.start();
-    Cache<String, Element> cache = caches.createCache("foo");
+    Cache<Element> cache = caches.createCache("foo");
     assertThat(cache).isNotNull();
   }
 
   @Test
   public void should_not_create_cache_twice() throws Exception {
     caches.start();
-    caches.<String, Element>createCache("foo");
+    caches.<Element>createCache("foo");
     try {
-      caches.<String, Element>createCache("foo");
+      caches.<Element>createCache("foo");
       fail();
     } catch (IllegalStateException e) {
       // ok
index f669da66c7e9a1fe4d5df4190b50b0325e907241..776f9b4a4b75300478020e12d1e82c9995fe27ff 100644 (file)
@@ -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) {
index 8f8eba536f7b2803c10503ab4b93b9900f26badc..31001bc9843bacd7dfb7003d4388cc9fa0b8b2fc 100644 (file)
 
 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);
index 22ec32b6e227035e12fa51d74f7672a545d8d8ea..68d1cde8c4a8c472da843a0dca99dcd80cc75bd5 100644 (file)
@@ -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<Language> 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.<Language>emptyList());
+    settings.setProperty("sonar.profile", "Unknown");
+    when(languages.keys()).thenReturn(Collections.<String>emptyList());
 
     ProfileLogger profileLogger = new ProfileLogger(settings, languages, profiles);
 
index 8d4bdbda1ca2b8c1a866baa3feef7ac19b0b55ef..bda70b4e5eead699ecd359ebeabf849780d3f324 100644 (file)
@@ -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.<ModuleQProfiles.QProfile>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 (file)
index c5abdd3..0000000
+++ /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();
-
-  }
-}
index 3bd5f2dbbdcc17d74b01492e0c5503cd4f38e082..1744309ea1d585fbe4411ac848cca4f75e2da599 100644 (file)
@@ -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);
   }
 
 }
index 4041895dff45612dff09e60042451c698f64c061..cccc194e107bf4cfd4111c2532c21c8a84568aec 100644 (file)
  */
 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<InputFile> inputFiles = fs.inputFiles(FileQuery.onSource());
+    Iterable<InputFile> inputFiles = fs.inputFiles(FilePredicates.hasType(InputFile.Type.MAIN));
     assertThat(inputFiles).containsOnly(mainInput);
 
-    List<File> files = fs.files(FileQuery.onSource());
+    Iterable<File> 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);
   }
 
index 6fafbb57e2038abaf9f211a6562837948b886934..5592ecfa204e59cfcdd82c8fd8847503da5d2f4f 100644 (file)
  */
 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.<String, String>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);
   }
 }
index 1f2551a119ce9121bfb2381e7b3c3b0239b6025f..c08dbe3b1c4e3df3438d56f9fbbc0c9eccea61f9 100644 (file)
  */
 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();
   }
index 70f00226796a209e1ddbb2f1dadcb3372c2497ee..6083f224a5cc7c8b60a5df644e0da82298391f0a 100644 (file)
@@ -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
index b0a4703d77307646772c3b044a35e5782e2de305..2a92f70d84ab2d7533f674c12b54a2ac5beac125 100644 (file)
@@ -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 (file)
index 443f706..0000000
+++ /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);
-  }
-}
index a8ce2a9194da88f98049f21a1554c4055bfb95f3..21afc18791c099f50f0b6cbe8fdacb9af2787d7b 100644 (file)
  */
 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();
   }
index 5eba1db22609937a74afcc45aa0c829018b0fd9d..c5ee1254df264a2fae9aff9c20e87b838a7c1a12 100644 (file)
@@ -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();
index 4e19c94bd1b329a18c68ec8aaf6cb61ad72492f3..fadd7426a0cece93091fdbd1be354ba9aa005ab9 100644 (file)
@@ -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");
 
   }
 }
index a829e350f3c5d203cadf79a1027f3e663d4ffa26..3cfbb4bd64d090ab1ea6294fd4561091de975242 100644 (file)
  */
 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.<String, String>newHashMap()));
-    cache.put("struts-core", DefaultInputFile.create(temp.newFile(), Charsets.UTF_8, "src/main/java/Foo.java", Maps.<String, String>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);
index 4f4551525126fbe61214f87df9f2dd02173b2f23..308604508c725df72c2b111cbc86aca2ed1fb175 100644 (file)
  */
 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 {
index 79404404f8fa1a4f4a462f75492bcafe8915e8cf..3c99e842b8961ffbc42a1f313f86ade716b62aa3 100644 (file)
@@ -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.<String, String>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);
   }
 }
index e4b8a34850941938d6e1367504b9afc9b893e026..8ea696629fc1ea9aed4cbeaf7b358fee3eea34d1 100644 (file)
@@ -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.<InputFile>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.<DefaultIssue>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/ComponentIndexerTest/encoding/CP1252Encoding.java b/sonar-batch/test-resources/org/sonar/batch/phases/ComponentIndexerTest/encoding/CP1252Encoding.java
new file mode 100644 (file)
index 0000000..5f80ef5
--- /dev/null
@@ -0,0 +1,13 @@
+public class Car {
+
+       public AClaèss() {
+       }
+
+       public int explicação() {
+         return 1;
+       }
+
+       public String getS() {
+               return "";
+       }
+}
diff --git a/sonar-batch/test-resources/org/sonar/batch/phases/ComponentIndexerTest/encoding/MacRomanEncoding.java b/sonar-batch/test-resources/org/sonar/batch/phases/ComponentIndexerTest/encoding/MacRomanEncoding.java
new file mode 100644 (file)
index 0000000..30e5200
--- /dev/null
@@ -0,0 +1,13 @@
+public class Car {
+
+  public ACla\8fss() {
+  }
+
+  public int explica\8d\8bo() {
+    return 1;
+  }
+
+  public String getS() {
+    return "";
+  }
+}
diff --git a/sonar-batch/test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/CP1252Encoding.java b/sonar-batch/test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/CP1252Encoding.java
deleted file mode 100644 (file)
index 5f80ef5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-public class Car {
-
-       public AClaèss() {
-       }
-
-       public int explicação() {
-         return 1;
-       }
-
-       public String getS() {
-               return "";
-       }
-}
diff --git a/sonar-batch/test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/MacRomanEncoding.java b/sonar-batch/test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/MacRomanEncoding.java
deleted file mode 100644 (file)
index 30e5200..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-public class Car {
-
-  public ACla\8fss() {
-  }
-
-  public int explica\8d\8bo() {
-    return 1;
-  }
-
-  public String getS() {
-    return "";
-  }
-}
index 730a62e14f188d8aae1068b53eab8ec41eeb40ad..e91b9d7673996e452e056000e4d7c6fb3d577d84 100644 (file)
@@ -33,6 +33,4 @@ public interface ModuleLanguages extends BatchComponent {
 
   Collection<String> keys();
 
-  Collection<Language> languages();
-
 }
index 42cb48fac6d5410e3bc45e9b0e8f0be763b60a7c..da1dcccfe49075dd4ae057b0db47d56fc2cac8b8 100644 (file)
@@ -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.
    * <p>
@@ -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 (file)
index 0000000..a659ad2
--- /dev/null
@@ -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/batch/fs/AndPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/AndPredicate.java
new file mode 100644 (file)
index 0000000..f1221c1
--- /dev/null
@@ -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 AndPredicate implements FilePredicate {
+
+  private final Iterable<FilePredicate> predicates;
+
+  AndPredicate(@Nullable Iterable<FilePredicate> predicates) {
+    this.predicates = predicates;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    for (FilePredicate predicate : predicates) {
+      if (!predicate.apply(f)) {
+        return false;
+      }
+    }
+    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 (file)
index 0000000..5cc7b7a
--- /dev/null
@@ -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 (file)
index 0000000..877666c
--- /dev/null
@@ -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<String> languages) {
+    List<FilePredicate> 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<FilePredicate> 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<FilePredicate> 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 (file)
index 0000000..7d285af
--- /dev/null
@@ -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;
+
+/**
+ * <p>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}:</p>
+ * <pre>
+ *   FileSystem fs = new DefaultFileSystem();
+ *   fs.add(new DefaultInputFile("src/foo/bar.php"));
+ * </pre>
+ *
+ * @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.
+   * <p/>
+   * 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
+   * <code>attributes</code> is empty.
+   * @see org.sonar.api.batch.fs.FilePredicates
+   */
+  Iterable<InputFile> 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 <code>attributes</code> 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<File> files(FilePredicate predicate);
+
+  /**
+   * Languages detected in all the files, whatever their type (main code or test)
+   */
+  Set<String> 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 (file)
index 0000000..fb37090
--- /dev/null
@@ -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 <code>{@link FileSystem}</code>.
+   * File separator is the forward slash ('/'), even on Microsoft Windows.
+   * <p/>
+   * Returns <code>src/main/java/com/Foo.java</code> if module base dir is
+   * <code>/absolute/path/to/module</code> and if file is
+   * <code>/absolute/path/to/module/src/main/java/com/Foo.java</code>.
+   * <p/>
+   * 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.
+   * <p/>
+   * 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/batch/fs/InputFileFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java
new file mode 100644 (file)
index 0000000..d9bdac2
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.BatchExtension;
+
+/**
+ * Extension point to complete the list of files to ignore during inspection
+ * @since 4.2
+ */
+public interface InputFileFilter extends BatchExtension {
+
+  // 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 (file)
index 0000000..9ab1578
--- /dev/null
@@ -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 (file)
index 0000000..5a83803
--- /dev/null
@@ -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 (file)
index 0000000..af36452
--- /dev/null
@@ -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<FilePredicate> predicates;
+
+  OrPredicate(@Nullable Iterable<FilePredicate> 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 (file)
index 0000000..2a34202
--- /dev/null
@@ -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-plugin-api/src/main/java/org/sonar/api/batch/fs/RelativePathPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/RelativePathPredicate.java
new file mode 100644 (file)
index 0000000..98453eb
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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;
+import org.sonar.api.batch.fs.internal.RelativePathIndex;
+
+/**
+ * @since 4.2
+ */
+class RelativePathPredicate implements FilePredicate, UniqueIndexPredicate {
+
+  private final String path;
+
+  RelativePathPredicate(String path) {
+    this.path = FilenameUtils.normalize(path, true);
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return path.equals(f.relativePath());
+  }
+
+  @Override
+  public Object value() {
+    return path;
+  }
+
+  @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 (file)
index 0000000..c80b483
--- /dev/null
@@ -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 (file)
index 0000000..84be0a2
--- /dev/null
@@ -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/main/java/org/sonar/api/batch/fs/UniqueIndexPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/UniqueIndexPredicate.java
new file mode 100644 (file)
index 0000000..693722d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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
+ */
+public interface UniqueIndexPredicate {
+
+  String indexId();
+
+  Object value();
+
+}
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 (file)
index 0000000..4754c1a
--- /dev/null
@@ -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<String> 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<InputFile> files = inputFiles(predicate);
+      return Iterables.getOnlyElement(files);
+    } catch (NoSuchElementException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public Iterable<InputFile> 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<File> files(FilePredicate predicate) {
+    return Iterables.transform(inputFiles(predicate), new Function<InputFile, File>() {
+      @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<String> languages() {
+    return languages;
+  }
+
+  public static abstract class Cache {
+    protected abstract Iterable<InputFile> 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<InputFile> files = Lists.newArrayList();
+    private final Map<String, Map<Object, InputFile>> fileMap = Maps.newHashMap();
+
+    @Override
+    public Iterable<InputFile> inputFiles() {
+      return Lists.newArrayList(files);
+    }
+
+    @Override
+    public InputFile inputFile(UniqueIndexPredicate predicate) {
+      Map<Object, InputFile> 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<Object, InputFile> attrValues = fileMap.get(indexId);
+      if (attrValues == null) {
+        attrValues = Maps.newHashMap();
+        fileMap.put(indexId, attrValues);
+      }
+      attrValues.put(value, inputFile);
+    }
+  }
+
+  private static class GuavaPredicate implements Predicate<InputFile> {
+    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 (file)
index 0000000..fa3f49d
--- /dev/null
@@ -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 (file)
index 0000000..a6a6d45
--- /dev/null
@@ -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<FileIndex> ALL = ImmutableList.<FileIndex>of(new RelativePathIndex());
+
+  @CheckForNull
+  Object valueOf(InputFile f);
+
+  String id();
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java
new file mode 100644 (file)
index 0000000..186226f
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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.apache.commons.lang.StringUtils;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.utils.PathUtils;
+import org.sonar.api.utils.WildcardPattern;
+
+import java.io.File;
+
+public abstract class PathPattern {
+
+  final WildcardPattern pattern;
+
+  PathPattern(String pattern) {
+    this.pattern = WildcardPattern.create(pattern);
+  }
+
+  public abstract boolean match(InputFile inputFile);
+
+  public abstract boolean match(File ioFile, String relativePathFromBasedir);
+
+  public abstract boolean match(InputFile inputFile, boolean caseSensitiveFileExtension);
+
+  public static PathPattern create(String s) {
+    String trimmed = StringUtils.trim(s);
+    if (StringUtils.startsWithIgnoreCase(trimmed, "file:")) {
+      return new AbsolutePathPattern(StringUtils.substring(trimmed, "file:".length()));
+    }
+    return new RelativePathPattern(trimmed);
+  }
+
+  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]);
+    }
+    return result;
+  }
+
+  private static class AbsolutePathPattern extends PathPattern {
+    private AbsolutePathPattern(String pattern) {
+      super(pattern);
+    }
+
+    @Override
+    public boolean match(File ioFile, String relativePathFromBasedir) {
+      String path = PathUtils.sanitize(ioFile.getAbsolutePath());
+      return pattern.match(path);
+    }
+
+    @Override
+    public boolean match(InputFile inputFile) {
+      return match(inputFile, true);
+    }
+
+    @Override
+    public boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) {
+      String path = inputFile.absolutePath();
+      if (!caseSensitiveFileExtension) {
+        String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName()));
+        if (StringUtils.isNotBlank(extension)) {
+          StringUtils.removeEndIgnoreCase(path, extension);
+          path = path + extension;
+        }
+      }
+      return pattern.match(path);
+    }
+
+    @Override
+    public String toString() {
+      return "file:" + pattern.toString();
+    }
+  }
+
+  /**
+   * Path relative to module basedir
+   */
+  private static class RelativePathPattern extends PathPattern {
+    private RelativePathPattern(String pattern) {
+      super(pattern);
+    }
+
+    @Override
+    public boolean match(File ioFile, String relativePathFromBasedir) {
+      return relativePathFromBasedir != null && pattern.match(relativePathFromBasedir);
+    }
+
+    @Override
+    public boolean match(InputFile inputFile) {
+      return match(inputFile, true);
+    }
+
+    @Override
+    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)) {
+          path = StringUtils.removeEndIgnoreCase(path, extension);
+          path = path + extension;
+        }
+      }
+      return path != null && pattern.match(path);
+    }
+
+    @Override
+    public String toString() {
+      return pattern.toString();
+    }
+  }
+
+  static String sanitizeExtension(String suffix) {
+    return StringUtils.lowerCase(StringUtils.removeStart(suffix, "."));
+  }
+}
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 (file)
index 0000000..dc52ed7
--- /dev/null
@@ -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/batch/fs/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java
new file mode 100644 (file)
index 0000000..80283a0
--- /dev/null
@@ -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.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 (file)
index 0000000..02490a1
--- /dev/null
@@ -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;
index d9908d4583b46331251fce4eb132c5871854d5c0..f7af0d48af58ab17c339b3f07eba713ae480f782 100644 (file)
@@ -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;
 
 /**
  * <p>This interface is not intended to be implemented by clients.</p>
index e8d05fe14d04e47d37c70f2b8fee276517f49c82..f1adc52953f60b62850a73fb2691ba2a8ab4c870 100644 (file)
@@ -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<FileType> types() {
-    return Collections2.transform(attributes.get(InputFile.ATTRIBUTE_TYPE), new Function<String, FileType>() {
+    return Collections2.transform(attributes.get("TYPE"), new Function<String, FileType>() {
       @Override
       public FileType apply(@Nullable String input) {
         return input != null ? FileType.valueOf(input) : null;
@@ -111,15 +111,15 @@ public class FileQuery {
   }
 
   public Collection<String> typeAttributes() {
-    return attributes.get(InputFile.ATTRIBUTE_TYPE);
+    return attributes.get("TYPE");
   }
 
   public Collection<String> 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<String> 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) {
index 6754503a9f864a060f52898e0e86eb181c2a8aa4..bf296dc8ad2bfde74ddf01623478df4bed424767 100644 (file)
@@ -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 (file)
index e811576..0000000
+++ /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 <code>{@link org.sonar.api.scan.filesystem.ModuleFileSystem}</code>.
-   * File separator is the forward slash ('/'), even on MSWindows.
-   * <p/>
-   * Returns <code>src/main/java/com/Foo.java</code> if module base dir is
-   * <code>/absolute/path/to/module</code> and if file is
-   * <code>/absolute/path/to/module/src/main/java/com/Foo.java</code>.
-   * <p/>
-   * 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 <code>TYPE_</code>, 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<String, String> attributes();
-}
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/scan/filesystem/InputFileFilter.java
deleted file mode 100644 (file)
index 7c58519..0000000
+++ /dev/null
@@ -1,34 +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 org.sonar.api.BatchExtension;
-
-/**
- * Implement this extension to limit the set of files to be analyzed. Global file inclusion/exclusion patterns
- * are already applied.
- *
- * @since 4.2
- */
-public interface InputFileFilter extends BatchExtension {
-
-  boolean accept(InputFile inputFile);
-
-}
index 9ea6ec091e9892d1f15ebf37a318f9bd16a3a54c..89d721d27ec92f93757b32b8db6ff6bc51eb53e3 100644 (file)
@@ -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<File> 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<File> testDirs();
 
   /**
@@ -70,29 +69,13 @@ public interface ModuleFileSystem extends BatchComponent {
    * </ul>
    * @deprecated since 4.2 sonar.binaries should be converted to language specific property
    */
-  @Deprecated
   List<File> binaryDirs();
 
   /**
    * Search for files. Never return null.
-   * @deprecated since 4.2 use {@link #inputFiles(FileQuery)}
    */
-  @Deprecated
   List<File> files(FileQuery query);
 
-  /**
-   * Search for input files. Never return null.
-   * @since 4.2
-   */
-  Iterable<InputFile> 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 (file)
index 9f75219..0000000
+++ /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: <code>/path/to/module/src/main/java</code> or <code>C:\path\to\module\src\main\java</code>
-   * @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<String, String> attributes;
-  private final String encoding;
-
-  private DefaultInputFile(File file, Charset encoding, String path, Map<String, String> 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.
-   * <p/>
-   * Usage: <code>InputFile.create(file, "src/main/java/com/Foo.java", attributes)</code>
-   */
-  public static DefaultInputFile create(File file, Charset encoding, String path, Map<String, String> 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<String, String> 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 (file)
index d7e2d73..0000000
+++ /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<String, String> attributes = new HashMap<String, String>();
-  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/main/java/org/sonar/api/scan/filesystem/internal/InputFiles.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/InputFiles.java
deleted file mode 100644 (file)
index 923cd32..0000000
+++ /dev/null
@@ -1,44 +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.collect.Lists;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * @since 4.0
- */
-public class InputFiles {
-  InputFiles() {
-    // static methods only
-  }
-
-  public static List<File> toFiles(Iterable<InputFile> inputFiles) {
-    List<File> files = Lists.newArrayList();
-    for (InputFile inputFile : inputFiles) {
-      files.add(inputFile.file());
-    }
-    return files;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/internal/package-info.java
deleted file mode 100644 (file)
index 2018417..0000000
+++ /dev/null
@@ -1,23 +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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.scan.filesystem.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
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 (file)
index 0000000..afbc74f
--- /dev/null
@@ -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 (file)
index a8346a0..0000000
+++ /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/InputFileBuilderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/internal/InputFileBuilderTest.java
deleted file mode 100644 (file)
index 6e70f14..0000000
+++ /dev/null
@@ -1,30 +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.junit.Test;
-
-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/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 (file)
index f0b522b..0000000
+++ /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);
-  }
-}
index 26f9ad15676823b8469e4d283706825d6fce3924..d7b35b3f6b6713388a57aa63cc01b41b853fc1ec 100644 (file)
@@ -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");
index 17c8b893cfae835ad03af6fe37e6d9c96dd80d2c..bfa4bf55207b57f94550cae36d097fe348207556 100644 (file)
@@ -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 (file)
index a3a00e8..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "TODO": true
-}