]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5389 New Analyzer API
authorJulien HENRY <julien.henry@sonarsource.com>
Thu, 12 Jun 2014 07:38:46 +0000 (09:38 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Mon, 16 Jun 2014 07:42:46 +0000 (09:42 +0200)
188 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/UserManagedMetrics.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/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/test/java/org/sonar/plugins/cpd/SonarEngineTest.java
pom.xml
sonar-batch-plugin-api/pom.xml [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchComponent.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchExtension.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/InstantiationStrategy.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/Analyzer.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerContext.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerDescriptor.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/AnalyzerIssue.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/package-info.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/AnalyzerMeasure.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/package-info.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/package-info.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/FilenameUtils.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/Preconditions.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/StringUtils.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/WildcardPattern.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/package-info.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/Language.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/package-info.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/Metric.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/package-info.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/QProfile.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/RuleKey.java [new file with mode: 0644]
sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/package-info.java [new file with mode: 0644]
sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java [new file with mode: 0644]
sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java [new file with mode: 0644]
sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java [new file with mode: 0644]
sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java [new file with mode: 0644]
sonar-batch/pom.xml
sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisMode.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java
sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java
sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java
sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java
sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java
sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java
sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java
sonar-batch/src/main/java/org/sonar/batch/languages/DeprecatedLanguagesReferential.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/languages/LanguagesReferential.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/languages/package-info.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/phases/Phase2Executor.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/phases/SensorMatcher.java
sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java
sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java
sonar-batch/src/main/java/org/sonar/batch/rule/QProfileEventsDecorator.java
sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java
sonar-batch/src/main/java/org/sonar/batch/rule/QProfileVerifier.java
sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java
sonar-batch/src/main/java/org/sonar/batch/rule/UsedQProfiles.java
sonar-batch/src/main/java/org/sonar/batch/rules/DefaultQProfileReferential.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/rules/QProfileWithId.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/rules/QProfilesReferential.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/rules/package-info.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/AnalyzerContextAdaptor.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/LanguageVerifier.java
sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java
sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicates.java
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/FileIndexer.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/LanguageDetectionFactory.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java
sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java
sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java
sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzersExecutor.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultAnalyzerContext.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan2/MeasureCache.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/scan2/Phase2Executor.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObserver.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObservers.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan2/package-info.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/settings/package-info.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/MetricProviderTest.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/medium/Scan2MediumTest.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/rule/ActiveRulesProviderTest.java
sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java
sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
sonar-batch/src/test/java/org/sonar/batch/rule/QProfileVerifierTest.java
sonar-batch/src/test/java/org/sonar/batch/rule/RulesProfileProviderTest.java
sonar-batch/src/test/java/org/sonar/batch/rule/UsedQProfilesTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/LanguageVerifierTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java
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/ExclusionFiltersTest.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/LanguageDetectionFactoryTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java
sonar-batch/src/test/resources/org/sonar/batch/medium/simple-project/sonar-project.properties [new file with mode: 0644]
sonar-batch/src/test/resources/org/sonar/batch/medium/simple-project/sources/Fake.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java
sonar-deprecated/src/main/java/org/sonar/api/batch/BatchExtensionDictionnary.java
sonar-plugin-api/pom.xml
sonar-plugin-api/src/main/java/org/sonar/api/batch/InstantiationStrategy.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileIndex.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathIndex.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/UniqueIndexPredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java
sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectFileSystem.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/AbstractSumChildrenDecoratorTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/TimeMachineQueryTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java

index cf5996477f68f6495622a84813252a7afcca8f01..1bc1d597a6b5963b8b8a8592ccc54c7225ce01fe 100644 (file)
@@ -29,24 +29,24 @@ public final class UserManagedMetrics implements Metrics {
   private static final String DOMAIN = "Management";
 
   public List<Metric> getMetrics() {
-    return ImmutableList.of(
-        new Metric.Builder("burned_budget", "Burned budget", Metric.ValueType.FLOAT)
-            .setDirection(Metric.DIRECTION_NONE)
-            .setQualitative(false)
-            .setDomain(DOMAIN)
-            .setUserManaged(true)
-            .create(),
-        new Metric.Builder("business_value", "Business value", Metric.ValueType.FLOAT)
-            .setDirection(Metric.DIRECTION_BETTER)
-            .setQualitative(true)
-            .setDomain(DOMAIN)
-            .setUserManaged(true)
-            .create(),
-        new Metric.Builder("team_size", "Team size", Metric.ValueType.INT)
-            .setDirection(Metric.DIRECTION_NONE)
-            .setQualitative(false)
-            .setDomain(DOMAIN)
-            .setUserManaged(true)
-            .create());
+    return ImmutableList.<Metric>of(
+      new Metric.Builder("burned_budget", "Burned budget", Metric.ValueType.FLOAT)
+        .setDirection(Metric.DIRECTION_NONE)
+        .setQualitative(false)
+        .setDomain(DOMAIN)
+        .setUserManaged(true)
+        .create(),
+      new Metric.Builder("business_value", "Business value", Metric.ValueType.FLOAT)
+        .setDirection(Metric.DIRECTION_BETTER)
+        .setQualitative(true)
+        .setDomain(DOMAIN)
+        .setUserManaged(true)
+        .create(),
+      new Metric.Builder("team_size", "Team size", Metric.ValueType.INT)
+        .setDirection(Metric.DIRECTION_NONE)
+        .setQualitative(false)
+        .setDomain(DOMAIN)
+        .setUserManaged(true)
+        .create());
   }
 }
index 3e758761c18b44356b5c3d80c3d3a5ae8869d8ab..b1c5dac5147bc5f0e5eaea4f72f20743201646e0 100644 (file)
@@ -23,7 +23,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.resources.Project;
 import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.batch.index.ComponentDataCache;
@@ -59,7 +59,7 @@ 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 = ((DefaultInputFile) inputFile).hash();
+      String hash = ((DeprecatedDefaultInputFile) inputFile).hash();
       if (hash != null) {
         map.put(inputFile.relativePath(), hash);
       }
index 4db5159ed48acbd6a3d488f669a84188c32fe0d8..29f5e64cce94750ce535ba6a4345918f3aa22dc3 100644 (file)
@@ -28,7 +28,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.resources.Project;
 import org.sonar.batch.index.ComponentDataCache;
 import org.sonar.batch.scan.filesystem.InputFileCache;
@@ -58,8 +58,8 @@ public class FileHashSensorTest {
   @Test
   public void store_file_hashes() throws Exception {
     when(fileCache.byModule("struts")).thenReturn(Lists.<InputFile>newArrayList(
-      new DefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"),
-      new DefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF")));
+      new DeprecatedDefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"),
+      new DeprecatedDefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF")));
 
     SensorContext sensorContext = mock(SensorContext.class);
     sensor.analyse(project, sensorContext);
@@ -72,8 +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(
-      new DefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"),
-      new DefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF")));
+      new DeprecatedDefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"),
+      new DeprecatedDefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF")));
 
     SensorContext sensorContext = mock(SensorContext.class);
     sensor.analyse(project, sensorContext);
index 7c24a89bb3a47ed96dd3ea80e60c0f661853620b..df4bc03611590ad2486b508b80b295dce48b18f1 100644 (file)
@@ -31,7 +31,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.config.Settings;
 import org.sonar.api.resources.Project;
 import org.sonar.api.utils.SonarException;
@@ -106,7 +106,7 @@ public class SonarBridgeEngine extends CpdEngine {
     TokenizerBridge bridge = new TokenizerBridge(mapping.getTokenizer(), fs.encoding().name(), getBlockSize(project, languageKey));
     for (InputFile inputFile : sourceFiles) {
       LOG.debug("Populating index from {}", inputFile);
-      String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
+      String resourceEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key();
       List<Block> blocks = bridge.chunk(resourceEffectiveKey, inputFile.file());
       index.insert(inputFile, blocks);
     }
@@ -118,7 +118,7 @@ public class SonarBridgeEngine extends CpdEngine {
     try {
       for (InputFile inputFile : sourceFiles) {
         LOG.debug("Detection of duplications for {}", inputFile);
-        String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
+        String resourceEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key();
         Collection<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
 
         Iterable<CloneGroup> filtered;
index 8255053db315636e1beea341a3c48740ac33494c..130206427fcedc3782a15400a20d34927263840b 100644 (file)
@@ -31,7 +31,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
@@ -115,7 +115,7 @@ public class SonarEngine extends CpdEngine {
 
     for (InputFile inputFile : sourceFiles) {
       LOG.debug("Populating index from {}", inputFile);
-      String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
+      String resourceEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key();
 
       List<Statement> statements;
 
@@ -141,7 +141,7 @@ public class SonarEngine extends CpdEngine {
     try {
       for (InputFile inputFile : sourceFiles) {
         LOG.debug("Detection of duplications for {}", inputFile);
-        String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
+        String resourceEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key();
 
         Collection<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
 
index ac2be64ac60b9b2f88d777ac330f06106e2e50c8..c8551a741668c3759681f9db7a90b7974c30a0b6 100644 (file)
@@ -25,7 +25,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.test.IsMeasure;
 import org.sonar.duplications.index.CloneGroup;
@@ -46,11 +46,11 @@ public class SonarEngineTest {
   public TemporaryFolder temp = new TemporaryFolder();
 
   SensorContext context = mock(SensorContext.class);
-  DefaultInputFile inputFile;
+  DeprecatedDefaultInputFile inputFile;
 
   @Before
   public void before() throws IOException {
-    inputFile = new DefaultInputFile("src/main/java/Foo.java");
+    inputFile = new DeprecatedDefaultInputFile("src/main/java/Foo.java");
     inputFile.setFile(temp.newFile("Foo.java"));
   }
 
@@ -138,7 +138,7 @@ public class SonarEngineTest {
 
   @Test
   public void shouldEscapeXmlEntities() throws IOException {
-    InputFile csharpFile = new DefaultInputFile("Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs")
+    InputFile csharpFile = new DeprecatedDefaultInputFile("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),
diff --git a/pom.xml b/pom.xml
index c1b603d8bfdbcd7af85439f3ef1088559c522664..2b63e2a50210da18674644308de5a11c547aae68 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -14,6 +14,7 @@
   <modules>
     <module>sonar-application</module>
     <module>sonar-batch</module>
+    <module>sonar-batch-plugin-api</module>
     <module>sonar-batch-maven-compat</module>
     <module>sonar-check-api</module>
     <module>sonar-colorizer</module>
         <artifactId>sonar-plugin-api</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.codehaus.sonar</groupId>
+        <artifactId>sonar-batch-plugin-api</artifactId>
+        <version>${project.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.codehaus.sonar</groupId>
         <artifactId>sonar-update-center-common</artifactId>
diff --git a/sonar-batch-plugin-api/pom.xml b/sonar-batch-plugin-api/pom.xml
new file mode 100644 (file)
index 0000000..f90ff63
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.codehaus.sonar</groupId>
+    <artifactId>sonar</artifactId>
+    <version>4.4-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>sonar-batch-plugin-api</artifactId>
+  <packaging>jar</packaging>
+
+  <name>SonarQube :: Batch Plugin API</name>
+  
+  <dependencies>
+    <dependency>
+      <groupId>com.google.code.findbugs</groupId>
+      <artifactId>jsr305</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.easytesting</groupId>
+      <artifactId>fest-assert</artifactId>
+    </dependency>
+  </dependencies>
+
+
+</project>
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java
new file mode 100644 (file)
index 0000000..830859e
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java
new file mode 100644 (file)
index 0000000..65a2e19
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.util.Collection;
+
+/**
+ * Factory of {@link org.sonar.api.batch.fs.FilePredicate}
+ *
+ * @since 4.2
+ */
+public interface FilePredicates {
+  /**
+   * Returns a predicate that always evaluates to true
+   */
+  FilePredicate all();
+
+  /**
+   * Returns a predicate that always evaluates to false
+   */
+  FilePredicate none();
+
+  /**
+   * Warning - not efficient because absolute path is not indexed yet.
+   */
+  FilePredicate hasAbsolutePath(String s);
+
+  /**
+   * TODO document that non-normalized path and Windows-style path are supported
+   */
+  FilePredicate hasRelativePath(String s);
+
+  FilePredicate matchesPathPattern(String inclusionPattern);
+
+  FilePredicate matchesPathPatterns(String[] inclusionPatterns);
+
+  FilePredicate doesNotMatchPathPattern(String exclusionPattern);
+
+  FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns);
+
+  FilePredicate hasPath(String s);
+
+  FilePredicate is(File ioFile);
+
+  FilePredicate hasLanguage(String language);
+
+  FilePredicate hasLanguages(Collection<String> languages);
+
+  FilePredicate hasLanguages(String... languages);
+
+  FilePredicate hasStatus(InputFile.Status status);
+
+  FilePredicate hasType(InputFile.Type type);
+
+  FilePredicate not(FilePredicate p);
+
+  FilePredicate or(Collection<FilePredicate> or);
+
+  FilePredicate or(FilePredicate... or);
+
+  FilePredicate or(FilePredicate first, FilePredicate second);
+
+  FilePredicate and(Collection<FilePredicate> and);
+
+  FilePredicate and(FilePredicate... and);
+
+  FilePredicate and(FilePredicate first, FilePredicate second);
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java
new file mode 100644 (file)
index 0000000..0c050f0
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.BatchComponent;
+
+import javax.annotation.CheckForNull;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.util.SortedSet;
+
+/**
+ * The {@link FileSystem} manages all the source files to be analyzed.
+ * <p/>
+ * This is not an extension point so it must not be implemented by plugins. It must be injected as a
+ * constructor parameter :
+ * <pre>
+ * public class MySensor implements Sensor {
+ *   private final FileSystem fs;
+ *
+ *   public MySensor(FileSystem fs) {
+ *     this.fs = fs;
+ *   }
+ * }
+ * </pre>
+ *
+ * <h2>How to use in unit tests</h2>
+ * 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.batch.fs.internal.DefaultInputFile},
+ * for example :
+ * <pre>
+ * DefaultFileSystem 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();
+
+  /**
+   * Factory of {@link FilePredicate}
+   */
+  FilePredicates predicates();
+
+  /**
+   * Returns the single element matching the predicate. If more than one elements match
+   * the predicate, then {@link IllegalArgumentException} is thrown. Returns {@code null}
+   * if no files match.
+   *
+   * <p/>
+   * How to use :
+   * <pre>
+   * InputFile file = fs.inputFile(fs.predicates().hasRelativePath("src/Foo.php"));
+   * </pre>
+   *
+   * @see #predicates()
+   */
+  @CheckForNull
+  InputFile inputFile(FilePredicate predicate);
+
+  /**
+   * Input files matching the given attributes. Return all the files if the parameter
+   * <code>attributes</code> is empty.
+   * <p/>
+   * <b>Important</b> - result is an {@link java.lang.Iterable} to benefit from streaming and decreasing
+   * memory consumption. It should be iterated only once, else copy it into a list :
+   * {@code com.google.common.collect.Lists.newArrayList(inputFiles(predicate))}
+   * <p/>
+   * How to use :
+   * <pre>
+   * FilePredicates p = fs.predicates();
+   * Iterable<InputFile> files = fs.inputFiles(p.and(p.hasLanguage("java"), p.hasType(InputFile.Type.MAIN)));
+   * </pre>
+   *
+   * @see #predicates()
+   */
+  Iterable<InputFile> inputFiles(FilePredicate predicate);
+
+  /**
+   * Returns true if at least one {@link org.sonar.api.batch.fs.InputFile} matches
+   * the given predicate. This method can be faster than checking if {@link #inputFiles(org.sonar.api.batch.fs.FilePredicate)}
+   * has elements.
+   * @see #predicates()
+   */
+  boolean hasFiles(FilePredicate predicate);
+
+  /**
+   * Files matching the given predicate.
+   * @see #predicates()
+   */
+  Iterable<File> files(FilePredicate predicate);
+
+  /**
+   * Languages detected in all files, whatever their type (main or test)
+   */
+  SortedSet<String> languages();
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java
new file mode 100644 (file)
index 0000000..83e9697
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 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>/path/to/module</code> and if file is
+   * <code>/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 if it is not
+   * set in project settings.
+   */
+  String language();
+
+  /**
+   * Does it contain main or test code ?
+   */
+  Type type();
+
+  /**
+   * Status regarding previous analysis
+   */
+  Status status();
+
+  /**
+   * Number of physical lines. This method supports all end-of-line characters. Returns
+   * zero if the file is empty.
+   */
+  int lines();
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java
new file mode 100644 (file)
index 0000000..166af9e
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.BatchExtension;
+
+/**
+ * Extension point to exclude some files from inspection
+ * @since 4.2
+ */
+public interface InputFileFilter extends BatchExtension {
+
+  // TODO requires a context (FileSystem) ?
+  boolean accept(InputFile f);
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java
new file mode 100644 (file)
index 0000000..367c1ea
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.internal.FilenameUtils;
+
+/**
+ * @since 4.2
+ */
+class AbsolutePathPredicate implements FilePredicate {
+
+  private final String path;
+
+  AbsolutePathPredicate(String path) {
+    this.path = FilenameUtils.normalize(path);
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return path.equals(f.absolutePath());
+  }
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java
new file mode 100644 (file)
index 0000000..0494ed5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.util.Collection;
+
+/**
+ * @since 4.2
+ */
+class AndPredicate implements FilePredicate {
+
+  private final Collection<FilePredicate> predicates;
+
+  AndPredicate(Collection<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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java
new file mode 100644 (file)
index 0000000..8036d90
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.io.File;
+import java.util.ArrayList;
+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 DefaultFilePredicates implements FilePredicates {
+  /**
+   * Client code should use {@link org.sonar.api.batch.fs.FileSystem#predicates()} to get an instance
+   */
+  DefaultFilePredicates() {
+  }
+
+  /**
+   * Returns a predicate that always evaluates to true
+   */
+  public FilePredicate all() {
+    return TruePredicate.TRUE;
+  }
+
+  /**
+   * Returns a predicate that always evaluates to false
+   */
+  public FilePredicate none() {
+    return FalsePredicate.FALSE;
+  }
+
+  /**
+   * Warning - not efficient because absolute path is not indexed yet.
+   */
+  public FilePredicate hasAbsolutePath(String s) {
+    return new AbsolutePathPredicate(s);
+  }
+
+  /**
+   * TODO document that non-normalized path and Windows-style path are supported
+   */
+  public FilePredicate hasRelativePath(String s) {
+    return new RelativePathPredicate(s);
+  }
+
+  public FilePredicate matchesPathPattern(String inclusionPattern) {
+    return new PathPatternPredicate(PathPattern.create(inclusionPattern));
+  }
+
+  public FilePredicate matchesPathPatterns(String[] inclusionPatterns) {
+    if (inclusionPatterns.length == 0) {
+      return TruePredicate.TRUE;
+    }
+    FilePredicate[] predicates = new FilePredicate[inclusionPatterns.length];
+    for (int i = 0; i < inclusionPatterns.length; i++) {
+      predicates[i] = new PathPatternPredicate(PathPattern.create(inclusionPatterns[i]));
+    }
+    return or(predicates);
+  }
+
+  public FilePredicate doesNotMatchPathPattern(String exclusionPattern) {
+    return not(matchesPathPattern(exclusionPattern));
+  }
+
+  public FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns) {
+    if (exclusionPatterns.length == 0) {
+      return TruePredicate.TRUE;
+    }
+    return not(matchesPathPatterns(exclusionPatterns));
+  }
+
+  public FilePredicate hasPath(String s) {
+    File file = new File(s);
+    if (file.isAbsolute()) {
+      return hasAbsolutePath(s);
+    }
+    return hasRelativePath(s);
+  }
+
+  public FilePredicate is(File ioFile) {
+    if (ioFile.isAbsolute()) {
+      return hasAbsolutePath(ioFile.getAbsolutePath());
+    }
+    return hasRelativePath(ioFile.getPath());
+  }
+
+  public FilePredicate hasLanguage(String language) {
+    return new LanguagePredicate(language);
+  }
+
+  public FilePredicate hasLanguages(Collection<String> languages) {
+    List<FilePredicate> list = new ArrayList<FilePredicate>();
+    for (String language : languages) {
+      list.add(hasLanguage(language));
+    }
+    return or(list);
+  }
+
+  public FilePredicate hasLanguages(String... languages) {
+    List<FilePredicate> list = new ArrayList<FilePredicate>();
+    for (String language : languages) {
+      list.add(hasLanguage(language));
+    }
+    return or(list);
+  }
+
+  public FilePredicate hasStatus(InputFile.Status status) {
+    return new StatusPredicate(status);
+  }
+
+  public FilePredicate hasType(InputFile.Type type) {
+    return new TypePredicate(type);
+  }
+
+  public FilePredicate not(FilePredicate p) {
+    return new NotPredicate(p);
+  }
+
+  public FilePredicate or(Collection<FilePredicate> or) {
+    return new OrPredicate(or);
+  }
+
+  public FilePredicate or(FilePredicate... or) {
+    return new OrPredicate(Arrays.asList(or));
+  }
+
+  public FilePredicate or(FilePredicate first, FilePredicate second) {
+    return new OrPredicate(Arrays.asList(first, second));
+  }
+
+  public FilePredicate and(Collection<FilePredicate> and) {
+    return new AndPredicate(and);
+  }
+
+  public FilePredicate and(FilePredicate... and) {
+    return new AndPredicate(Arrays.asList(and));
+  }
+
+  public FilePredicate and(FilePredicate first, FilePredicate second) {
+    return new AndPredicate(Arrays.asList(first, second));
+  }
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java
new file mode 100644 (file)
index 0000000..89abb9e
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.internal.Preconditions;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * @since 4.2
+ */
+public class DefaultFileSystem implements FileSystem {
+
+  private final Cache cache;
+  private final SortedSet<String> languages = new TreeSet<String>();
+  private File baseDir, workDir;
+  private Charset encoding;
+  private final FilePredicates predicates = new DefaultFilePredicates();
+
+  /**
+   * 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;
+  }
+
+  @Override
+  public File baseDir() {
+    return baseDir;
+  }
+
+  public DefaultFileSystem setEncoding(@Nullable Charset e) {
+    this.encoding = e;
+    return this;
+  }
+
+  @Override
+  public Charset encoding() {
+    return encoding == null ? Charset.defaultCharset() : encoding;
+  }
+
+  public boolean isDefaultJvmEncoding() {
+    return encoding == null;
+  }
+
+  public DefaultFileSystem setWorkDir(File d) {
+    this.workDir = d.getAbsoluteFile();
+    return this;
+  }
+
+  @Override
+  public File workDir() {
+    return workDir;
+  }
+
+  @Override
+  public InputFile inputFile(FilePredicate predicate) {
+    doPreloadFiles();
+    if (predicate instanceof RelativePathPredicate) {
+      return cache.inputFile((RelativePathPredicate) predicate);
+    }
+    Iterable<InputFile> files = inputFiles(predicate);
+    Iterator<InputFile> iterator = files.iterator();
+    if (!iterator.hasNext()) {
+      return null;
+    }
+    InputFile first = iterator.next();
+    if (!iterator.hasNext()) {
+      return first;
+    }
+
+    StringBuilder sb = new StringBuilder();
+    sb.append("expected one element but was: <" + first);
+    for (int i = 0; i < 4 && iterator.hasNext(); i++) {
+      sb.append(", " + iterator.next());
+    }
+    if (iterator.hasNext()) {
+      sb.append(", ...");
+    }
+    sb.append('>');
+
+    throw new IllegalArgumentException(sb.toString());
+
+  }
+
+  @Override
+  public Iterable<InputFile> inputFiles(FilePredicate predicate) {
+    doPreloadFiles();
+    return filter(cache.inputFiles(), predicate);
+  }
+
+  @Override
+  public boolean hasFiles(FilePredicate predicate) {
+    doPreloadFiles();
+    for (InputFile element : cache.inputFiles()) {
+      if (predicate.apply(element)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public Iterable<File> files(FilePredicate predicate) {
+    doPreloadFiles();
+    Collection<File> result = new ArrayList<File>();
+    for (InputFile element : inputFiles(predicate)) {
+      if (predicate.apply(element)) {
+        result.add(element.file());
+      }
+    }
+    return result;
+  }
+
+  public static Collection<InputFile> filter(Iterable<InputFile> target, FilePredicate predicate) {
+    Collection<InputFile> result = new ArrayList<InputFile>();
+    for (InputFile element : target) {
+      if (predicate.apply(element)) {
+        result.add(element);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Adds InputFile to the list and registers its language, if present.
+   */
+  public DefaultFileSystem add(InputFile inputFile) {
+    cache.add(inputFile);
+    if (inputFile.language() != null) {
+      languages.add(inputFile.language());
+    }
+    return this;
+  }
+
+  /**
+   * Adds a language to the list. To be used only for unit tests that need to use {@link #languages()} without
+   * using {@link #add(org.sonar.api.batch.fs.InputFile)}.
+   */
+  public DefaultFileSystem addLanguages(String language, String... others) {
+    languages.add(language);
+    Collections.addAll(languages, others);
+    return this;
+  }
+
+  @Override
+  public SortedSet<String> languages() {
+    doPreloadFiles();
+    return languages;
+  }
+
+  @Override
+  public FilePredicates predicates() {
+    return predicates;
+  }
+
+  /**
+   * This method is called before each search of files.
+   */
+  protected void doPreloadFiles() {
+    // nothing to do by default
+  }
+
+  public static abstract class Cache {
+    protected abstract Iterable<InputFile> inputFiles();
+
+    @CheckForNull
+    protected abstract InputFile inputFile(RelativePathPredicate predicate);
+
+    protected abstract void doAdd(InputFile inputFile);
+
+    final void add(InputFile inputFile) {
+      doAdd(inputFile);
+    }
+  }
+
+  /**
+   * Used only for testing
+   */
+  private static class MapCache extends Cache {
+    private final Map<String, InputFile> fileMap = new HashMap<String, InputFile>();
+
+    @Override
+    public Iterable<InputFile> inputFiles() {
+      return new ArrayList<InputFile>(fileMap.values());
+    }
+
+    @Override
+    public InputFile inputFile(RelativePathPredicate predicate) {
+      return fileMap.get(predicate.path());
+    }
+
+    @Override
+    protected void doAdd(InputFile inputFile) {
+      fileMap.put(inputFile.relativePath(), inputFile);
+    }
+  }
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java
new file mode 100644 (file)
index 0000000..5767d74
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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;
+import org.sonar.batch.api.internal.FilenameUtils;
+
+import javax.annotation.CheckForNull;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * @since 4.2
+ */
+public class DefaultInputFile implements 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;
+
+  public DefaultInputFile(String relativePath) {
+    this.relativePath = FilenameUtils.normalize(relativePath);
+  }
+
+  @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() {
+    if (absolutePath == null) {
+      throw new IllegalStateException("Can not return the java.io.File because absolute path is not set (see method setFile(java.io.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;
+  }
+
+  /**
+   * Digest hash of the file. 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;
+  }
+
+  /**
+   * Component key. It's 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);
+    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;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof DefaultInputFile)) {
+      return false;
+    }
+
+    DefaultInputFile that = (DefaultInputFile) o;
+    return relativePath.equals(that.relativePath);
+  }
+
+  @Override
+  public int hashCode() {
+    return relativePath.hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return "[relative=" + relativePath + ", abs=" + absolutePath + "]";
+  }
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java
new file mode 100644 (file)
index 0000000..b092f84
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+class FalsePredicate implements FilePredicate {
+
+  static final FilePredicate FALSE = new FalsePredicate();
+
+  @Override
+  public boolean apply(InputFile inputFile) {
+    return false;
+  }
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java
new file mode 100644 (file)
index 0000000..77d2f74
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java
new file mode 100644 (file)
index 0000000..5f2359e
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java
new file mode 100644 (file)
index 0000000..a887c63
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * @since 4.2
+ */
+class OrPredicate implements FilePredicate {
+
+  private final Collection<FilePredicate> predicates;
+
+  OrPredicate(Collection<FilePredicate> predicates) {
+    if (predicates.isEmpty()) {
+      this.predicates = Arrays.asList(TruePredicate.TRUE);
+    } else {
+      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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java
new file mode 100644 (file)
index 0000000..cdcfd8e
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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;
+import org.sonar.batch.api.internal.FilenameUtils;
+import org.sonar.batch.api.internal.StringUtils;
+import org.sonar.batch.api.internal.WildcardPattern;
+
+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(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(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)) {
+          path = 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(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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java
new file mode 100644 (file)
index 0000000..0cf614b
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @since 4.2
+ */
+class PathPatternPredicate implements FilePredicate {
+
+  private final PathPattern pattern;
+
+  PathPatternPredicate(PathPattern pattern) {
+    this.pattern = pattern;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return pattern.match(f);
+  }
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java
new file mode 100644 (file)
index 0000000..d0c4a3d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.internal.FilenameUtils;
+
+/**
+ * @since 4.2
+ */
+public class RelativePathPredicate implements FilePredicate {
+
+  private final String path;
+
+  RelativePathPredicate(String path) {
+    this.path = FilenameUtils.normalize(path);
+  }
+
+  public String path() {
+    return path;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return path.equals(f.relativePath());
+  }
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java
new file mode 100644 (file)
index 0000000..fe7c934
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java
new file mode 100644 (file)
index 0000000..ec2aebd
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+class TruePredicate implements FilePredicate {
+
+  static final FilePredicate TRUE = new TruePredicate();
+
+  @Override
+  public boolean apply(InputFile inputFile) {
+    return true;
+  }
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java
new file mode 100644 (file)
index 0000000..ac8b6d5
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java
new file mode 100644 (file)
index 0000000..713fe61
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java
new file mode 100644 (file)
index 0000000..c97db58
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.fs;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchComponent.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchComponent.java
new file mode 100644 (file)
index 0000000..d48e225
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api;
+
+/**
+ * Dependency Injection : all the classes implementing this interface are available in the batch IoC container.
+ * Just add a parameter to the constructor of your component.
+ *
+ * @since 4.4
+ */
+public interface BatchComponent {
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchExtension.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchExtension.java
new file mode 100644 (file)
index 0000000..1a774a1
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api;
+
+
+/**
+ * Batch extension point.
+ *
+ * @since 4.4
+ */
+public interface BatchExtension extends BatchComponent {
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/InstantiationStrategy.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/InstantiationStrategy.java
new file mode 100644 (file)
index 0000000..521c6dd
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Define instantiation strategy of batch extensions. If an extension is not annotated, then default value
+ * is {@link #PER_PROJECT}.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface InstantiationStrategy {
+
+  /**
+   * Shared extension. Lifecycle is the full analysis.
+   */
+  String PER_BATCH = "PER_BATCH";
+
+  /**
+   * Created and initialized for each project and sub-project (a project is a module in Maven terminology).
+   */
+  String PER_PROJECT = "PER_PROJECT";
+
+  String value();
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/Analyzer.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/Analyzer.java
new file mode 100644 (file)
index 0000000..6123545
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.analyzer;
+
+import org.sonar.batch.api.BatchExtension;
+
+/**
+ * <p>
+ * An Analyzer is invoked once during the analysis of a project. The analyzer can parse a flat file, connect to a web server... Analyzers are
+ * used to add measure and issues at file level.
+ * </p>
+ *
+ * <p>
+ * For example the Cobertura Analyzer parses Cobertura report and saves the first-level of measures on files.
+ * </p>
+ *
+ * @since 4.4
+ */
+public interface Analyzer extends BatchExtension {
+
+  /**
+   * Describe what this analyzer is doing.
+   * @return
+   */
+  AnalyzerDescriptor describe();
+
+  /**
+   * The method that is going to be run when the analyzer is called
+   *
+   * @param context the context
+   */
+  void analyse(AnalyzerContext context);
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerContext.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerContext.java
new file mode 100644 (file)
index 0000000..e29dfaf
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.analyzer;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.analyzer.issue.AnalyzerIssue;
+import org.sonar.batch.api.analyzer.measure.AnalyzerMeasure;
+import org.sonar.batch.api.measures.Metric;
+
+import javax.annotation.CheckForNull;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+/**
+ * @since 4.4
+ */
+public interface AnalyzerContext {
+
+  // ----------- MEASURES --------------
+
+  /**
+   * Find a project measure.
+   */
+  @CheckForNull
+  AnalyzerMeasure<?> getMeasure(String metricKey);
+
+  /**
+   * Find a project measure.
+   */
+  @CheckForNull
+  <G extends Serializable> AnalyzerMeasure<G> getMeasure(Metric<G> metric);
+
+  /**
+   * Find a file measure.
+   */
+  @CheckForNull
+  AnalyzerMeasure<?> getMeasure(InputFile file, String metricKey);
+
+  /**
+   * Find a file measure.
+   */
+  @CheckForNull
+  <G extends Serializable> AnalyzerMeasure<G> getMeasure(InputFile file, Metric<G> metric);
+
+  /**
+   * Add a measure.
+   */
+  void addMeasure(AnalyzerMeasure<?> measure);
+
+  // ----------- ISSUES --------------
+
+  /**
+   * Add an issue.
+   */
+  void addIssue(AnalyzerIssue issue);
+
+  /**
+   * Add a list of issues.
+   */
+  void addIssues(Collection<AnalyzerIssue> issues);
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerDescriptor.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerDescriptor.java
new file mode 100644 (file)
index 0000000..0b97200
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.analyzer;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.measures.Metric;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public class AnalyzerDescriptor {
+
+  private final String name;
+  private final Metric<?>[] dependsOn;
+  private final Metric<?>[] provides;
+  private final String[] languages;
+  private final InputFile.Type[] types;
+
+  private AnalyzerDescriptor(Builder builder) {
+    this.name = builder.name;
+    this.dependsOn = builder.dependsOn != null ? builder.dependsOn : new Metric<?>[0];
+    this.provides = builder.provides != null ? builder.provides : new Metric<?>[0];
+    this.languages = builder.languages != null ? builder.languages : new String[0];
+    this.types = builder.types;
+  }
+
+  public String name() {
+    return name;
+  }
+
+  public Metric<?>[] dependsOn() {
+    return dependsOn;
+  }
+
+  public Metric<?>[] provides() {
+    return provides;
+  }
+
+  public Collection<String> languages() {
+    return Arrays.asList(languages);
+  }
+
+  public InputFile.Type[] types() {
+    return types;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+
+    private String name;
+    private Metric<?>[] dependsOn;
+    private Metric<?>[] provides;
+    private String[] languages;
+    private InputFile.Type[] types;
+
+    public Builder name(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public Builder dependsOn(Metric<?>... metrics) {
+      this.dependsOn = metrics;
+      return this;
+    }
+
+    public Builder provides(Metric<?>... metrics) {
+      this.provides = metrics;
+      return this;
+    }
+
+    public Builder runOnLanguages(String... languageKeys) {
+      this.languages = languageKeys;
+      return this;
+    }
+
+    public Builder runOnTypes(InputFile.Type... types) {
+      this.types = types;
+      return this;
+    }
+
+    public AnalyzerDescriptor build() {
+      return new AnalyzerDescriptor(this);
+    }
+
+  }
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/AnalyzerIssue.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/AnalyzerIssue.java
new file mode 100644 (file)
index 0000000..f39d884
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.analyzer.issue;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.analyzer.Analyzer;
+import org.sonar.batch.api.internal.Preconditions;
+import org.sonar.batch.api.rules.RuleKey;
+
+import javax.annotation.Nullable;
+
+/**
+ * Issue reported by an {@link Analyzer}
+ *
+ * @since 4.4
+ */
+public class AnalyzerIssue {
+
+  private final InputFile inputFile;
+  private final RuleKey ruleKey;
+  private final String message;
+  private final Integer line;
+  private final Double effortToFix;
+
+  private AnalyzerIssue(Builder builder) {
+    this.inputFile = builder.file;
+    this.ruleKey = builder.ruleKey;
+    this.message = builder.message;
+    this.line = builder.line;
+    this.effortToFix = builder.effortToFix;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  @Nullable
+  public InputFile inputFile() {
+    return inputFile;
+  }
+
+  public RuleKey ruleKey() {
+    return ruleKey;
+  }
+
+  public String message() {
+    return message;
+  }
+
+  public Integer line() {
+    return line;
+  }
+
+  @Nullable
+  public Double effortToFix() {
+    return effortToFix;
+  }
+
+  public static class Builder {
+
+    private Boolean onProject = null;
+    private InputFile file;
+    private RuleKey ruleKey;
+    private String message;
+    private Integer line;
+    private Double effortToFix;
+
+    public AnalyzerIssue build() {
+      return new AnalyzerIssue(this);
+    }
+
+    public Builder ruleKey(RuleKey ruleKey) {
+      this.ruleKey = ruleKey;
+      return this;
+    }
+
+    public Builder onFile(InputFile file) {
+      Preconditions.checkState(onProject == null, "onFile or onProject can be called only once");
+      Preconditions.checkNotNull(file, "InputFile should be non null");
+      this.file = file;
+      this.onProject = false;
+      return this;
+    }
+
+    public Builder onProject() {
+      Preconditions.checkState(onProject == null, "onFile or onProject can be called only once");
+      this.file = null;
+      this.onProject = true;
+      return this;
+    }
+
+    public Builder atLine(int line) {
+      this.line = line;
+      return this;
+    }
+
+    public Builder effortToFix(@Nullable Double effortToFix) {
+      this.effortToFix = effortToFix;
+      return this;
+    }
+
+    public Builder message(String message) {
+      this.message = message;
+      return this;
+    }
+
+  }
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/package-info.java
new file mode 100644 (file)
index 0000000..70a6600
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.analyzer.issue;
\ No newline at end of file
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/AnalyzerMeasure.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/AnalyzerMeasure.java
new file mode 100644 (file)
index 0000000..3d74dca
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.analyzer.measure;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.internal.Preconditions;
+import org.sonar.batch.api.measures.Metric;
+
+import javax.annotation.Nullable;
+
+import java.io.Serializable;
+
+public class AnalyzerMeasure<G extends Serializable> implements Serializable {
+
+  private final InputFile inputFile;
+  private final String metricKey;
+  private final G value;
+
+  private AnalyzerMeasure(Builder<G> builder) {
+    Preconditions.checkNotNull(builder.value, "Measure value can't be null");
+    Preconditions.checkNotNull(builder.metricKey, "Measure metricKey can't be null");
+    this.inputFile = builder.file;
+    this.metricKey = builder.metricKey;
+    this.value = builder.value;
+  }
+
+  @Nullable
+  public InputFile inputFile() {
+    return inputFile;
+  }
+
+  public String metricKey() {
+    return metricKey;
+  }
+
+  public Serializable value() {
+    return value;
+  }
+
+  public static <G extends Serializable> Builder<G> builder() {
+    return new Builder<G>();
+  }
+
+  public static class Builder<G extends Serializable> {
+
+    private Boolean onProject = null;
+    private InputFile file;
+    private String metricKey;
+    private G value;
+
+    public Builder<G> onFile(InputFile file) {
+      Preconditions.checkState(onProject == null, "onFile or onProject can be called only once");
+      Preconditions.checkNotNull(file, "InputFile should be non null");
+      this.file = file;
+      this.onProject = false;
+      return this;
+    }
+
+    public Builder<G> onProject() {
+      Preconditions.checkState(onProject == null, "onFile or onProject can be called only once");
+      this.file = null;
+      this.onProject = true;
+      return this;
+    }
+
+    private Builder<G> metricKey(String metricKey) {
+      Preconditions.checkState(metricKey != null, "Metric already defined");
+      this.metricKey = metricKey;
+      return this;
+    }
+
+    public Builder<G> forMetric(Metric<G> metric) {
+      return metricKey(metric.key());
+    }
+
+    public Builder<G> withValue(G value) {
+      Preconditions.checkState(value != null, "Measure value already defined");
+      Preconditions.checkNotNull(value, "Measure value can't be null");
+      this.value = value;
+      return this;
+    }
+
+    public AnalyzerMeasure<G> build() {
+      return new AnalyzerMeasure<G>(this);
+    }
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (!(obj instanceof AnalyzerMeasure)) {
+      return false;
+    }
+    AnalyzerMeasure<?> other = (AnalyzerMeasure<?>) obj;
+    return metricKey.equals(other.metricKey)
+      && value.equals(other.value)
+      && (inputFile == null ? other.inputFile == null : inputFile.equals(other.inputFile));
+  }
+
+  @Override
+  public int hashCode() {
+    return metricKey.hashCode()
+      + value.hashCode()
+      + (inputFile != null ? inputFile.hashCode() : 0);
+  }
+
+  @Override
+  public String toString() {
+    return "AnalyzerMeasure[" + (inputFile != null ? "inputFile=" + inputFile.toString() : "onProject")
+      + ",metricKey=" + metricKey + ",value=" + value + "]";
+  }
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/package-info.java
new file mode 100644 (file)
index 0000000..b490662
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.analyzer.measure;
\ No newline at end of file
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/package-info.java
new file mode 100644 (file)
index 0000000..5b72f8c
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.analyzer;
\ No newline at end of file
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/FilenameUtils.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/FilenameUtils.java
new file mode 100644 (file)
index 0000000..0461255
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.internal;
+
+import java.io.File;
+
+/**
+ * Copied from commons io
+ *
+ */
+public class FilenameUtils {
+
+  public static final char EXTENSION_SEPARATOR = '.';
+
+  private static final char UNIX_SEPARATOR = '/';
+
+  /**
+   * The Windows separator character.
+   */
+  private static final char WINDOWS_SEPARATOR = '\\';
+
+  /**
+   * The system separator character.
+   */
+  private static final char SYSTEM_SEPARATOR = File.separatorChar;
+
+  /**
+   * The separator character that is the opposite of the system separator.
+   */
+  private static final char OTHER_SEPARATOR;
+  static {
+    if (isSystemWindows()) {
+      OTHER_SEPARATOR = UNIX_SEPARATOR;
+    } else {
+      OTHER_SEPARATOR = WINDOWS_SEPARATOR;
+    }
+  }
+
+  static boolean isSystemWindows() {
+    return SYSTEM_SEPARATOR == WINDOWS_SEPARATOR;
+  }
+
+  public static String normalize(String filename) {
+    return doNormalize(filename, UNIX_SEPARATOR, true);
+  }
+
+  private static String doNormalize(String filename, char separator, boolean keepSeparator) {
+    if (filename == null) {
+      return null;
+    }
+    int size = filename.length();
+    if (size == 0) {
+      return filename;
+    }
+    int prefix = getPrefixLength(filename);
+    if (prefix < 0) {
+      return null;
+    }
+
+    char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy
+    filename.getChars(0, filename.length(), array, 0);
+
+    // fix separators throughout
+    char otherSeparator = separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR;
+    for (int i = 0; i < array.length; i++) {
+      if (array[i] == otherSeparator) {
+        array[i] = separator;
+      }
+    }
+
+    // add extra separator on the end to simplify code below
+    boolean lastIsDirectory = true;
+    if (array[size - 1] != separator) {
+      array[size++] = separator;
+      lastIsDirectory = false;
+    }
+
+    // adjoining slashes
+    for (int i = prefix + 1; i < size; i++) {
+      if (array[i] == separator && array[i - 1] == separator) {
+        System.arraycopy(array, i, array, i - 1, size - i);
+        size--;
+        i--;
+      }
+    }
+
+    // dot slash
+    for (int i = prefix + 1; i < size; i++) {
+      if (array[i] == separator && array[i - 1] == '.' &&
+        (i == prefix + 1 || array[i - 2] == separator)) {
+        if (i == size - 1) {
+          lastIsDirectory = true;
+        }
+        System.arraycopy(array, i + 1, array, i - 1, size - i);
+        size -= 2;
+        i--;
+      }
+    }
+
+    // double dot slash
+    outer: for (int i = prefix + 2; i < size; i++) {
+      if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' &&
+        (i == prefix + 2 || array[i - 3] == separator)) {
+        if (i == prefix + 2) {
+          return null;
+        }
+        if (i == size - 1) {
+          lastIsDirectory = true;
+        }
+        int j;
+        for (j = i - 4; j >= prefix; j--) {
+          if (array[j] == separator) {
+            // remove b/../ from a/b/../c
+            System.arraycopy(array, i + 1, array, j + 1, size - i);
+            size -= i - j;
+            i = j + 1;
+            continue outer;
+          }
+        }
+        // remove a/../ from a/../c
+        System.arraycopy(array, i + 1, array, prefix, size - i);
+        size -= i + 1 - prefix;
+        i = prefix + 1;
+      }
+    }
+
+    if (size <= 0) { // should never be less than 0
+      return "";
+    }
+    if (size <= prefix) { // should never be less than prefix
+      return new String(array, 0, size);
+    }
+    if (lastIsDirectory && keepSeparator) {
+      return new String(array, 0, size); // keep trailing separator
+    }
+    return new String(array, 0, size - 1); // lose trailing separator
+  }
+
+  public static int getPrefixLength(String filename) {
+    if (filename == null) {
+      return -1;
+    }
+    int len = filename.length();
+    if (len == 0) {
+      return 0;
+    }
+    char ch0 = filename.charAt(0);
+    if (ch0 == ':') {
+      return -1;
+    }
+    if (len == 1) {
+      if (ch0 == '~') {
+        return 2; // return a length greater than the input
+      }
+      return isSeparator(ch0) ? 1 : 0;
+    } else {
+      if (ch0 == '~') {
+        int posUnix = filename.indexOf(UNIX_SEPARATOR, 1);
+        int posWin = filename.indexOf(WINDOWS_SEPARATOR, 1);
+        if (posUnix == -1 && posWin == -1) {
+          return len + 1; // return a length greater than the input
+        }
+        posUnix = posUnix == -1 ? posWin : posUnix;
+        posWin = posWin == -1 ? posUnix : posWin;
+        return Math.min(posUnix, posWin) + 1;
+      }
+      char ch1 = filename.charAt(1);
+      if (ch1 == ':') {
+        ch0 = Character.toUpperCase(ch0);
+        if (ch0 >= 'A' && ch0 <= 'Z') {
+          if (len == 2 || isSeparator(filename.charAt(2)) == false) {
+            return 2;
+          }
+          return 3;
+        }
+        return -1;
+
+      } else if (isSeparator(ch0) && isSeparator(ch1)) {
+        int posUnix = filename.indexOf(UNIX_SEPARATOR, 2);
+        int posWin = filename.indexOf(WINDOWS_SEPARATOR, 2);
+        if (posUnix == -1 && posWin == -1 || posUnix == 2 || posWin == 2) {
+          return -1;
+        }
+        posUnix = posUnix == -1 ? posWin : posUnix;
+        posWin = posWin == -1 ? posUnix : posWin;
+        return Math.min(posUnix, posWin) + 1;
+      } else {
+        return isSeparator(ch0) ? 1 : 0;
+      }
+    }
+  }
+
+  private static boolean isSeparator(char ch) {
+    return ch == UNIX_SEPARATOR || ch == WINDOWS_SEPARATOR;
+  }
+
+  public static String getExtension(String filename) {
+    if (filename == null) {
+      return null;
+    }
+    int index = indexOfExtension(filename);
+    if (index == -1) {
+      return "";
+    } else {
+      return filename.substring(index + 1);
+    }
+  }
+
+  public static int indexOfExtension(String filename) {
+    if (filename == null) {
+      return -1;
+    }
+    int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
+    int lastSeparator = indexOfLastSeparator(filename);
+    return lastSeparator > extensionPos ? -1 : extensionPos;
+  }
+
+  public static int indexOfLastSeparator(String filename) {
+    if (filename == null) {
+      return -1;
+    }
+    int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR);
+    int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
+    return Math.max(lastUnixPos, lastWindowsPos);
+  }
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/Preconditions.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/Preconditions.java
new file mode 100644 (file)
index 0000000..75ac73f
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.internal;
+
+import javax.annotation.Nullable;
+
+/**
+ * Copied from Guava
+ */
+public final class Preconditions {
+  private Preconditions() {
+  }
+
+  /**
+   * Ensures the truth of an expression involving one or more parameters to the
+   * calling method.
+   *
+   * @param expression a boolean expression
+   * @throws IllegalArgumentException if {@code expression} is false
+   */
+  public static void checkArgument(boolean expression) {
+    if (!expression) {
+      throw new IllegalArgumentException();
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving one or more parameters to the
+   * calling method.
+   *
+   * @param expression a boolean expression
+   * @param errorMessage the exception message to use if the check fails; will
+   *     be converted to a string using {@link String#valueOf(Object)}
+   * @throws IllegalArgumentException if {@code expression} is false
+   */
+  public static void checkArgument(
+    boolean expression, @Nullable Object errorMessage) {
+    if (!expression) {
+      throw new IllegalArgumentException(String.valueOf(errorMessage));
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving one or more parameters to the
+   * calling method.
+   *
+   * @param expression a boolean expression
+   * @param errorMessageTemplate a template for the exception message should the
+   *     check fail. The message is formed by replacing each {@code %s}
+   *     placeholder in the template with an argument. These are matched by
+   *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+   *     Unmatched arguments will be appended to the formatted message in square
+   *     braces. Unmatched placeholders will be left as-is.
+   * @param errorMessageArgs the arguments to be substituted into the message
+   *     template. Arguments are converted to strings using
+   *     {@link String#valueOf(Object)}.
+   * @throws IllegalArgumentException if {@code expression} is false
+   * @throws NullPointerException if the check fails and either {@code
+   *     errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
+   *     this happen)
+   */
+  public static void checkArgument(boolean expression,
+    @Nullable String errorMessageTemplate,
+    @Nullable Object... errorMessageArgs) {
+    if (!expression) {
+      throw new IllegalArgumentException(
+        format(errorMessageTemplate, errorMessageArgs));
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving the state of the calling
+   * instance, but not involving any parameters to the calling method.
+   *
+   * @param expression a boolean expression
+   * @throws IllegalStateException if {@code expression} is false
+   */
+  public static void checkState(boolean expression) {
+    if (!expression) {
+      throw new IllegalStateException();
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving the state of the calling
+   * instance, but not involving any parameters to the calling method.
+   *
+   * @param expression a boolean expression
+   * @param errorMessage the exception message to use if the check fails; will
+   *     be converted to a string using {@link String#valueOf(Object)}
+   * @throws IllegalStateException if {@code expression} is false
+   */
+  public static void checkState(
+    boolean expression, @Nullable Object errorMessage) {
+    if (!expression) {
+      throw new IllegalStateException(String.valueOf(errorMessage));
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving the state of the calling
+   * instance, but not involving any parameters to the calling method.
+   *
+   * @param expression a boolean expression
+   * @param errorMessageTemplate a template for the exception message should the
+   *     check fail. The message is formed by replacing each {@code %s}
+   *     placeholder in the template with an argument. These are matched by
+   *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+   *     Unmatched arguments will be appended to the formatted message in square
+   *     braces. Unmatched placeholders will be left as-is.
+   * @param errorMessageArgs the arguments to be substituted into the message
+   *     template. Arguments are converted to strings using
+   *     {@link String#valueOf(Object)}.
+   * @throws IllegalStateException if {@code expression} is false
+   * @throws NullPointerException if the check fails and either {@code
+   *     errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
+   *     this happen)
+   */
+  public static void checkState(boolean expression,
+    @Nullable String errorMessageTemplate,
+    @Nullable Object... errorMessageArgs) {
+    if (!expression) {
+      throw new IllegalStateException(
+        format(errorMessageTemplate, errorMessageArgs));
+    }
+  }
+
+  /**
+   * Ensures that an object reference passed as a parameter to the calling
+   * method is not null.
+   *
+   * @param reference an object reference
+   * @return the non-null reference that was validated
+   * @throws NullPointerException if {@code reference} is null
+   */
+  public static <T> T checkNotNull(T reference) {
+    if (reference == null) {
+      throw new NullPointerException();
+    }
+    return reference;
+  }
+
+  /**
+   * Ensures that an object reference passed as a parameter to the calling
+   * method is not null.
+   *
+   * @param reference an object reference
+   * @param errorMessage the exception message to use if the check fails; will
+   *     be converted to a string using {@link String#valueOf(Object)}
+   * @return the non-null reference that was validated
+   * @throws NullPointerException if {@code reference} is null
+   */
+  public static <T> T checkNotNull(T reference, @Nullable Object errorMessage) {
+    if (reference == null) {
+      throw new NullPointerException(String.valueOf(errorMessage));
+    }
+    return reference;
+  }
+
+  /**
+   * Ensures that an object reference passed as a parameter to the calling
+   * method is not null.
+   *
+   * @param reference an object reference
+   * @param errorMessageTemplate a template for the exception message should the
+   *     check fail. The message is formed by replacing each {@code %s}
+   *     placeholder in the template with an argument. These are matched by
+   *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+   *     Unmatched arguments will be appended to the formatted message in square
+   *     braces. Unmatched placeholders will be left as-is.
+   * @param errorMessageArgs the arguments to be substituted into the message
+   *     template. Arguments are converted to strings using
+   *     {@link String#valueOf(Object)}.
+   * @return the non-null reference that was validated
+   * @throws NullPointerException if {@code reference} is null
+   */
+  public static <T> T checkNotNull(T reference,
+    @Nullable String errorMessageTemplate,
+    @Nullable Object... errorMessageArgs) {
+    if (reference == null) {
+      // If either of these parameters is null, the right thing happens anyway
+      throw new NullPointerException(
+        format(errorMessageTemplate, errorMessageArgs));
+    }
+    return reference;
+  }
+
+  /*
+   * All recent hotspots (as of 2009) *really* like to have the natural code
+   * 
+   * if (guardExpression) {
+   * throw new BadException(messageExpression);
+   * }
+   * 
+   * refactored so that messageExpression is moved to a separate
+   * String-returning method.
+   * 
+   * if (guardExpression) {
+   * throw new BadException(badMsg(...));
+   * }
+   * 
+   * The alternative natural refactorings into void or Exception-returning
+   * methods are much slower. This is a big deal - we're talking factors of
+   * 2-8 in microbenchmarks, not just 10-20%. (This is a hotspot optimizer
+   * bug, which should be fixed, but that's a separate, big project).
+   * 
+   * The coding pattern above is heavily used in java.util, e.g. in ArrayList.
+   * There is a RangeCheckMicroBenchmark in the JDK that was used to test this.
+   * 
+   * But the methods in this class want to throw different exceptions,
+   * depending on the args, so it appears that this pattern is not directly
+   * applicable. But we can use the ridiculous, devious trick of throwing an
+   * exception in the middle of the construction of another exception.
+   * Hotspot is fine with that.
+   */
+
+  /**
+   * Ensures that {@code index} specifies a valid <i>element</i> in an array,
+   * list or string of size {@code size}. An element index may range from zero,
+   * inclusive, to {@code size}, exclusive.
+   *
+   * @param index a user-supplied index identifying an element of an array, list
+   *     or string
+   * @param size the size of that array, list or string
+   * @return the value of {@code index}
+   * @throws IndexOutOfBoundsException if {@code index} is negative or is not
+   *     less than {@code size}
+   * @throws IllegalArgumentException if {@code size} is negative
+   */
+  public static int checkElementIndex(int index, int size) {
+    return checkElementIndex(index, size, "index");
+  }
+
+  /**
+   * Ensures that {@code index} specifies a valid <i>element</i> in an array,
+   * list or string of size {@code size}. An element index may range from zero,
+   * inclusive, to {@code size}, exclusive.
+   *
+   * @param index a user-supplied index identifying an element of an array, list
+   *     or string
+   * @param size the size of that array, list or string
+   * @param desc the text to use to describe this index in an error message
+   * @return the value of {@code index}
+   * @throws IndexOutOfBoundsException if {@code index} is negative or is not
+   *     less than {@code size}
+   * @throws IllegalArgumentException if {@code size} is negative
+   */
+  public static int checkElementIndex(
+    int index, int size, @Nullable String desc) {
+    // Carefully optimized for execution by hotspot (explanatory comment above)
+    if (index < 0 || index >= size) {
+      throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
+    }
+    return index;
+  }
+
+  private static String badElementIndex(int index, int size, String desc) {
+    if (index < 0) {
+      return format("%s (%s) must not be negative", desc, index);
+    } else if (size < 0) {
+      throw new IllegalArgumentException("negative size: " + size);
+    } else { // index >= size
+      return format("%s (%s) must be less than size (%s)", desc, index, size);
+    }
+  }
+
+  /**
+   * Ensures that {@code index} specifies a valid <i>position</i> in an array,
+   * list or string of size {@code size}. A position index may range from zero
+   * to {@code size}, inclusive.
+   *
+   * @param index a user-supplied index identifying a position in an array, list
+   *     or string
+   * @param size the size of that array, list or string
+   * @return the value of {@code index}
+   * @throws IndexOutOfBoundsException if {@code index} is negative or is
+   *     greater than {@code size}
+   * @throws IllegalArgumentException if {@code size} is negative
+   */
+  public static int checkPositionIndex(int index, int size) {
+    return checkPositionIndex(index, size, "index");
+  }
+
+  /**
+   * Ensures that {@code index} specifies a valid <i>position</i> in an array,
+   * list or string of size {@code size}. A position index may range from zero
+   * to {@code size}, inclusive.
+   *
+   * @param index a user-supplied index identifying a position in an array, list
+   *     or string
+   * @param size the size of that array, list or string
+   * @param desc the text to use to describe this index in an error message
+   * @return the value of {@code index}
+   * @throws IndexOutOfBoundsException if {@code index} is negative or is
+   *     greater than {@code size}
+   * @throws IllegalArgumentException if {@code size} is negative
+   */
+  public static int checkPositionIndex(
+    int index, int size, @Nullable String desc) {
+    // Carefully optimized for execution by hotspot (explanatory comment above)
+    if (index < 0 || index > size) {
+      throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
+    }
+    return index;
+  }
+
+  private static String badPositionIndex(int index, int size, String desc) {
+    if (index < 0) {
+      return format("%s (%s) must not be negative", desc, index);
+    } else if (size < 0) {
+      throw new IllegalArgumentException("negative size: " + size);
+    } else { // index > size
+      return format("%s (%s) must not be greater than size (%s)",
+        desc, index, size);
+    }
+  }
+
+  /**
+   * Ensures that {@code start} and {@code end} specify a valid <i>positions</i>
+   * in an array, list or string of size {@code size}, and are in order. A
+   * position index may range from zero to {@code size}, inclusive.
+   *
+   * @param start a user-supplied index identifying a starting position in an
+   *     array, list or string
+   * @param end a user-supplied index identifying a ending position in an array,
+   *     list or string
+   * @param size the size of that array, list or string
+   * @throws IndexOutOfBoundsException if either index is negative or is
+   *     greater than {@code size}, or if {@code end} is less than {@code start}
+   * @throws IllegalArgumentException if {@code size} is negative
+   */
+  public static void checkPositionIndexes(int start, int end, int size) {
+    // Carefully optimized for execution by hotspot (explanatory comment above)
+    if (start < 0 || end < start || end > size) {
+      throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
+    }
+  }
+
+  private static String badPositionIndexes(int start, int end, int size) {
+    if (start < 0 || start > size) {
+      return badPositionIndex(start, size, "start index");
+    }
+    if (end < 0 || end > size) {
+      return badPositionIndex(end, size, "end index");
+    }
+    // end < start
+    return format("end index (%s) must not be less than start index (%s)",
+      end, start);
+  }
+
+  /**
+   * Substitutes each {@code %s} in {@code template} with an argument. These
+   * are matched by position - the first {@code %s} gets {@code args[0]}, etc.
+   * If there are more arguments than placeholders, the unmatched arguments will
+   * be appended to the end of the formatted message in square braces.
+   *
+   * @param template a non-null string containing 0 or more {@code %s}
+   *     placeholders.
+   * @param args the arguments to be substituted into the message
+   *     template. Arguments are converted to strings using
+   *     {@link String#valueOf(Object)}. Arguments can be null.
+   */
+  static String format(String template,
+    @Nullable Object... args) {
+    template = String.valueOf(template); // null -> "null"
+
+    // start substituting the arguments into the '%s' placeholders
+    StringBuilder builder = new StringBuilder(
+      template.length() + 16 * args.length);
+    int templateStart = 0;
+    int i = 0;
+    while (i < args.length) {
+      int placeholderStart = template.indexOf("%s", templateStart);
+      if (placeholderStart == -1) {
+        break;
+      }
+      builder.append(template.substring(templateStart, placeholderStart));
+      builder.append(args[i++]);
+      templateStart = placeholderStart + 2;
+    }
+    builder.append(template.substring(templateStart));
+
+    // if we run out of placeholders, append the extra args in square braces
+    if (i < args.length) {
+      builder.append(" [");
+      builder.append(args[i++]);
+      while (i < args.length) {
+        builder.append(", ");
+        builder.append(args[i++]);
+      }
+      builder.append(']');
+    }
+
+    return builder.toString();
+  }
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/StringUtils.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/StringUtils.java
new file mode 100644 (file)
index 0000000..ab279ae
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.internal;
+
+/**
+ * Copied from commons lang
+ */
+public class StringUtils {
+
+  public static final String EMPTY = "";
+
+  public static String trim(String str) {
+    return str == null ? null : str.trim();
+  }
+
+  public static String removeStart(String str, String remove) {
+    if (isEmpty(str) || isEmpty(remove)) {
+      return str;
+    }
+    if (str.startsWith(remove)) {
+      return str.substring(remove.length());
+    }
+    return str;
+  }
+
+  public static String removeEnd(String str, String remove) {
+    if (isEmpty(str) || isEmpty(remove)) {
+      return str;
+    }
+    if (str.endsWith(remove)) {
+      return str.substring(0, str.length() - remove.length());
+    }
+    return str;
+  }
+
+  public static boolean isEmpty(String str) {
+    return str == null || str.length() == 0;
+  }
+
+  public static boolean startsWithIgnoreCase(String str, String prefix) {
+    return startsWith(str, prefix, true);
+  }
+
+  private static boolean startsWith(String str, String prefix, boolean ignoreCase) {
+    if (str == null || prefix == null) {
+      return (str == null && prefix == null);
+    }
+    if (prefix.length() > str.length()) {
+      return false;
+    }
+    return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
+  }
+
+  public static String substring(String str, int start) {
+    if (str == null) {
+      return null;
+    }
+
+    // handle negatives, which means last n characters
+    if (start < 0) {
+      start = str.length() + start; // remember start is negative
+    }
+
+    if (start < 0) {
+      start = 0;
+    }
+    if (start > str.length()) {
+      return EMPTY;
+    }
+
+    return str.substring(start);
+  }
+
+  public static boolean isBlank(String str) {
+    int strLen;
+    if (str == null || (strLen = str.length()) == 0) {
+      return true;
+    }
+    for (int i = 0; i < strLen; i++) {
+      if ((Character.isWhitespace(str.charAt(i)) == false)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public static boolean isNotBlank(String str) {
+    return !StringUtils.isBlank(str);
+  }
+
+  public static String removeEndIgnoreCase(String str, String remove) {
+    if (isEmpty(str) || isEmpty(remove)) {
+      return str;
+    }
+    if (endsWithIgnoreCase(str, remove)) {
+      return str.substring(0, str.length() - remove.length());
+    }
+    return str;
+  }
+
+  public static boolean endsWithIgnoreCase(String str, String suffix) {
+    return endsWith(str, suffix, true);
+  }
+
+  private static boolean endsWith(String str, String suffix, boolean ignoreCase) {
+    if (str == null || suffix == null) {
+      return (str == null && suffix == null);
+    }
+    if (suffix.length() > str.length()) {
+      return false;
+    }
+    int strOffset = str.length() - suffix.length();
+    return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length());
+  }
+
+  public static String lowerCase(String str) {
+    if (str == null) {
+      return null;
+    }
+    return str.toLowerCase();
+  }
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/WildcardPattern.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/WildcardPattern.java
new file mode 100644 (file)
index 0000000..f179fd7
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * Implementation of Ant-style matching patterns.
+ * Contrary to other implementations (like AntPathMatcher from Spring Framework) it is based on {@link Pattern Java Regular Expressions}.
+ * To increase performance it holds an internal cache of all processed patterns.
+ * <p>
+ * Following rules are applied:
+ * <ul>
+ * <li>? matches single character</li>
+ * <li>* matches zero or more characters</li>
+ * <li>** matches zero or more 'directories'</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Some examples of patterns:
+ * <ul>
+ * <li><code>org/T?st.java</code> - matches <code>org/Test.java</code> and also <code>org/Tost.java</code></li>
+ * <li><code>org/*.java</code> - matches all <code>.java</code> files in the <code>org</code> directory,
+ * e.g. <code>org/Foo.java</code> or <code>org/Bar.java</code></li>
+ * <li><code>org/**</code> - matches all files underneath the <code>org</code> directory,
+ * e.g. <code>org/Foo.java</code> or <code>org/foo/bar.jsp</code></li>
+ * <li><code>org/&#42;&#42;/Test.java</code> - matches all <code>Test.java</code> files underneath the <code>org</code> directory,
+ * e.g. <code>org/Test.java</code> or <code>org/foo/Test.java</code> or <code>org/foo/bar/Test.java</code></li>
+ * <li><code>org/&#42;&#42;/*.java</code> - matches all <code>.java</code> files underneath the <code>org</code> directory,
+ * e.g. <code>org/Foo.java</code> or <code>org/foo/Bar.java</code> or <code>org/foo/bar/Baz.java</code></li>
+ * </ul>
+ * </p>
+ * <p>
+ * Another implementation, which is also based on Java Regular Expressions, can be found in
+ * <a href="https://github.com/JetBrains/intellij-community/blob/idea/107.743/platform/util/src/com/intellij/openapi/util/io/FileUtil.java#L847">FileUtil</a>
+ * from IntelliJ OpenAPI.
+ * </p>
+ * 
+ */
+public class WildcardPattern {
+
+  private static final Map<String, WildcardPattern> CACHE = new HashMap<String, WildcardPattern>();
+  private static final String SPECIAL_CHARS = "()[]^$.{}+|";
+
+  private Pattern pattern;
+  private String stringRepresentation;
+
+  protected WildcardPattern(String pattern, String directorySeparator) {
+    this.stringRepresentation = pattern;
+    this.pattern = Pattern.compile(toRegexp(pattern, directorySeparator));
+  }
+
+  private static String toRegexp(String antPattern, String directorySeparator) {
+    final String escapedDirectorySeparator = '\\' + directorySeparator;
+
+    final StringBuilder sb = new StringBuilder(antPattern.length());
+
+    sb.append('^');
+
+    int i = antPattern.startsWith("/") || antPattern.startsWith("\\") ? 1 : 0;
+    while (i < antPattern.length()) {
+      final char ch = antPattern.charAt(i);
+
+      if (SPECIAL_CHARS.indexOf(ch) != -1) {
+        // Escape regexp-specific characters
+        sb.append('\\').append(ch);
+      } else if (ch == '*') {
+        if (i + 1 < antPattern.length() && antPattern.charAt(i + 1) == '*') {
+          // Double asterisk
+          // Zero or more directories
+          if (i + 2 < antPattern.length() && isSlash(antPattern.charAt(i + 2))) {
+            sb.append("(?:.*").append(escapedDirectorySeparator).append("|)");
+            i += 2;
+          } else {
+            sb.append(".*");
+            i += 1;
+          }
+        } else {
+          // Single asterisk
+          // Zero or more characters excluding directory separator
+          sb.append("[^").append(escapedDirectorySeparator).append("]*?");
+        }
+      } else if (ch == '?') {
+        // Any single character excluding directory separator
+        sb.append("[^").append(escapedDirectorySeparator).append("]");
+      } else if (isSlash(ch)) {
+        // Directory separator
+        sb.append(escapedDirectorySeparator);
+      } else {
+        // Single character
+        sb.append(ch);
+      }
+
+      i++;
+    }
+
+    sb.append('$');
+
+    return sb.toString();
+  }
+
+  private static boolean isSlash(char ch) {
+    return ch == '/' || ch == '\\';
+  }
+
+  /**
+   * Returns string representation of this pattern.
+   * 
+   * @since 2.5
+   */
+  @Override
+  public String toString() {
+    return stringRepresentation;
+  }
+
+  /**
+   * Returns true if specified value matches this pattern.
+   */
+  public boolean match(String value) {
+    value = StringUtils.removeStart(value, "/");
+    value = StringUtils.removeEnd(value, "/");
+    return pattern.matcher(value).matches();
+  }
+
+  /**
+   * Returns true if specified value matches one of specified patterns.
+   * 
+   * @since 2.4
+   */
+  public static boolean match(WildcardPattern[] patterns, String value) {
+    for (WildcardPattern pattern : patterns) {
+      if (pattern.match(value)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Creates pattern with "/" as a directory separator.
+   * 
+   * @see #create(String, String)
+   */
+  public static WildcardPattern create(String pattern) {
+    return create(pattern, "/");
+  }
+
+  /**
+   * Creates array of patterns with "/" as a directory separator.
+   * 
+   * @see #create(String, String)
+   */
+  public static WildcardPattern[] create(String[] patterns) {
+    if (patterns == null) {
+      return new WildcardPattern[0];
+    }
+    WildcardPattern[] exclusionPAtterns = new WildcardPattern[patterns.length];
+    for (int i = 0; i < patterns.length; i++) {
+      exclusionPAtterns[i] = create(patterns[i]);
+    }
+    return exclusionPAtterns;
+  }
+
+  /**
+   * Creates pattern with specified separator for directories.
+   * <p>
+   * This is used to match Java-classes, i.e. <code>org.foo.Bar</code> against <code>org/**</code>.
+   * <b>However usage of character other than "/" as a directory separator is misleading and should be avoided,
+   * so method {@link #create(String)} is preferred over this one.</b>
+   * </p>
+   * <p>
+   * Also note that no matter whether forward or backward slashes were used in the <code>antPattern</code>
+   * the returned pattern will use <code>directorySeparator</code>.
+   * Thus to match Windows-style path "dir\file.ext" against pattern "dir/file.ext" normalization should be performed.
+   * </p>
+   */
+  public static WildcardPattern create(String pattern, String directorySeparator) {
+    String key = pattern + directorySeparator;
+    WildcardPattern wildcardPattern = CACHE.get(key);
+    if (wildcardPattern == null) {
+      wildcardPattern = new WildcardPattern(pattern, directorySeparator);
+      CACHE.put(key, wildcardPattern);
+    }
+    return wildcardPattern;
+  }
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/package-info.java
new file mode 100644 (file)
index 0000000..9870b99
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.internal;
\ No newline at end of file
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/Language.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/Language.java
new file mode 100644 (file)
index 0000000..7dd6c8b
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.languages;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public final class Language {
+
+  private final String key, name;
+  private final String[] fileSuffixes;
+
+  public Language(String key, String name, String... fileSuffixes) {
+    this.key = key;
+    this.name = name;
+    this.fileSuffixes = fileSuffixes;
+  }
+
+  /**
+   * For example "java".
+   */
+  public String key() {
+    return key;
+  }
+
+  /**
+   * For example "Java"
+   */
+  public String name() {
+    return name;
+  }
+
+  /**
+   * For example ["jav", "java"].
+   */
+  public Collection<String> fileSuffixes() {
+    return Arrays.asList(fileSuffixes);
+  }
+
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/package-info.java
new file mode 100644 (file)
index 0000000..a36d1c1
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.languages;
\ No newline at end of file
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/Metric.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/Metric.java
new file mode 100644 (file)
index 0000000..52dc17c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.measures;
+
+import java.io.Serializable;
+
+public interface Metric<G extends Serializable> {
+
+  Class<G> type();
+
+  String key();
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/package-info.java
new file mode 100644 (file)
index 0000000..e684b54
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.measures;
\ No newline at end of file
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/QProfile.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/QProfile.java
new file mode 100644 (file)
index 0000000..1d074e1
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.rules;
+
+public class QProfile {
+  private final String name, language;
+  private final Integer version;
+
+  public QProfile(String name, String language, Integer version) {
+    this.name = name;
+    this.language = language;
+    this.version = version;
+  }
+
+  public String name() {
+    return name;
+  }
+
+  public String language() {
+    return language;
+  }
+
+  public Integer version() {
+    return version;
+  }
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/RuleKey.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/RuleKey.java
new file mode 100644 (file)
index 0000000..3af1337
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.api.rules;
+
+import java.io.Serializable;
+
+/**
+ * Key of a rule. Unique among all the rule repositories.
+ *
+ * @since 3.6
+ */
+public class RuleKey implements Serializable {
+  private final String repository, rule;
+
+  protected RuleKey(String repositoryKey, String ruleKey) {
+    this.repository = repositoryKey;
+    this.rule = ruleKey;
+  }
+
+  /**
+   * Create a key. Parameters are NOT null.
+   */
+  public static RuleKey of(String repository, String rule) {
+    return new RuleKey(repository, rule);
+  }
+
+  /**
+   * Never null
+   */
+  public String repository() {
+    return repository;
+  }
+
+  /**
+   * Never null
+   */
+  public String rule() {
+    return rule;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    RuleKey ruleKey = (RuleKey) o;
+    if (!repository.equals(ruleKey.repository)) {
+      return false;
+    }
+    if (!rule.equals(ruleKey.rule)) {
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = repository.hashCode();
+    result = 31 * result + rule.hashCode();
+    return result;
+  }
+
+  /**
+   * Format is "repository:rule", for example "squid:AvoidCycle"
+   */
+  @Override
+  public String toString() {
+    return String.format("%s:%s", repository, rule);
+  }
+}
diff --git a/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/package-info.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/package-info.java
new file mode 100644 (file)
index 0000000..d91eb34
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.api.rules;
\ No newline at end of file
diff --git a/sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java b/sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java
new file mode 100644 (file)
index 0000000..95888fe
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.fest.assertions.Assertions;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.InputFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DefaultFilePredicatesTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  DefaultInputFile javaFile;
+  FilePredicates predicates = new DefaultFilePredicates();
+
+  @Before
+  public void before() throws IOException {
+    javaFile = new DefaultInputFile("src/main/java/struts/Action.java")
+      .setFile(temp.newFile("Action.java"))
+      .setLanguage("java")
+      .setStatus(InputFile.Status.ADDED);
+  }
+
+  @Test
+  public void all() throws Exception {
+    Assertions.assertThat(predicates.all().apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void none() throws Exception {
+    assertThat(predicates.none().apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void matches_inclusion_pattern() throws Exception {
+    assertThat(predicates.matchesPathPattern("src/main/**/Action.java").apply(javaFile)).isTrue();
+    assertThat(predicates.matchesPathPattern("Action.java").apply(javaFile)).isFalse();
+    assertThat(predicates.matchesPathPattern("src/**/*.php").apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void matches_inclusion_patterns() throws Exception {
+    assertThat(predicates.matchesPathPatterns(new String[] {"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isTrue();
+    assertThat(predicates.matchesPathPatterns(new String[] {}).apply(javaFile)).isTrue();
+    assertThat(predicates.matchesPathPatterns(new String[] {"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void does_not_match_exclusion_pattern() throws Exception {
+    assertThat(predicates.doesNotMatchPathPattern("src/main/**/Action.java").apply(javaFile)).isFalse();
+    assertThat(predicates.doesNotMatchPathPattern("Action.java").apply(javaFile)).isTrue();
+    assertThat(predicates.doesNotMatchPathPattern("src/**/*.php").apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void does_not_match_exclusion_patterns() throws Exception {
+    assertThat(predicates.doesNotMatchPathPatterns(new String[] {}).apply(javaFile)).isTrue();
+    assertThat(predicates.doesNotMatchPathPatterns(new String[] {"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isTrue();
+    assertThat(predicates.doesNotMatchPathPatterns(new String[] {"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_relative_path() throws Exception {
+    assertThat(predicates.hasRelativePath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
+    assertThat(predicates.hasRelativePath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
+
+    // path is normalized
+    assertThat(predicates.hasRelativePath("src/main/java/../java/struts/Action.java").apply(javaFile)).isTrue();
+
+    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Action.java").apply(javaFile)).isTrue();
+    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Other.java").apply(javaFile)).isFalse();
+    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\..\\struts\\Action.java").apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void has_absolute_path() throws Exception {
+    String path = javaFile.file().getAbsolutePath();
+    assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
+    assertThat(predicates.hasAbsolutePath(path.replaceAll("/", "\\\\")).apply(javaFile)).isTrue();
+
+    assertThat(predicates.hasAbsolutePath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
+    assertThat(predicates.hasAbsolutePath("src/main/java/struts/Action.java").apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_path() throws Exception {
+    // is relative path
+    assertThat(predicates.hasPath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
+    assertThat(predicates.hasPath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
+
+    // is absolute path
+    String path = javaFile.file().getAbsolutePath();
+    assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
+    assertThat(predicates.hasPath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void is_file() throws Exception {
+    // relative file
+    assertThat(predicates.is(new File(javaFile.relativePath())).apply(javaFile)).isTrue();
+
+    // absolute file
+    assertThat(predicates.is(javaFile.file()).apply(javaFile)).isTrue();
+    assertThat(predicates.is(javaFile.file().getAbsoluteFile()).apply(javaFile)).isTrue();
+    assertThat(predicates.is(javaFile.file().getCanonicalFile()).apply(javaFile)).isTrue();
+    assertThat(predicates.is(new File(javaFile.file().toURI())).apply(javaFile)).isTrue();
+    assertThat(predicates.is(temp.newFile()).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_language() throws Exception {
+    assertThat(predicates.hasLanguage("java").apply(javaFile)).isTrue();
+    assertThat(predicates.hasLanguage("php").apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_languages() throws Exception {
+    assertThat(predicates.hasLanguages(Arrays.asList("java", "php")).apply(javaFile)).isTrue();
+    assertThat(predicates.hasLanguages(Arrays.asList("cobol", "php")).apply(javaFile)).isFalse();
+    assertThat(predicates.hasLanguages(Collections.<String>emptyList()).apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void has_status() throws Exception {
+    assertThat(predicates.hasStatus(InputFile.Status.ADDED).apply(javaFile)).isTrue();
+    assertThat(predicates.hasStatus(InputFile.Status.CHANGED).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_type() throws Exception {
+    assertThat(predicates.hasType(InputFile.Type.MAIN).apply(javaFile)).isTrue();
+    assertThat(predicates.hasType(InputFile.Type.TEST).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void not() throws Exception {
+    assertThat(predicates.not(predicates.hasType(InputFile.Type.MAIN)).apply(javaFile)).isFalse();
+    assertThat(predicates.not(predicates.hasType(InputFile.Type.TEST)).apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void and() throws Exception {
+    // empty
+    assertThat(predicates.and().apply(javaFile)).isTrue();
+    assertThat(predicates.and(new FilePredicate[0]).apply(javaFile)).isTrue();
+    assertThat(predicates.and(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
+
+    // two arguments
+    assertThat(predicates.and(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
+    assertThat(predicates.and(predicates.all(), predicates.none()).apply(javaFile)).isFalse();
+    assertThat(predicates.and(predicates.none(), predicates.all()).apply(javaFile)).isFalse();
+
+    // collection
+    assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
+    assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isFalse();
+
+    // array
+    assertThat(predicates.and(new FilePredicate[] {predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
+    assertThat(predicates.and(new FilePredicate[] {predicates.all(), predicates.none()}).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void or() throws Exception {
+    // empty
+    assertThat(predicates.or().apply(javaFile)).isTrue();
+    assertThat(predicates.or(new FilePredicate[0]).apply(javaFile)).isTrue();
+    assertThat(predicates.or(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
+
+    // two arguments
+    assertThat(predicates.or(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
+    assertThat(predicates.or(predicates.all(), predicates.none()).apply(javaFile)).isTrue();
+    assertThat(predicates.or(predicates.none(), predicates.all()).apply(javaFile)).isTrue();
+    assertThat(predicates.or(predicates.none(), predicates.none()).apply(javaFile)).isFalse();
+
+    // collection
+    assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
+    assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isTrue();
+    assertThat(predicates.or(Arrays.asList(predicates.none(), predicates.none())).apply(javaFile)).isFalse();
+
+    // array
+    assertThat(predicates.or(new FilePredicate[] {predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
+    assertThat(predicates.or(new FilePredicate[] {predicates.all(), predicates.none()}).apply(javaFile)).isTrue();
+    assertThat(predicates.or(new FilePredicate[] {predicates.none(), predicates.none()}).apply(javaFile)).isFalse();
+  }
+}
diff --git a/sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java b/sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java
new file mode 100644 (file)
index 0000000..678fdc5
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.nio.charset.Charset;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DefaultFileSystemTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  @Test
+  public void test_directories() throws Exception {
+    DefaultFileSystem fs = new DefaultFileSystem();
+
+    File basedir = temp.newFolder();
+    fs.setBaseDir(basedir);
+    assertThat(fs.baseDir()).isAbsolute().isDirectory().exists();
+    assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
+
+    File workdir = temp.newFolder();
+    fs.setWorkDir(workdir);
+    assertThat(fs.workDir()).isAbsolute().isDirectory().exists();
+    assertThat(fs.workDir().getCanonicalPath()).isEqualTo(workdir.getCanonicalPath());
+  }
+
+  @Test
+  public void test_encoding() throws Exception {
+    DefaultFileSystem fs = new DefaultFileSystem();
+
+    assertThat(fs.isDefaultJvmEncoding()).isTrue();
+    assertThat(fs.encoding()).isEqualTo(Charset.defaultCharset());
+
+    fs.setEncoding(Charset.forName("ISO-8859-1"));
+    assertThat(fs.encoding()).isEqualTo(Charset.forName("ISO-8859-1"));
+    assertThat(fs.isDefaultJvmEncoding()).isFalse();
+  }
+
+  @Test
+  public void add_languages() throws Exception {
+    DefaultFileSystem fs = new DefaultFileSystem();
+
+    assertThat(fs.languages()).isEmpty();
+
+    fs.addLanguages("java", "php", "cobol");
+    assertThat(fs.languages()).containsOnly("cobol", "java", "php");
+  }
+
+  @Test
+  public void files() throws Exception {
+    DefaultFileSystem fs = new DefaultFileSystem();
+
+    assertThat(fs.inputFiles(fs.predicates().all())).isEmpty();
+
+    fs.add(new DefaultInputFile("src/Foo.php").setLanguage("php").setFile(temp.newFile()));
+    fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
+    fs.add(new DefaultInputFile("src/Baz.java").setLanguage("java").setFile(temp.newFile()));
+
+    // no language
+    fs.add(new DefaultInputFile("src/readme.txt").setFile(temp.newFile()));
+
+    assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNotNull();
+    assertThat(fs.inputFile(fs.predicates().hasRelativePath("does/not/exist"))).isNull();
+
+    assertThat(fs.files(fs.predicates().all())).hasSize(4);
+    assertThat(fs.files(fs.predicates().hasLanguage("java"))).hasSize(2);
+    assertThat(fs.files(fs.predicates().hasLanguage("cobol"))).isEmpty();
+
+    assertThat(fs.hasFiles(fs.predicates().all())).isTrue();
+    assertThat(fs.hasFiles(fs.predicates().hasLanguage("java"))).isTrue();
+    assertThat(fs.hasFiles(fs.predicates().hasLanguage("cobol"))).isFalse();
+
+    assertThat(fs.inputFiles(fs.predicates().all())).hasSize(4);
+    assertThat(fs.inputFiles(fs.predicates().hasLanguage("php"))).hasSize(1);
+    assertThat(fs.inputFiles(fs.predicates().hasLanguage("java"))).hasSize(2);
+    assertThat(fs.inputFiles(fs.predicates().hasLanguage("cobol"))).isEmpty();
+
+    assertThat(fs.languages()).containsOnly("java", "php");
+  }
+
+  @Test
+  public void input_file_returns_null_if_file_not_found() throws Exception {
+    DefaultFileSystem fs = new DefaultFileSystem();
+    assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNull();
+    assertThat(fs.inputFile(fs.predicates().hasLanguage("cobol"))).isNull();
+  }
+
+  @Test
+  public void input_file_fails_if_too_many_results() throws Exception {
+    thrown.expect(IllegalArgumentException.class);
+    thrown.expectMessage("expected one element");
+
+    DefaultFileSystem fs = new DefaultFileSystem();
+    fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
+    fs.add(new DefaultInputFile("src/Baz.java").setLanguage("java").setFile(temp.newFile()));
+
+    fs.inputFile(fs.predicates().all());
+  }
+
+  @Test
+  public void input_file_supports_non_indexed_predicates() throws Exception {
+    DefaultFileSystem fs = new DefaultFileSystem();
+    fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
+
+    // it would fail if more than one java file
+    assertThat(fs.inputFile(fs.predicates().hasLanguage("java"))).isNotNull();
+  }
+}
diff --git a/sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java b/sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java
new file mode 100644 (file)
index 0000000..b96821f
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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"))
+      .setKey("ABCDE")
+      .setHash("1234")
+      .setLines(42)
+      .setLanguage("php")
+      .setStatus(InputFile.Status.ADDED)
+      .setType(InputFile.Type.TEST);
+
+    assertThat(inputFile.relativePath()).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());
+  }
+
+  @Test
+  public void test_toString() throws Exception {
+    DefaultInputFile file = new DefaultInputFile("src/Foo.php").setAbsolutePath("/path/to/src/Foo.php");
+    assertThat(file.toString()).isEqualTo("[relative=src/Foo.php, abs=/path/to/src/Foo.php]");
+  }
+}
diff --git a/sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java b/sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java
new file mode 100644 (file)
index 0000000..01d6dab
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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 PathPatternTest {
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Test
+  public void match_relative_path() throws Exception {
+    PathPattern pattern = PathPattern.create("**/*Foo.java");
+    assertThat(pattern.toString()).isEqualTo("**/*Foo.java");
+
+    File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java");
+    InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java").setFile(file);
+    assertThat(pattern.match(inputFile)).isTrue();
+
+    // case sensitive by default
+    file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
+    inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
+    assertThat(pattern.match(inputFile)).isFalse();
+
+    file = new File(temp.newFolder(), "src/main/java/org/Other.java");
+    inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
+    assertThat(pattern.match(inputFile)).isFalse();
+  }
+
+  @Test
+  public void match_relative_path_and_insensitive_file_extension() throws Exception {
+    PathPattern pattern = PathPattern.create("**/*Foo.java");
+
+    File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
+    InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
+    assertThat(pattern.match(inputFile, false)).isTrue();
+
+    file = new File(temp.newFolder(), "src/main/java/org/Other.java");
+    inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
+    assertThat(pattern.match(inputFile, false)).isFalse();
+  }
+
+  @Test
+  public void match_absolute_path() throws Exception {
+    PathPattern pattern = PathPattern.create("file:**/src/main/**Foo.java");
+    assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
+
+    File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java");
+    InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java").setFile(file);
+    assertThat(pattern.match(inputFile)).isTrue();
+
+    // case sensitive by default
+    file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
+    inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
+    assertThat(pattern.match(inputFile)).isFalse();
+
+    file = new File(temp.newFolder(), "src/main/java/org/Other.java");
+    inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
+    assertThat(pattern.match(inputFile)).isFalse();
+  }
+
+  @Test
+  public void match_absolute_path_and_insensitive_file_extension() throws Exception {
+    PathPattern pattern = PathPattern.create("file:**/src/main/**Foo.java");
+    assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
+
+    File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
+    InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
+    assertThat(pattern.match(inputFile, false)).isTrue();
+
+    file = new File(temp.newFolder(), "src/main/java/org/Other.JAVA");
+    inputFile = new DefaultInputFile("src/main/java/org/Other.JAVA").setFile(file);
+    assertThat(pattern.match(inputFile, false)).isFalse();
+  }
+
+  @Test
+  public void create_array_of_patterns() throws Exception {
+    PathPattern[] patterns = PathPattern.create(new String[]{
+      "**/src/main/**Foo.java",
+      "file:**/src/main/**Bar.java"
+    });
+    assertThat(patterns).hasSize(2);
+    assertThat(patterns[0].toString()).isEqualTo("**/src/main/**Foo.java");
+    assertThat(patterns[1].toString()).isEqualTo("file:**/src/main/**Bar.java");
+  }
+}
index db45a80e535562ef36631374765e6ba301094fd6..1db1f35f0e90183603a4d496120734270af0e3f2 100644 (file)
       <groupId>org.codehaus.sonar</groupId>
       <artifactId>sonar-java-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.codehaus.sonar</groupId>
+      <artifactId>sonar-batch-plugin-api</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.codehaus.sonar</groupId>
       <artifactId>sonar-plugin-api</artifactId>
index 4d71b95e470528e6d26a6c7c816c390ddac4d2d9..089b2a3c58f5e9bad745573a60981e893572eaa2 100644 (file)
@@ -30,11 +30,16 @@ 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.resources.File;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.ProjectLink;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Resource;
 import org.sonar.api.rules.Violation;
 import org.sonar.api.utils.SonarException;
 import org.sonar.core.measure.MeasurementFilters;
 
+import java.io.Serializable;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
@@ -110,7 +115,7 @@ public class DefaultSensorContext implements SensorContext {
   }
 
   @Override
-  public Measure getMeasure(Metric metric) {
+  public <G extends Serializable> Measure<G> getMeasure(Metric<G> metric) {
     return index.getMeasure(project, metric);
   }
 
@@ -130,7 +135,7 @@ public class DefaultSensorContext implements SensorContext {
   }
 
   @Override
-  public Measure getMeasure(Resource resource, Metric metric) {
+  public <G extends Serializable> Measure<G> getMeasure(Resource resource, Metric<G> metric) {
     return index.getMeasure(resource, metric);
   }
 
index 4415122c3f657e99c16e180ad8bc7b2a75ffbb5f..896402195620f2c0119df25e8e853467f528494d 100644 (file)
@@ -38,6 +38,7 @@ public class AnalysisMode implements BatchComponent {
   private boolean preview;
   private boolean incremental;
   private int previewReadTimeoutSec;
+  private boolean sensorMode;
 
   public AnalysisMode(BootstrapProperties bootstrapProps) {
     init(bootstrapProps);
@@ -51,20 +52,28 @@ public class AnalysisMode implements BatchComponent {
     return incremental;
   }
 
+  public boolean isSensorMode() {
+    return sensorMode;
+  }
+
   private void init(BootstrapProperties bootstrapProps) {
     if (bootstrapProps.properties().containsKey(CoreProperties.DRY_RUN)) {
       LOG.warn(MessageFormat.format("Property {0} is deprecated. Please use {1} instead.", CoreProperties.DRY_RUN, CoreProperties.ANALYSIS_MODE));
       preview = "true".equals(bootstrapProps.property(CoreProperties.DRY_RUN));
       incremental = false;
+      sensorMode = false;
     } else {
       String mode = bootstrapProps.property(CoreProperties.ANALYSIS_MODE);
       preview = CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode);
       incremental = CoreProperties.ANALYSIS_MODE_INCREMENTAL.equals(mode);
+      sensorMode = CoreProperties.ANALYSIS_MODE_SENSOR.equals(mode);
     }
     if (incremental) {
       LOG.info("Incremental mode");
     } else if (preview) {
       LOG.info("Preview mode");
+    } else if (sensorMode) {
+      LOG.info("Sensor mode");
     }
     // To stay compatible with plugins that use the old property to check mode
     if (incremental || preview) {
index 02c98554fa6eff84d8564b6d1a33277b6822bee6..0391110d3a51221c9743b77b2aa09c049fc6ead9 100644 (file)
@@ -20,9 +20,6 @@
 package org.sonar.batch.bootstrap;
 
 import com.google.common.collect.Lists;
-import org.sonar.batch.debt.DebtDecorator;
-import org.sonar.batch.debt.IssueChangelogDebtCalculator;
-import org.sonar.batch.debt.NewDebtDecorator;
 import org.sonar.batch.maven.DefaultMavenPluginExecutor;
 import org.sonar.batch.maven.MavenProjectBootstrapper;
 import org.sonar.batch.maven.MavenProjectBuilder;
@@ -36,11 +33,8 @@ public class BatchComponents {
   public static Collection all() {
     List components = Lists.newArrayList(
       // Maven
-      MavenProjectBootstrapper.class, DefaultMavenPluginExecutor.class, MavenProjectConverter.class, MavenProjectBuilder.class,
-
-      // Debt
-      IssueChangelogDebtCalculator.class, DebtDecorator.class, NewDebtDecorator.class
-    );
+      MavenProjectBootstrapper.class, DefaultMavenPluginExecutor.class, MavenProjectConverter.class, MavenProjectBuilder.class
+      );
     components.addAll(CorePropertyDefinitions.all());
     return components;
   }
index 7cbf67570b12db8503c46badf0f78cd58da1b3ce..538e3091e424d5a3f7aa7353295b4b7d220c3e94 100644 (file)
@@ -21,10 +21,14 @@ package org.sonar.batch.bootstrap;
 
 import com.google.common.collect.Lists;
 import org.apache.commons.lang.ClassUtils;
-import org.sonar.api.BatchExtension;
 import org.sonar.api.batch.CheckProject;
+import org.sonar.api.batch.Sensor;
+import org.sonar.api.batch.fs.FileSystem;
 import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
+import org.sonar.batch.api.analyzer.Analyzer;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.scan.SensorWrapper;
 
 import java.util.Collection;
 import java.util.List;
@@ -34,8 +38,13 @@ import java.util.List;
  */
 public class BatchExtensionDictionnary extends org.sonar.api.batch.BatchExtensionDictionnary {
 
-  public BatchExtensionDictionnary(ComponentContainer componentContainer) {
+  private FileSystem fs;
+  private AnalyzerContext context;
+
+  public BatchExtensionDictionnary(ComponentContainer componentContainer, FileSystem fs, AnalyzerContext context) {
     super(componentContainer);
+    this.fs = fs;
+    this.context = context;
   }
 
   public <T> Collection<T> select(Class<T> type, Project project, boolean sort, ExtensionMatcher matcher) {
@@ -48,7 +57,10 @@ public class BatchExtensionDictionnary extends org.sonar.api.batch.BatchExtensio
 
   private <T> List<T> getFilteredExtensions(Class<T> type, Project project, ExtensionMatcher matcher) {
     List<T> result = Lists.newArrayList();
-    for (BatchExtension extension : getExtensions()) {
+    for (Object extension : getExtensions()) {
+      if (type == Sensor.class && extension instanceof Analyzer) {
+        extension = new SensorWrapper((Analyzer) extension, context, fs);
+      }
       if (shouldKeep(type, extension, project, matcher)) {
         result.add((T) extension);
       }
@@ -57,7 +69,9 @@ public class BatchExtensionDictionnary extends org.sonar.api.batch.BatchExtensio
   }
 
   private boolean shouldKeep(Class type, Object extension, Project project, ExtensionMatcher matcher) {
-    boolean keep = ClassUtils.isAssignable(extension.getClass(), type) && (matcher == null || matcher.accept(extension));
+    boolean keep = (ClassUtils.isAssignable(extension.getClass(), type)
+      || (type == Sensor.class && ClassUtils.isAssignable(extension.getClass(), Analyzer.class)))
+      && (matcher == null || matcher.accept(extension));
     if (keep && project != null && ClassUtils.isAssignable(extension.getClass(), CheckProject.class)) {
       keep = ((CheckProject) extension).shouldExecuteOnProject(project);
     }
index 693be2183a2753e764e9c008a0c184602f67d369..5d7e836786bae4b03368e628c61f1aea18bcfe76 100644 (file)
@@ -39,6 +39,10 @@ import org.sonar.batch.components.PastSnapshotFinderByDays;
 import org.sonar.batch.components.PastSnapshotFinderByPreviousAnalysis;
 import org.sonar.batch.components.PastSnapshotFinderByPreviousVersion;
 import org.sonar.batch.components.PastSnapshotFinderByVersion;
+import org.sonar.batch.debt.DebtModelProvider;
+import org.sonar.batch.rule.RulesProvider;
+import org.sonar.batch.rules.DefaultQProfileReferential;
+import org.sonar.batch.rules.QProfilesReferential;
 import org.sonar.batch.settings.DefaultSettingsReferential;
 import org.sonar.batch.settings.SettingsReferential;
 import org.sonar.core.cluster.NullQueue;
@@ -83,8 +87,8 @@ public class BootstrapContainer extends ComponentContainer {
     addBootstrapComponents();
     if (!sensorMode) {
       addDatabaseComponents();
+      addCoreComponents();
     }
-    addCoreComponents();
   }
 
   private void addBootstrapComponents() {
@@ -118,6 +122,9 @@ public class BootstrapContainer extends ComponentContainer {
     if (getComponentByType(MetricFinder.class) == null) {
       add(CacheMetricFinder.class);
     }
+    if (getComponentByType(QProfilesReferential.class) == null) {
+      add(DefaultQProfileReferential.class);
+    }
   }
 
   private void addDatabaseComponents() {
@@ -156,7 +163,9 @@ public class BootstrapContainer extends ComponentContainer {
       PastSnapshotFinderByPreviousVersion.class,
       PastMeasuresLoader.class,
       PastSnapshotFinder.class,
-      Durations.class);
+      Durations.class,
+      new DebtModelProvider(),
+      new RulesProvider());
   }
 
   @Override
@@ -172,8 +181,8 @@ public class BootstrapContainer extends ComponentContainer {
     }
   }
 
-  public void executeTask(Map<String, String> taskProperties) {
-    new TaskContainer(this, taskProperties).execute();
+  public void executeTask(Map<String, String> taskProperties, Object... components) {
+    new TaskContainer(this, taskProperties, components).execute();
   }
 
 }
index bb2b2e431f2a0d6e105f383795022cb780688c6d..b7088cf4c013f006d75382da833dc32ed2046772 100644 (file)
@@ -43,11 +43,10 @@ public class ExtensionInstaller {
   }
 
   public ExtensionInstaller install(ComponentContainer container, ExtensionMatcher matcher) {
-    boolean preview = analysisMode.isPreview();
 
     // core components
     for (Object o : BatchComponents.all()) {
-      doInstall(container, matcher, null, preview, o);
+      doInstall(container, matcher, null, o);
     }
 
     // plugin extensions
@@ -55,7 +54,7 @@ public class ExtensionInstaller {
       PluginMetadata metadata = entry.getKey();
       Plugin plugin = entry.getValue();
       for (Object extension : plugin.getExtensions()) {
-        doInstall(container, matcher, metadata, preview, extension);
+        doInstall(container, matcher, metadata, extension);
       }
     }
     List<ExtensionProvider> providers = container.getComponentsByType(ExtensionProvider.class);
@@ -63,18 +62,18 @@ public class ExtensionInstaller {
       Object object = provider.provide();
       if (object instanceof Iterable) {
         for (Object extension : (Iterable) object) {
-          doInstall(container, matcher, null, preview, extension);
+          doInstall(container, matcher, null, extension);
         }
       } else {
-        doInstall(container, matcher, null, preview, object);
+        doInstall(container, matcher, null, object);
       }
     }
     return this;
   }
 
-  private void doInstall(ComponentContainer container, ExtensionMatcher matcher, @Nullable PluginMetadata metadata, boolean dryRun, Object extension) {
+  private void doInstall(ComponentContainer container, ExtensionMatcher matcher, @Nullable PluginMetadata metadata, Object extension) {
     if (ExtensionUtils.supportsEnvironment(extension, env)
-      && (!dryRun || ExtensionUtils.supportsPreview(extension))
+      && (!analysisMode.isPreview() || ExtensionUtils.supportsPreview(extension))
       && matcher.accept(extension)) {
       container.addExtension(metadata, extension);
     } else {
index 86122e7dec45704d8c5780bd0dc63e713df93ec0..e7fd8427a2d11e712086c94ebb2a935ebe09675f 100644 (file)
@@ -41,10 +41,12 @@ import java.util.Map;
 public class TaskContainer extends ComponentContainer {
 
   private final Map<String, String> taskProperties;
+  private final Object[] components;
 
-  public TaskContainer(ComponentContainer parent, Map<String, String> taskProperties) {
+  public TaskContainer(ComponentContainer parent, Map<String, String> taskProperties, Object... components) {
     super(parent);
     this.taskProperties = taskProperties;
+    this.components = components;
   }
 
   @Override
@@ -52,6 +54,9 @@ public class TaskContainer extends ComponentContainer {
     installCoreTasks();
     installTaskExtensions();
     installComponentsUsingTaskExtensions();
+    for (Object component : components) {
+      add(component);
+    }
   }
 
   void installCoreTasks() {
index 972450aebdeab54ea8b16325760b8ea6fe038dcb..ac107141bc3e44fddb4e3056a9239198a629ba9a 100644 (file)
@@ -87,12 +87,12 @@ public final class Batch {
   /**
    * @since 4.4
    */
-  public Batch executeTask(Map<String, String> taskProperties) {
+  public Batch executeTask(Map<String, String> taskProperties, Object... components) {
     if (!started) {
       throw new IllegalStateException("Batch is not started. Unable to execute task.");
     }
 
-    bootstrapContainer.executeTask(taskProperties);
+    bootstrapContainer.executeTask(taskProperties, components);
     return this;
   }
 
index 44db4e53f733dbb074ef2088ca7e2a2cdf5f9cdf..ae75f47f2a47d5b0e76bbecc59635d2d7bfa2757 100644 (file)
@@ -178,7 +178,7 @@ public class DefaultIndex extends SonarIndex {
   }
 
   @Override
-  public Measure getMeasure(Resource resource, Metric metric) {
+  public Measure getMeasure(Resource resource, org.sonar.batch.api.measures.Metric<?> metric) {
     return getMeasures(resource, MeasuresFilters.metric(metric));
   }
 
index 99eeb05cac9a51e853ecc5c6eba442fe29041c8c..4e169391d11e11475b3659c0faa16e79d92950a3 100644 (file)
@@ -26,7 +26,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.database.DatabaseSession;
 import org.sonar.api.database.model.ResourceModel;
 import org.sonar.api.resources.Directory;
@@ -80,7 +80,7 @@ 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 = ((DefaultInputFile) inputFile).deprecatedKey();
+      String deprecatedKey = ((DeprecatedDefaultInputFile) inputFile).deprecatedKey();
       if (deprecatedKey != null) {
         if (InputFile.Type.TEST == inputFile.type() && !deprecatedTestKeyMapper.containsKey(deprecatedKey)) {
           deprecatedTestKeyMapper.put(deprecatedKey, inputFile);
@@ -109,7 +109,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 = ((DefaultInputFile) matchedFile).key();
+        String newEffectiveKey = ((DeprecatedDefaultInputFile) matchedFile).key();
         // Now compute migration of the parent dir
         String oldKey = StringUtils.substringAfterLast(oldEffectiveKey, ":");
         Resource sonarFile;
index e896729663a7de68ae06d1244a153efdc1167395..79b576d3398e7439ccdd81a4494fb94ba1117f92 100644 (file)
@@ -53,15 +53,34 @@ public class IssueFilters implements BatchExtension {
     this(deprecatedFilters, deprecatedViolations, new org.sonar.api.issue.IssueFilter[0]);
   }
 
+  /**
+   * Used by scan2
+   */
+  public IssueFilters(org.sonar.api.issue.IssueFilter[] exclusionFilters, IssueFilter[] filters) {
+    this(null, null, exclusionFilters, filters);
+  }
+
+  public IssueFilters(org.sonar.api.issue.IssueFilter[] exclusionFilters) {
+    this(null, null, exclusionFilters, new IssueFilter[0]);
+  }
+
+  public IssueFilters(IssueFilter[] filters) {
+    this(null, null, new org.sonar.api.issue.IssueFilter[0], filters);
+  }
+
+  public IssueFilters() {
+    this(null, null, new org.sonar.api.issue.IssueFilter[0], new IssueFilter[0]);
+  }
+
   public boolean accept(DefaultIssue issue, @Nullable Violation violation) {
-    if(new DefaultIssueFilterChain(filters).accept(issue)) {
+    if (new DefaultIssueFilterChain(filters).accept(issue)) {
       // Apply deprecated rules only if filter chain accepts the current issue
       for (org.sonar.api.issue.IssueFilter filter : exclusionFilters) {
         if (!filter.accept(issue)) {
           return false;
         }
       }
-      if (!deprecatedFilters.isEmpty()) {
+      if (deprecatedFilters != null && !deprecatedFilters.isEmpty()) {
         Violation v = violation != null ? violation : deprecatedViolations.toViolation(issue);
         return !deprecatedFilters.isIgnored(v);
       }
index 6f46e2cc7a9bcda27cc86d06ecbebc87d3c02f0e..1e880a6b31d0ecef0cba983a5fc233415a744cb0 100644 (file)
@@ -47,7 +47,7 @@ public class ModuleIssues {
   private final Project project;
   private final IssueFilters filters;
 
-  public ModuleIssues(ActiveRules activeRules, Rules rules, IssueCache cache, Project project, IssueFilters filters) {
+  public ModuleIssues(ActiveRules activeRules, Rules rules, IssueCache cache, @Nullable Project project, IssueFilters filters) {
     this.activeRules = activeRules;
     this.rules = rules;
     this.cache = cache;
@@ -55,6 +55,13 @@ public class ModuleIssues {
     this.filters = filters;
   }
 
+  /** 
+   * Used by scan2
+   */
+  public ModuleIssues(ActiveRules activeRules, Rules rules, IssueCache cache, IssueFilters filters) {
+    this(activeRules, rules, cache, null, filters);
+  }
+
   public boolean initAndAddIssue(DefaultIssue issue) {
     return initAndAddIssue(issue, null);
   }
@@ -67,6 +74,7 @@ public class ModuleIssues {
   private DefaultIssue newIssue(Violation violation) {
     return (DefaultIssue) new DefaultIssueBuilder()
       .componentKey(violation.getResource().getEffectiveKey())
+      // Project can be null but Violation not used by scan2
       .projectKey(project.getRoot().getEffectiveKey())
       .ruleKey(RuleKey.of(violation.getRule().getRepositoryKey(), violation.getRule().getKey()))
       .effortToFix(violation.getCost())
@@ -107,8 +115,10 @@ public class ModuleIssues {
     if (Strings.isNullOrEmpty(issue.message())) {
       issue.setMessage(rule.name());
     }
-    issue.setCreationDate(project.getAnalysisDate());
-    issue.setUpdateDate(project.getAnalysisDate());
+    if (project != null) {
+      issue.setCreationDate(project.getAnalysisDate());
+      issue.setUpdateDate(project.getAnalysisDate());
+    }
     if (issue.severity() == null) {
       issue.setSeverity(activeRule.severity());
     }
index 1dad68550bb455b5beba57f2af086497d5a6dc37..5f3e9c308e8fbe8ed4a429dc1f22f21a51bcd8c4 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.batch.issue.ignore.scanner;
 
 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.resources.Project;
 import org.sonar.api.utils.SonarException;
 import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
@@ -59,7 +59,7 @@ public final class IssueExclusionsLoader {
 
     for (InputFile inputFile : fileSystem.inputFiles(fileSystem.predicates().all())) {
       try {
-        String componentEffectiveKey = ((DefaultInputFile) inputFile).key();
+        String componentEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key();
         if (componentEffectiveKey != null) {
           String path = inputFile.relativePath();
           inclusionPatternInitializer.initializePatternsForPath(path, componentEffectiveKey);
index ca77b7c239c06e0849d661e50738a7725c0cee57..fcada30d053202ca5568cffe63e73ee372003455 100644 (file)
@@ -44,14 +44,14 @@ public class LanguageDistributionDecorator implements Decorator {
 
   @DependsUpon
   public List<Metric> dependsUponMetrics() {
-    return ImmutableList.of(CoreMetrics.LINES);
+    return ImmutableList.<Metric>of(CoreMetrics.LINES);
   }
 
   @DependedUpon
   public List<Metric> generatesMetrics() {
     return ImmutableList.of(
       CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION
-    );
+      );
   }
 
   public void decorate(Resource resource, DecoratorContext context) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/languages/DeprecatedLanguagesReferential.java b/sonar-batch/src/main/java/org/sonar/batch/languages/DeprecatedLanguagesReferential.java
new file mode 100644 (file)
index 0000000..1084b7d
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.languages;
+
+import org.sonar.api.resources.Languages;
+import org.sonar.batch.api.languages.Language;
+
+import javax.annotation.CheckForNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Languages referential using {@link Languages}
+ * @since 4.4
+ */
+public class DeprecatedLanguagesReferential implements LanguagesReferential {
+
+  private Languages languages;
+
+  public DeprecatedLanguagesReferential(Languages languages) {
+    this.languages = languages;
+  }
+
+  /**
+   * Get language.
+   */
+  @CheckForNull
+  public Language get(String languageKey) {
+    org.sonar.api.resources.Language language = languages.get(languageKey);
+    return language != null ? new Language(language.getKey(), language.getName(), language.getFileSuffixes()) : null;
+  }
+
+  /**
+   * Get list of all supported languages.
+   */
+  public Collection<Language> all() {
+    org.sonar.api.resources.Language[] all = languages.all();
+    Collection<Language> result = new ArrayList<Language>(all.length);
+    for (org.sonar.api.resources.Language language : all) {
+      result.add(new Language(language.getKey(), language.getName(), language.getFileSuffixes()));
+    }
+    return result;
+  }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/languages/LanguagesReferential.java b/sonar-batch/src/main/java/org/sonar/batch/languages/LanguagesReferential.java
new file mode 100644 (file)
index 0000000..bf9fcd0
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.languages;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.batch.api.languages.Language;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Collection;
+
+/**
+ * Languages referential
+ * @since 4.4
+ */
+public interface LanguagesReferential extends BatchComponent {
+
+  /**
+   * Get language.
+   */
+  @CheckForNull
+  Language get(String languageKey);
+
+  /**
+   * Get list of all supported languages.
+   */
+  Collection<Language> all();
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/languages/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/languages/package-info.java
new file mode 100644 (file)
index 0000000..5ce5bc1
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.languages;
\ No newline at end of file
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/Phase2Executor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/Phase2Executor.java
deleted file mode 100644 (file)
index 87d1348..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.phases;
-
-import com.google.common.collect.Lists;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.resources.Project;
-import org.sonar.batch.events.EventBus;
-import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
-import org.sonar.batch.rule.QProfileVerifier;
-import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
-import org.sonar.batch.scan.filesystem.FileSystemLogger;
-import org.sonar.batch.scan.maven.MavenPluginsConfigurator;
-
-import java.util.Collection;
-
-public final class Phase2Executor {
-
-  public static final Logger LOGGER = LoggerFactory.getLogger(Phase2Executor.class);
-
-  private final EventBus eventBus;
-  private final Phases phases;
-  private final MavenPluginsConfigurator mavenPluginsConfigurator;
-  private final InitializersExecutor initializersExecutor;
-  private final SensorsExecutor sensorsExecutor;
-  private final SensorContext sensorContext;
-  private final ProjectInitializer pi;
-  private final FileSystemLogger fsLogger;
-  private final DefaultModuleFileSystem fs;
-  private final QProfileVerifier profileVerifier;
-  private final IssueExclusionsLoader issueExclusionsLoader;
-
-  public Phase2Executor(Phases phases,
-    MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
-    SensorsExecutor sensorsExecutor,
-    SensorContext sensorContext,
-    EventBus eventBus, ProjectInitializer pi,
-    FileSystemLogger fsLogger, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
-    IssueExclusionsLoader issueExclusionsLoader) {
-    this.phases = phases;
-    this.mavenPluginsConfigurator = mavenPluginsConfigurator;
-    this.initializersExecutor = initializersExecutor;
-    this.sensorsExecutor = sensorsExecutor;
-    this.sensorContext = sensorContext;
-    this.eventBus = eventBus;
-    this.pi = pi;
-    this.fsLogger = fsLogger;
-    this.fs = fs;
-    this.profileVerifier = profileVerifier;
-    this.issueExclusionsLoader = issueExclusionsLoader;
-  }
-
-  public static Collection<Class> getPhaseClasses() {
-    return Lists.<Class>newArrayList(SensorsExecutor.class, InitializersExecutor.class, ProjectInitializer.class);
-  }
-
-  /**
-   * Executed on each module
-   */
-  public void execute(Project module) {
-    pi.execute(module);
-
-    eventBus.fireEvent(new ProjectAnalysisEvent(module, true));
-
-    executeMavenPhase(module);
-
-    executeInitializersPhase();
-
-    // Index and lock the filesystem
-    fs.index();
-
-    // Log detected languages and their profiles after FS is indexed and languages detected
-    profileVerifier.execute();
-
-    // Initialize issue exclusions
-    issueExclusionsLoader.execute();
-
-    sensorsExecutor.execute(sensorContext);
-
-    eventBus.fireEvent(new ProjectAnalysisEvent(module, false));
-  }
-
-  private void executeInitializersPhase() {
-    if (phases.isEnabled(Phases.Phase.INIT)) {
-      initializersExecutor.execute();
-      fsLogger.log();
-    }
-  }
-
-  private void executeMavenPhase(Project module) {
-    if (phases.isEnabled(Phases.Phase.MAVEN)) {
-      eventBus.fireEvent(new MavenPhaseEvent(true));
-      mavenPluginsConfigurator.execute(module);
-      eventBus.fireEvent(new MavenPhaseEvent(false));
-    }
-  }
-}
index 2ee73f61dfbedc04e535ccb9cc960da4f27e7b84..6328ac77a4614241527fe8846e42fa3738712a1b 100644 (file)
  */
 package org.sonar.batch.phases;
 
-import org.sonar.batch.bootstrap.ExtensionMatcher;
-
 import org.apache.commons.lang.ClassUtils;
 import org.sonar.api.BatchExtension;
 import org.sonar.api.batch.InstantiationStrategy;
 import org.sonar.api.batch.Sensor;
+import org.sonar.batch.api.analyzer.Analyzer;
+import org.sonar.batch.bootstrap.ExtensionMatcher;
 
 /**
  * Allow to filter sensors that will be executed.
@@ -36,7 +36,8 @@ public abstract class SensorMatcher implements BatchExtension, ExtensionMatcher
 
   @Override
   public final boolean accept(Object extension) {
-    return ClassUtils.isAssignable(extension.getClass(), Sensor.class) && acceptSensor((Sensor) extension);
+    return ClassUtils.isAssignable(extension.getClass(), Sensor.class)
+      && acceptSensor((Sensor) extension) || ClassUtils.isAssignable(extension.getClass(), Analyzer.class);
   }
 
   public abstract boolean acceptSensor(Sensor sensor);
index 95762afd79d5f981829b961295f15d833c82e280..a7aea325d484545be71244d8676fb98fdc377620 100644 (file)
@@ -28,6 +28,8 @@ import org.sonar.api.batch.rule.internal.NewActiveRule;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RuleFinder;
 import org.sonar.api.rules.RuleParam;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
 import org.sonar.core.qualityprofile.db.ActiveRuleDao;
 import org.sonar.core.qualityprofile.db.ActiveRuleDto;
 import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
@@ -49,13 +51,14 @@ public class ActiveRulesProvider extends ProviderAdapter {
 
   private ActiveRules load(ModuleQProfiles qProfiles, ActiveRuleDao dao, RuleFinder ruleFinder) {
     ActiveRulesBuilder builder = new ActiveRulesBuilder();
-    for (ModuleQProfiles.QProfile qProfile : qProfiles.findAll()) {
+    for (QProfile qProfile : qProfiles.findAll()) {
+      QProfileWithId qProfileWithId = (QProfileWithId) qProfile;
       ListMultimap<Integer, ActiveRuleParamDto> paramDtosByActiveRuleId = ArrayListMultimap.create();
-      for (ActiveRuleParamDto dto : dao.selectParamsByProfileId(qProfile.id())) {
+      for (ActiveRuleParamDto dto : dao.selectParamsByProfileId(qProfileWithId.id())) {
         paramDtosByActiveRuleId.put(dto.getActiveRuleId(), dto);
       }
 
-      for (ActiveRuleDto activeDto : dao.selectByProfileId(qProfile.id())) {
+      for (ActiveRuleDto activeDto : dao.selectByProfileId(qProfileWithId.id())) {
         Rule rule = ruleFinder.findById(activeDto.getRulId());
         if (rule != null) {
           NewActiveRule newActiveRule = builder.activate(rule.ruleKey());
index fb5027d923b3a5d91f845314af2ba95e084e8020..674fbb59a564e059275045481ba48ff93e263e2b 100644 (file)
@@ -23,11 +23,11 @@ import com.google.common.collect.ImmutableMap;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.BatchComponent;
 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.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.batch.api.languages.Language;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.languages.LanguagesReferential;
+import org.sonar.batch.rules.QProfilesReferential;
 
 import javax.annotation.CheckForNull;
 
@@ -41,55 +41,19 @@ public class ModuleQProfiles implements BatchComponent {
 
   public static final String SONAR_PROFILE_PROP = "sonar.profile";
 
-  public static class QProfile {
-    private final String name, language;
-    private final Integer version;
-    private final int id;
-
-    public QProfile(QualityProfileDto dto) {
-      this.id = dto.getId();
-      this.name = dto.getName();
-      this.language = dto.getLanguage();
-      this.version = dto.getVersion();
-    }
-
-    QProfile(int id, String name, String language, Integer version) {
-      this.id = id;
-      this.name = name;
-      this.language = language;
-      this.version = version;
-    }
-
-    public int id() {
-      return id;
-    }
-
-    public String name() {
-      return name;
-    }
-
-    public String language() {
-      return language;
-    }
-
-    public Integer version() {
-      return version;
-    }
-  }
-
   private final Map<String, QProfile> byLanguage;
 
-  public ModuleQProfiles(Settings settings, Languages languages, QualityProfileDao dao) {
+  public ModuleQProfiles(Settings settings, LanguagesReferential languages, QProfilesReferential qProfileRef) {
     ImmutableMap.Builder<String, QProfile> builder = ImmutableMap.builder();
     String defaultName = settings.getString(SONAR_PROFILE_PROP);
 
     for (Language language : languages.all()) {
       QProfile profile = null;
       if (StringUtils.isNotBlank(defaultName)) {
-        profile = loadDefaultQProfile(dao, defaultName, language.getKey());
+        profile = loadDefaultQProfile(qProfileRef, defaultName, language.key());
       }
       if (profile == null) {
-        profile = loadQProfile(dao, settings, language.getKey());
+        profile = loadQProfile(qProfileRef, settings, language.key());
       }
       if (profile != null) {
         builder.put(profile.language(), profile);
@@ -99,25 +63,21 @@ public class ModuleQProfiles implements BatchComponent {
   }
 
   @CheckForNull
-  private QProfile loadQProfile(QualityProfileDao dao, Settings settings, String language) {
+  private QProfile loadQProfile(QProfilesReferential qProfileRef, Settings settings, String language) {
     String profileName = settings.getString("sonar.profile." + language);
     if (profileName != null) {
-      QualityProfileDto dto = dao.selectByNameAndLanguage(profileName, language);
+      QProfile dto = qProfileRef.get(language, profileName);
       if (dto == null) {
         throw MessageException.of(String.format("Quality profile not found : '%s' on language '%s'", profileName, language));
       }
-      return new QProfile(dto);
+      return dto;
     }
     return null;
   }
 
   @CheckForNull
-  private QProfile loadDefaultQProfile(QualityProfileDao dao, String profileName, String language) {
-    QualityProfileDto dto = dao.selectByNameAndLanguage(profileName, language);
-    if (dto != null) {
-      return new QProfile(dto);
-    }
-    return null;
+  private QProfile loadDefaultQProfile(QProfilesReferential qProfileRef, String profileName, String language) {
+    return qProfileRef.get(language, profileName);
   }
 
   public Collection<QProfile> findAll() {
index ee67fcb31cd95636e01e490023e1c37777aef23f..e84dc342c1779e6062f8bfb0a6189a202171d880 100644 (file)
@@ -34,8 +34,7 @@ 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.resources.ResourceUtils;
-import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
 import org.sonar.core.qualityprofile.db.QualityProfileDao;
 import org.sonar.core.qualityprofile.db.QualityProfileDto;
 
@@ -101,14 +100,14 @@ public class QProfileEventsDecorator implements Decorator {
       } else {
         pastProfileVersion = pastProfileVersionMeasure.getIntValue();
       }
-      pastProfiles = UsedQProfiles.fromProfiles(new ModuleQProfiles.QProfile(pastProfileId, pastProfileName, pastProfileLanguage, pastProfileVersion));
+      pastProfiles = UsedQProfiles.fromProfiles(new QProfileWithId(pastProfileId, pastProfileName, pastProfileLanguage, pastProfileVersion));
     }
 
     // Now create appropriate events
-    Map<Integer, QProfile> pastProfilesById = Maps.newHashMap(pastProfiles.profilesById());
-    for (QProfile profile : currentProfiles.profilesById().values()) {
+    Map<Integer, QProfileWithId> pastProfilesById = Maps.newHashMap(pastProfiles.profilesById());
+    for (QProfileWithId profile : currentProfiles.profilesById().values()) {
       if (pastProfilesById.containsKey(profile.id())) {
-        QProfile pastProfile = pastProfilesById.get(profile.id());
+        QProfileWithId pastProfile = pastProfilesById.get(profile.id());
         if (pastProfile.version() < profile.version()) {
           // New version of the same QP
           usedProfile(context, profile);
@@ -118,25 +117,25 @@ public class QProfileEventsDecorator implements Decorator {
         usedProfile(context, profile);
       }
     }
-    for (QProfile profile : pastProfilesById.values()) {
+    for (QProfileWithId profile : pastProfilesById.values()) {
       // Following profiles are no more used
       stopUsedProfile(context, profile);
     }
   }
 
-  private void stopUsedProfile(DecoratorContext context, QProfile profile) {
+  private void stopUsedProfile(DecoratorContext context, QProfileWithId profile) {
     Language language = languages.get(profile.language());
     String languageName = language != null ? language.getName() : profile.language();
     context.createEvent("Stop using " + format(profile) + " (" + languageName + ")", format(profile) + " no more used for " + languageName, Event.CATEGORY_PROFILE, null);
   }
 
-  private void usedProfile(DecoratorContext context, QProfile profile) {
+  private void usedProfile(DecoratorContext context, QProfileWithId profile) {
     Language language = languages.get(profile.language());
     String languageName = language != null ? language.getName() : profile.language();
     context.createEvent("Use " + format(profile) + " (" + languageName + ")", format(profile) + " used for " + languageName, Event.CATEGORY_PROFILE, null);
   }
 
-  private String format(QProfile profile) {
+  private String format(QProfileWithId profile) {
     return profile.name() + " version " + profile.version();
   }
 
index 0773a3c64723216fdb25d0e9b48d73a31c1da998..620f769d8b76243e415b9ad40b1494078c93fe50 100644 (file)
@@ -26,6 +26,7 @@ import org.sonar.api.batch.fs.FileSystem;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.resources.Project;
+import org.sonar.batch.rules.QProfileWithId;
 import org.sonar.core.qualityprofile.db.QualityProfileDao;
 
 import java.util.List;
@@ -51,9 +52,9 @@ public class QProfileSensor implements Sensor {
   }
 
   public void analyse(Project project, SensorContext context) {
-    List<ModuleQProfiles.QProfile> profiles = Lists.newArrayList();
+    List<QProfileWithId> profiles = Lists.newArrayList();
     for (String language : fs.languages()) {
-      ModuleQProfiles.QProfile qProfile = moduleQProfiles.findByLanguage(language);
+      QProfileWithId qProfile = (QProfileWithId) moduleQProfiles.findByLanguage(language);
       if (qProfile != null) {
         dao.updateUsedColumn(qProfile.id(), true);
         profiles.add(qProfile);
@@ -65,7 +66,7 @@ public class QProfileSensor implements Sensor {
 
     // For backward compatibility
     if (profiles.size() == 1) {
-      ModuleQProfiles.QProfile qProfile = profiles.get(0);
+      QProfileWithId qProfile = profiles.get(0);
       Measure measure = new Measure(CoreMetrics.PROFILE, qProfile.name()).setValue((double) qProfile.id());
       Measure measureVersion = new Measure(CoreMetrics.PROFILE_VERSION, qProfile.version().doubleValue());
       context.saveMeasure(measure);
index ac8e51eb10ec10293817e48ea68c3edc5c7d79b1..10e110b6ee9e568c7ac3bb7974d4ee98eeda3b41 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.BatchComponent;
 import org.sonar.api.batch.fs.FileSystem;
 import org.sonar.api.config.Settings;
 import org.sonar.api.utils.MessageException;
-import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+import org.sonar.batch.api.rules.QProfile;
 
 public class QProfileVerifier implements BatchComponent {
 
index 2b778be21dc04e7535966682284cc8cde1737d1d..2c5ec75a2355b2c82782776a03b139254eaa5026 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.api.rules.ActiveRule;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RuleFinder;
 import org.sonar.api.rules.RulePriority;
+import org.sonar.batch.api.rules.QProfile;
 
 import java.util.Collection;
 import java.util.Map;
@@ -55,8 +56,8 @@ public class RulesProfileProvider extends ProviderAdapter {
   }
 
   private RulesProfile loadSingleLanguageProfile(ModuleQProfiles qProfiles, ActiveRules activeRules,
-                                                 RuleFinder ruleFinder, String language) {
-    ModuleQProfiles.QProfile qProfile = qProfiles.findByLanguage(language);
+    RuleFinder ruleFinder, String language) {
+    QProfile qProfile = qProfiles.findByLanguage(language);
     if (qProfile != null) {
       return new RulesProfileWrapper(select(qProfile, activeRules, ruleFinder));
     }
@@ -65,13 +66,13 @@ public class RulesProfileProvider extends ProviderAdapter {
 
   private RulesProfile loadProfiles(ModuleQProfiles qProfiles, ActiveRules activeRules, RuleFinder ruleFinder) {
     Collection<RulesProfile> dtos = Lists.newArrayList();
-    for (ModuleQProfiles.QProfile qProfile : qProfiles.findAll()) {
+    for (QProfile qProfile : qProfiles.findAll()) {
       dtos.add(select(qProfile, activeRules, ruleFinder));
     }
     return new RulesProfileWrapper(dtos);
   }
 
-  private RulesProfile select(ModuleQProfiles.QProfile qProfile, ActiveRules activeRules, RuleFinder ruleFinder) {
+  private RulesProfile select(QProfile qProfile, ActiveRules activeRules, RuleFinder ruleFinder) {
     RulesProfile deprecatedProfile = new RulesProfile();
     deprecatedProfile.setVersion(qProfile.version());
     deprecatedProfile.setName(qProfile.name());
index 1b1115ed18bd5ea208983a885d6968f50a13b975..5973a74c59342029225af8496589a15a47cd9db0 100644 (file)
@@ -26,7 +26,7 @@ import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
 
 import javax.annotation.concurrent.Immutable;
 
@@ -37,14 +37,14 @@ import java.util.Map;
 @Immutable
 public class UsedQProfiles {
 
-  private Map<Integer, ModuleQProfiles.QProfile> profilesById = Maps.newLinkedHashMap();
+  private Map<Integer, QProfileWithId> profilesById = Maps.newLinkedHashMap();
 
   private UsedQProfiles() {
   }
 
-  public static final UsedQProfiles fromProfiles(Iterable<QProfile> profiles) {
+  public static final UsedQProfiles fromProfiles(Iterable<QProfileWithId> profiles) {
     UsedQProfiles result = new UsedQProfiles();
-    for (QProfile qProfile : profiles) {
+    for (QProfileWithId qProfile : profiles) {
       result.add(qProfile);
     }
     return result;
@@ -54,7 +54,7 @@ public class UsedQProfiles {
     return new UsedQProfiles();
   }
 
-  public static final UsedQProfiles fromProfiles(QProfile... profiles) {
+  public static final UsedQProfiles fromProfiles(QProfileWithId... profiles) {
     return fromProfiles(Arrays.asList(profiles));
   }
 
@@ -63,7 +63,7 @@ public class UsedQProfiles {
     JsonArray root = new JsonParser().parse(json).getAsJsonArray();
     for (JsonElement elt : root) {
       JsonObject profile = elt.getAsJsonObject();
-      result.add(new QProfile(profile.get("id").getAsInt(), profile.get("name").getAsString(), profile.get("language").getAsString(), profile.get("version").getAsInt()));
+      result.add(new QProfileWithId(profile.get("id").getAsInt(), profile.get("name").getAsString(), profile.get("language").getAsString(), profile.get("version").getAsInt()));
     }
     return result;
   }
@@ -72,7 +72,7 @@ public class UsedQProfiles {
     StringWriter json = new StringWriter();
     JsonWriter writer = JsonWriter.of(json);
     writer.beginArray();
-    for (ModuleQProfiles.QProfile qProfile : profilesById.values()) {
+    for (QProfileWithId qProfile : profilesById.values()) {
       writer.beginObject()
         .prop("id", qProfile.id())
         .prop("name", qProfile.name())
@@ -89,8 +89,8 @@ public class UsedQProfiles {
     return empty().mergeInPlace(this).mergeInPlace(other);
   }
 
-  private void add(ModuleQProfiles.QProfile profile) {
-    QProfile alreadyAdded = profilesById.get(profile.id());
+  private void add(QProfileWithId profile) {
+    QProfileWithId alreadyAdded = profilesById.get(profile.id());
     if (alreadyAdded == null
       // Keep only latest version
       || profile.version() > alreadyAdded.version()) {
@@ -98,8 +98,8 @@ public class UsedQProfiles {
     }
   }
 
-  private UsedQProfiles addAll(Iterable<QProfile> profiles) {
-    for (QProfile profile : profiles) {
+  private UsedQProfiles addAll(Iterable<QProfileWithId> profiles) {
+    for (QProfileWithId profile : profiles) {
       this.add(profile);
     }
     return this;
@@ -110,7 +110,7 @@ public class UsedQProfiles {
     return this;
   }
 
-  public Map<Integer, ModuleQProfiles.QProfile> profilesById() {
+  public Map<Integer, QProfileWithId> profilesById() {
     return ImmutableMap.copyOf(profilesById);
   }
 
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rules/DefaultQProfileReferential.java b/sonar-batch/src/main/java/org/sonar/batch/rules/DefaultQProfileReferential.java
new file mode 100644 (file)
index 0000000..936b17e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.rules;
+
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+
+/**
+ * @since 4.4
+ */
+public class DefaultQProfileReferential implements QProfilesReferential {
+
+  private QualityProfileDao qualityProfileDao;
+
+  public DefaultQProfileReferential(QualityProfileDao qualityProfileDao) {
+    this.qualityProfileDao = qualityProfileDao;
+  }
+
+  @Override
+  public QProfile get(String language, String name) {
+    QualityProfileDto dto = qualityProfileDao.selectByNameAndLanguage(name, language);
+    if (dto == null) {
+      return null;
+    }
+    return new QProfileWithId(dto.getId(), dto.getName(), dto.getLanguage(), dto.getVersion());
+  }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rules/QProfileWithId.java b/sonar-batch/src/main/java/org/sonar/batch/rules/QProfileWithId.java
new file mode 100644 (file)
index 0000000..4d25116
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.rules;
+
+import org.sonar.batch.api.rules.QProfile;
+
+public class QProfileWithId extends QProfile {
+  private final int id;
+
+  public QProfileWithId(int id, String name, String language, Integer version) {
+    super(name, language, version);
+    this.id = id;
+  }
+
+  public int id() {
+    return id;
+  }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rules/QProfilesReferential.java b/sonar-batch/src/main/java/org/sonar/batch/rules/QProfilesReferential.java
new file mode 100644 (file)
index 0000000..aec78dc
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.rules;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.batch.api.rules.QProfile;
+
+import javax.annotation.CheckForNull;
+
+/**
+ * Quality profiles referential
+ * @since 4.4
+ */
+public interface QProfilesReferential extends BatchComponent {
+
+  /**
+   * Get quality profile
+   */
+  @CheckForNull
+  QProfile get(String language, String name);
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rules/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/rules/package-info.java
new file mode 100644 (file)
index 0000000..819e886
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.rules;
\ No newline at end of file
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/AnalyzerContextAdaptor.java b/sonar-batch/src/main/java/org/sonar/batch/scan/AnalyzerContextAdaptor.java
new file mode 100644 (file)
index 0000000..a3f125d
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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;
+
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.issue.Issuable;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MetricFinder;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.api.analyzer.issue.AnalyzerIssue;
+import org.sonar.batch.api.analyzer.measure.AnalyzerMeasure;
+import org.sonar.batch.api.measures.Metric;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+public class AnalyzerContextAdaptor implements AnalyzerContext {
+
+  private SensorContext sensorContext;
+  private MetricFinder metricFinder;
+  private Project project;
+  private ResourcePerspectives perspectives;
+
+  public AnalyzerContextAdaptor(SensorContext sensorContext, MetricFinder metricFinder, Project project, ResourcePerspectives perspectives) {
+    this.sensorContext = sensorContext;
+    this.metricFinder = metricFinder;
+    this.project = project;
+    this.perspectives = perspectives;
+  }
+
+  @Override
+  public AnalyzerMeasure<?> getMeasure(String metricKey) {
+    Metric<?> m = metricFinder.findByKey(metricKey);
+    if (m == null) {
+      throw new IllegalStateException("Unknow metric with key: " + metricKey);
+    }
+    return getMeasure(m);
+  }
+
+  @Override
+  public <G extends Serializable> AnalyzerMeasure<G> getMeasure(Metric<G> metric) {
+    org.sonar.api.measures.Metric<G> m = metricFinder.findByKey(metric.key());
+    Measure<G> measure = sensorContext.getMeasure(m);
+    if (measure == null) {
+      return null;
+    }
+    return AnalyzerMeasure.<G>builder()
+      .onProject()
+      .forMetric(metric)
+      .withValue(measure.value())
+      .build();
+  }
+
+  @Override
+  public AnalyzerMeasure<?> getMeasure(InputFile file, String metricKey) {
+    Metric<?> m = metricFinder.findByKey(metricKey);
+    if (m == null) {
+      throw new IllegalStateException("Unknow metric with key: " + metricKey);
+    }
+    return getMeasure(file, m);
+  }
+
+  @Override
+  public <G extends Serializable> AnalyzerMeasure<G> getMeasure(InputFile file, Metric<G> metric) {
+    File fileRes = File.fromIOFile(file.file(), project);
+    org.sonar.api.measures.Metric<G> m = metricFinder.findByKey(metric.key());
+    Measure<G> measure = sensorContext.getMeasure(fileRes, m);
+    if (measure == null) {
+      return null;
+    }
+    return AnalyzerMeasure.<G>builder()
+      .onFile(file)
+      .forMetric(metric)
+      .withValue(measure.value())
+      .build();
+  }
+
+  @Override
+  public void addMeasure(AnalyzerMeasure<?> measure) {
+    org.sonar.api.measures.Metric<?> m = metricFinder.findByKey(measure.metricKey());
+
+    Measure measureToSave = new Measure(m);
+    switch (m.getType()) {
+      case BOOL:
+        measureToSave.setValue(Boolean.TRUE.equals(measure.value()) ? 1.0 : 0.0);
+        break;
+      case INT:
+      case MILLISEC:
+        measureToSave.setValue(Double.valueOf(((Integer) measure.value())));
+        break;
+      case FLOAT:
+      case PERCENT:
+      case RATING:
+        measureToSave.setValue(((Double) measure.value()));
+        break;
+      case STRING:
+      case LEVEL:
+      case DATA:
+      case DISTRIB:
+        measureToSave.setData(((String) measure.value()));
+        break;
+      case WORK_DUR:
+        measureToSave.setValue(Double.valueOf(((Long) measure.value())));
+        break;
+      default:
+        if (m.isNumericType()) {
+          measureToSave.setValue(((Double) measure.value()));
+        } else if (m.isDataType()) {
+          measureToSave.setData(((String) measure.value()));
+        } else {
+          throw new UnsupportedOperationException("Unsupported type :" + m.getType());
+        }
+    }
+    if (measure.inputFile() != null) {
+      File fileRes = File.fromIOFile(measure.inputFile().file(), project);
+      sensorContext.saveMeasure(fileRes, measureToSave);
+    } else {
+      sensorContext.saveMeasure(measureToSave);
+    }
+  }
+
+  @Override
+  public void addIssue(AnalyzerIssue issue) {
+    Resource r;
+    if (issue.inputFile() != null) {
+      r = File.fromIOFile(issue.inputFile().file(), project);
+    } else {
+      r = project;
+    }
+    Issuable issuable = perspectives.as(Issuable.class, r);
+    issuable.addIssue(issuable.newIssueBuilder()
+      .ruleKey(RuleKey.of(issue.ruleKey().repository(), issue.ruleKey().rule()))
+      .effortToFix(issue.effortToFix())
+      .line(issue.line())
+      .message(issue.message())
+      .build());
+  }
+
+  @Override
+  public void addIssues(Collection<AnalyzerIssue> issues) {
+    for (AnalyzerIssue analyzerIssue : issues) {
+      addIssue(analyzerIssue);
+    }
+  }
+
+}
index f64dd0d72194319134ddec8219c27a3e920c954d..7f32e03e98e336fc39b9d7c6ca7231d86054f9b3 100644 (file)
@@ -25,9 +25,9 @@ import org.slf4j.LoggerFactory;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.fs.internal.DefaultFileSystem;
 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.batch.api.languages.Language;
+import org.sonar.batch.languages.LanguagesReferential;
 
 /**
  * Verifies that the property sonar.language is valid
@@ -37,16 +37,15 @@ public class LanguageVerifier implements Startable {
   private static final Logger LOG = LoggerFactory.getLogger(LanguageVerifier.class);
 
   private final Settings settings;
-  private final Languages languages;
+  private final LanguagesReferential languages;
   private final DefaultFileSystem fs;
 
-  public LanguageVerifier(Settings settings, Languages languages, DefaultFileSystem fs) {
+  public LanguageVerifier(Settings settings, LanguagesReferential languages, DefaultFileSystem fs) {
     this.settings = settings;
     this.languages = languages;
     this.fs = fs;
   }
 
-
   @Override
   public void start() {
     if (settings.hasKey(CoreProperties.PROJECT_LANGUAGE_PROPERTY)) {
index 6e4ebd39b6a85e01f5578469f6278022bb2ad974..6b1e0e1a501cda3951b76ad18415f982144a31e9 100644 (file)
@@ -39,6 +39,9 @@ import org.sonar.batch.bootstrap.ExtensionInstaller;
 import org.sonar.batch.bootstrap.ExtensionMatcher;
 import org.sonar.batch.bootstrap.ExtensionUtils;
 import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.batch.debt.DebtDecorator;
+import org.sonar.batch.debt.IssueChangelogDebtCalculator;
+import org.sonar.batch.debt.NewDebtDecorator;
 import org.sonar.batch.events.EventBus;
 import org.sonar.batch.index.DefaultIndex;
 import org.sonar.batch.index.ResourcePersister;
@@ -139,6 +142,7 @@ public class ModuleScanContainer extends ComponentContainer {
 
       TimeMachineConfiguration.class,
       DefaultSensorContext.class,
+      AnalyzerContextAdaptor.class,
       BatchExtensionDictionnary.class,
       DefaultTimeMachine.class,
       ViolationFilters.class,
@@ -178,6 +182,11 @@ public class ModuleScanContainer extends ComponentContainer {
       // language
       LanguageDistributionDecorator.class,
 
+      // Debt
+      IssueChangelogDebtCalculator.class,
+      DebtDecorator.class,
+      NewDebtDecorator.class,
+
       ScanPerspectives.class);
   }
 
@@ -191,7 +200,8 @@ public class ModuleScanContainer extends ComponentContainer {
           // Example : C# plugin adds sub-projects at runtime, even if they are not defined in root pom.
           return !ExtensionUtils.isMavenExtensionOnly(extension) || module.getPom() != null;
         }
-        return false;
+        return ExtensionUtils.isType(extension, org.sonar.batch.api.BatchComponent.class)
+          && ExtensionUtils.isInstantiationStrategy(extension, org.sonar.batch.api.InstantiationStrategy.PER_PROJECT);
       }
     });
   }
index b6dca14dafd8e722dae41348848e7e04d5ebf190..8d4dfa22df717f956fd5da0fa32fb8546878ac30 100644 (file)
@@ -40,7 +40,6 @@ import org.sonar.batch.bootstrap.ExtensionMatcher;
 import org.sonar.batch.bootstrap.ExtensionUtils;
 import org.sonar.batch.bootstrap.MetricProvider;
 import org.sonar.batch.components.PeriodsDefinition;
-import org.sonar.batch.debt.DebtModelProvider;
 import org.sonar.batch.debt.IssueChangelogDebtCalculator;
 import org.sonar.batch.index.Caches;
 import org.sonar.batch.index.ComponentDataCache;
@@ -61,9 +60,9 @@ import org.sonar.batch.issue.DeprecatedViolations;
 import org.sonar.batch.issue.IssueCache;
 import org.sonar.batch.issue.IssuePersister;
 import org.sonar.batch.issue.ScanIssueStorage;
+import org.sonar.batch.languages.DeprecatedLanguagesReferential;
 import org.sonar.batch.phases.GraphPersister;
 import org.sonar.batch.profiling.PhasesSumUpTimeProfiler;
-import org.sonar.batch.rule.RulesProvider;
 import org.sonar.batch.scan.filesystem.InputFileCache;
 import org.sonar.batch.scan.maven.FakeMavenPluginExecutor;
 import org.sonar.batch.scan.maven.MavenPluginExecutor;
@@ -101,27 +100,23 @@ public class ProjectScanContainer extends ComponentContainer {
   }
 
   private void projectBootstrap() {
-    // Old versions of bootstrappers used to pass project reactor as an extension
-    // so check if it is already present in parent container
-    ProjectReactor reactor = getComponentByType(ProjectReactor.class);
+    ProjectReactor reactor;
+    // OK, not present, so look for a custom ProjectBootstrapper
+    ProjectBootstrapper bootstrapper = getComponentByType(ProjectBootstrapper.class);
+    Settings settings = getComponentByType(Settings.class);
+    if (bootstrapper == null
+      // Starting from Maven plugin 2.3 then only DefaultProjectBootstrapper should be used.
+      || "true".equals(settings.getString("sonar.mojoUseRunner"))) {
+      // Use default SonarRunner project bootstrapper
+      ProjectReactorBuilder builder = getComponentByType(ProjectReactorBuilder.class);
+      reactor = builder.execute();
+    } else {
+      reactor = bootstrapper.bootstrap();
+    }
     if (reactor == null) {
-      // OK, not present, so look for a custom ProjectBootstrapper
-      ProjectBootstrapper bootstrapper = getComponentByType(ProjectBootstrapper.class);
-      Settings settings = getComponentByType(Settings.class);
-      if (bootstrapper == null
-        // Starting from Maven plugin 2.3 then only DefaultProjectBootstrapper should be used.
-        || "true".equals(settings.getString("sonar.mojoUseRunner"))) {
-        // Use default SonarRunner project bootstrapper
-        ProjectReactorBuilder builder = getComponentByType(ProjectReactorBuilder.class);
-        reactor = builder.execute();
-      } else {
-        reactor = bootstrapper.bootstrap();
-      }
-      if (reactor == null) {
-        throw new SonarException(bootstrapper + " has returned null as ProjectReactor");
-      }
-      add(reactor);
+      throw new SonarException(bootstrapper + " has returned null as ProjectReactor");
     }
+    add(reactor);
   }
 
   private void addBatchComponents() {
@@ -175,15 +170,12 @@ public class ProjectScanContainer extends ComponentContainer {
 
       // lang
       Languages.class,
+      DeprecatedLanguagesReferential.class,
       HighlightableBuilder.class,
       SymbolizableBuilder.class,
 
       // technical debt
       DefaultTechnicalDebtModel.class,
-      new DebtModelProvider(),
-
-      // rules
-      new RulesProvider(),
 
       // Differential periods
       PeriodsDefinition.class,
index 1ccbb3935224fc152bd69008c21796984fc2e887..33285ae2be6741291f32d6eb1912af6bbbdb7cc0 100644 (file)
@@ -24,8 +24,10 @@ import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.task.Task;
 import org.sonar.api.task.TaskDefinition;
 import org.sonar.batch.DefaultProjectTree;
+import org.sonar.batch.bootstrap.BootstrapProperties;
 import org.sonar.batch.bootstrap.TaskContainer;
 import org.sonar.batch.phases.Phases;
+import org.sonar.batch.scan2.ProjectScanContainer;
 
 public class ScanTask implements Task {
   public static final TaskDefinition DEFINITION = TaskDefinition.builder()
@@ -41,7 +43,12 @@ public class ScanTask implements Task {
   }
 
   public void execute() {
-    scan(new ProjectScanContainer(taskContainer));
+    boolean sensorMode = CoreProperties.ANALYSIS_MODE_SENSOR.equals(taskContainer.getComponentByType(BootstrapProperties.class).property(CoreProperties.ANALYSIS_MODE));
+    if (sensorMode) {
+      new ProjectScanContainer(taskContainer).execute();
+    } else {
+      scan(new org.sonar.batch.scan.ProjectScanContainer(taskContainer));
+    }
   }
 
   // Add components specific to project scan (views will use different ones)
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java
new file mode 100644 (file)
index 0000000..ae9a25c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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;
+
+import org.sonar.api.batch.DependedUpon;
+import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.batch.Sensor;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.resources.Project;
+import org.sonar.batch.api.analyzer.Analyzer;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.api.measures.Metric;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class SensorWrapper implements Sensor {
+
+  private Analyzer analyzer;
+  private AnalyzerContext adaptor;
+  private FileSystem fs;
+
+  public SensorWrapper(Analyzer analyzer, AnalyzerContext adaptor, FileSystem fs) {
+    this.analyzer = analyzer;
+    this.adaptor = adaptor;
+    this.fs = fs;
+  }
+
+  @DependedUpon
+  public List<Metric<?>> provides() {
+    return Arrays.asList(analyzer.describe().provides());
+  }
+
+  @DependsUpon
+  public List<Metric<?>> depends() {
+    return Arrays.asList(analyzer.describe().dependsOn());
+  }
+
+  @Override
+  public boolean shouldExecuteOnProject(Project project) {
+    if (!analyzer.describe().languages().isEmpty()) {
+      if (project.getLanguageKey() != null && !analyzer.describe().languages().contains(project.getLanguageKey())) {
+        return false;
+      }
+      boolean hasFile = false;
+      for (String languageKey : analyzer.describe().languages()) {
+        hasFile |= fs.hasFiles(fs.predicates().hasLanguage(languageKey));
+      }
+      if (!hasFile) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public void analyse(Project module, SensorContext context) {
+    analyzer.analyse(adaptor);
+  }
+}
index af44e9b8783ddc3e9b1714a5249e7d6f93d81cb2..6332d51a2ed5b6bee82297e990941b1fc318d6a0 100644 (file)
@@ -22,7 +22,7 @@ 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;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
 
 /**
  * Additional {@link org.sonar.api.batch.fs.FilePredicate}s that are
@@ -43,7 +43,7 @@ class AdditionalFilePredicates {
 
     @Override
     public boolean apply(InputFile f) {
-      return key.equals(((DefaultInputFile) f).key());
+      return key.equals(((DeprecatedDefaultInputFile) f).key());
     }
   }
 
@@ -56,7 +56,7 @@ class AdditionalFilePredicates {
 
     @Override
     public boolean apply(InputFile f) {
-      return key.equals(((DefaultInputFile) f).deprecatedKey());
+      return key.equals(((DeprecatedDefaultInputFile) f).deprecatedKey());
     }
   }
 
@@ -69,7 +69,7 @@ class AdditionalFilePredicates {
 
     @Override
     public boolean apply(InputFile f) {
-      return path.equals(((DefaultInputFile) f).pathRelativeToSourceDir());
+      return path.equals(((DeprecatedDefaultInputFile) f).pathRelativeToSourceDir());
     }
   }
 
@@ -82,7 +82,7 @@ class AdditionalFilePredicates {
 
     @Override
     public boolean apply(InputFile f) {
-      return path.equals(((DefaultInputFile) f).sourceDirAbsolutePath());
+      return path.equals(((DeprecatedDefaultInputFile) f).sourceDirAbsolutePath());
     }
   }
 }
index 4729d7f0361458aba881b1acd8de2d6a59476753..f7f289ddf643afd5bd44f6850d40a1d00f342633 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.SonarIndex;
 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.config.Settings;
 import org.sonar.api.resources.File;
 import org.sonar.api.resources.Languages;
@@ -65,7 +65,7 @@ public class ComponentIndexer implements BatchComponent {
     for (InputFile inputFile : fs.inputFiles(fs.predicates().all())) {
       String languageKey = inputFile.language();
       boolean unitTest = InputFile.Type.TEST == inputFile.type();
-      String pathFromSourceDir = ((DefaultInputFile) inputFile).pathRelativeToSourceDir();
+      String pathFromSourceDir = ((DeprecatedDefaultInputFile) inputFile).pathRelativeToSourceDir();
       if (pathFromSourceDir == null) {
         pathFromSourceDir = inputFile.relativePath();
       }
index ea5692fb4b34678ce5b3d4b4a9189e07f6e068d9..7205c1c483f047fd8b5515b199e85ade50a45c1c 100644 (file)
@@ -27,13 +27,14 @@ import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.fs.FilePredicate;
 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.ModuleFileSystem;
-import org.sonar.api.utils.SonarException;
+import org.sonar.api.utils.MessageException;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
@@ -66,11 +67,24 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
   private ComponentIndexer componentIndexer;
   private boolean initialized;
 
-  public DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, Project module, Settings settings, FileIndexer indexer, ModuleFileSystemInitializer initializer,
+  /**
+   * Used by scan2 
+   */
+  public DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, ProjectDefinition def, Settings settings, FileIndexer indexer, ModuleFileSystemInitializer initializer) {
+    this(moduleInputFileCache, def.getKey(), settings, indexer, initializer, null);
+  }
+
+  public DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, ProjectDefinition def, Project project, Settings settings, FileIndexer indexer,
+    ModuleFileSystemInitializer initializer,
     ComponentIndexer componentIndexer) {
+    this(moduleInputFileCache, project.getKey(), settings, indexer, initializer, componentIndexer);
+  }
+
+  private DefaultModuleFileSystem(ModuleInputFileCache moduleInputFileCache, String moduleKey, Settings settings, FileIndexer indexer, ModuleFileSystemInitializer initializer,
+    @Nullable ComponentIndexer componentIndexer) {
     super(moduleInputFileCache);
     this.componentIndexer = componentIndexer;
-    this.moduleKey = module.getKey();
+    this.moduleKey = moduleKey;
     this.settings = settings;
     this.indexer = indexer;
     if (initializer.baseDir() != null) {
@@ -202,7 +216,7 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
 
   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. Modifications of filesystem are only allowed during Initializer phase.");
+      throw MessageException.of("Module filesystem is already initialized. Modifications of filesystem are only allowed during Initializer phase.");
     }
     setBaseDir(basedir);
     this.buildDir = buildDir;
@@ -213,11 +227,13 @@ public class DefaultModuleFileSystem extends DefaultFileSystem implements Module
 
   public void index() {
     if (initialized) {
-      throw new SonarException("Module filesystem can only be indexed once");
+      throw MessageException.of("Module filesystem can only be indexed once");
     }
     initialized = true;
     indexer.index(this);
-    componentIndexer.execute(this);
+    if (componentIndexer != null) {
+      componentIndexer.execute(this);
+    }
   }
 
   private List<File> existingDirs(List<File> dirs) {
index 8545dc4ef45e366e7b2c6743f2dc1b74c8efffd0..d52e19b0b0be1d57fbe2997d2f146356d67d21a9 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.batch.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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.scan.filesystem.FileSystemFilter;
 import org.sonar.api.scan.filesystem.FileType;
 import org.sonar.api.scan.filesystem.ModuleFileSystem;
@@ -72,12 +72,12 @@ public class DeprecatedFileFilters implements InputFileFilter {
 
     @Override
     public File relativeDir() {
-      return new File(((DefaultInputFile)inputFile).sourceDirAbsolutePath());
+      return new File(((DeprecatedDefaultInputFile)inputFile).sourceDirAbsolutePath());
     }
 
     @Override
     public String relativePath() {
-      return ((DefaultInputFile)inputFile).pathRelativeToSourceDir();
+      return ((DeprecatedDefaultInputFile)inputFile).pathRelativeToSourceDir();
     }
 
     @Override
index b9d784723fa379263ddb6bd021b3946df676b578..b3142c9cc054a62252654e9e7763203dba939495 100644 (file)
@@ -27,11 +27,12 @@ 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.bootstrap.ProjectDefinition;
 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.resources.Project;
-import org.sonar.api.utils.SonarException;
+import org.sonar.api.utils.MessageException;
 
 import java.io.File;
 import java.util.Collection;
@@ -44,31 +45,45 @@ import java.util.Set;
  */
 public class FileIndexer implements BatchComponent {
 
+  private static final Logger LOG = LoggerFactory.getLogger(FileIndexer.class);
+
   private static final IOFileFilter DIR_FILTER = FileFilterUtils.and(HiddenFileFilter.VISIBLE, FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter(".")));
   private static final IOFileFilter FILE_FILTER = HiddenFileFilter.VISIBLE;
 
   private final List<InputFileFilter> filters;
   private final InputFileCache fileCache;
-  private final Project module;
+  private final boolean isAggregator;
   private final ExclusionFilters exclusionFilters;
   private final InputFileBuilderFactory inputFileBuilderFactory;
 
   public FileIndexer(List<InputFileFilter> filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory,
-                     InputFileCache cache, Project module) {
+    InputFileCache cache, Project module, ProjectDefinition def) {
+    this(filters, exclusionFilters, inputFileBuilderFactory, cache, !module.getModules().isEmpty());
+  }
+
+  /**
+   * Used by scan2
+   */
+  public FileIndexer(List<InputFileFilter> filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory,
+    InputFileCache cache, ProjectDefinition def) {
+    this(filters, exclusionFilters, inputFileBuilderFactory, cache, !def.getSubProjects().isEmpty());
+  }
+
+  private FileIndexer(List<InputFileFilter> filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory,
+    InputFileCache cache, boolean isAggregator) {
     this.filters = filters;
     this.exclusionFilters = exclusionFilters;
     this.inputFileBuilderFactory = inputFileBuilderFactory;
     this.fileCache = cache;
-    this.module = module;
+    this.isAggregator = isAggregator;
   }
 
   void index(DefaultModuleFileSystem fileSystem) {
-    Logger logger = LoggerFactory.getLogger(FileIndexer.class);
-    if (!module.getModules().isEmpty()) {
+    if (isAggregator) {
       // No indexing for an aggregator module
       return;
     }
-    logger.info("Index files");
+    LOG.info("Index files");
     exclusionFilters.prepare();
 
     Progress progress = new Progress(fileCache.byModule(fileSystem.moduleKey()));
@@ -93,13 +108,13 @@ public class FileIndexer implements BatchComponent {
       fileCache.remove(fileSystem.moduleKey(), removed);
     }
 
-    logger.info(String.format("%d files indexed", progress.count()));
+    LOG.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) {
-      DefaultInputFile inputFile = inputFileBuilder.create(sourceFile);
+      DeprecatedDefaultInputFile inputFile = inputFileBuilder.create(sourceFile);
       if (inputFile != null && exclusionFilters.accept(inputFile, type)) {
         indexFile(inputFileBuilder, fileSystem, progress, inputFile, type);
       }
@@ -109,7 +124,7 @@ public class FileIndexer implements BatchComponent {
   private void indexDirectory(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress status, File dirToIndex, InputFile.Type type) {
     Collection<File> files = FileUtils.listFiles(dirToIndex, FILE_FILTER, DIR_FILTER);
     for (File file : files) {
-      DefaultInputFile inputFile = inputFileBuilder.create(file);
+      DeprecatedDefaultInputFile inputFile = inputFileBuilder.create(file);
       if (inputFile != null && exclusionFilters.accept(inputFile, type)) {
         indexFile(inputFileBuilder, fileSystem, status, inputFile, type);
       }
@@ -117,7 +132,7 @@ public class FileIndexer implements BatchComponent {
   }
 
   private void indexFile(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fs,
-                         Progress status, DefaultInputFile inputFile, InputFile.Type type) {
+    Progress status, DeprecatedDefaultInputFile inputFile, InputFile.Type type) {
     InputFile completedFile = inputFileBuilder.complete(inputFile, type);
     if (completedFile != null && accept(completedFile)) {
       fs.add(completedFile);
@@ -146,7 +161,7 @@ public class FileIndexer implements BatchComponent {
 
     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 "
+        throw MessageException.of("File " + inputFile + " can't be indexed twice. Please check that inclusion/exclusion patterns produce "
           + "disjoint sets for main and test files");
       }
       removed.remove(inputFile);
index 10b888344b9c72a190c23a92d5f65c271a004cb1..cd7844fd4ded12c39304f7f0fd25aa8d10560e5f 100644 (file)
@@ -24,7 +24,7 @@ import org.slf4j.Logger;
 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.scan.filesystem.PathResolver;
 import org.sonar.batch.bootstrap.AnalysisMode;
 import org.sonar.batch.util.DeprecatedKeyUtils;
@@ -76,13 +76,13 @@ class InputFileBuilder {
   }
 
   @CheckForNull
-  DefaultInputFile create(File file) {
+  DeprecatedDefaultInputFile create(File file) {
     String relativePath = pathResolver.relativePath(fs.baseDir(), file);
     if (relativePath == null) {
       LOG.warn("File '{}' is ignored. It is not located in module basedir '{}'.", file.getAbsolutePath(), fs.baseDir());
       return null;
     }
-    DefaultInputFile inputFile = new DefaultInputFile(relativePath);
+    DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile(relativePath);
     inputFile.setBasedir(fs.baseDir());
     inputFile.setFile(file);
     return inputFile;
@@ -92,7 +92,7 @@ class InputFileBuilder {
    * Optimization to not set all InputFile data if the file is excluded from analysis.
    */
   @CheckForNull
-  DefaultInputFile complete(DefaultInputFile inputFile, InputFile.Type type) {
+  DeprecatedDefaultInputFile complete(DeprecatedDefaultInputFile inputFile, InputFile.Type type) {
     inputFile.setType(type);
     inputFile.setKey(new StringBuilder().append(moduleKey).append(":").append(inputFile.relativePath()).toString());
     inputFile.setBasedir(fs.baseDir());
@@ -112,7 +112,7 @@ class InputFileBuilder {
     return inputFile;
   }
 
-  private void fillDeprecatedData(DefaultInputFile inputFile) {
+  private void fillDeprecatedData(DeprecatedDefaultInputFile inputFile) {
     List<File> sourceDirs = InputFile.Type.MAIN == inputFile.type() ? fs.sourceDirs() : fs.testDirs();
     for (File sourceDir : sourceDirs) {
       String sourceRelativePath = pathResolver.relativePath(sourceDir, inputFile.file());
index 90dcfc870d7a1edbc86e7451985534a5e7a2a672..772f773cb5f040257f105d5419f17418af216951 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.batch.scan.filesystem;
 
 import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.resources.Project;
 import org.sonar.api.scan.filesystem.PathResolver;
 import org.sonar.batch.bootstrap.AnalysisMode;
@@ -32,9 +33,22 @@ public class InputFileBuilderFactory implements BatchComponent {
   private final StatusDetectionFactory statusDetectionFactory;
   private final AnalysisMode analysisMode;
 
-  public InputFileBuilderFactory(Project moduleDef, PathResolver pathResolver, LanguageDetectionFactory langDetectionFactory,
-                                 StatusDetectionFactory statusDetectionFactory, AnalysisMode analysisMode) {
-    this.moduleKey = moduleDef.getEffectiveKey();
+  public InputFileBuilderFactory(Project module, ProjectDefinition def, PathResolver pathResolver, LanguageDetectionFactory langDetectionFactory,
+    StatusDetectionFactory statusDetectionFactory, AnalysisMode analysisMode) {
+    this(module.getEffectiveKey(), pathResolver, langDetectionFactory, statusDetectionFactory, analysisMode);
+  }
+
+  /**
+   * Used by scan2
+   */
+  public InputFileBuilderFactory(ProjectDefinition def, PathResolver pathResolver, LanguageDetectionFactory langDetectionFactory,
+    StatusDetectionFactory statusDetectionFactory, AnalysisMode analysisMode) {
+    this(def.getKey(), pathResolver, langDetectionFactory, statusDetectionFactory, analysisMode);
+  }
+
+  private InputFileBuilderFactory(String effectiveKey, PathResolver pathResolver, LanguageDetectionFactory langDetectionFactory,
+    StatusDetectionFactory statusDetectionFactory, AnalysisMode analysisMode) {
+    this.moduleKey = effectiveKey;
     this.pathResolver = pathResolver;
     this.langDetectionFactory = langDetectionFactory;
     this.statusDetectionFactory = statusDetectionFactory;
index 3035f115c5c18ecdcdac991fa15cb7c0803324f2..3b12d8ba5f6a49ad54915e83654d617d5e62ee5e 100644 (file)
@@ -21,8 +21,6 @@ package org.sonar.batch.scan.filesystem;
 
 import org.sonar.api.BatchComponent;
 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;
 
@@ -69,23 +67,8 @@ public class InputFileCache implements BatchComponent {
     return this;
   }
 
-
-  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");
-    }
-  }
-
   @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);
+  public InputFile get(String moduleKey, String relativePath) {
+    return cache.get(moduleKey, relativePath);
   }
 }
index da4900f2145fe3b252d06e3c1db0b6d90c3c64c7..7256c5592a3af88204ae3dc3738b8420f6430366 100644 (file)
@@ -29,14 +29,13 @@ 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.utils.MessageException;
+import org.sonar.batch.api.languages.Language;
+import org.sonar.batch.languages.LanguagesReferential;
 
 import javax.annotation.CheckForNull;
 
 import java.text.MessageFormat;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -54,23 +53,23 @@ class LanguageDetection {
   private final List<String> languagesToConsider = Lists.newArrayList();
   private final String forcedLanguage;
 
-  LanguageDetection(Settings settings, Languages languages) {
+  LanguageDetection(Settings settings, LanguagesReferential languages) {
     for (Language language : languages.all()) {
-      String[] filePatterns = settings.getStringArray(getFileLangPatternPropKey(language.getKey()));
+      String[] filePatterns = settings.getStringArray(getFileLangPatternPropKey(language.key()));
       PathPattern[] pathPatterns = PathPattern.create(filePatterns);
       if (pathPatterns.length > 0) {
-        patternsByLanguage.put(language.getKey(), pathPatterns);
+        patternsByLanguage.put(language.key(), pathPatterns);
       } else {
         // If no custom language pattern is defined then fallback to suffixes declared by language
-        String[] patterns = Arrays.copyOf(language.getFileSuffixes(), language.getFileSuffixes().length);
+        String[] patterns = language.fileSuffixes().toArray(new String[language.fileSuffixes().size()]);
         for (int i = 0; i < patterns.length; i++) {
           String suffix = patterns[i];
           String extension = sanitizeExtension(suffix);
           patterns[i] = "**/*." + extension;
         }
         PathPattern[] defaultLanguagePatterns = PathPattern.create(patterns);
-        patternsByLanguage.put(language.getKey(), defaultLanguagePatterns);
-        LOG.debug("Declared extensions of language " + language + " were converted to " + getDetails(language.getKey()));
+        patternsByLanguage.put(language.key(), defaultLanguagePatterns);
+        LOG.debug("Declared extensions of language " + language + " were converted to " + getDetails(language.key()));
       }
     }
 
index 814b6e380ed35abf1e8b6ac4026e9addd781c606..6ff579fd769010ddfbca32e1ece050e7be8cb175 100644 (file)
@@ -21,13 +21,13 @@ package org.sonar.batch.scan.filesystem;
 
 import org.sonar.api.BatchComponent;
 import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Languages;
+import org.sonar.batch.languages.LanguagesReferential;
 
 public class LanguageDetectionFactory implements BatchComponent {
   private final Settings settings;
-  private final Languages languages;
+  private final LanguagesReferential languages;
 
-  public LanguageDetectionFactory(Settings settings, Languages languages) {
+  public LanguageDetectionFactory(Settings settings, LanguagesReferential languages) {
     this.settings = settings;
     this.languages = languages;
   }
index 4a909f29cf43ad3325f36f5fd700fa610e82d4b5..d555074db79187b0a268845f0aa8ebd8c1aa6610 100644 (file)
 package org.sonar.batch.scan.filesystem;
 
 import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.UniqueIndexPredicate;
 import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.RelativePathPredicate;
 import org.sonar.api.resources.Project;
 
 public class ModuleInputFileCache extends DefaultFileSystem.Cache implements BatchComponent {
@@ -30,28 +31,31 @@ public class ModuleInputFileCache extends DefaultFileSystem.Cache implements Bat
   private final String moduleKey;
   private final InputFileCache projectCache;
 
-  public ModuleInputFileCache(Project module, InputFileCache projectCache) {
+  public ModuleInputFileCache(Project module, ProjectDefinition projectDef, InputFileCache projectCache) {
     this.moduleKey = module.getKey();
     this.projectCache = projectCache;
   }
 
+  /**
+   * Used by scan2
+   */
+  public ModuleInputFileCache(ProjectDefinition projectDef, InputFileCache projectCache) {
+    this.moduleKey = projectDef.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());
+  protected InputFile inputFile(RelativePathPredicate predicate) {
+    return projectCache.get(moduleKey, predicate.path());
   }
 
   @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);
-  }
 }
index dd1e4a247c2dcdda729f7d1ac4f8fb08bd4618b3..53729dde5925458f15cd3d8ac8b3d6a48497c294 100644 (file)
@@ -21,6 +21,8 @@ package org.sonar.batch.scan.filesystem;
 
 import org.sonar.api.BatchComponent;
 
+import java.util.Collections;
+
 public class StatusDetectionFactory implements BatchComponent {
 
   private final PreviousFileHashLoader previousFileHashLoader;
@@ -29,7 +31,14 @@ public class StatusDetectionFactory implements BatchComponent {
     this.previousFileHashLoader = l;
   }
 
+  /**
+   * Used by scan2
+   */
+  public StatusDetectionFactory() {
+    this.previousFileHashLoader = null;
+  }
+
   StatusDetection create() {
-    return new StatusDetection(previousFileHashLoader.hashByRelativePath());
+    return new StatusDetection(previousFileHashLoader != null ? previousFileHashLoader.hashByRelativePath() : Collections.<String, String>emptyMap());
   }
 }
index a2056966ef2013ffd7a22663aa4a530ba7474d9a..e3732308cf53458e11d7f4d65a081d94778afbdb 100644 (file)
@@ -34,11 +34,9 @@ import org.sonar.batch.index.Caches;
 public class MeasureCache implements BatchComponent {
 
   private final Cache<Measure> cache;
-  private final Cache<String> dataCache;
 
   public MeasureCache(Caches caches) {
     cache = caches.createCache("measures");
-    dataCache = caches.createCache("measuresData");
   }
 
   public Iterable<Entry<Measure>> entries() {
@@ -50,7 +48,11 @@ public class MeasureCache implements BatchComponent {
   }
 
   public Iterable<Measure> byMetric(Resource r, String metricKey) {
-    return cache.values(r.getEffectiveKey(), metricKey);
+    return byMetric(r.getEffectiveKey(), metricKey);
+  }
+
+  public Iterable<Measure> byMetric(String resourceKey, String metricKey) {
+    return cache.values(resourceKey, metricKey);
   }
 
   public MeasureCache put(Resource resource, Measure measure) {
@@ -85,4 +87,5 @@ public class MeasureCache implements BatchComponent {
     }
     return sb.toString();
   }
+
 }
index 20731c631a31e1712b0cadaaf2e4a34b4e0857bb..fe8ddc7826ded4eee00e74619412bd56a9f36d32 100644 (file)
@@ -27,7 +27,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.config.Settings;
 import org.sonar.api.issue.internal.DefaultIssue;
 import org.sonar.api.platform.Server;
@@ -169,7 +169,7 @@ public class JsonReport implements BatchComponent {
     writeJsonModuleComponents(json, rootModule);
     // TODO we need to dump directories
     for (InputFile inputFile : fileCache.all()) {
-      String key = ((DefaultInputFile) inputFile).key();
+      String key = ((DeprecatedDefaultInputFile) inputFile).key();
       json
         .beginObject()
         .prop("key", key)
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzersExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzersExecutor.java
new file mode 100644 (file)
index 0000000..c0ae6db
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.scan2;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.platform.ComponentContainer;
+import org.sonar.batch.api.analyzer.Analyzer;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.api.analyzer.AnalyzerDescriptor;
+
+import java.util.Collection;
+
+public class AnalyzersExecutor implements BatchComponent {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AnalyzersExecutor.class);
+
+  private ComponentContainer container;
+
+  public AnalyzersExecutor(ComponentContainer container) {
+    this.container = container;
+  }
+
+  public void execute(AnalyzerContext context) {
+    Collection<Analyzer> analyzers = container.getComponentsByType(Analyzer.class);
+
+    for (Analyzer analyzer : analyzers) {
+
+      AnalyzerDescriptor descriptor = analyzer.describe();
+
+      LOG.info("Execute analyzer: " + descriptor.name());
+
+      executeSensor(context, analyzer);
+    }
+
+  }
+
+  private void executeSensor(AnalyzerContext context, Analyzer analyzer) {
+    analyzer.analyse(context);
+  }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultAnalyzerContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultAnalyzerContext.java
new file mode 100644 (file)
index 0000000..253bf0c
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.scan2;
+
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.api.analyzer.issue.AnalyzerIssue;
+import org.sonar.batch.api.analyzer.measure.AnalyzerMeasure;
+import org.sonar.batch.api.measures.Metric;
+import org.sonar.batch.issue.ModuleIssues;
+import org.sonar.core.component.ComponentKeys;
+import org.sonar.core.issue.DefaultIssueBuilder;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+public class DefaultAnalyzerContext implements AnalyzerContext {
+
+  private final MeasureCache measureCache;
+  private ProjectDefinition def;
+  private ModuleIssues moduleIssues;
+
+  public DefaultAnalyzerContext(ProjectDefinition def, MeasureCache measureCache, ModuleIssues moduleIssues) {
+    this.def = def;
+    this.measureCache = measureCache;
+    this.moduleIssues = moduleIssues;
+  }
+
+  @Override
+  public AnalyzerMeasure getMeasure(String metricKey) {
+    return measureCache.byMetric(def.getKey(), metricKey);
+  }
+
+  @Override
+  public <G extends Serializable> AnalyzerMeasure<G> getMeasure(Metric<G> metric) {
+    return (AnalyzerMeasure<G>) measureCache.byMetric(def.getKey(), metric.key());
+  }
+
+  @Override
+  public AnalyzerMeasure getMeasure(InputFile file, String metricKey) {
+    return measureCache.byMetric(ComponentKeys.createEffectiveKey(def.getKey(), file), metricKey);
+  }
+
+  @Override
+  public <G extends Serializable> AnalyzerMeasure<G> getMeasure(InputFile file, Metric<G> metric) {
+    return (AnalyzerMeasure<G>) measureCache.byMetric(ComponentKeys.createEffectiveKey(def.getKey(), file), metric.key());
+  }
+
+  @Override
+  public void addMeasure(org.sonar.batch.api.analyzer.measure.AnalyzerMeasure<?> measure) {
+    if (measure.inputFile() != null) {
+      measureCache.put(ComponentKeys.createEffectiveKey(def.getKey(), measure.inputFile()), measure);
+    } else {
+      measureCache.put(def.getKey(), measure);
+    }
+  }
+
+  @Override
+  public void addIssue(AnalyzerIssue issue) {
+    DefaultIssueBuilder builder = new DefaultIssueBuilder()
+      .projectKey(def.getKey());
+    if (issue.inputFile() != null) {
+      builder.componentKey(ComponentKeys.createEffectiveKey(def.getKey(), issue.inputFile()));
+    } else {
+      builder.componentKey(def.getKey());
+    }
+
+    moduleIssues.initAndAddIssue((DefaultIssue) builder
+      .ruleKey(RuleKey.of(issue.ruleKey().repository(), issue.ruleKey().rule()))
+      .message(issue.message())
+      .line(issue.line())
+      .effortToFix(issue.effortToFix())
+      .build());
+  }
+
+  @Override
+  public void addIssues(Collection<AnalyzerIssue> issues) {
+    for (AnalyzerIssue analyzerIssue : issues) {
+      addIssue(analyzerIssue);
+    }
+
+  }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/MeasureCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/MeasureCache.java
new file mode 100644 (file)
index 0000000..96ab8ad
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.scan2;
+
+import com.google.common.base.Preconditions;
+import org.sonar.api.BatchComponent;
+import org.sonar.batch.api.analyzer.measure.AnalyzerMeasure;
+import org.sonar.batch.index.Cache;
+import org.sonar.batch.index.Cache.Entry;
+import org.sonar.batch.index.Caches;
+
+/**
+ * Cache of all measures. This cache is shared amongst all project modules.
+ */
+public class MeasureCache implements BatchComponent {
+
+  private final Cache<AnalyzerMeasure<?>> cache;
+
+  public MeasureCache(Caches caches) {
+    cache = caches.createCache("measures");
+  }
+
+  public Iterable<Entry<AnalyzerMeasure<?>>> entries() {
+    return cache.entries();
+  }
+
+  public AnalyzerMeasure<?> byMetric(String resourceKey, String metricKey) {
+    return cache.get(resourceKey, metricKey);
+  }
+
+  public MeasureCache put(String resourceKey, AnalyzerMeasure<?> measure) {
+    Preconditions.checkNotNull(resourceKey);
+    Preconditions.checkNotNull(measure.metricKey());
+    cache.put(resourceKey, measure.metricKey(), measure);
+    return this;
+  }
+
+  public boolean contains(String resourceKey, AnalyzerMeasure<?> measure) {
+    Preconditions.checkNotNull(resourceKey);
+    Preconditions.checkNotNull(measure);
+    return cache.containsKey(resourceKey, measure.metricKey());
+  }
+
+  public Iterable<AnalyzerMeasure<?>> all() {
+    return cache.values();
+  }
+
+}
index 44bcadc309c406aaeac6da22b8073f8b9b36fd7e..24435c0dc555c211dab2b50c57ec46d5e774d05f 100644 (file)
@@ -21,27 +21,17 @@ package org.sonar.batch.scan2;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.batch.InstantiationStrategy;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.rule.CheckFactory;
 import org.sonar.api.platform.ComponentContainer;
-import org.sonar.api.resources.Project;
 import org.sonar.api.scan.filesystem.FileExclusions;
-import org.sonar.batch.DefaultProjectClasspath;
-import org.sonar.batch.DefaultSensorContext;
-import org.sonar.batch.DefaultTimeMachine;
-import org.sonar.batch.ProjectTree;
-import org.sonar.batch.ResourceFilters;
-import org.sonar.batch.ViolationFilters;
+import org.sonar.batch.api.BatchComponent;
+import org.sonar.batch.api.InstantiationStrategy;
 import org.sonar.batch.bootstrap.BatchExtensionDictionnary;
 import org.sonar.batch.bootstrap.ExtensionInstaller;
 import org.sonar.batch.bootstrap.ExtensionMatcher;
 import org.sonar.batch.bootstrap.ExtensionUtils;
-import org.sonar.batch.components.TimeMachineConfiguration;
 import org.sonar.batch.events.EventBus;
-import org.sonar.batch.index.DefaultIndex;
-import org.sonar.batch.index.ResourcePersister;
 import org.sonar.batch.issue.IssuableFactory;
 import org.sonar.batch.issue.IssueFilters;
 import org.sonar.batch.issue.ModuleIssues;
@@ -51,23 +41,10 @@ import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
 import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer;
 import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
 import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner;
-import org.sonar.batch.language.LanguageDistributionDecorator;
-import org.sonar.batch.phases.Phase2Executor;
-import org.sonar.batch.phases.PhaseExecutor;
-import org.sonar.batch.phases.PhasesTimeProfiler;
-import org.sonar.batch.qualitygate.GenerateQualityGateEvents;
-import org.sonar.batch.qualitygate.QualityGateProvider;
-import org.sonar.batch.qualitygate.QualityGateVerifier;
-import org.sonar.batch.rule.ActiveRulesProvider;
 import org.sonar.batch.rule.ModuleQProfiles;
-import org.sonar.batch.rule.QProfileDecorator;
-import org.sonar.batch.rule.QProfileEventsDecorator;
-import org.sonar.batch.rule.QProfileSensor;
 import org.sonar.batch.rule.QProfileVerifier;
-import org.sonar.batch.rule.RulesProfileProvider;
 import org.sonar.batch.scan.LanguageVerifier;
 import org.sonar.batch.scan.ModuleSettings;
-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;
@@ -77,46 +54,34 @@ 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.ModuleInputFileCache;
-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.report.JsonReport;
-import org.sonar.core.component.ScanPerspectives;
-import org.sonar.core.measure.MeasurementFilters;
 
 public class ModuleScanContainer extends ComponentContainer {
   private static final Logger LOG = LoggerFactory.getLogger(ModuleScanContainer.class);
-  private final Project module;
+  private final ProjectDefinition moduleDefinition;
 
-  public ModuleScanContainer(ProjectScanContainer parent, Project module) {
+  public ModuleScanContainer(ProjectScanContainer parent, ProjectDefinition moduleDefinition) {
     super(parent);
-    this.module = module;
+    this.moduleDefinition = moduleDefinition;
   }
 
   @Override
   protected void doBeforeStart() {
-    LOG.info("-------------  Scan {}", module.getName());
+    LOG.info("-------------  Scan {}", moduleDefinition.getName());
     addCoreComponents();
     addExtensions();
   }
 
   private void addCoreComponents() {
-    ProjectDefinition moduleDefinition = getComponentByType(ProjectTree.class).getProjectDefinition(module);
     add(
       moduleDefinition,
-      module.getConfiguration(),
-      module,
-      ModuleSettings.class);
+      ModuleSettings.class,
 
-    // hack to initialize commons-configuration before ExtensionProviders
-    getComponentByType(ModuleSettings.class);
-
-    add(
       EventBus.class,
       Phase2Executor.class,
-      PhasesTimeProfiler.class,
       Phase2Executor.getPhaseClasses(),
       moduleDefinition.getContainerExtensions(),
+      AnalyzersExecutor.class,
 
       // file system
       ModuleInputFileCache.class,
@@ -126,46 +91,21 @@ public class ModuleScanContainer extends ComponentContainer {
       InputFileBuilderFactory.class,
       StatusDetectionFactory.class,
       LanguageDetectionFactory.class,
-      PreviousFileHashLoader.class,
       FileIndexer.class,
-      ComponentIndexer.class,
       LanguageVerifier.class,
       FileSystemLogger.class,
-      DefaultProjectClasspath.class,
       DefaultModuleFileSystem.class,
       ModuleFileSystemInitializer.class,
-      ProjectFileSystemAdapter.class,
       QProfileVerifier.class,
 
-      // the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
-      getComponentByType(ResourcePersister.class).getSnapshot(module),
-
-      TimeMachineConfiguration.class,
-      DefaultSensorContext.class,
+      DefaultAnalyzerContext.class,
       BatchExtensionDictionnary.class,
-      DefaultTimeMachine.class,
-      ViolationFilters.class,
       IssueFilters.class,
-      MeasurementFilters.class,
-      ResourceFilters.class,
-
-      // quality gates
-      new QualityGateProvider(),
-      QualityGateVerifier.class,
-      GenerateQualityGateEvents.class,
 
       // rules
       ModuleQProfiles.class,
-      new ActiveRulesProvider(),
-      new RulesProfileProvider(),
-      QProfileSensor.class,
-      QProfileDecorator.class,
-      QProfileEventsDecorator.class,
       CheckFactory.class,
 
-      // report
-      JsonReport.class,
-
       // issues
       IssuableFactory.class,
       ModuleIssues.class,
@@ -176,36 +116,22 @@ public class ModuleScanContainer extends ComponentContainer {
       IssueExclusionsRegexpScanner.class,
       IssueExclusionsLoader.class,
       EnforceIssuesFilter.class,
-      IgnoreIssuesFilter.class,
-
-      // language
-      LanguageDistributionDecorator.class,
-
-      ScanPerspectives.class);
+      IgnoreIssuesFilter.class);
   }
 
   private void addExtensions() {
     ExtensionInstaller installer = getComponentByType(ExtensionInstaller.class);
     installer.install(this, new ExtensionMatcher() {
       public boolean accept(Object extension) {
-        if (ExtensionUtils.isType(extension, BatchComponent.class) && ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_PROJECT)) {
-          // Special use-case: the extension point ProjectBuilder is used in a Maven environment to define some
-          // new sub-projects without pom.
-          // Example : C# plugin adds sub-projects at runtime, even if they are not defined in root pom.
-          return !ExtensionUtils.isMavenExtensionOnly(extension) || module.getPom() != null;
-        }
-        return false;
+        return ExtensionUtils.isType(extension, BatchComponent.class)
+          && ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_PROJECT);
       }
     });
   }
 
   @Override
   protected void doAfterStart() {
-    DefaultIndex index = getComponentByType(DefaultIndex.class);
-    index.setCurrentProject(module,
-      getComponentByType(ModuleIssues.class));
-
-    getComponentByType(PhaseExecutor.class).execute(module);
+    getComponentByType(Phase2Executor.class).execute(moduleDefinition);
   }
 
 }
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/Phase2Executor.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/Phase2Executor.java
new file mode 100644 (file)
index 0000000..fcbec9b
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.scan2;
+
+import com.google.common.collect.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
+import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
+import org.sonar.batch.phases.SensorsExecutor;
+import org.sonar.batch.rule.QProfileVerifier;
+import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
+import org.sonar.batch.scan.filesystem.FileSystemLogger;
+
+import java.util.Collection;
+
+public final class Phase2Executor {
+
+  public static final Logger LOGGER = LoggerFactory.getLogger(Phase2Executor.class);
+
+  private final AnalyzersExecutor analyzersExecutor;
+  private final AnalyzerContext analyzerContext;
+  private final FileSystemLogger fsLogger;
+  private final DefaultModuleFileSystem fs;
+  private final QProfileVerifier profileVerifier;
+  private final IssueExclusionsLoader issueExclusionsLoader;
+
+  public Phase2Executor(AnalyzersExecutor analyzersExecutor,
+    AnalyzerContext analyzerContext,
+    FileSystemLogger fsLogger, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
+    IssueExclusionsLoader issueExclusionsLoader) {
+    this.analyzersExecutor = analyzersExecutor;
+    this.analyzerContext = analyzerContext;
+    this.fsLogger = fsLogger;
+    this.fs = fs;
+    this.profileVerifier = profileVerifier;
+    this.issueExclusionsLoader = issueExclusionsLoader;
+  }
+
+  public static Collection<Class> getPhaseClasses() {
+    return Lists.<Class>newArrayList(SensorsExecutor.class);
+  }
+
+  /**
+   * Executed on each module
+   */
+  public void execute(ProjectDefinition moduleDefinition) {
+    fsLogger.log();
+
+    // Index and lock the filesystem
+    fs.index();
+
+    // Log detected languages and their profiles after FS is indexed and languages detected
+    profileVerifier.execute();
+
+    // Initialize issue exclusions
+    issueExclusionsLoader.execute();
+
+    analyzersExecutor.execute(analyzerContext);
+  }
+}
index 3ca92f4bc5b72df2e5550cb26ac8c6feca159f23..6a3d9bfcfacf2083cceabca2769371edec266e71 100644 (file)
 package org.sonar.batch.scan2;
 
 import com.google.common.annotations.VisibleForTesting;
-import org.sonar.api.BatchComponent;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.InstantiationStrategy;
 import org.sonar.api.batch.bootstrap.ProjectBootstrapper;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.api.config.Settings;
 import org.sonar.api.platform.ComponentContainer;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.resources.Project;
 import org.sonar.api.scan.filesystem.PathResolver;
 import org.sonar.api.utils.SonarException;
-import org.sonar.batch.DefaultFileLinesContextFactory;
-import org.sonar.batch.ProjectConfigurator;
-import org.sonar.batch.ProjectTree;
+import org.sonar.batch.api.BatchComponent;
+import org.sonar.batch.api.InstantiationStrategy;
 import org.sonar.batch.bootstrap.ExtensionInstaller;
 import org.sonar.batch.bootstrap.ExtensionMatcher;
 import org.sonar.batch.bootstrap.ExtensionUtils;
-import org.sonar.batch.bootstrap.MetricProvider;
-import org.sonar.batch.components.PeriodsDefinition;
-import org.sonar.batch.debt.DebtModelProvider;
 import org.sonar.batch.debt.IssueChangelogDebtCalculator;
 import org.sonar.batch.index.Caches;
 import org.sonar.batch.index.ComponentDataCache;
 import org.sonar.batch.index.ComponentDataPersister;
-import org.sonar.batch.index.DefaultIndex;
-import org.sonar.batch.index.DefaultPersistenceManager;
-import org.sonar.batch.index.DefaultResourcePersister;
-import org.sonar.batch.index.DependencyPersister;
-import org.sonar.batch.index.EventPersister;
-import org.sonar.batch.index.LinkPersister;
-import org.sonar.batch.index.MeasurePersister;
 import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.index.ResourceKeyMigration;
 import org.sonar.batch.index.SnapshotCache;
-import org.sonar.batch.index.SourcePersister;
 import org.sonar.batch.issue.DefaultProjectIssues;
 import org.sonar.batch.issue.DeprecatedViolations;
 import org.sonar.batch.issue.IssueCache;
@@ -62,13 +46,10 @@ import org.sonar.batch.issue.IssuePersister;
 import org.sonar.batch.issue.ScanIssueStorage;
 import org.sonar.batch.phases.GraphPersister;
 import org.sonar.batch.profiling.PhasesSumUpTimeProfiler;
-import org.sonar.batch.rule.RulesProvider;
 import org.sonar.batch.scan.ProjectReactorBuilder;
-import org.sonar.batch.scan.ProjectSettingsReady;
 import org.sonar.batch.scan.filesystem.InputFileCache;
 import org.sonar.batch.scan.maven.FakeMavenPluginExecutor;
 import org.sonar.batch.scan.maven.MavenPluginExecutor;
-import org.sonar.batch.scan.measure.MeasureCache;
 import org.sonar.batch.source.HighlightableBuilder;
 import org.sonar.batch.source.SymbolizableBuilder;
 import org.sonar.core.component.ScanGraph;
@@ -76,13 +57,10 @@ import org.sonar.core.issue.IssueNotifications;
 import org.sonar.core.issue.IssueUpdater;
 import org.sonar.core.issue.workflow.FunctionExecutor;
 import org.sonar.core.issue.workflow.IssueWorkflow;
-import org.sonar.core.notification.DefaultNotificationManager;
-import org.sonar.core.technicaldebt.DefaultTechnicalDebtModel;
 import org.sonar.core.test.TestPlanBuilder;
 import org.sonar.core.test.TestPlanPerspectiveLoader;
 import org.sonar.core.test.TestableBuilder;
 import org.sonar.core.test.TestablePerspectiveLoader;
-import org.sonar.core.user.DefaultUserFinder;
 
 public class ProjectScanContainer extends ComponentContainer {
   public ProjectScanContainer(ComponentContainer taskContainer) {
@@ -102,50 +80,32 @@ public class ProjectScanContainer extends ComponentContainer {
   }
 
   private void projectBootstrap() {
-    // Old versions of bootstrappers used to pass project reactor as an extension
-    // so check if it is already present in parent container
-    ProjectReactor reactor = getComponentByType(ProjectReactor.class);
+    ProjectReactor reactor;
+    ProjectBootstrapper bootstrapper = getComponentByType(ProjectBootstrapper.class);
+    Settings settings = getComponentByType(Settings.class);
+    if (bootstrapper == null
+      // Starting from Maven plugin 2.3 then only DefaultProjectBootstrapper should be used.
+      || "true".equals(settings.getString("sonar.mojoUseRunner"))) {
+      // Use default SonarRunner project bootstrapper
+      ProjectReactorBuilder builder = getComponentByType(ProjectReactorBuilder.class);
+      reactor = builder.execute();
+    } else {
+      reactor = bootstrapper.bootstrap();
+    }
     if (reactor == null) {
-      // OK, not present, so look for a custom ProjectBootstrapper
-      ProjectBootstrapper bootstrapper = getComponentByType(ProjectBootstrapper.class);
-      Settings settings = getComponentByType(Settings.class);
-      if (bootstrapper == null
-        // Starting from Maven plugin 2.3 then only DefaultProjectBootstrapper should be used.
-        || "true".equals(settings.getString("sonar.mojoUseRunner"))) {
-        // Use default SonarRunner project bootstrapper
-        ProjectReactorBuilder builder = getComponentByType(ProjectReactorBuilder.class);
-        reactor = builder.execute();
-      } else {
-        reactor = bootstrapper.bootstrap();
-      }
-      if (reactor == null) {
-        throw new SonarException(bootstrapper + " has returned null as ProjectReactor");
-      }
-      add(reactor);
+      throw new SonarException(bootstrapper + " has returned null as ProjectReactor");
     }
+    add(reactor);
   }
 
   private void addBatchComponents() {
     add(
-      DefaultPersistenceManager.class,
-      DependencyPersister.class,
-      EventPersister.class,
-      LinkPersister.class,
-      MeasurePersister.class,
-      DefaultResourcePersister.class,
-      SourcePersister.class,
-      DefaultNotificationManager.class,
-      MetricProvider.class,
-      ProjectConfigurator.class,
-      DefaultIndex.class,
-      ResourceKeyMigration.class,
-      DefaultFileLinesContextFactory.class,
       Caches.class,
       SnapshotCache.class,
       ResourceCache.class,
       ComponentDataCache.class,
       ComponentDataPersister.class,
-      DefaultUserFinder.class,
+      MeasureCache.class,
 
       // file system
       InputFileCache.class,
@@ -172,24 +132,10 @@ public class ProjectScanContainer extends ComponentContainer {
       GraphPersister.class,
 
       // lang
-      Languages.class,
       HighlightableBuilder.class,
       SymbolizableBuilder.class,
 
-      // technical debt
-      DefaultTechnicalDebtModel.class,
-      new DebtModelProvider(),
-
-      // rules
-      new RulesProvider(),
-
-      // Differential periods
-      PeriodsDefinition.class,
-
-      // Measures
-      MeasureCache.class,
-
-      ProjectSettingsReady.class);
+      ScanTaskObservers.class);
   }
 
   private void fixMavenExecutor() {
@@ -204,19 +150,20 @@ public class ProjectScanContainer extends ComponentContainer {
 
   @Override
   protected void doAfterStart() {
-    ProjectTree tree = getComponentByType(ProjectTree.class);
-    scanRecursively(tree.getRootProject());
+    ProjectReactor tree = getComponentByType(ProjectReactor.class);
+    scanRecursively(tree.getRoot());
+    getComponentByType(ScanTaskObservers.class).notifyEndOfScanTask();
   }
 
-  private void scanRecursively(Project module) {
-    for (Project subModules : module.getModules()) {
+  private void scanRecursively(ProjectDefinition module) {
+    for (ProjectDefinition subModules : module.getSubProjects()) {
       scanRecursively(subModules);
     }
     scan(module);
   }
 
   @VisibleForTesting
-  void scan(Project module) {
+  void scan(ProjectDefinition module) {
     new ModuleScanContainer(this, module).execute();
   }
 
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObserver.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObserver.java
new file mode 100644 (file)
index 0000000..89f5c76
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.scan2;
+
+import org.sonar.batch.api.BatchExtension;
+
+public interface ScanTaskObserver extends BatchExtension {
+
+  void scanTaskCompleted(ProjectScanContainer container);
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObservers.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObservers.java
new file mode 100644 (file)
index 0000000..6dc8fa6
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.scan2;
+
+public class ScanTaskObservers {
+
+  private ScanTaskObserver[] observers;
+  private ProjectScanContainer projectScanContainer;
+
+  public ScanTaskObservers(ProjectScanContainer projectScanContainer, ScanTaskObserver... observers) {
+    this.projectScanContainer = projectScanContainer;
+    this.observers = observers;
+  }
+
+  public ScanTaskObservers(ProjectScanContainer projectScanContainer) {
+    this(projectScanContainer, new ScanTaskObserver[0]);
+  }
+
+  public void notifyEndOfScanTask() {
+    for (ScanTaskObserver scanTaskObserver : observers) {
+      scanTaskObserver.scanTaskCompleted(projectScanContainer);
+    }
+  }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/package-info.java
new file mode 100644 (file)
index 0000000..d5d167b
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.scan2;
\ No newline at end of file
diff --git a/sonar-batch/src/main/java/org/sonar/batch/settings/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/settings/package-info.java
new file mode 100644 (file)
index 0000000..6d2df16
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.settings;
\ No newline at end of file
index 79af9782d6deaf606a13597f07351d55c02630e7..d7f5df2e76138e487bce3e5db8bc5008ca4d35dc 100644 (file)
@@ -23,14 +23,17 @@ import org.junit.Test;
 import org.sonar.api.BatchExtension;
 import org.sonar.api.batch.Sensor;
 import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.fs.FileSystem;
 import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
+import org.sonar.batch.api.analyzer.AnalyzerContext;
 
 import java.util.Collection;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
+import static org.mockito.Mockito.mock;
 
 public class BatchExtensionDictionnaryTest {
 
@@ -39,7 +42,7 @@ public class BatchExtensionDictionnaryTest {
     for (BatchExtension extension : extensions) {
       iocContainer.addSingleton(extension);
     }
-    return new BatchExtensionDictionnary(iocContainer);
+    return new BatchExtensionDictionnary(iocContainer, mock(FileSystem.class), mock(AnalyzerContext.class));
   }
 
   @Test
index 37b6736a89ef3cd553c18c018ab8ae7f1e537c10..1af98413155c4ab379b5009e9ded7bd4a2245fd1 100644 (file)
@@ -41,12 +41,12 @@ public class MetricProviderTest {
 
   @Test
   public void should_provide_plugin_metrics() {
-    Metrics factory = new Metrics(){
+    Metrics factory = new Metrics() {
       public List<Metric> getMetrics() {
-        return Arrays.asList(new Metric.Builder("custom", "Custom", Metric.ValueType.FLOAT).create());
+        return Arrays.<Metric>asList(new Metric.Builder("custom", "Custom", Metric.ValueType.FLOAT).create());
       }
     };
-    MetricProvider provider = new MetricProvider(new Metrics[]{factory});
+    MetricProvider provider = new MetricProvider(new Metrics[] {factory});
     List<Metric> metrics = provider.provide();
 
     assertThat(metrics.size()).isEqualTo(1 + CoreMetrics.getMetrics().size());
index 564a6845a04340d6fc0c4adbfa04e2f2a6997398..1fe27bc91b1976159be6350480cb735159f398cf 100644 (file)
@@ -28,6 +28,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.resources.Project;
 import org.sonar.jpa.test.AbstractDbUnitTestCase;
 
@@ -86,9 +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 DefaultInputFile(path).setFile(file)
-      .setKey(effectiveKey)
+    return new DeprecatedDefaultInputFile(path)
       .setDeprecatedKey(deprecatedEffectiveKey)
+      .setFile(file)
+      .setKey(effectiveKey)
       .setType(isTest ? InputFile.Type.TEST : InputFile.Type.MAIN);
   }
 
@@ -99,7 +101,7 @@ public class ResourceKeyMigrationTest extends AbstractDbUnitTestCase {
     Logger logger = mock(Logger.class);
     ResourceKeyMigration migration = new ResourceKeyMigration(getSession(), logger);
     migration.checkIfMigrationNeeded(multiModuleProject);
-    
+
     migration.migrateIfNeeded(javaModule, javaInputFiles);
     migration.migrateIfNeeded(phpModule, phpInputFiles);
 
@@ -110,7 +112,7 @@ public class ResourceKeyMigrationTest extends AbstractDbUnitTestCase {
     verify(logger).info("Component {} changed to {}", "b:org/foo", "b:src/main/java/org/foo");
     verify(logger).info("Component {} changed 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 065601b9a9127db6b5b0612bea931d104cdd8a55..5b97df2c7f5cf269c1e5576e18e79e4bbb24a46b 100644 (file)
@@ -29,7 +29,7 @@ import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.utils.SonarException;
 import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
 import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer;
@@ -101,12 +101,12 @@ public class IssueExclusionsLoaderTest {
   @Test
   public void shouldAnalyzeProject() throws IOException {
     File javaFile1 = new File(baseDir, "src/main/java/Foo.java");
-    fs.add(new DefaultInputFile("src/main/java/Foo.java")
+    fs.add(new DeprecatedDefaultInputFile("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");
-    fs.add(new DefaultInputFile("src/test/java/FooTest.java")
+    fs.add(new DeprecatedDefaultInputFile("src/test/java/FooTest.java")
       .setFile(javaTestFile1)
       .setType(InputFile.Type.TEST)
       .setKey("polop:src/test/java/FooTest.java"));
@@ -126,12 +126,12 @@ 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")
+    fs.add(new DeprecatedDefaultInputFile("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");
-    fs.add(new DefaultInputFile("src/test/java/FooTest.java")
+    fs.add(new DeprecatedDefaultInputFile("src/test/java/FooTest.java")
       .setFile(javaTestFile1)
       .setType(InputFile.Type.TEST)
       .setKey("polop:src/test/java/FooTest.java"));
@@ -149,7 +149,7 @@ public class IssueExclusionsLoaderTest {
   @Test
   public void shouldReportFailure() throws IOException {
     File phpFile1 = new File(baseDir, "src/Foo.php");
-    fs.add(new DefaultInputFile("src/Foo.php")
+    fs.add(new DeprecatedDefaultInputFile("src/Foo.php")
       .setFile(phpFile1)
       .setType(InputFile.Type.MAIN)
       .setKey("polop:src/Foo.php"));
diff --git a/sonar-batch/src/test/java/org/sonar/batch/medium/Scan2MediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/medium/Scan2MediumTest.java
deleted file mode 100644 (file)
index ae4a9ec..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.medium;
-
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import org.junit.Test;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.MetricFinder;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.rules.RuleQuery;
-import org.sonar.batch.bootstrap.PluginsReferential;
-import org.sonar.batch.bootstrapper.Batch;
-import org.sonar.batch.bootstrapper.EnvironmentInformation;
-import org.sonar.batch.settings.SettingsReferential;
-import org.sonar.core.plugins.RemotePlugin;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class Scan2MediumTest {
-
-  @Test
-  public void mediumTest() {
-    Batch batch = Batch.builder()
-      .setEnableLoggingConfiguration(true)
-      .addComponent(new EnvironmentInformation("mediumTest", "1.0"))
-      .addComponent(new MockSettingsReferential())
-      .addComponent(new MockPluginsReferential())
-      .addComponent(new MockMetricFinder())
-      .addComponent(new MockRuleFinder())
-      .setBootstrapProperties(ImmutableMap.of("sonar.analysis.mode", "sensor"))
-      .build();
-
-    batch.start();
-
-    // batch.executeTask(ImmutableMap.<String, String>builder().put("sonar.task", "scan").build());
-
-    batch.stop();
-  }
-
-  private static class MockSettingsReferential implements SettingsReferential {
-
-    private Map<String, String> globalSettings = new HashMap<String, String>();
-    private Map<String, Map<String, String>> projectSettings = new HashMap<String, Map<String, String>>();
-
-    @Override
-    public Map<String, String> globalSettings() {
-      return globalSettings;
-    }
-
-    @Override
-    public Map<String, String> projectSettings(String projectKey) {
-      return projectSettings.containsKey(projectKey) ? projectSettings.get(projectKey) : Collections.<String, String>emptyMap();
-    }
-
-  }
-
-  private static class MockPluginsReferential implements PluginsReferential {
-
-    private List<RemotePlugin> pluginList = new ArrayList<RemotePlugin>();
-    private Map<RemotePlugin, File> pluginFiles = new HashMap<RemotePlugin, File>();
-
-    @Override
-    public List<RemotePlugin> pluginList() {
-      return pluginList;
-    }
-
-    @Override
-    public File pluginFile(RemotePlugin remote) {
-      return pluginFiles.get(remote);
-    }
-
-  }
-
-  private static class MockMetricFinder implements MetricFinder {
-
-    private Map<String, Metric> metricsByKey = Maps.newLinkedHashMap();
-    private Map<Integer, Metric> metricsById = Maps.newLinkedHashMap();
-
-    @Override
-    public Metric findById(int metricId) {
-      return metricsById.get(metricId);
-    }
-
-    @Override
-    public Metric findByKey(String key) {
-      return metricsByKey.get(key);
-    }
-
-    @Override
-    public Collection<Metric> findAll(List<String> metricKeys) {
-      List<Metric> result = Lists.newLinkedList();
-      for (String metricKey : metricKeys) {
-        Metric metric = findByKey(metricKey);
-        if (metric != null) {
-          result.add(metric);
-        }
-      }
-      return result;
-    }
-
-    @Override
-    public Collection<Metric> findAll() {
-      return metricsByKey.values();
-    }
-
-  }
-
-  private static class MockRuleFinder implements RuleFinder {
-    private BiMap<Integer, Rule> rulesById = HashBiMap.create();
-    private Map<String, Map<String, Rule>> rulesByRepoKeyAndRuleKey = Maps.newHashMap();
-
-    @Override
-    public Rule findById(int ruleId) {
-      return rulesById.get(ruleId);
-    }
-
-    @Override
-    public Rule findByKey(String repositoryKey, String ruleKey) {
-      Map<String, Rule> repository = rulesByRepoKeyAndRuleKey.get(repositoryKey);
-      return repository != null ? repository.get(ruleKey) : null;
-    }
-
-    @Override
-    public Rule findByKey(RuleKey key) {
-      return findByKey(key.repository(), key.rule());
-    }
-
-    @Override
-    public Rule find(RuleQuery query) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Collection<Rule> findAll(RuleQuery query) {
-      throw new UnsupportedOperationException();
-    }
-  }
-
-}
index c2039e71bf217d321337c16aa37d13ad8dea3c95..205fe2e8a8c3229286da3f52d8088ef9a6d4ceab 100644 (file)
@@ -27,9 +27,10 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RuleFinder;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
 import org.sonar.core.persistence.AbstractDaoTestCase;
 import org.sonar.core.qualityprofile.db.ActiveRuleDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
 
 import java.util.Arrays;
 
@@ -53,13 +54,12 @@ public class ActiveRulesProviderTest extends AbstractDaoTestCase {
   @Test
   public void build_active_rules() throws Exception {
     setupData("shared");
-    QualityProfileDao profileDao = new QualityProfileDao(getMyBatis());
-    when(qProfiles.findAll()).thenReturn(Arrays.asList(
+    when(qProfiles.findAll()).thenReturn(Arrays.<QProfile>asList(
       // 1 rule is enabled on java with severity INFO
-      new ModuleQProfiles.QProfile(profileDao.selectById(2)),
+      new QProfileWithId(2, "Java Two", "java", 20),
       // 1 rule is enabled on php with severity BLOCKER
-      new ModuleQProfiles.QProfile(profileDao.selectById(3))
-    ));
+      new QProfileWithId(3, "Php One", "php", 30)
+      ));
 
     ActiveRulesProvider provider = new ActiveRulesProvider();
     ActiveRuleDao activeRuleDao = new ActiveRuleDao(getMyBatis());
index 99b39d199863232870ad1bfa6557b56e0df0179f..6b3102206f3be8f7a7fe59725acf2054fa74f4c1 100644 (file)
@@ -25,6 +25,12 @@ 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.batch.api.rules.QProfile;
+import org.sonar.batch.languages.DeprecatedLanguagesReferential;
+import org.sonar.batch.languages.LanguagesReferential;
+import org.sonar.batch.rules.DefaultQProfileReferential;
+import org.sonar.batch.rules.QProfilesReferential;
+import org.sonar.batch.rules.QProfileWithId;
 import org.sonar.core.persistence.AbstractDaoTestCase;
 import org.sonar.core.qualityprofile.db.QualityProfileDao;
 
@@ -35,31 +41,32 @@ import static org.fest.assertions.Fail.fail;
 
 public class ModuleQProfilesTest extends AbstractDaoTestCase {
 
-  Languages languages = new Languages(new SimpleLanguage("java"), new SimpleLanguage("php"));
+  LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new SimpleLanguage("java"), new SimpleLanguage("php")));
   Settings settings = new Settings();
 
   @Test
   public void find_profiles() throws Exception {
     setupData("shared");
     QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+    QProfilesReferential ref = new DefaultQProfileReferential(dao);
 
     settings.setProperty("sonar.profile.java", "Java Two");
     settings.setProperty("sonar.profile.abap", "Abap One");
     settings.setProperty("sonar.profile.php", "Php One");
 
-    ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, dao);
-    List<ModuleQProfiles.QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
+    ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, ref);
+    List<QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
 
     assertThat(qProfiles).hasSize(2);
     assertThat(moduleQProfiles.findByLanguage("java")).isNotNull();
     assertThat(moduleQProfiles.findByLanguage("php")).isNotNull();
     assertThat(moduleQProfiles.findByLanguage("abap")).isNull();
-    ModuleQProfiles.QProfile javaProfile = qProfiles.get(0);
+    QProfileWithId javaProfile = (QProfileWithId) qProfiles.get(0);
     assertThat(javaProfile.id()).isEqualTo(2);
     assertThat(javaProfile.name()).isEqualTo("Java Two");
     assertThat(javaProfile.language()).isEqualTo("java");
     assertThat(javaProfile.version()).isEqualTo(20);
-    ModuleQProfiles.QProfile phpProfile = qProfiles.get(1);
+    QProfileWithId phpProfile = (QProfileWithId) qProfiles.get(1);
     assertThat(phpProfile.id()).isEqualTo(3);
     assertThat(phpProfile.name()).isEqualTo("Php One");
     assertThat(phpProfile.language()).isEqualTo("php");
@@ -71,22 +78,23 @@ public class ModuleQProfilesTest extends AbstractDaoTestCase {
   public void use_sonar_profile_property() throws Exception {
     setupData("shared");
     QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+    QProfilesReferential ref = new DefaultQProfileReferential(dao);
 
     settings.setProperty("sonar.profile", "Java Two");
     settings.setProperty("sonar.profile.php", "Php One");
 
-    ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, dao);
-    List<ModuleQProfiles.QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
+    ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, ref);
+    List<QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
 
     assertThat(qProfiles).hasSize(2);
-    ModuleQProfiles.QProfile javaProfile = qProfiles.get(0);
+    QProfileWithId javaProfile = (QProfileWithId) qProfiles.get(0);
     assertThat(javaProfile.id()).isEqualTo(2);
     assertThat(javaProfile.name()).isEqualTo("Java Two");
     assertThat(javaProfile.language()).isEqualTo("java");
     assertThat(javaProfile.version()).isEqualTo(20);
 
     // Fallback to sonar.profile.php if no match for sonar.profile
-    ModuleQProfiles.QProfile phpProfile = qProfiles.get(1);
+    QProfileWithId phpProfile = (QProfileWithId) qProfiles.get(1);
     assertThat(phpProfile.id()).isEqualTo(3);
     assertThat(phpProfile.name()).isEqualTo("Php One");
     assertThat(phpProfile.language()).isEqualTo("php");
@@ -98,12 +106,13 @@ public class ModuleQProfilesTest extends AbstractDaoTestCase {
   public void fail_if_unknown_profile() throws Exception {
     setupData("shared");
     QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+    QProfilesReferential ref = new DefaultQProfileReferential(dao);
 
     settings.setProperty("sonar.profile.java", "Unknown");
     settings.setProperty("sonar.profile.php", "Php One");
 
     try {
-      new ModuleQProfiles(settings, languages, dao);
+      new ModuleQProfiles(settings, languages, ref);
       fail();
     } catch (MessageException e) {
       assertThat(e).hasMessage("Quality profile not found : 'Unknown' on language 'java'");
index a074f7185dfdecbd18b69fb4828d0c7e9b565b7a..04ba7b1c2515a6d1353159469884b396eeb86883 100644 (file)
@@ -25,6 +25,8 @@ import org.sonar.api.batch.fs.internal.DefaultFileSystem;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.resources.Project;
 import org.sonar.api.test.IsMeasure;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
 import org.sonar.core.persistence.AbstractDaoTestCase;
 import org.sonar.core.qualityprofile.db.QualityProfileDao;
 
@@ -54,7 +56,7 @@ public class QProfileSensorTest extends AbstractDaoTestCase {
   public void no_qprofiles() throws Exception {
     setupData("shared");
     QualityProfileDao dao = new QualityProfileDao(getMyBatis());
-    when(moduleQProfiles.findAll()).thenReturn(Collections.<ModuleQProfiles.QProfile>emptyList());
+    when(moduleQProfiles.findAll()).thenReturn(Collections.<QProfile>emptyList());
 
     QProfileSensor sensor = new QProfileSensor(moduleQProfiles, fs, dao);
     assertThat(sensor.shouldExecuteOnProject(project)).isTrue();
@@ -69,8 +71,8 @@ public class QProfileSensorTest extends AbstractDaoTestCase {
     setupData("shared");
 
     QualityProfileDao dao = new QualityProfileDao(getMyBatis());
-    when(moduleQProfiles.findByLanguage("java")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(2)));
-    when(moduleQProfiles.findByLanguage("php")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(3)));
+    when(moduleQProfiles.findByLanguage("java")).thenReturn(new QProfileWithId(2, "Java Two", "java", 20));
+    when(moduleQProfiles.findByLanguage("php")).thenReturn(new QProfileWithId(3, "Php One", "php", 30));
     when(moduleQProfiles.findByLanguage("abap")).thenReturn(null);
     fs.addLanguages("java", "php", "abap");
 
@@ -86,8 +88,8 @@ public class QProfileSensorTest extends AbstractDaoTestCase {
     setupData("shared");
 
     QualityProfileDao dao = new QualityProfileDao(getMyBatis());
-    when(moduleQProfiles.findByLanguage("java")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(2)));
-    when(moduleQProfiles.findByLanguage("php")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(3)));
+    when(moduleQProfiles.findByLanguage("java")).thenReturn(new QProfileWithId(2, "Java Two", "java", 20));
+    when(moduleQProfiles.findByLanguage("php")).thenReturn(new QProfileWithId(3, "Php One", "php", 30));
     when(moduleQProfiles.findByLanguage("abap")).thenReturn(null);
     fs.addLanguages("java");
 
@@ -106,8 +108,8 @@ public class QProfileSensorTest extends AbstractDaoTestCase {
     setupData("shared");
 
     QualityProfileDao dao = new QualityProfileDao(getMyBatis());
-    when(moduleQProfiles.findByLanguage("java")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(2)));
-    when(moduleQProfiles.findByLanguage("php")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(3)));
+    when(moduleQProfiles.findByLanguage("java")).thenReturn(new QProfileWithId(2, "Java Two", "java", 20));
+    when(moduleQProfiles.findByLanguage("php")).thenReturn(new QProfileWithId(3, "Php One", "php", 30));
     when(moduleQProfiles.findByLanguage("abap")).thenReturn(null);
     fs.addLanguages("java", "php");
 
index 0fd8c58d040cf7c8e654570b01ee38cf05f13d94..483b6c7e3972caef1e97d7d43f0bc0c4884a8d38 100644 (file)
@@ -28,9 +28,11 @@ import org.sonar.api.batch.fs.internal.DefaultFileSystem;
 import org.sonar.api.config.Settings;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.utils.MessageException;
-import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
 
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 public class QProfileVerifierTest {
 
@@ -46,11 +48,11 @@ public class QProfileVerifierTest {
   @Before
   public void before() {
     profiles = mock(ModuleQProfiles.class);
-    QProfile javaProfile = mock(QProfile.class);
+    QProfileWithId javaProfile = mock(QProfileWithId.class);
     when(javaProfile.name()).thenReturn("My Java profile");
     javaRulesProfile = mock(RulesProfile.class);
     when(profiles.findByLanguage("java")).thenReturn(javaProfile);
-    QProfile cobolProfile = mock(QProfile.class);
+    QProfileWithId cobolProfile = mock(QProfileWithId.class);
     when(cobolProfile.name()).thenReturn("My Cobol profile");
     cobolRulesProfile = mock(RulesProfile.class);
     when(profiles.findByLanguage("cobol")).thenReturn(cobolProfile);
index 3a980631b1c5d7f099534656da69806c38ccfe53..789f4a354854040778759a3eeeb68a476db23d5c 100644 (file)
@@ -24,6 +24,8 @@ import org.sonar.api.batch.rule.ActiveRules;
 import org.sonar.api.config.Settings;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.rules.RuleFinder;
+import org.sonar.batch.api.rules.QProfile;
+import org.sonar.batch.rules.QProfileWithId;
 
 import java.util.Arrays;
 
@@ -42,8 +44,8 @@ public class RulesProfileProviderTest {
 
   @Test
   public void merge_profiles() throws Exception {
-    ModuleQProfiles.QProfile qProfile = new ModuleQProfiles.QProfile(33, "Sonar way", "java", 12);
-    when(qProfiles.findAll()).thenReturn(Arrays.asList(qProfile));
+    QProfileWithId qProfile = new QProfileWithId(33, "Sonar way", "java", 12);
+    when(qProfiles.findAll()).thenReturn(Arrays.<QProfile>asList(qProfile));
 
     RulesProfile profile = provider.provide(qProfiles, activeRules, ruleFinder, settings);
 
@@ -64,7 +66,7 @@ public class RulesProfileProviderTest {
   public void keep_compatibility_with_single_language_projects() throws Exception {
     settings.setProperty("sonar.language", "java");
 
-    ModuleQProfiles.QProfile qProfile = new ModuleQProfiles.QProfile(33, "Sonar way", "java", 12);
+    QProfileWithId qProfile = new QProfileWithId(33, "Sonar way", "java", 12);
     when(qProfiles.findByLanguage("java")).thenReturn(qProfile);
 
     RulesProfile profile = provider.provide(qProfiles, activeRules, ruleFinder, settings);
index b3cab37a325ebc91334857ce4b90d76fbbe3d468..1e9d47db0ec4cdbad14a149568ec3859147e82d6 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.batch.rule;
 
 import org.junit.Test;
+import org.sonar.batch.rules.QProfileWithId;
 
 import static org.fest.assertions.Assertions.assertThat;
 
@@ -28,8 +29,8 @@ public class UsedQProfilesTest {
   @Test
   public void serialization() throws Exception {
 
-    ModuleQProfiles.QProfile java = new ModuleQProfiles.QProfile(1, "Sonar Way", "java", 1);
-    ModuleQProfiles.QProfile php = new ModuleQProfiles.QProfile(2, "Sonar Way", "php", 1);
+    QProfileWithId java = new QProfileWithId(1, "Sonar Way", "java", 1);
+    QProfileWithId php = new QProfileWithId(2, "Sonar Way", "php", 1);
 
     UsedQProfiles used = UsedQProfiles.fromProfiles(java, php);
     assertThat(used.toJSON()).isEqualTo(
index 8ea87446d82362481c932bba97960d38028fb44f..30b6b571883ca33e97dcc41e553471e87e328b63 100644 (file)
@@ -27,13 +27,15 @@ import org.sonar.api.config.Settings;
 import org.sonar.api.resources.Java;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.utils.MessageException;
+import org.sonar.batch.languages.DeprecatedLanguagesReferential;
+import org.sonar.batch.languages.LanguagesReferential;
 
 import static org.fest.assertions.Assertions.assertThat;
 
 public class LanguageVerifierTest {
 
   Settings settings = new Settings();
-  Languages languages = new Languages(Java.INSTANCE);
+  LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(Java.INSTANCE));
   DefaultFileSystem fs = new DefaultFileSystem();
 
   @Rule
index 8612195548538f012335a265d3a2512cef59cc78..0bb4b2432268cc64788afa83417850e33a98ea8e 100644 (file)
@@ -24,6 +24,7 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.FilePredicate;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
 
 import java.io.File;
 
@@ -38,10 +39,10 @@ public class AdditionalFilePredicatesTest {
   public void key() throws Exception {
     FilePredicate predicate = new AdditionalFilePredicates.KeyPredicate("struts:Action.java");
 
-    DefaultInputFile inputFile = new DefaultInputFile("Action.java").setKey("struts:Action.java");
+    DefaultInputFile inputFile = new DeprecatedDefaultInputFile("Action.java").setKey("struts:Action.java");
     assertThat(predicate.apply(inputFile)).isTrue();
 
-    inputFile = new DefaultInputFile("Filter.java").setKey("struts:Filter.java");
+    inputFile = new DeprecatedDefaultInputFile("Filter.java").setKey("struts:Filter.java");
     assertThat(predicate.apply(inputFile)).isFalse();
   }
 
@@ -49,10 +50,10 @@ public class AdditionalFilePredicatesTest {
   public void deprecated_key() throws Exception {
     FilePredicate predicate = new AdditionalFilePredicates.DeprecatedKeyPredicate("struts:Action.java");
 
-    DefaultInputFile inputFile = new DefaultInputFile("Action.java").setDeprecatedKey("struts:Action.java");
+    DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("Action.java").setDeprecatedKey("struts:Action.java");
     assertThat(predicate.apply(inputFile)).isTrue();
 
-    inputFile = new DefaultInputFile("Filter.java").setDeprecatedKey("struts:Filter.java");
+    inputFile = new DeprecatedDefaultInputFile("Filter.java").setDeprecatedKey("struts:Filter.java");
     assertThat(predicate.apply(inputFile)).isFalse();
   }
 
@@ -61,10 +62,10 @@ public class AdditionalFilePredicatesTest {
     File dir = temp.newFolder();
     FilePredicate predicate = new AdditionalFilePredicates.SourceDirPredicate(dir.getAbsolutePath());
 
-    DefaultInputFile inputFile = new DefaultInputFile("Action.java").setSourceDirAbsolutePath(dir.getAbsolutePath());
+    DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("Action.java").setSourceDirAbsolutePath(dir.getAbsolutePath());
     assertThat(predicate.apply(inputFile)).isTrue();
 
-    inputFile = new DefaultInputFile("Filter.java").setSourceDirAbsolutePath(temp.newFolder().getAbsolutePath());
+    inputFile = new DeprecatedDefaultInputFile("Filter.java").setSourceDirAbsolutePath(temp.newFolder().getAbsolutePath());
     assertThat(predicate.apply(inputFile)).isFalse();
   }
 
@@ -72,10 +73,10 @@ public class AdditionalFilePredicatesTest {
   public void path_relative_to_source_dir() throws Exception {
     FilePredicate predicate = new AdditionalFilePredicates.SourceRelativePathPredicate("foo/Bar.php");
 
-    DefaultInputFile inputFile = new DefaultInputFile("src/php/foo/Bar.php").setPathRelativeToSourceDir("foo/Bar.php");
+    DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("src/php/foo/Bar.php").setPathRelativeToSourceDir("foo/Bar.php");
     assertThat(predicate.apply(inputFile)).isTrue();
 
-    inputFile = new DefaultInputFile("foo/Bar.php").setPathRelativeToSourceDir("Bar.php");
+    inputFile = new DeprecatedDefaultInputFile("foo/Bar.php").setPathRelativeToSourceDir("Bar.php");
     assertThat(predicate.apply(inputFile)).isFalse();
   }
 }
index 4ae7bf09d6c7e16d9b03901c3dd66bcc38bb0a4a..122b9c618deb6a69d684476f3dca3aac3d472afa 100644 (file)
@@ -33,6 +33,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.config.Settings;
 import org.sonar.api.resources.AbstractLanguage;
 import org.sonar.api.resources.Java;
@@ -160,8 +161,9 @@ public class ComponentIndexerTest {
 
     File javaFile1 = new File(baseDir, "src/main/java/foo/bar/Foo.java");
     FileUtils.write(javaFile1, "\uFEFFpublic class Test", Charsets.UTF_8);
-    fs.add(new DefaultInputFile("src/main/java/foo/bar/Foo.java").setFile(javaFile1)
+    fs.add(new DeprecatedDefaultInputFile("src/main/java/foo/bar/Foo.java")
       .setPathRelativeToSourceDir("foo/bar/Foo.java")
+      .setFile(javaFile1)
       .setLanguage("java"));
     Languages languages = new Languages(Java.INSTANCE);
     ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class));
@@ -184,9 +186,9 @@ public class ComponentIndexerTest {
 
     File javaFile1 = new File(baseDir, "src/main/java/foo/bar/Foo.java");
     FileUtils.copyFile(getFile(testFile), javaFile1);
-    fs.add(new DefaultInputFile("src/main/java/foo/bar/Foo.java")
-      .setFile(javaFile1)
+    fs.add(new DeprecatedDefaultInputFile("src/main/java/foo/bar/Foo.java")
       .setPathRelativeToSourceDir("foo/bar/Foo.java")
+      .setFile(javaFile1)
       .setLanguage("java"));
     Languages languages = new Languages(Java.INSTANCE);
     ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class));
@@ -210,8 +212,9 @@ public class ComponentIndexerTest {
   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 DefaultInputFile(path).setFile(file)
+    return new DeprecatedDefaultInputFile(path)
       .setPathRelativeToSourceDir(sourceRelativePath)
+      .setFile(file)
       .setLanguage(languageKey)
       .setType(unitTest ? InputFile.Type.TEST : InputFile.Type.MAIN);
   }
index 594a777095d6f0bc068adc317be53c8eb9ab6b08..0de8ac80c56811e08a0d8ef5d102d0efee54b187 100644 (file)
@@ -26,8 +26,9 @@ import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.mockito.Mockito;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.config.Settings;
 import org.sonar.api.resources.Project;
 
@@ -58,13 +59,13 @@ public class DefaultModuleFileSystemTest {
 
   @Test
   public void test_equals_and_hashCode() throws Exception {
-    DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem(moduleInputFileCache,
+    DefaultModuleFileSystem foo1 = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
-    DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem(moduleInputFileCache,
+    DefaultModuleFileSystem foo2 = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
-    DefaultModuleFileSystem bar = new DefaultModuleFileSystem(moduleInputFileCache,
+    DefaultModuleFileSystem bar = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("bar"), settings, fileIndexer, initializer, componentIndexer);
-    DefaultModuleFileSystem branch = new DefaultModuleFileSystem(moduleInputFileCache,
+    DefaultModuleFileSystem branch = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("bar", "branch", "My project"), settings, fileIndexer, initializer, componentIndexer);
 
     assertThat(foo1.moduleKey()).isEqualTo("foo");
@@ -79,7 +80,7 @@ public class DefaultModuleFileSystemTest {
 
   @Test
   public void default_source_encoding() {
-    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
 
     assertThat(fs.sourceCharset()).isEqualTo(Charset.defaultCharset());
@@ -89,7 +90,7 @@ public class DefaultModuleFileSystemTest {
   @Test
   public void source_encoding_is_set() {
     settings.setProperty(CoreProperties.ENCODING_PROPERTY, "Cp1124");
-    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
 
     assertThat(fs.encoding()).isEqualTo(Charset.forName("Cp1124"));
@@ -115,7 +116,7 @@ public class DefaultModuleFileSystemTest {
     when(initializer.additionalSourceFiles()).thenReturn(Arrays.asList(additionalFile));
     when(initializer.additionalTestFiles()).thenReturn(Arrays.asList(additionalTest));
 
-    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
 
     assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
@@ -135,7 +136,7 @@ public class DefaultModuleFileSystemTest {
     when(initializer.workingDir()).thenReturn(basedir);
     when(initializer.sourceDirs()).thenReturn(Arrays.asList(new File(basedir, "src/main/java")));
 
-    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
 
     File existingDir = temp.newFolder("new_folder");
@@ -156,12 +157,12 @@ public class DefaultModuleFileSystemTest {
 
   @Test
   public void should_search_input_files() throws Exception {
-    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
 
     File mainFile = temp.newFile();
-    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);
+    InputFile mainInput = new DeprecatedDefaultInputFile("Main.java").setFile(mainFile).setType(InputFile.Type.MAIN);
+    InputFile testInput = new DeprecatedDefaultInputFile("Test.java").setFile(temp.newFile()).setType(InputFile.Type.TEST);
     when(moduleInputFileCache.inputFiles()).thenReturn(Lists.newArrayList(mainInput, testInput));
 
     fs.index();
@@ -174,7 +175,7 @@ public class DefaultModuleFileSystemTest {
 
   @Test
   public void should_index() throws Exception {
-    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache,
+    DefaultModuleFileSystem fs = new DefaultModuleFileSystem(moduleInputFileCache, ProjectDefinition.create(),
       new Project("foo"), settings, fileIndexer, initializer, componentIndexer);
 
     verifyZeroInteractions(fileIndexer);
index cc909035c1ac813c7a16278c98a24ff91c852abd..02f314e6b719dbba3340187df987ca9b1fe2d94e 100644 (file)
@@ -25,7 +25,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.scan.filesystem.FileSystemFilter;
 import org.sonar.api.scan.filesystem.FileType;
 
@@ -34,7 +34,9 @@ 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.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 public class DeprecatedFileFiltersTest {
 
@@ -47,7 +49,7 @@ public class DeprecatedFileFiltersTest {
   public void no_filters() throws Exception {
     DeprecatedFileFilters filters = new DeprecatedFileFilters();
 
-    InputFile inputFile = new DefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile());
+    InputFile inputFile = new DeprecatedDefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile());
     assertThat(filters.accept(inputFile)).isTrue();
   }
 
@@ -57,11 +59,11 @@ public class DeprecatedFileFiltersTest {
 
     File basedir = temp.newFolder();
     File file = temp.newFile();
-    InputFile inputFile = new DefaultInputFile("src/main/java/Foo.java")
-      .setFile(file)
-      .setType(InputFile.Type.MAIN)
+    InputFile inputFile = new DeprecatedDefaultInputFile("src/main/java/Foo.java")
       .setSourceDirAbsolutePath(new File(basedir, "src/main/java").getAbsolutePath())
-      .setPathRelativeToSourceDir("Foo.java");
+      .setPathRelativeToSourceDir("Foo.java")
+      .setFile(file)
+      .setType(InputFile.Type.MAIN);
     when(filter.accept(eq(file), any(DeprecatedFileFilters.DeprecatedContext.class))).thenReturn(false);
 
     assertThat(filters.accept(inputFile)).isFalse();
index d84fdce8563e1e40920f5d00f25a9e28664b1668..6255bd6629b9775ebd48baa6be6d175d999d30d6 100644 (file)
@@ -63,7 +63,6 @@ public class ExclusionFiltersTest {
     assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isFalse();
   }
 
-
   @Test
   public void match_at_least_one_inclusion() throws IOException {
     Settings settings = new Settings();
index 268f007e1b9f02d10f97f02c87a7e39f713d8ae7..e38081b62be0bcdcc833744385cbf3d04674584d 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.batch.scan.filesystem;
 
 import org.junit.Test;
 import org.mockito.Mockito;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.resources.Project;
 import org.sonar.api.scan.filesystem.PathResolver;
 import org.sonar.batch.bootstrap.AnalysisMode;
@@ -39,7 +40,7 @@ public class InputFileBuilderFactoryTest {
     AnalysisMode analysisMode = mock(AnalysisMode.class);
 
     InputFileBuilderFactory factory = new InputFileBuilderFactory(
-      project, pathResolver, langDetectionFactory,
+      project, ProjectDefinition.create(), pathResolver, langDetectionFactory,
       statusDetectionFactory, analysisMode);
     InputFileBuilder builder = factory.create(fs);
 
index 5193101ff3879c61702fce57a4f1f7515b3d7426..067f1f99d5899407faaacd680db52c74c6d8d9d2 100644 (file)
@@ -25,7 +25,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.scan.filesystem.PathResolver;
 import org.sonar.api.utils.PathUtils;
 import org.sonar.batch.bootstrap.AnalysisMode;
@@ -67,7 +67,7 @@ public class InputFileBuilderTest {
 
     InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
       langDetection, statusDetection, fs, analysisMode);
-    DefaultInputFile inputFile = builder.create(srcFile);
+    DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
     inputFile = builder.complete(inputFile, InputFile.Type.MAIN);
 
     assertThat(inputFile.type()).isEqualTo(InputFile.Type.MAIN);
@@ -93,7 +93,7 @@ public class InputFileBuilderTest {
 
     InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
       langDetection, statusDetection, fs, analysisMode);
-    DefaultInputFile inputFile = builder.create(srcFile);
+    DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
 
     assertThat(inputFile).isNull();
   }
@@ -113,7 +113,7 @@ public class InputFileBuilderTest {
 
     InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
       langDetection, statusDetection, fs, analysisMode);
-    DefaultInputFile inputFile = builder.create(srcFile);
+    DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
     inputFile = builder.complete(inputFile, InputFile.Type.MAIN);
 
     assertThat(inputFile).isNull();
@@ -140,7 +140,7 @@ public class InputFileBuilderTest {
 
     InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
       langDetection, statusDetection, fs, analysisMode);
-    DefaultInputFile inputFile = builder.create(srcFile);
+    DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
     inputFile = builder.complete(inputFile, InputFile.Type.MAIN);
 
     assertThat(inputFile.pathRelativeToSourceDir()).isEqualTo("foo/Bar.java");
@@ -169,7 +169,7 @@ public class InputFileBuilderTest {
 
     InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
       langDetection, statusDetection, fs, analysisMode);
-    DefaultInputFile inputFile = builder.create(srcFile);
+    DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
     inputFile = builder.complete(inputFile, InputFile.Type.MAIN);
 
     assertThat(inputFile.pathRelativeToSourceDir()).isEqualTo("foo/Bar.php");
index 1dedd839828c8e4a079ce337cd227d359dd1bae2..3da4eeba2c0da4ad9209a357323bf46c0d824e32 100644 (file)
@@ -26,12 +26,11 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.RelativePathIndex;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.batch.index.Caches;
 import org.sonar.batch.index.CachesTest;
 
 import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
 
 public class InputFileCacheTest {
 
@@ -56,10 +55,9 @@ public class InputFileCacheTest {
     InputFileCache cache = new InputFileCache(caches);
     DefaultInputFile fooFile = new DefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile("Foo.java"));
     cache.put("struts", fooFile);
-    cache.put("struts-core", new DefaultInputFile("src/main/java/Bar.java").setFile(temp.newFile("Bar.java")));
+    cache.put("struts-core", new DeprecatedDefaultInputFile("src/main/java/Bar.java").setFile(temp.newFile("Bar.java")));
 
-    // index by relative path is automatically fed
-    assertThat(cache.get("struts", RelativePathIndex.ID, "src/main/java/Foo.java").relativePath())
+    assertThat(cache.get("struts", "src/main/java/Foo.java").relativePath())
       .isEqualTo("src/main/java/Foo.java");
 
     assertThat(cache.byModule("struts")).hasSize(1);
@@ -78,23 +76,4 @@ public class InputFileCacheTest {
     assertThat(cache.all()).hasSize(1);
   }
 
-  @Test
-  public void only_relative_path_index_is_supported() throws Exception {
-    InputFileCache cache = new InputFileCache(caches);
-    DefaultInputFile input = new DefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile("Foo.java"));
-
-    try {
-      cache.index("struts", "unsupported-index", "index-value", input);
-      fail();
-    } catch (UnsupportedOperationException e) {
-      assertThat(e).hasMessage("Only relative path index is supported yet");
-    }
-
-    try {
-      cache.get("struts", "unsupported-index", "index-value");
-      fail();
-    } catch (UnsupportedOperationException e) {
-      assertThat(e).hasMessage("Only relative path index is supported yet");
-    }
-  }
 }
index 35d09f661d6ae80c97afa0be777892b1e5b03596..cda01e168810100e5e2aac561ec7885bef94de4c 100644 (file)
@@ -23,13 +23,15 @@ import org.junit.Test;
 import org.sonar.api.config.Settings;
 import org.sonar.api.resources.Java;
 import org.sonar.api.resources.Languages;
+import org.sonar.batch.languages.DeprecatedLanguagesReferential;
+import org.sonar.batch.languages.LanguagesReferential;
 
 import static org.fest.assertions.Assertions.assertThat;
 
 public class LanguageDetectionFactoryTest {
   @Test
   public void testCreate() throws Exception {
-    Languages languages = new Languages(Java.INSTANCE);
+    LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(Java.INSTANCE));
     LanguageDetectionFactory factory = new LanguageDetectionFactory(new Settings(), languages);
     LanguageDetection languageDetection = factory.create();
     assertThat(languageDetection).isNotNull();
index f1500b541c2b56f2d310b5086983d23461fc3b41..7c6eb7ff4f2a5b269244a00b5c31a02d6a33b26f 100644 (file)
@@ -30,6 +30,8 @@ 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.batch.languages.DeprecatedLanguagesReferential;
+import org.sonar.batch.languages.LanguagesReferential;
 
 import java.io.File;
 import java.io.IOException;
@@ -56,7 +58,7 @@ public class LanguageDetectionTest {
 
   @Test
   public void search_by_file_extension() throws Exception {
-    Languages languages = new Languages(new MockLanguage("java", "java", "jav"), new MockLanguage("cobol", "cbl", "cob"));
+    LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("java", "java", "jav"), new MockLanguage("cobol", "cbl", "cob")));
     LanguageDetection detection = new LanguageDetection(new Settings(), languages);
 
     assertThat(detection.language(newInputFile("Foo.java"))).isEqualTo("java");
@@ -74,13 +76,13 @@ public class LanguageDetectionTest {
 
   @Test
   public void should_not_fail_if_no_language() throws Exception {
-    LanguageDetection detection = spy(new LanguageDetection(new Settings(), new Languages()));
+    LanguageDetection detection = spy(new LanguageDetection(new Settings(), new DeprecatedLanguagesReferential(new Languages())));
     assertThat(detection.language(newInputFile("Foo.java"))).isNull();
   }
 
   @Test
   public void plugin_can_declare_a_file_extension_twice_for_case_sensitivity() throws Exception {
-    Languages languages = new Languages(new MockLanguage("abap", "abap", "ABAP"));
+    LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("abap", "abap", "ABAP")));
 
     LanguageDetection detection = new LanguageDetection(new Settings(), languages);
     assertThat(detection.language(newInputFile("abc.abap"))).isEqualTo("abap");
@@ -90,7 +92,7 @@ public class LanguageDetectionTest {
   public void language_with_no_extension() throws Exception {
     // abap does not declare any file extensions.
     // When analyzing an ABAP project, then all source files must be parsed.
-    Languages languages = new Languages(new MockLanguage("java", "java"), new MockLanguage("abap"));
+    LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("java", "java"), new MockLanguage("abap")));
 
     // No side-effect on non-ABAP projects
     LanguageDetection detection = new LanguageDetection(new Settings(), languages);
@@ -108,7 +110,7 @@ public class LanguageDetectionTest {
 
   @Test
   public void force_language_using_deprecated_property() throws Exception {
-    Languages languages = new Languages(new MockLanguage("java", "java"), new MockLanguage("php", "php"));
+    LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("java", "java"), new MockLanguage("php", "php")));
 
     Settings settings = new Settings();
     settings.setProperty(CoreProperties.PROJECT_LANGUAGE_PROPERTY, "java");
@@ -124,7 +126,7 @@ public class LanguageDetectionTest {
     thrown.expect(MessageException.class);
     thrown.expectMessage("No language is installed with key 'unknown'. Please update property 'sonar.language'");
 
-    Languages languages = new Languages(new MockLanguage("java", "java"), new MockLanguage("php", "php"));
+    LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("java", "java"), new MockLanguage("php", "php")));
     Settings settings = new Settings();
     settings.setProperty(CoreProperties.PROJECT_LANGUAGE_PROPERTY, "unknown");
     new LanguageDetection(settings, languages);
@@ -132,7 +134,7 @@ public class LanguageDetectionTest {
 
   @Test
   public void fail_if_conflicting_language_suffix() throws Exception {
-    Languages languages = new Languages(new MockLanguage("xml", "xhtml"), new MockLanguage("web", "xhtml"));
+    LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("xml", "xhtml"), new MockLanguage("web", "xhtml")));
     LanguageDetection detection = new LanguageDetection(new Settings(), languages);
     try {
       detection.language(newInputFile("abc.xhtml"));
@@ -147,7 +149,7 @@ public class LanguageDetectionTest {
 
   @Test
   public void solve_conflict_using_filepattern() throws Exception {
-    Languages languages = new Languages(new MockLanguage("xml", "xhtml"), new MockLanguage("web", "xhtml"));
+    LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("xml", "xhtml"), new MockLanguage("web", "xhtml")));
 
     Settings settings = new Settings();
     settings.setProperty("sonar.lang.patterns.xml", "xml/**");
@@ -159,7 +161,7 @@ public class LanguageDetectionTest {
 
   @Test
   public void fail_if_conflicting_filepattern() throws Exception {
-    Languages languages = new Languages(new MockLanguage("abap", "abap"), new MockLanguage("cobol", "cobol"));
+    LanguagesReferential languages = new DeprecatedLanguagesReferential(new Languages(new MockLanguage("abap", "abap"), new MockLanguage("cobol", "cobol")));
     Settings settings = new Settings();
     settings.setProperty("sonar.lang.patterns.abap", "*.abap,*.txt");
     settings.setProperty("sonar.lang.patterns.cobol", "*.cobol,*.txt");
index c232c3344f5e47ec049d87ff0060f94d200f7c96..6f4f306a0c5ee59ab38528a75c2a5c88a66547b1 100644 (file)
@@ -29,7 +29,7 @@ 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.batch.fs.internal.DeprecatedDefaultInputFile;
 import org.sonar.api.config.Settings;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.issue.internal.DefaultIssue;
@@ -85,7 +85,7 @@ public class JsonReportTest {
     mode = mock(AnalysisMode.class);
     when(mode.isPreview()).thenReturn(true);
     userFinder = mock(UserFinder.class);
-    DefaultInputFile inputFile = new DefaultInputFile("src/main/java/org/apache/struts/Action.java");
+    DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("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);
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/medium/simple-project/sonar-project.properties b/sonar-batch/src/test/resources/org/sonar/batch/medium/simple-project/sonar-project.properties
new file mode 100644 (file)
index 0000000..69ccd8d
--- /dev/null
@@ -0,0 +1,7 @@
+sonar.projectKey=com.foo.project
+sonar.projectName=Foo Project
+sonar.projectVersion=1.0-SNAPSHOT
+sonar.projectDescription=Description of Foo Project
+
+sonar.sources=sources
+sonar.libraries=libs/*.txt
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/medium/simple-project/sources/Fake.java b/sonar-batch/src/test/resources/org/sonar/batch/medium/simple-project/sources/Fake.java
new file mode 100644 (file)
index 0000000..b2e6462
--- /dev/null
@@ -0,0 +1 @@
+Fake
index 25d1a66d4b5ae741612cf48397e935da08db15ff..ed2e5abdd7f463731cd46065969d2f41f2f84688 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.core.component;
 
 import org.apache.commons.lang.StringUtils;
+import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.database.model.ResourceModel;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
@@ -63,6 +64,15 @@ public final class ComponentKeys {
     return key;
   }
 
+  public static String createEffectiveKey(String projectKey, InputFile inputFile) {
+    // not a project nor a library
+    return new StringBuilder(ResourceModel.KEY_SIZE)
+      .append(projectKey)
+      .append(':')
+      .append(inputFile.relativePath())
+      .toString();
+  }
+
   /**
    * <p>Test if given parameter is valid for a project/module. Valid format is:</p>
    * <ul>
index bc1deda33bb2ca674e42339d765e4b665a456749..c951512e8f6b269d2fc15d448556648d96a1704e 100644 (file)
@@ -30,11 +30,13 @@ import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
 import org.sonar.api.utils.AnnotationUtils;
 import org.sonar.api.utils.dag.DirectAcyclicGraph;
+import org.sonar.batch.api.analyzer.Analyzer;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Array;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
@@ -66,7 +68,7 @@ public class BatchExtensionDictionnary {
 
   public Collection<MavenPluginHandler> selectMavenPluginHandlers(Project project) {
     List<DependsUponMavenPlugin> selectedExtensions = Lists.newArrayList();
-    for (BatchExtension extension : getExtensions()) {
+    for (Object extension : getExtensions()) {
       if (ClassUtils.isAssignable(extension.getClass(), DependsUponMavenPlugin.class)) {
         selectedExtensions.add((DependsUponMavenPlugin) extension);
       }
@@ -88,22 +90,23 @@ public class BatchExtensionDictionnary {
     return handlers;
   }
 
-  protected List<BatchExtension> getExtensions() {
-    List<BatchExtension> extensions = Lists.newArrayList();
+  protected List<Object> getExtensions() {
+    List<Object> extensions = Lists.newArrayList();
     completeBatchExtensions(componentContainer, extensions);
     return extensions;
   }
 
-  private static void completeBatchExtensions(ComponentContainer container, List<BatchExtension> extensions) {
+  private static void completeBatchExtensions(ComponentContainer container, List<Object> extensions) {
     if (container != null) {
       extensions.addAll(container.getComponentsByType(BatchExtension.class));
+      extensions.addAll(container.getComponentsByType(org.sonar.batch.api.BatchExtension.class));
       completeBatchExtensions(container.getParent(), extensions);
     }
   }
 
   private <T> List<T> getFilteredExtensions(Class<T> type, Project project) {
     List<T> result = Lists.newArrayList();
-    for (BatchExtension extension : getExtensions()) {
+    for (Object extension : getExtensions()) {
       if (shouldKeep(type, extension, project)) {
         result.add((T) extension);
       }
@@ -140,15 +143,25 @@ public class BatchExtensionDictionnary {
   /**
    * Extension dependencies
    */
-  private <T> List getDependencies(T extension) {
-    return evaluateAnnotatedClasses(extension, DependsUpon.class);
+  private <T> List<Object> getDependencies(T extension) {
+    List<Object> result = new ArrayList<Object>();
+    result.addAll(evaluateAnnotatedClasses(extension, DependsUpon.class));
+    if (ClassUtils.isAssignable(extension.getClass(), Analyzer.class)) {
+      result.addAll(Arrays.asList(((Analyzer) extension).describe().dependsOn()));
+    }
+    return result;
   }
 
   /**
    * Objects that depend upon this extension.
    */
-  public <T> List getDependents(T extension) {
-    return evaluateAnnotatedClasses(extension, DependedUpon.class);
+  public <T> List<Object> getDependents(T extension) {
+    List<Object> result = new ArrayList<Object>();
+    result.addAll(evaluateAnnotatedClasses(extension, DependedUpon.class));
+    if (ClassUtils.isAssignable(extension.getClass(), Analyzer.class)) {
+      result.addAll(Arrays.asList(((Analyzer) extension).describe().provides()));
+    }
+    return result;
   }
 
   private void completePhaseDependencies(DirectAcyclicGraph dag, Object extension) {
@@ -163,7 +176,7 @@ public class BatchExtensionDictionnary {
     }
   }
 
-  protected List evaluateAnnotatedClasses(Object extension, Class<? extends Annotation> annotation) {
+  protected List<Object> evaluateAnnotatedClasses(Object extension, Class<? extends Annotation> annotation) {
     List<Object> results = Lists.newArrayList();
     Class aClass = extension.getClass();
     while (aClass != null) {
index 09d12366d3f48a86c2056ceca71bd6bbdbedfc24..165e9fc5eafd5cbd1554c70b520a595d87109d4c 100644 (file)
       <groupId>org.codehaus.sonar</groupId>
       <artifactId>sonar-check-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.codehaus.sonar</groupId>
+      <artifactId>sonar-batch-plugin-api</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.codehaus.sonar</groupId>
       <artifactId>sonar-colorizer</artifactId>
index dcd215cd4c7560cfffca5d28c68ad3c89087196b..5cfea413fc54cc35af2fcd212ab11a10e6529d5d 100644 (file)
@@ -27,6 +27,7 @@ import java.lang.annotation.Target;
 /**
  * Define instantiation strategy of batch extensions. If an extension is not annotated, then default value
  * is {@link org.sonar.api.batch.InstantiationStrategy#PER_PROJECT}.
+ * @since 4.4
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
index bbe0af3c3d2eb567d778102ecf05e2abea00d96c..ccdec2dbf2f69cfc30377749dd565cc53c22f9ba 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.api.rules.Violation;
 
 import javax.annotation.CheckForNull;
 
+import java.io.Serializable;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
@@ -104,7 +105,7 @@ public interface SensorContext {
   /**
    * Find a project measure
    */
-  Measure getMeasure(Metric metric);
+  <G extends Serializable> Measure<G> getMeasure(Metric<G> metric);
 
   /**
    * All measures of the project. Never return null.
@@ -126,7 +127,7 @@ public interface SensorContext {
   /**
    * Find a measure for this project
    */
-  Measure getMeasure(Resource resource, Metric metric);
+  <G extends Serializable> Measure<G> getMeasure(Resource resource, Metric<G> metric);
 
   /**
    * Key is updated when saving the resource.
index 4eb61021ca55b4d1d3de6f50bde66d6a05ae6caa..1be238923aeb8674b56cfdb67fe4904ad2879640 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.api.batch;
 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.Project;
 import org.sonar.api.resources.ProjectLink;
 import org.sonar.api.resources.Resource;
@@ -121,7 +120,7 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe
   public abstract Resource addResource(Resource resource);
 
   @CheckForNull
-  public abstract Measure getMeasure(Resource resource, Metric metric);
+  public abstract Measure getMeasure(Resource resource, org.sonar.batch.api.measures.Metric<?> metric);
 
   @CheckForNull
   public abstract <M> M getMeasures(Resource resource, MeasuresFilter<M> filter);
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
deleted file mode 100644 (file)
index 830859e..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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
deleted file mode 100644 (file)
index dd9f148..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.util.Collection;
-
-/**
- * Factory of {@link org.sonar.api.batch.fs.FilePredicate}
- *
- * @since 4.2
- */
-public interface FilePredicates {
-  /**
-   * Returns a predicate that always evaluates to true
-   */
-  FilePredicate all();
-
-  /**
-   * Returns a predicate that always evaluates to false
-   */
-  FilePredicate none();
-
-  /**
-   * Warning - not efficient because absolute path is not indexed yet.
-   */
-  FilePredicate hasAbsolutePath(String s);
-
-  /**
-   * TODO document that non-normalized path and Windows-style path are supported
-   */
-  FilePredicate hasRelativePath(String s);
-
-  FilePredicate matchesPathPattern(String inclusionPattern);
-
-  FilePredicate matchesPathPatterns(String[] inclusionPatterns);
-
-  FilePredicate doesNotMatchPathPattern(String exclusionPattern);
-
-  FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns);
-
-  FilePredicate hasPath(String s);
-
-  FilePredicate is(File ioFile);
-
-  FilePredicate hasLanguage(String language);
-
-  FilePredicate hasLanguages(Collection<String> languages);
-
-  FilePredicate hasStatus(InputFile.Status status);
-
-  FilePredicate hasType(InputFile.Type type);
-
-  FilePredicate not(FilePredicate p);
-
-  FilePredicate or(Collection<FilePredicate> or);
-
-  FilePredicate or(FilePredicate... or);
-
-  FilePredicate or(FilePredicate first, FilePredicate second);
-
-  FilePredicate and(Collection<FilePredicate> and);
-
-  FilePredicate and(FilePredicate... and);
-
-  FilePredicate and(FilePredicate first, FilePredicate second);
-
-}
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
deleted file mode 100644 (file)
index 5172eb8..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.SortedSet;
-
-/**
- * The {@link FileSystem} manages all the source files to be analyzed.
- * <p/>
- * This is not an extension point so it must not be implemented by plugins. It must be injected as a
- * constructor parameter :
- * <pre>
- * public class MySensor implements Sensor {
- *   private final FileSystem fs;
- *
- *   public MySensor(FileSystem fs) {
- *     this.fs = fs;
- *   }
- * }
- * </pre>
- *
- * <h2>How to use in unit tests</h2>
- * 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.batch.fs.internal.DefaultInputFile},
- * for example :
- * <pre>
- * DefaultFileSystem 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();
-
-  /**
-   * Factory of {@link FilePredicate}
-   */
-  FilePredicates predicates();
-
-  /**
-   * Returns the single element matching the predicate. If more than one elements match
-   * the predicate, then {@link IllegalArgumentException} is thrown. Returns {@code null}
-   * if no files match.
-   *
-   * <p/>
-   * How to use :
-   * <pre>
-   * InputFile file = fs.inputFile(fs.predicates().hasRelativePath("src/Foo.php"));
-   * </pre>
-   *
-   * @see #predicates()
-   */
-  @CheckForNull
-  InputFile inputFile(FilePredicate predicate);
-
-  /**
-   * Input files matching the given attributes. Return all the files if the parameter
-   * <code>attributes</code> is empty.
-   * <p/>
-   * <b>Important</b> - result is an {@link java.lang.Iterable} to benefit from streaming and decreasing
-   * memory consumption. It should be iterated only once, else copy it into a list :
-   * {@code com.google.common.collect.Lists.newArrayList(inputFiles(predicate))}
-   * <p/>
-   * How to use :
-   * <pre>
-   * FilePredicates p = fs.predicates();
-   * Iterable<InputFile> files = fs.inputFiles(p.and(p.hasLanguage("java"), p.hasType(InputFile.Type.MAIN)));
-   * </pre>
-   *
-   * @see #predicates()
-   */
-  Iterable<InputFile> inputFiles(FilePredicate predicate);
-
-  /**
-   * Returns true if at least one {@link org.sonar.api.batch.fs.InputFile} matches
-   * the given predicate. This method can be faster than checking if {@link #inputFiles(org.sonar.api.batch.fs.FilePredicate)}
-   * has elements.
-   * @see #predicates()
-   */
-  boolean hasFiles(FilePredicate predicate);
-
-  /**
-   * Files matching the given predicate.
-   * @see #predicates()
-   */
-  Iterable<File> files(FilePredicate predicate);
-
-  /**
-   * Languages detected in all files, whatever their type (main or test)
-   */
-  SortedSet<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
deleted file mode 100644 (file)
index e4728a4..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 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>/path/to/module</code> and if file is
-   * <code>/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 if it is not
-   * set in project settings.
-   */
-  String language();
-
-  /**
-   * Does it contain main or test code ?
-   */
-  Type type();
-
-  /**
-   * Status regarding previous analysis
-   */
-  Status status();
-
-  /**
-   * Number of physical lines. This method supports all end-of-line characters. Returns
-   * zero if the file is empty.
-   */
-  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
deleted file mode 100644 (file)
index 1ece508..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 exclude some files from 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/internal/AbsolutePathPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java
deleted file mode 100644 (file)
index 8e943a0..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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/internal/AndPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java
deleted file mode 100644 (file)
index 0494ed5..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-import java.util.Collection;
-
-/**
- * @since 4.2
- */
-class AndPredicate implements FilePredicate {
-
-  private final Collection<FilePredicate> predicates;
-
-  AndPredicate(Collection<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/internal/DefaultFilePredicates.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java
deleted file mode 100644 (file)
index 52bb75a..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.Lists;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FilePredicates;
-import org.sonar.api.batch.fs.InputFile;
-
-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 DefaultFilePredicates implements FilePredicates {
-  /**
-   * Client code should use {@link org.sonar.api.batch.fs.FileSystem#predicates()} to get an instance
-   */
-  DefaultFilePredicates() {
-  }
-
-  /**
-   * Returns a predicate that always evaluates to true
-   */
-  public FilePredicate all() {
-    return TruePredicate.TRUE;
-  }
-
-  /**
-   * Returns a predicate that always evaluates to false
-   */
-  public FilePredicate none() {
-    return FalsePredicate.FALSE;
-  }
-
-  /**
-   * Warning - not efficient because absolute path is not indexed yet.
-   */
-  public FilePredicate hasAbsolutePath(String s) {
-    return new AbsolutePathPredicate(s);
-  }
-
-  /**
-   * TODO document that non-normalized path and Windows-style path are supported
-   */
-  public FilePredicate hasRelativePath(String s) {
-    return new RelativePathPredicate(s);
-  }
-
-  public FilePredicate matchesPathPattern(String inclusionPattern) {
-    return new PathPatternPredicate(PathPattern.create(inclusionPattern));
-  }
-
-  public FilePredicate matchesPathPatterns(String[] inclusionPatterns) {
-    if (inclusionPatterns.length == 0) {
-      return TruePredicate.TRUE;
-    }
-    FilePredicate[] predicates = new FilePredicate[inclusionPatterns.length];
-    for (int i = 0; i < inclusionPatterns.length; i++) {
-      predicates[i] = new PathPatternPredicate(PathPattern.create(inclusionPatterns[i]));
-    }
-    return or(predicates);
-  }
-
-  public FilePredicate doesNotMatchPathPattern(String exclusionPattern) {
-    return not(matchesPathPattern(exclusionPattern));
-  }
-
-  public FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns) {
-    if (exclusionPatterns.length == 0) {
-      return TruePredicate.TRUE;
-    }
-    return not(matchesPathPatterns(exclusionPatterns));
-  }
-
-  public FilePredicate hasPath(String s) {
-    File file = new File(s);
-    if (file.isAbsolute()) {
-      return hasAbsolutePath(s);
-    }
-    return hasRelativePath(s);
-  }
-
-  public FilePredicate is(File ioFile) {
-    if (ioFile.isAbsolute()) {
-      return hasAbsolutePath(ioFile.getAbsolutePath());
-    }
-    return hasRelativePath(ioFile.getPath());
-  }
-
-  public FilePredicate hasLanguage(String language) {
-    return new LanguagePredicate(language);
-  }
-
-  public FilePredicate hasLanguages(Collection<String> languages) {
-    List<FilePredicate> list = Lists.newArrayList();
-    for (String language : languages) {
-      list.add(hasLanguage(language));
-    }
-    return or(list);
-  }
-
-  public FilePredicate hasStatus(InputFile.Status status) {
-    return new StatusPredicate(status);
-  }
-
-  public FilePredicate hasType(InputFile.Type type) {
-    return new TypePredicate(type);
-  }
-
-  public FilePredicate not(FilePredicate p) {
-    return new NotPredicate(p);
-  }
-
-  public FilePredicate or(Collection<FilePredicate> or) {
-    return new OrPredicate(or);
-  }
-
-  public FilePredicate or(FilePredicate... or) {
-    return new OrPredicate(Arrays.asList(or));
-  }
-
-  public FilePredicate or(FilePredicate first, FilePredicate second) {
-    return new OrPredicate(Arrays.asList(first, second));
-  }
-
-  public FilePredicate and(Collection<FilePredicate> and) {
-    return new AndPredicate(and);
-  }
-
-  public FilePredicate and(FilePredicate... and) {
-    return new AndPredicate(Arrays.asList(and));
-  }
-
-  public FilePredicate and(FilePredicate first, FilePredicate second) {
-    return new AndPredicate(Arrays.asList(first, second));
-  }
-}
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
deleted file mode 100644 (file)
index 3a97f46..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FilePredicates;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import java.io.File;
-import java.nio.charset.Charset;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.SortedSet;
-
-/**
- * @since 4.2
- */
-public class DefaultFileSystem implements FileSystem {
-
-  private final Cache cache;
-  private final SortedSet<String> languages = Sets.newTreeSet();
-  private File baseDir, workDir;
-  private Charset encoding;
-  private final FilePredicates predicates = new DefaultFilePredicates();
-
-  /**
-   * 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;
-  }
-
-  @Override
-  public File baseDir() {
-    return baseDir;
-  }
-
-  public DefaultFileSystem setEncoding(@Nullable Charset e) {
-    this.encoding = e;
-    return this;
-  }
-
-  @Override
-  public Charset encoding() {
-    return encoding == null ? Charset.defaultCharset() : encoding;
-  }
-
-  public boolean isDefaultJvmEncoding() {
-    return encoding == null;
-  }
-
-  public DefaultFileSystem setWorkDir(File d) {
-    this.workDir = d.getAbsoluteFile();
-    return this;
-  }
-
-  @Override
-  public File workDir() {
-    return workDir;
-  }
-
-  @Override
-  public InputFile inputFile(FilePredicate predicate) {
-    doPreloadFiles();
-    if (predicate instanceof UniqueIndexPredicate) {
-      return cache.inputFile((UniqueIndexPredicate) predicate);
-    }
-    try {
-      Iterable<InputFile> files = inputFiles(predicate);
-      return Iterables.getOnlyElement(files);
-    } catch (NoSuchElementException e) {
-      // contrary to guava, return null if iterable is empty
-      return null;
-    }
-  }
-
-  @Override
-  public Iterable<InputFile> inputFiles(FilePredicate predicate) {
-    doPreloadFiles();
-    return Iterables.filter(cache.inputFiles(), new GuavaPredicate(predicate));
-  }
-
-  @Override
-  public boolean hasFiles(FilePredicate predicate) {
-    doPreloadFiles();
-    return Iterables.indexOf(cache.inputFiles(), new GuavaPredicate(predicate)) >= 0;
-  }
-
-  @Override
-  public Iterable<File> files(FilePredicate predicate) {
-    doPreloadFiles();
-    return Iterables.transform(inputFiles(predicate), new Function<InputFile, File>() {
-      @Override
-      public File apply(@Nullable InputFile input) {
-        return input == null ? null : input.file();
-      }
-    });
-  }
-
-  /**
-   * Adds InputFile to the list and registers its language, if present.
-   */
-  public DefaultFileSystem add(InputFile inputFile) {
-    cache.add(inputFile);
-    if (inputFile.language() != null) {
-      languages.add(inputFile.language());
-    }
-    return this;
-  }
-
-  /**
-   * Adds a language to the list. To be used only for unit tests that need to use {@link #languages()} without
-   * using {@link #add(org.sonar.api.batch.fs.InputFile)}.
-   */
-  public DefaultFileSystem addLanguages(String language, String... others) {
-    languages.add(language);
-    Collections.addAll(languages, others);
-    return this;
-  }
-
-  @Override
-  public SortedSet<String> languages() {
-    doPreloadFiles();
-    return languages;
-  }
-
-  @Override
-  public FilePredicates predicates() {
-    return predicates;
-  }
-
-  /**
-   * This method is called before each search of files.
-   */
-  protected void doPreloadFiles() {
-    // nothing to do by default
-  }
-
-  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
deleted file mode 100644 (file)
index 888ae7a..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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() {
-    if (absolutePath == null) {
-      throw new IllegalStateException("Can not return the java.io.File because absolute path is not set (see method setFile(java.io.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;
-  }
-
-  /**
-   * Digest hash of the file. 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;
-  }
-
-  /**
-   * Component key. It's 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 can be 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;
-  }
-
-  /**
-   * @deprecated in 4.2. Replaced by {@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 pathRelativeToSourceDir;
-  }
-
-  @Override
-  public InputStream getInputStream() throws FileNotFoundException {
-    return new BufferedInputStream(new FileInputStream(file()));
-  }
-
-  @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();
-  }
-
-  @Override
-  public String toString() {
-    return "[relative=" + relativePath + ", abs=" + absolutePath + "]";
-  }
-}
-
-
-
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java
new file mode 100644 (file)
index 0000000..fad4e6d
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.api.internal.FilenameUtils;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+/**
+ * @since 4.2
+ */
+public class DeprecatedDefaultInputFile extends DefaultInputFile implements org.sonar.api.resources.InputFile {
+
+  private String basedir;
+  private String deprecatedKey;
+  private String sourceDirAbsolutePath;
+  private String pathRelativeToSourceDir;
+
+  public DeprecatedDefaultInputFile(String relativePath) {
+    super(relativePath);
+  }
+
+  /**
+   * @deprecated in 4.2. Replaced by {@link org.sonar.api.batch.fs.FileSystem#baseDir()}
+   */
+  @Deprecated
+  @Override
+  public File getFileBaseDir() {
+    return new File(basedir);
+  }
+
+  public void setBasedir(File basedir) {
+    this.basedir = FilenameUtils.normalize(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 pathRelativeToSourceDir;
+  }
+
+  /**
+   * Key used before version 4.2. It can be different than {@link #key} on Java files.
+   */
+  public String deprecatedKey() {
+    return deprecatedKey;
+  }
+
+  public DeprecatedDefaultInputFile setDeprecatedKey(String s) {
+    this.deprecatedKey = s;
+    return this;
+  }
+
+  /**
+   * Used only for backward-compatibility. Meaningless since version 4.2.
+   */
+  public String sourceDirAbsolutePath() {
+    return sourceDirAbsolutePath;
+  }
+
+  public DeprecatedDefaultInputFile setSourceDirAbsolutePath(String s) {
+    this.sourceDirAbsolutePath = FilenameUtils.normalize(s);
+    return this;
+  }
+
+  /**
+   * Used only for backward-compatibility. Meaningless since version 4.2.
+   */
+
+  public String pathRelativeToSourceDir() {
+    return pathRelativeToSourceDir;
+  }
+
+  public DeprecatedDefaultInputFile setPathRelativeToSourceDir(String s) {
+    this.pathRelativeToSourceDir = FilenameUtils.normalize(s);
+    return this;
+  }
+
+  @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/FalsePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java
deleted file mode 100644 (file)
index b092f84..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-class FalsePredicate implements FilePredicate {
-
-  static final FilePredicate FALSE = new FalsePredicate();
-
-  @Override
-  public boolean apply(InputFile inputFile) {
-    return false;
-  }
-}
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
deleted file mode 100644 (file)
index 4c61809..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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/LanguagePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java
deleted file mode 100644 (file)
index 77d2f74..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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/internal/NotPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java
deleted file mode 100644 (file)
index 5f2359e..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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/internal/OrPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java
deleted file mode 100644 (file)
index a887c63..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-/**
- * @since 4.2
- */
-class OrPredicate implements FilePredicate {
-
-  private final Collection<FilePredicate> predicates;
-
-  OrPredicate(Collection<FilePredicate> predicates) {
-    if (predicates.isEmpty()) {
-      this.predicates = Arrays.asList(TruePredicate.TRUE);
-    } else {
-      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/internal/PathPattern.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java
deleted file mode 100644 (file)
index c1b53b6..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.WildcardPattern;
-
-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(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(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)) {
-          path = 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(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/PathPatternPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java
deleted file mode 100644 (file)
index c2402a4..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-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/internal/RelativePathIndex.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathIndex.java
deleted file mode 100644 (file)
index 33facf1..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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/RelativePathPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java
deleted file mode 100644 (file)
index 22aed6e..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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/internal/StatusPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java
deleted file mode 100644 (file)
index fe7c934..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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/internal/TruePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java
deleted file mode 100644 (file)
index ec2aebd..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-class TruePredicate implements FilePredicate {
-
-  static final FilePredicate TRUE = new TruePredicate();
-
-  @Override
-  public boolean apply(InputFile inputFile) {
-    return true;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java
deleted file mode 100644 (file)
index ac8b6d5..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @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/internal/UniqueIndexPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/UniqueIndexPredicate.java
deleted file mode 100644 (file)
index 8b7404d..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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;
-
-/**
- * @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/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java
deleted file mode 100644 (file)
index 8fac559..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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
deleted file mode 100644 (file)
index 197da99..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 025f27fc511ea8889ba496dbdc7f0c877abe3d27..f94a4345af23089d08a288a1fa510cdd5a4d35fb 100644 (file)
@@ -61,7 +61,7 @@ public final class CoreMetrics {
   public static String DOMAIN_TECHNICAL_DEBT = "Technical Debt";
 
   public static final String LINES_KEY = "lines";
-  public static final Metric LINES = new Metric.Builder(LINES_KEY, "Lines", Metric.ValueType.INT)
+  public static final Metric<Integer> LINES = new Metric.Builder(LINES_KEY, "Lines", Metric.ValueType.INT)
     .setDescription("Lines")
     .setDirection(Metric.DIRECTION_WORST)
     .setQualitative(false)
index 3d38e52aea8595344b9c4957a4f65fc0364b11fc..b6a90add399f9a62ac39ccefe015146ae6af7552 100644 (file)
@@ -38,7 +38,7 @@ import java.util.Date;
  *
  * @since 1.10
  */
-public class Measure implements Serializable {
+public class Measure<G extends Serializable> implements Serializable {
   private static final String INDEX_SHOULD_BE_IN_RANGE_FROM_1_TO_5 = "Index should be in range from 1 to 5";
 
   protected static final int MAX_TEXT_SIZE = 96;
@@ -49,7 +49,7 @@ public class Measure implements Serializable {
   public static final int DEFAULT_PRECISION = 1;
 
   protected String metricKey;
-  protected Metric metric;
+  protected Metric<G> metric;
   protected Double value;
   protected String data;
   protected String description;
@@ -237,6 +237,38 @@ public class Measure implements Serializable {
     return value;
   }
 
+  /**
+   * For internal use.
+   */
+  public G value() {
+    switch (getMetric().getType()) {
+      case BOOL:
+        return (G) Boolean.valueOf(1.0 == value);
+      case INT:
+      case MILLISEC:
+        return (G) Integer.valueOf(value.intValue());
+      case FLOAT:
+      case PERCENT:
+      case RATING:
+        return (G) value;
+      case STRING:
+      case LEVEL:
+      case DATA:
+      case DISTRIB:
+        return (G) getData();
+      case WORK_DUR:
+        return (G) Long.valueOf(value.longValue());
+      default:
+        if (getMetric().isNumericType()) {
+          return (G) getValue();
+        } else if (getMetric().isDataType()) {
+          return (G) getData();
+        } else {
+          throw new UnsupportedOperationException("Unsupported type :" + getMetric().getType());
+        }
+    }
+  }
+
   /**
    * @return the value of the measure as an int
    */
@@ -692,4 +724,5 @@ public class Measure implements Serializable {
   public String toString() {
     return ReflectionToStringBuilder.toString(this);
   }
+
 }
index f11a225e6686e7d3da552592626765b68917a2b2..c51973b79b79b96069e1197d1815216afe6809f2 100644 (file)
@@ -51,8 +51,8 @@ public final class MeasuresFilters {
     };
   }
 
-  public static MeasuresFilter<Measure> metric(final Metric metric) {
-    return metric(metric.getKey());
+  public static MeasuresFilter<Measure> metric(final org.sonar.batch.api.measures.Metric<?> metric) {
+    return metric(metric.key());
   }
 
   public static MeasuresFilter<Measure> metric(final String metricKey) {
index bc809c88884f32cd96b292de045654393078e4fb..9ea0288fd0ab21e23cb070480d1c7d66ee11bea1 100644 (file)
@@ -46,7 +46,7 @@ import java.io.Serializable;
 @Table(name = "metrics")
 @Entity(name = "Metric")
 @InstantiationStrategy(InstantiationStrategy.PER_BATCH)
-public class Metric implements ServerExtension, BatchExtension, Serializable {
+public class Metric<G extends Serializable> implements ServerExtension, BatchExtension, Serializable, org.sonar.batch.api.measures.Metric<G> {
 
   /**
    * A metric bigger value means a degradation
@@ -62,7 +62,28 @@ public class Metric implements ServerExtension, BatchExtension, Serializable {
   public static final int DIRECTION_NONE = 0;
 
   public enum ValueType {
-    INT, FLOAT, PERCENT, BOOL, STRING, MILLISEC, DATA, LEVEL, DISTRIB, RATING, WORK_DUR
+    INT(Integer.class),
+    FLOAT(Double.class),
+    PERCENT(Double.class),
+    BOOL(Boolean.class),
+    STRING(String.class),
+    MILLISEC(Integer.class),
+    DATA(String.class),
+    LEVEL(String.class),
+    DISTRIB(String.class),
+    RATING(String.class),
+    WORK_DUR(Long.class);
+
+    private final Class measureJavaType;
+
+    private ValueType(Class measureJavaType) {
+      this.measureJavaType = measureJavaType;
+    }
+
+    private Class measureJavaType() {
+      return measureJavaType;
+    }
+
   }
 
   public enum Level {
@@ -211,10 +232,8 @@ public class Metric implements ServerExtension, BatchExtension, Serializable {
    * @param qualitative whether the metric is qualitative
    * @param domain      the metric domain
    * @param userManaged whether the metric is user managed
-   * @deprecated since 2.7 use the {@link Builder} factory.
    */
-  @Deprecated
-  public Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, @Nullable String domain,
+  private Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, @Nullable String domain,
     boolean userManaged) {
     this.key = key;
     this.description = description;
@@ -231,41 +250,6 @@ public class Metric implements ServerExtension, BatchExtension, Serializable {
     }
   }
 
-  /**
-   * Creates a fully qualified metric. This defaults some values:
-   * <ul>
-   * <li>origin : Origin.JAV</li>
-   * <li>enabled : true</li>
-   * <li>userManaged : true</li>
-   * </ul>
-   *
-   * @param key         the metric key
-   * @param name        the metric name
-   * @param type        the metric type
-   * @param direction   the metric direction
-   * @param qualitative whether the metric is qualitative
-   * @param domain      the metric domain
-   * @param formula     the metric formula
-   * @deprecated since 2.7 use the {@link Builder} factory.
-   */
-  @Deprecated
-  public Metric(String key, String name, ValueType type, Integer direction, Boolean qualitative, String domain, Formula formula) {
-    this.key = key;
-    this.name = name;
-    this.type = type;
-    this.direction = direction;
-    this.domain = domain;
-    this.qualitative = qualitative;
-    this.origin = Origin.JAV;
-    this.enabled = true;
-    this.userManaged = false;
-    this.formula = formula;
-    if (ValueType.PERCENT.equals(this.type)) {
-      this.bestValue = (direction == DIRECTION_BETTER ? 100.0 : 0.0);
-      this.worstValue = (direction == DIRECTION_BETTER ? 0.0 : 100.0);
-    }
-  }
-
   /**
    * For internal use only
    */
@@ -803,12 +787,22 @@ public class Metric implements ServerExtension, BatchExtension, Serializable {
      *
      * @return a new {@link Metric} object
      */
-    public Metric create() {
+    public <G extends Serializable> Metric<G> create() {
       if (ValueType.PERCENT.equals(this.type)) {
         this.bestValue = (direction == DIRECTION_BETTER ? 100.0 : 0.0);
         this.worstValue = (direction == DIRECTION_BETTER ? 0.0 : 100.0);
       }
-      return new Metric(this);
+      return new Metric<G>(this);
     }
   }
+
+  @Override
+  public String key() {
+    return getKey();
+  }
+
+  @Override
+  public Class<G> type() {
+    return getType().measureJavaType();
+  }
 }
index 41ed8f6ff8a3b2c4eba937edf26d74e1009aca51..944b1278a6afedf5e7e75c59e8925e8e754e95e6 100644 (file)
@@ -28,7 +28,7 @@ import java.util.List;
 
 /**
  * @since 1.10
- * @deprecated replaced by {@link org.sonar.api.scan.filesystem.ModuleFileSystem} in 3.5
+ * @deprecated since 3.5 replaced by {@link org.sonar.api.scan.filesystem.ModuleFileSystem}
  */
 @Deprecated
 public interface ProjectFileSystem extends BatchComponent {
index 67baa3cbfe08dbf2187ab632a530cf1c408af61a..9f6de72da31663bebdbaeb318ab4873a4af1f5d5 100644 (file)
@@ -41,8 +41,8 @@ public class AbstractSumChildrenDecoratorTest {
   public void sumChildren() {
     DecoratorContext context = mock(DecoratorContext.class);
     when(context.getChildrenMeasures(CoreMetrics.LINES)).thenReturn(Arrays.<Measure>asList(
-        new Measure(CoreMetrics.LINES, 100.0),
-        new Measure(CoreMetrics.LINES, 50.0)));
+      new Measure(CoreMetrics.LINES, 100.0),
+      new Measure(CoreMetrics.LINES, 50.0)));
 
     create(false).decorate(null, context);
 
@@ -75,7 +75,7 @@ public class AbstractSumChildrenDecoratorTest {
       @Override
       @DependedUpon
       public List<Metric> generatesMetrics() {
-        return Arrays.asList(CoreMetrics.LINES);
+        return Arrays.<Metric>asList(CoreMetrics.LINES);
       }
 
       @Override
index 7831cb2975e763bde44aad0c73969156d68653bd..1b4908c728ec28437135c24833e42ec012117573 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.api.batch;
 
 import org.junit.Test;
 import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Metric;
 
 import java.util.Arrays;
 
@@ -30,7 +31,7 @@ public class TimeMachineQueryTest {
 
   @Test
   public void setNullMetrics() {
-    TimeMachineQuery query = new TimeMachineQuery(null).setMetrics(Arrays.asList(CoreMetrics.LINES));
+    TimeMachineQuery query = new TimeMachineQuery(null).setMetrics(Arrays.<Metric>asList(CoreMetrics.LINES));
     assertThat(query.getMetrics()).contains(CoreMetrics.LINES);
 
     query.unsetMetrics();
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java
deleted file mode 100644 (file)
index e78bff0..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.fest.assertions.Assertions;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FilePredicates;
-import org.sonar.api.batch.fs.InputFile;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class DefaultFilePredicatesTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  DefaultInputFile javaFile;
-  FilePredicates predicates = new DefaultFilePredicates();
-
-  @Before
-  public void before() throws IOException {
-    javaFile = new DefaultInputFile("src/main/java/struts/Action.java")
-      .setFile(temp.newFile("Action.java"))
-      .setLanguage("java")
-      .setStatus(InputFile.Status.ADDED);
-  }
-
-  @Test
-  public void all() throws Exception {
-    Assertions.assertThat(predicates.all().apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void none() throws Exception {
-    assertThat(predicates.none().apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void matches_inclusion_pattern() throws Exception {
-    assertThat(predicates.matchesPathPattern("src/main/**/Action.java").apply(javaFile)).isTrue();
-    assertThat(predicates.matchesPathPattern("Action.java").apply(javaFile)).isFalse();
-    assertThat(predicates.matchesPathPattern("src/**/*.php").apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void matches_inclusion_patterns() throws Exception {
-    assertThat(predicates.matchesPathPatterns(new String[]{"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isTrue();
-    assertThat(predicates.matchesPathPatterns(new String[]{}).apply(javaFile)).isTrue();
-    assertThat(predicates.matchesPathPatterns(new String[]{"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void does_not_match_exclusion_pattern() throws Exception {
-    assertThat(predicates.doesNotMatchPathPattern("src/main/**/Action.java").apply(javaFile)).isFalse();
-    assertThat(predicates.doesNotMatchPathPattern("Action.java").apply(javaFile)).isTrue();
-    assertThat(predicates.doesNotMatchPathPattern("src/**/*.php").apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void does_not_match_exclusion_patterns() throws Exception {
-    assertThat(predicates.doesNotMatchPathPatterns(new String[]{}).apply(javaFile)).isTrue();
-    assertThat(predicates.doesNotMatchPathPatterns(new String[]{"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isTrue();
-    assertThat(predicates.doesNotMatchPathPatterns(new String[]{"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_relative_path() throws Exception {
-    assertThat(predicates.hasRelativePath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
-    assertThat(predicates.hasRelativePath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
-
-    // path is normalized
-    assertThat(predicates.hasRelativePath("src/main/java/../java/struts/Action.java").apply(javaFile)).isTrue();
-
-    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Action.java").apply(javaFile)).isTrue();
-    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Other.java").apply(javaFile)).isFalse();
-    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\..\\struts\\Action.java").apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void has_absolute_path() throws Exception {
-    String path = javaFile.file().getAbsolutePath();
-    assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
-    assertThat(predicates.hasAbsolutePath(FilenameUtils.separatorsToWindows(path)).apply(javaFile)).isTrue();
-
-    assertThat(predicates.hasAbsolutePath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
-    assertThat(predicates.hasAbsolutePath("src/main/java/struts/Action.java").apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_path() throws Exception {
-    // is relative path
-    assertThat(predicates.hasPath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
-    assertThat(predicates.hasPath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
-
-    // is absolute path
-    String path = javaFile.file().getAbsolutePath();
-    assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
-    assertThat(predicates.hasPath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void is_file() throws Exception {
-    // relative file
-    assertThat(predicates.is(new File(javaFile.relativePath())).apply(javaFile)).isTrue();
-
-
-    // absolute file
-    assertThat(predicates.is(javaFile.file()).apply(javaFile)).isTrue();
-    assertThat(predicates.is(javaFile.file().getAbsoluteFile()).apply(javaFile)).isTrue();
-    assertThat(predicates.is(javaFile.file().getCanonicalFile()).apply(javaFile)).isTrue();
-    assertThat(predicates.is(new File(javaFile.file().toURI())).apply(javaFile)).isTrue();
-    assertThat(predicates.is(temp.newFile()).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_language() throws Exception {
-    assertThat(predicates.hasLanguage("java").apply(javaFile)).isTrue();
-    assertThat(predicates.hasLanguage("php").apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_languages() throws Exception {
-    assertThat(predicates.hasLanguages(Arrays.asList("java", "php")).apply(javaFile)).isTrue();
-    assertThat(predicates.hasLanguages(Arrays.asList("cobol", "php")).apply(javaFile)).isFalse();
-    assertThat(predicates.hasLanguages(Collections.<String>emptyList()).apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void has_status() throws Exception {
-    assertThat(predicates.hasStatus(InputFile.Status.ADDED).apply(javaFile)).isTrue();
-    assertThat(predicates.hasStatus(InputFile.Status.CHANGED).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_type() throws Exception {
-    assertThat(predicates.hasType(InputFile.Type.MAIN).apply(javaFile)).isTrue();
-    assertThat(predicates.hasType(InputFile.Type.TEST).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void not() throws Exception {
-    assertThat(predicates.not(predicates.hasType(InputFile.Type.MAIN)).apply(javaFile)).isFalse();
-    assertThat(predicates.not(predicates.hasType(InputFile.Type.TEST)).apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void and() throws Exception {
-    // empty
-    assertThat(predicates.and().apply(javaFile)).isTrue();
-    assertThat(predicates.and(new FilePredicate[0]).apply(javaFile)).isTrue();
-    assertThat(predicates.and(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
-
-    // two arguments
-    assertThat(predicates.and(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
-    assertThat(predicates.and(predicates.all(), predicates.none()).apply(javaFile)).isFalse();
-    assertThat(predicates.and(predicates.none(), predicates.all()).apply(javaFile)).isFalse();
-
-    // collection
-    assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
-    assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isFalse();
-
-    // array
-    assertThat(predicates.and(new FilePredicate[]{predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
-    assertThat(predicates.and(new FilePredicate[]{predicates.all(), predicates.none()}).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void or() throws Exception {
-    // empty
-    assertThat(predicates.or().apply(javaFile)).isTrue();
-    assertThat(predicates.or(new FilePredicate[0]).apply(javaFile)).isTrue();
-    assertThat(predicates.or(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
-
-    // two arguments
-    assertThat(predicates.or(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
-    assertThat(predicates.or(predicates.all(), predicates.none()).apply(javaFile)).isTrue();
-    assertThat(predicates.or(predicates.none(), predicates.all()).apply(javaFile)).isTrue();
-    assertThat(predicates.or(predicates.none(), predicates.none()).apply(javaFile)).isFalse();
-
-    // collection
-    assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
-    assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isTrue();
-    assertThat(predicates.or(Arrays.asList(predicates.none(), predicates.none())).apply(javaFile)).isFalse();
-
-    // array
-    assertThat(predicates.or(new FilePredicate[]{predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
-    assertThat(predicates.or(new FilePredicate[]{predicates.all(), predicates.none()}).apply(javaFile)).isTrue();
-    assertThat(predicates.or(new FilePredicate[]{predicates.none(), predicates.none()}).apply(javaFile)).isFalse();
-  }
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java
deleted file mode 100644 (file)
index aa898e9..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.Charsets;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-
-import java.io.File;
-import java.nio.charset.Charset;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class DefaultFileSystemTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  @Test
-  public void test_directories() throws Exception {
-    DefaultFileSystem fs = new DefaultFileSystem();
-
-    File basedir = temp.newFolder();
-    fs.setBaseDir(basedir);
-    assertThat(fs.baseDir()).isAbsolute().isDirectory().exists();
-    assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
-
-    File workdir = temp.newFolder();
-    fs.setWorkDir(workdir);
-    assertThat(fs.workDir()).isAbsolute().isDirectory().exists();
-    assertThat(fs.workDir().getCanonicalPath()).isEqualTo(workdir.getCanonicalPath());
-  }
-
-  @Test
-  public void test_encoding() throws Exception {
-    DefaultFileSystem fs = new DefaultFileSystem();
-
-    assertThat(fs.isDefaultJvmEncoding()).isTrue();
-    assertThat(fs.encoding()).isEqualTo(Charset.defaultCharset());
-
-    fs.setEncoding(Charsets.ISO_8859_1);
-    assertThat(fs.encoding()).isEqualTo(Charsets.ISO_8859_1);
-    assertThat(fs.isDefaultJvmEncoding()).isFalse();
-  }
-
-  @Test
-  public void add_languages() throws Exception {
-    DefaultFileSystem fs = new DefaultFileSystem();
-
-    assertThat(fs.languages()).isEmpty();
-
-    fs.addLanguages("java", "php", "cobol");
-    assertThat(fs.languages()).containsOnly("cobol", "java", "php");
-  }
-
-  @Test
-  public void files() throws Exception {
-    DefaultFileSystem fs = new DefaultFileSystem();
-
-    assertThat(fs.inputFiles(fs.predicates().all())).isEmpty();
-
-    fs.add(new DefaultInputFile("src/Foo.php").setLanguage("php").setFile(temp.newFile()));
-    fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
-    fs.add(new DefaultInputFile("src/Baz.java").setLanguage("java").setFile(temp.newFile()));
-
-    // no language
-    fs.add(new DefaultInputFile("src/readme.txt").setFile(temp.newFile()));
-
-    assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNotNull();
-    assertThat(fs.inputFile(fs.predicates().hasRelativePath("does/not/exist"))).isNull();
-
-    assertThat(fs.files(fs.predicates().all())).hasSize(4);
-    assertThat(fs.files(fs.predicates().hasLanguage("java"))).hasSize(2);
-    assertThat(fs.files(fs.predicates().hasLanguage("cobol"))).isEmpty();
-
-    assertThat(fs.hasFiles(fs.predicates().all())).isTrue();
-    assertThat(fs.hasFiles(fs.predicates().hasLanguage("java"))).isTrue();
-    assertThat(fs.hasFiles(fs.predicates().hasLanguage("cobol"))).isFalse();
-
-    assertThat(fs.inputFiles(fs.predicates().all())).hasSize(4);
-    assertThat(fs.inputFiles(fs.predicates().hasLanguage("php"))).hasSize(1);
-    assertThat(fs.inputFiles(fs.predicates().hasLanguage("java"))).hasSize(2);
-    assertThat(fs.inputFiles(fs.predicates().hasLanguage("cobol"))).isEmpty();
-
-    assertThat(fs.languages()).containsOnly("java", "php");
-  }
-
-  @Test
-  public void input_file_returns_null_if_file_not_found() throws Exception {
-    DefaultFileSystem fs = new DefaultFileSystem();
-    assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNull();
-    assertThat(fs.inputFile(fs.predicates().hasLanguage("cobol"))).isNull();
-  }
-
-  @Test
-  public void input_file_fails_if_too_many_results() throws Exception {
-    thrown.expect(IllegalArgumentException.class);
-    thrown.expectMessage("expected one element");
-
-    DefaultFileSystem fs = new DefaultFileSystem();
-    fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
-    fs.add(new DefaultInputFile("src/Baz.java").setLanguage("java").setFile(temp.newFile()));
-
-    fs.inputFile(fs.predicates().all());
-  }
-
-  @Test
-  public void input_file_supports_non_indexed_predicates() throws Exception {
-    DefaultFileSystem fs = new DefaultFileSystem();
-    fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile()));
-
-    // it would fail if more than one java file
-    assertThat(fs.inputFile(fs.predicates().hasLanguage("java"))).isNotNull();
-  }
-}
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
deleted file mode 100644 (file)
index 3148a2d..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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)
-      .setPathRelativeToSourceDir("Foo.php");
-
-    assertThat(inputFile.relativePath()).isEqualTo("src/Foo.php");
-    // deprecated method is different -> path relative to source dir
-    assertThat(inputFile.getRelativePath()).isEqualTo("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());
-  }
-
-  @Test
-  public void test_toString() throws Exception {
-    DefaultInputFile file = new DefaultInputFile("src/Foo.php").setAbsolutePath("/path/to/src/Foo.php");
-    assertThat(file.toString()).isEqualTo("[relative=src/Foo.php, abs=/path/to/src/Foo.php]");
-  }
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java
new file mode 100644 (file)
index 0000000..321efa8
--- /dev/null
@@ -0,0 +1,84 @@
+package org.sonar.api.batch.fs.internal;
+
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+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 DeprecatedDefaultInputFileTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Test
+  public void test() throws Exception {
+    DeprecatedDefaultInputFile inputFile = (DeprecatedDefaultInputFile) new DeprecatedDefaultInputFile("src/Foo.php")
+      .setPathRelativeToSourceDir("Foo.php")
+      .setDeprecatedKey("deprecated")
+      .setFile(temp.newFile("Foo.php"))
+      .setKey("ABCDE")
+      .setHash("1234")
+      .setLines(42)
+      .setLanguage("php")
+      .setStatus(InputFile.Status.ADDED)
+      .setType(InputFile.Type.TEST);
+
+    assertThat(inputFile.relativePath()).isEqualTo("src/Foo.php");
+    // deprecated method is different -> path relative to source dir
+    assertThat(inputFile.getRelativePath()).isEqualTo("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());
+  }
+
+  @Test
+  public void test_toString() throws Exception {
+    DefaultInputFile file = new DefaultInputFile("src/Foo.php").setAbsolutePath("/path/to/src/Foo.php");
+    assertThat(file.toString()).isEqualTo("[relative=src/Foo.php, abs=/path/to/src/Foo.php]");
+  }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java
deleted file mode 100644 (file)
index 01d6dab..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 PathPatternTest {
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Test
-  public void match_relative_path() throws Exception {
-    PathPattern pattern = PathPattern.create("**/*Foo.java");
-    assertThat(pattern.toString()).isEqualTo("**/*Foo.java");
-
-    File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java");
-    InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java").setFile(file);
-    assertThat(pattern.match(inputFile)).isTrue();
-
-    // case sensitive by default
-    file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
-    inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
-    assertThat(pattern.match(inputFile)).isFalse();
-
-    file = new File(temp.newFolder(), "src/main/java/org/Other.java");
-    inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
-    assertThat(pattern.match(inputFile)).isFalse();
-  }
-
-  @Test
-  public void match_relative_path_and_insensitive_file_extension() throws Exception {
-    PathPattern pattern = PathPattern.create("**/*Foo.java");
-
-    File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
-    InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
-    assertThat(pattern.match(inputFile, false)).isTrue();
-
-    file = new File(temp.newFolder(), "src/main/java/org/Other.java");
-    inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
-    assertThat(pattern.match(inputFile, false)).isFalse();
-  }
-
-  @Test
-  public void match_absolute_path() throws Exception {
-    PathPattern pattern = PathPattern.create("file:**/src/main/**Foo.java");
-    assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
-
-    File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java");
-    InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java").setFile(file);
-    assertThat(pattern.match(inputFile)).isTrue();
-
-    // case sensitive by default
-    file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
-    inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
-    assertThat(pattern.match(inputFile)).isFalse();
-
-    file = new File(temp.newFolder(), "src/main/java/org/Other.java");
-    inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file);
-    assertThat(pattern.match(inputFile)).isFalse();
-  }
-
-  @Test
-  public void match_absolute_path_and_insensitive_file_extension() throws Exception {
-    PathPattern pattern = PathPattern.create("file:**/src/main/**Foo.java");
-    assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
-
-    File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA");
-    InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file);
-    assertThat(pattern.match(inputFile, false)).isTrue();
-
-    file = new File(temp.newFolder(), "src/main/java/org/Other.JAVA");
-    inputFile = new DefaultInputFile("src/main/java/org/Other.JAVA").setFile(file);
-    assertThat(pattern.match(inputFile, false)).isFalse();
-  }
-
-  @Test
-  public void create_array_of_patterns() throws Exception {
-    PathPattern[] patterns = PathPattern.create(new String[]{
-      "**/src/main/**Foo.java",
-      "file:**/src/main/**Bar.java"
-    });
-    assertThat(patterns).hasSize(2);
-    assertThat(patterns[0].toString()).isEqualTo("**/src/main/**Foo.java");
-    assertThat(patterns[1].toString()).isEqualTo("file:**/src/main/**Bar.java");
-  }
-}
index 2fa115a8626d9583828b1314ed08c5f70ab18ff8..9e375adfd29d0f059245079f868f6cb8d3b0a933 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.startup;
 
+import com.google.common.collect.Lists;
 import org.junit.Test;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
@@ -30,7 +31,6 @@ import org.sonar.jpa.test.AbstractDbUnitTestCase;
 import java.util.Arrays;
 import java.util.List;
 
-import static com.google.common.collect.Lists.newArrayList;
 import static org.fest.assertions.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -67,7 +67,7 @@ public class RegisterMetricsTest extends AbstractDbUnitTestCase {
     setupData("shouldUpdateIfAlreadyExists");
 
     RegisterMetrics synchronizer = new RegisterMetrics(new MeasuresDao(getSession()), mock(QualityGateConditionDao.class), new Metrics[0]);
-    synchronizer.register(newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
+    synchronizer.register(Lists.<Metric>newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
       .setDescription("new description")
       .setDirection(-1)
       .setQualitative(true)
@@ -81,7 +81,7 @@ public class RegisterMetricsTest extends AbstractDbUnitTestCase {
   @Test
   public void shouldAddUserManagesMetric() {
     Metrics metrics = mock(Metrics.class);
-    when(metrics.getMetrics()).thenReturn(newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
+    when(metrics.getMetrics()).thenReturn(Lists.<Metric>newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
       .setDescription("new description")
       .setDirection(-1)
       .setQualitative(true)
@@ -90,7 +90,7 @@ public class RegisterMetricsTest extends AbstractDbUnitTestCase {
       .create()));
 
     MeasuresDao measuresDao = new MeasuresDao(getSession());
-    RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[]{metrics});
+    RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[] {metrics});
     List<Metric> result = loader.getMetricsRepositories();
 
     assertThat(result).hasSize(1);
@@ -101,7 +101,7 @@ public class RegisterMetricsTest extends AbstractDbUnitTestCase {
     setupData("shouldNotUpdateUserManagesMetricIfAlreadyExists");
 
     Metrics metrics = mock(Metrics.class);
-    when(metrics.getMetrics()).thenReturn(newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
+    when(metrics.getMetrics()).thenReturn(Lists.<Metric>newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT)
       .setDescription("new description")
       .setDirection(-1)
       .setQualitative(true)
@@ -110,7 +110,7 @@ public class RegisterMetricsTest extends AbstractDbUnitTestCase {
       .create()));
 
     MeasuresDao measuresDao = new MeasuresDao(getSession());
-    RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[]{metrics});
+    RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[] {metrics});
     List<Metric> result = loader.getMetricsRepositories();
 
     assertThat(result).isEmpty();