summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-06-12 09:38:46 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2014-06-16 09:42:46 +0200
commitd35dc73824f38e3585b44d8b7ee9df867bccec5b (patch)
tree1248c5da0843b6218c677f1a375a82e3bb67b383
parent74e76cbd9f07045561a219efe49f220253508ddb (diff)
downloadsonarqube-d35dc73824f38e3585b44d8b7ee9df867bccec5b.tar.gz
sonarqube-d35dc73824f38e3585b44d8b7ee9df867bccec5b.zip
SONAR-5389 New Analyzer API
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/UserManagedMetrics.java38
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java4
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java10
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java6
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java6
-rw-r--r--plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java8
-rw-r--r--pom.xml6
-rw-r--r--sonar-batch-plugin-api/pom.xml34
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java)0
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java)2
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java)3
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java)2
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFileFilter.java)2
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java)4
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java)0
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java)12
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java)121
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java)95
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java)0
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java)0
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java)0
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java)0
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java)6
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java)1
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java)18
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java)0
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java)0
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java)0
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java)1
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java)1
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchComponent.java29
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchExtension.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/UniqueIndexPredicate.java)13
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/InstantiationStrategy.java46
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/Analyzer.java51
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerContext.java80
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerDescriptor.java107
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/AnalyzerIssue.java126
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/package-info.java21
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/AnalyzerMeasure.java129
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/package-info.java21
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/package-info.java21
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/FilenameUtils.java244
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/Preconditions.java413
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/StringUtils.java140
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/WildcardPattern.java205
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/package-info.java21
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/Language.java57
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/package-info.java21
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/Metric.java29
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/package-info.java21
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/QProfile.java43
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/RuleKey.java90
-rw-r--r--sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/package-info.java21
-rw-r--r--sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java (renamed from sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java)26
-rw-r--r--sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java (renamed from sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java)5
-rw-r--r--sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java (renamed from sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java)6
-rw-r--r--sonar-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java (renamed from sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java)0
-rw-r--r--sonar-batch/pom.xml4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisMode.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java10
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java22
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java17
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java13
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java23
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java16
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/languages/DeprecatedLanguagesReferential.java63
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/languages/LanguagesReferential.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileIndex.java)27
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/languages/package-info.java20
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/SensorMatcher.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java64
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/QProfileEventsDecorator.java19
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/QProfileVerifier.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/UsedQProfiles.java24
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rules/DefaultQProfileReferential.java46
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rules/QProfileWithId.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathIndex.java)23
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rules/QProfilesReferential.java39
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rules/package-info.java21
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/AnalyzerContextAdaptor.java169
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/LanguageVerifier.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java12
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java42
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java78
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicates.java10
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java28
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileFilters.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java41
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java10
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java20
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java21
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetection.java17
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetectionFactory.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java22
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzersExecutor.java60
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultAnalyzerContext.java104
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/MeasureCache.java65
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanContainer.java100
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/Phase2Executor.java (renamed from sonar-batch/src/main/java/org/sonar/batch/phases/Phase2Executor.java)65
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java103
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObserver.java28
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObservers.java42
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/package-info.java21
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/settings/package-info.java21
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java5
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/MetricProviderTest.java6
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java10
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java12
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/medium/Scan2MediumTest.java168
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/ActiveRulesProviderTest.java12
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java29
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java16
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/QProfileVerifierTest.java10
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/RulesProfileProviderTest.java8
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/UsedQProfilesTest.java5
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/LanguageVerifierTest.java4
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java17
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java11
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java27
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java16
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java1
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java3
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java12
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java27
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionFactoryTest.java4
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java20
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java4
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/medium/simple-project/sonar-project.properties7
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/medium/simple-project/sources/Fake.java1
-rw-r--r--sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java10
-rw-r--r--sonar-deprecated/src/main/java/org/sonar/api/batch/BatchExtensionDictionnary.java33
-rw-r--r--sonar-plugin-api/pom.xml4
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/InstantiationStrategy.java1
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java5
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java3
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java116
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java37
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java4
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java78
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectFileSystem.java2
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/AbstractSumChildrenDecoratorTest.java6
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/TimeMachineQueryTest.java3
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java84
-rw-r--r--sonar-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java12
158 files changed, 3786 insertions, 1084 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/UserManagedMetrics.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/UserManagedMetrics.java
index cf5996477f6..1bc1d597a6b 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/UserManagedMetrics.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/UserManagedMetrics.java
@@ -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());
}
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java
index 3e758761c18..b1c5dac5147 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FileHashSensor.java
@@ -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);
}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java
index 4db5159ed48..29f5e64cce9 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java
@@ -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);
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java
index 7c24a89bb3a..df4bc036115 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java
@@ -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;
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java
index 8255053db31..130206427fc 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java
@@ -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);
diff --git a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java
index ac2be64ac60..c8551a74166 100644
--- a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java
+++ b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java
@@ -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 c1b603d8bfd..2b63e2a5021 100644
--- 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>
@@ -576,6 +577,11 @@
</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>
<version>${sonarUpdateCenter.version}</version>
</dependency>
diff --git a/sonar-batch-plugin-api/pom.xml b/sonar-batch-plugin-api/pom.xml
new file mode 100644
index 00000000000..f90ff635f9c
--- /dev/null
+++ b/sonar-batch-plugin-api/pom.xml
@@ -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-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
index 830859ed3ba..830859ed3ba 100644
--- a/sonar-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
diff --git a/sonar-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
index dd9f14833ca..65a2e19d6a5 100644
--- a/sonar-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
@@ -64,6 +64,8 @@ public interface FilePredicates {
FilePredicate hasLanguages(Collection<String> languages);
+ FilePredicate hasLanguages(String... languages);
+
FilePredicate hasStatus(InputFile.Status status);
FilePredicate hasType(InputFile.Type type);
diff --git a/sonar-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
index 5172eb8d542..0c050f038c2 100644
--- a/sonar-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
@@ -19,9 +19,10 @@
*/
package org.sonar.api.batch.fs;
-import org.sonar.api.BatchComponent;
+import org.sonar.batch.api.BatchComponent;
import javax.annotation.CheckForNull;
+
import java.io.File;
import java.nio.charset.Charset;
import java.util.SortedSet;
diff --git a/sonar-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
index e4728a44408..83e9697f15f 100644
--- a/sonar-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
@@ -33,7 +33,7 @@ public interface InputFile extends Serializable {
MAIN, TEST
}
- /**
+ /**
* Status regarding previous analysis
*/
enum Status {
diff --git a/sonar-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
index 1ece5081290..166af9ea64b 100644
--- a/sonar-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
@@ -19,7 +19,7 @@
*/
package org.sonar.api.batch.fs;
-import org.sonar.api.BatchExtension;
+import org.sonar.batch.api.BatchExtension;
/**
* Extension point to exclude some files from inspection
diff --git a/sonar-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
index 8e943a0f5f8..367c1eabdeb 100644
--- a/sonar-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
@@ -19,9 +19,9 @@
*/
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;
+import org.sonar.batch.api.internal.FilenameUtils;
/**
* @since 4.2
@@ -31,7 +31,7 @@ class AbsolutePathPredicate implements FilePredicate {
private final String path;
AbsolutePathPredicate(String path) {
- this.path = FilenameUtils.normalize(path, true);
+ this.path = FilenameUtils.normalize(path);
}
@Override
diff --git a/sonar-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
index 0494ed524dc..0494ed524dc 100644
--- a/sonar-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
diff --git a/sonar-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
index 52bb75ad9b2..8036d90a3ea 100644
--- a/sonar-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
@@ -19,12 +19,12 @@
*/
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.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -115,7 +115,15 @@ public class DefaultFilePredicates implements FilePredicates {
}
public FilePredicate hasLanguages(Collection<String> languages) {
- List<FilePredicate> list = Lists.newArrayList();
+ 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));
}
diff --git a/sonar-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
index 3a97f46f757..89abb9e3ccf 100644
--- a/sonar-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
@@ -19,27 +19,25 @@
*/
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 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.List;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
-import java.util.NoSuchElementException;
import java.util.SortedSet;
+import java.util.TreeSet;
/**
* @since 4.2
@@ -47,7 +45,7 @@ import java.util.SortedSet;
public class DefaultFileSystem implements FileSystem {
private final Cache cache;
- private final SortedSet<String> languages = Sets.newTreeSet();
+ private final SortedSet<String> languages = new TreeSet<String>();
private File baseDir, workDir;
private Charset encoding;
private final FilePredicates predicates = new DefaultFilePredicates();
@@ -101,39 +99,70 @@ public class DefaultFileSystem implements FileSystem {
@Override
public InputFile inputFile(FilePredicate predicate) {
doPreloadFiles();
- if (predicate instanceof UniqueIndexPredicate) {
- return cache.inputFile((UniqueIndexPredicate) predicate);
+ if (predicate instanceof RelativePathPredicate) {
+ return cache.inputFile((RelativePathPredicate) predicate);
}
- try {
- Iterable<InputFile> files = inputFiles(predicate);
- return Iterables.getOnlyElement(files);
- } catch (NoSuchElementException e) {
- // contrary to guava, return null if iterable is empty
+ 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 Iterables.filter(cache.inputFiles(), new GuavaPredicate(predicate));
+ return filter(cache.inputFiles(), predicate);
}
@Override
public boolean hasFiles(FilePredicate predicate) {
doPreloadFiles();
- return Iterables.indexOf(cache.inputFiles(), new GuavaPredicate(predicate)) >= 0;
+ for (InputFile element : cache.inputFiles()) {
+ if (predicate.apply(element)) {
+ return true;
+ }
+ }
+ return false;
}
@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();
+ 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;
}
/**
@@ -179,17 +208,12 @@ public class DefaultFileSystem implements FileSystem {
protected abstract Iterable<InputFile> inputFiles();
@CheckForNull
- protected abstract InputFile inputFile(UniqueIndexPredicate predicate);
+ protected abstract InputFile inputFile(RelativePathPredicate 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);
- }
}
}
@@ -197,49 +221,22 @@ public class DefaultFileSystem implements FileSystem {
* 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();
+ private final Map<String, InputFile> fileMap = new HashMap<String, InputFile>();
@Override
public Iterable<InputFile> inputFiles() {
- return Lists.newArrayList(files);
+ return new ArrayList<InputFile>(fileMap.values());
}
@Override
- public InputFile inputFile(UniqueIndexPredicate predicate) {
- Map<Object, InputFile> byAttr = fileMap.get(predicate.indexId());
- if (byAttr != null) {
- return byAttr.get(predicate.value());
- }
- return null;
+ public InputFile inputFile(RelativePathPredicate predicate) {
+ return fileMap.get(predicate.path());
}
@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);
+ fileMap.put(inputFile.relativePath(), 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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java
index 888ae7ac313..5767d74a374 100644
--- a/sonar-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
@@ -19,17 +19,18 @@
*/
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 org.sonar.batch.api.internal.FilenameUtils;
import javax.annotation.CheckForNull;
-import java.io.*;
+
+import java.io.File;
+import java.io.Serializable;
/**
* @since 4.2
*/
-public class DefaultInputFile implements InputFile, org.sonar.api.resources.InputFile, Serializable {
+public class DefaultInputFile implements InputFile, Serializable {
private final String relativePath;
private String absolutePath;
@@ -39,13 +40,9 @@ public class DefaultInputFile implements InputFile, org.sonar.api.resources.Inpu
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);
+ this.relativePath = FilenameUtils.normalize(relativePath);
}
@Override
@@ -120,7 +117,7 @@ public class DefaultInputFile implements InputFile, org.sonar.api.resources.Inpu
}
public DefaultInputFile setAbsolutePath(String s) {
- this.absolutePath = FilenameUtils.normalize(s, true);
+ this.absolutePath = FilenameUtils.normalize(s);
return this;
}
@@ -159,85 +156,12 @@ public class DefaultInputFile implements InputFile, org.sonar.api.resources.Inpu
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()) {
+ if (!(o instanceof DefaultInputFile)) {
return false;
}
@@ -255,6 +179,3 @@ public class DefaultInputFile implements InputFile, org.sonar.api.resources.Inpu
return "[relative=" + relativePath + ", abs=" + absolutePath + "]";
}
}
-
-
-
diff --git a/sonar-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
index b092f848946..b092f848946 100644
--- a/sonar-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
diff --git a/sonar-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
index 77d2f74887a..77d2f74887a 100644
--- a/sonar-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
diff --git a/sonar-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
index 5f2359ee166..5f2359ee166 100644
--- a/sonar-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
diff --git a/sonar-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
index a887c631cf2..a887c631cf2 100644
--- a/sonar-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
diff --git a/sonar-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
index c1b53b68a40..cdcfd8e2028 100644
--- a/sonar-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
@@ -19,10 +19,10 @@
*/
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;
+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 {
diff --git a/sonar-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
index c2402a43cfe..0cf614bcb09 100644
--- a/sonar-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
@@ -21,7 +21,6 @@ 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
diff --git a/sonar-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
index 22aed6e09a5..d0c4a3d3fba 100644
--- a/sonar-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
@@ -19,34 +19,28 @@
*/
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;
+import org.sonar.batch.api.internal.FilenameUtils;
/**
* @since 4.2
*/
-class RelativePathPredicate implements FilePredicate, UniqueIndexPredicate {
+public class RelativePathPredicate implements FilePredicate {
private final String path;
RelativePathPredicate(String path) {
- this.path = FilenameUtils.normalize(path, true);
+ this.path = FilenameUtils.normalize(path);
}
- @Override
- public boolean apply(InputFile f) {
- return path.equals(f.relativePath());
- }
-
- @Override
- public Object value() {
+ public String path() {
return path;
}
@Override
- public String indexId() {
- return RelativePathIndex.ID;
+ public boolean apply(InputFile f) {
+ return path.equals(f.relativePath());
}
}
diff --git a/sonar-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
index fe7c934071e..fe7c934071e 100644
--- a/sonar-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
diff --git a/sonar-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
index ec2aebd624d..ec2aebd624d 100644
--- a/sonar-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
diff --git a/sonar-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
index ac8b6d5fe8d..ac8b6d5fe8d 100644
--- a/sonar-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
diff --git a/sonar-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
index 8fac5590440..713fe6131ca 100644
--- a/sonar-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
@@ -21,3 +21,4 @@
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-batch-plugin-api/src/main/java/org/sonar/api/batch/fs/package-info.java
index 197da9925ac..c97db582333 100644
--- a/sonar-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
@@ -21,3 +21,4 @@
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
index 00000000000..d48e2253190
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchComponent.java
@@ -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-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/UniqueIndexPredicate.java b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchExtension.java
index 8b7404d2571..1a774a16f5d 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/UniqueIndexPredicate.java
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/BatchExtension.java
@@ -17,15 +17,14 @@
* 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;
+package org.sonar.batch.api;
+
/**
- * @since 4.2
+ * Batch extension point.
+ *
+ * @since 4.4
*/
-public interface UniqueIndexPredicate {
-
- String indexId();
-
- Object value();
+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
index 00000000000..521c6ddd61f
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/InstantiationStrategy.java
@@ -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
index 00000000000..612354560a3
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/Analyzer.java
@@ -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
index 00000000000..e29dfaf711d
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerContext.java
@@ -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
index 00000000000..0b97200dd10
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/AnalyzerDescriptor.java
@@ -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
index 00000000000..f39d88493fe
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/AnalyzerIssue.java
@@ -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
index 00000000000..70a6600e6d1
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/issue/package-info.java
@@ -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
index 00000000000..3d74dca1b4c
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/AnalyzerMeasure.java
@@ -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
index 00000000000..b490662460a
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/measure/package-info.java
@@ -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
index 00000000000..5b72f8c6315
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/analyzer/package-info.java
@@ -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
index 00000000000..0461255879b
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/FilenameUtils.java
@@ -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
index 00000000000..75ac73f46f3
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/Preconditions.java
@@ -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
index 00000000000..ab279ae34e5
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/StringUtils.java
@@ -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
index 00000000000..f179fd73571
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/WildcardPattern.java
@@ -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
index 00000000000..9870b99bffc
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/internal/package-info.java
@@ -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
index 00000000000..7dd6c8b4e6b
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/Language.java
@@ -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
index 00000000000..a36d1c13de5
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/languages/package-info.java
@@ -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
index 00000000000..52dc17c1718
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/Metric.java
@@ -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
index 00000000000..e684b549c5f
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/measures/package-info.java
@@ -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
index 00000000000..1d074e105f2
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/QProfile.java
@@ -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
index 00000000000..3af1337a752
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/RuleKey.java
@@ -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
index 00000000000..d91eb3485c9
--- /dev/null
+++ b/sonar-batch-plugin-api/src/main/java/org/sonar/batch/api/rules/package-info.java
@@ -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-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
index e78bff01ce7..95888fecfe9 100644
--- a/sonar-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
@@ -19,7 +19,6 @@
*/
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;
@@ -71,9 +70,9 @@ public class DefaultFilePredicatesTest {
@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();
+ 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
@@ -85,9 +84,9 @@ public class DefaultFilePredicatesTest {
@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();
+ 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
@@ -107,7 +106,7 @@ public class DefaultFilePredicatesTest {
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(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();
@@ -130,7 +129,6 @@ public class DefaultFilePredicatesTest {
// 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();
@@ -187,8 +185,8 @@ public class DefaultFilePredicatesTest {
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();
+ 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
@@ -210,8 +208,8 @@ public class DefaultFilePredicatesTest {
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();
+ 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-batch-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java
index aa898e908c5..678fdc5687b 100644
--- a/sonar-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
@@ -19,7 +19,6 @@
*/
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;
@@ -60,8 +59,8 @@ public class DefaultFileSystemTest {
assertThat(fs.isDefaultJvmEncoding()).isTrue();
assertThat(fs.encoding()).isEqualTo(Charset.defaultCharset());
- fs.setEncoding(Charsets.ISO_8859_1);
- assertThat(fs.encoding()).isEqualTo(Charsets.ISO_8859_1);
+ fs.setEncoding(Charset.forName("ISO-8859-1"));
+ assertThat(fs.encoding()).isEqualTo(Charset.forName("ISO-8859-1"));
assertThat(fs.isDefaultJvmEncoding()).isFalse();
}
diff --git a/sonar-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
index 3148a2dc4c8..b96821ffd69 100644
--- a/sonar-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
@@ -37,18 +37,14 @@ public class DefaultInputFileTest {
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");
+ .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();
diff --git a/sonar-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
index 01d6dabd0fb..01d6dabd0fb 100644
--- a/sonar-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
diff --git a/sonar-batch/pom.xml b/sonar-batch/pom.xml
index db45a80e535..1db1f35f0e9 100644
--- a/sonar-batch/pom.xml
+++ b/sonar-batch/pom.xml
@@ -42,6 +42,10 @@
</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>
<exclusions>
<exclusion>
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
index 4d71b95e470..089b2a3c58f 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
@@ -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);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisMode.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisMode.java
index 4415122c3f6..89640219562 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisMode.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisMode.java
@@ -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) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
index 02c98554fa6..0391110d3a5 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
@@ -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;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
index 7cbf67570b1..538e3091e42 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
@@ -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);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java
index 693be2183a2..5d7e836786b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java
@@ -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();
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
index bb2b2e431f2..b7088cf4c01 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
@@ -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 {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java
index 86122e7dec4..e7fd8427a2d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java
@@ -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() {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java
index 972450aebde..ac107141bc3 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java
@@ -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;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
index 44db4e53f73..ae75f47f2a4 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
@@ -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));
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java
index 99eeb05cac9..4e169391d11 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceKeyMigration.java
@@ -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;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java
index e896729663a..79b576d3398 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java
@@ -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);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java
index 6f46e2cc7a9..1e880a6b31d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java
@@ -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());
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java
index 1dad68550bb..5f3e9c308e8 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java
@@ -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);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java
index ca77b7c239c..fcada30d053 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/language/LanguageDistributionDecorator.java
@@ -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
index 00000000000..1084b7d49a2
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/languages/DeprecatedLanguagesReferential.java
@@ -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-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileIndex.java b/sonar-batch/src/main/java/org/sonar/batch/languages/LanguagesReferential.java
index 4c61809fa3c..bf9fcd00de5 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileIndex.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/languages/LanguagesReferential.java
@@ -17,23 +17,30 @@
* 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;
+package org.sonar.batch.languages;
-import com.google.common.collect.ImmutableList;
-import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.BatchComponent;
+import org.sonar.batch.api.languages.Language;
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 {
+import java.util.Collection;
- // Currently only a single index is supported
- List<FileIndex> ALL = ImmutableList.<FileIndex>of(new RelativePathIndex());
+/**
+ * Languages referential
+ * @since 4.4
+ */
+public interface LanguagesReferential extends BatchComponent {
+ /**
+ * Get language.
+ */
@CheckForNull
- Object valueOf(InputFile f);
+ Language get(String languageKey);
- String id();
+ /**
+ * 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
index 00000000000..5ce5bc10019
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/languages/package-info.java
@@ -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/SensorMatcher.java b/sonar-batch/src/main/java/org/sonar/batch/phases/SensorMatcher.java
index 2ee73f61dfb..6328ac77a46 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/SensorMatcher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/SensorMatcher.java
@@ -19,12 +19,12 @@
*/
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);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java b/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java
index 95762afd79d..a7aea325d48 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java
@@ -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());
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java b/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java
index fb5027d923b..674fbb59a56 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java
@@ -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() {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileEventsDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileEventsDecorator.java
index ee67fcb31cd..e84dc342c17 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileEventsDecorator.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileEventsDecorator.java
@@ -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();
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java
index 0773a3c6472..620f769d8b7 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java
@@ -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);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileVerifier.java b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileVerifier.java
index ac8e51eb10e..10e110b6ee9 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileVerifier.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileVerifier.java
@@ -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 {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java
index 2b778be21dc..2c5ec75a235 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java
@@ -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());
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/UsedQProfiles.java b/sonar-batch/src/main/java/org/sonar/batch/rule/UsedQProfiles.java
index 1b1115ed18b..5973a74c593 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/rule/UsedQProfiles.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/UsedQProfiles.java
@@ -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
index 00000000000..936b17e63fe
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rules/DefaultQProfileReferential.java
@@ -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-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathIndex.java b/sonar-batch/src/main/java/org/sonar/batch/rules/QProfileWithId.java
index 33facf13cf2..4d2511676a9 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathIndex.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rules/QProfileWithId.java
@@ -17,23 +17,20 @@
* 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;
+package org.sonar.batch.rules;
-import org.sonar.api.batch.fs.InputFile;
+import org.sonar.batch.api.rules.QProfile;
-/**
- * @since 4.2
- */
-public class RelativePathIndex implements FileIndex {
- public static final String ID = "rel";
+public class QProfileWithId extends QProfile {
+ private final int id;
- @Override
- public Object valueOf(InputFile f) {
- return f.relativePath();
+ public QProfileWithId(int id, String name, String language, Integer version) {
+ super(name, language, version);
+ this.id = id;
}
- @Override
- public String id() {
- return 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
index 00000000000..aec78dc14c8
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rules/QProfilesReferential.java
@@ -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
index 00000000000..819e886c070
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rules/package-info.java
@@ -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
index 00000000000..a3f125d9c4f
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/AnalyzerContextAdaptor.java
@@ -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);
+ }
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/LanguageVerifier.java b/sonar-batch/src/main/java/org/sonar/batch/scan/LanguageVerifier.java
index f64dd0d7219..7f32e03e98e 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/LanguageVerifier.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/LanguageVerifier.java
@@ -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)) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
index 6e4ebd39b6a..6b1e0e1a501 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
@@ -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);
}
});
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
index b6dca14dafd..8d4dfa22df7 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
@@ -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,
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java
index 1ccbb393522..33285ae2be6 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java
@@ -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
index 00000000000..ae9a25c59dc
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java
@@ -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);
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicates.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicates.java
index af44e9b8783..6332d51a2ed 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicates.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicates.java
@@ -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());
}
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java
index 4729d7f0361..f7f289ddf64 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java
@@ -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();
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java
index ea5692fb4b3..7205c1c483f 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystem.java
@@ -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) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileFilters.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileFilters.java
index 8545dc4ef45..d52e19b0b0b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileFilters.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DeprecatedFileFilters.java
@@ -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
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
index b9d784723fa..b3142c9cc05 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
@@ -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);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
index 10b888344b9..cd7844fd4de 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
@@ -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());
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java
index 90dcfc870d7..772f773cb5f 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java
@@ -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;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java
index 3035f115c5c..3b12d8ba5f6 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileCache.java
@@ -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);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetection.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetection.java
index da4900f2145..7256c5592a3 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetection.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetection.java
@@ -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()));
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetectionFactory.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetectionFactory.java
index 814b6e380ed..6ff579fd769 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetectionFactory.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/LanguageDetectionFactory.java
@@ -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;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java
index 4a909f29cf4..d555074db79 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleInputFileCache.java
@@ -20,9 +20,10 @@
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);
- }
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java
index dd1e4a247c2..53729dde592 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java
@@ -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());
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java
index a2056966ef2..e3732308cf5 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java
@@ -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();
}
+
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java b/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java
index 20731c631a3..fe8ddc7826d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/report/JsonReport.java
@@ -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
index 00000000000..c0ae6dbbaab
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzersExecutor.java
@@ -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
index 00000000000..253bf0cab41
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultAnalyzerContext.java
@@ -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
index 00000000000..96ab8adc9de
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/MeasureCache.java
@@ -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();
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanContainer.java
index 44bcadc309c..24435c0dc55 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanContainer.java
@@ -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/phases/Phase2Executor.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/Phase2Executor.java
index 87d1348ae3b..fcbec9bf4b4 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/Phase2Executor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/Phase2Executor.java
@@ -17,19 +17,18 @@
* 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;
+package org.sonar.batch.scan2;
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.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 org.sonar.batch.scan.maven.MavenPluginsConfigurator;
import java.util.Collection;
@@ -37,32 +36,19 @@ 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 AnalyzersExecutor analyzersExecutor;
+ private final AnalyzerContext analyzerContext;
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,
+ public Phase2Executor(AnalyzersExecutor analyzersExecutor,
+ AnalyzerContext analyzerContext,
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.analyzersExecutor = analyzersExecutor;
+ this.analyzerContext = analyzerContext;
this.fsLogger = fsLogger;
this.fs = fs;
this.profileVerifier = profileVerifier;
@@ -70,20 +56,14 @@ public final class Phase2Executor {
}
public static Collection<Class> getPhaseClasses() {
- return Lists.<Class>newArrayList(SensorsExecutor.class, InitializersExecutor.class, ProjectInitializer.class);
+ return Lists.<Class>newArrayList(SensorsExecutor.class);
}
/**
* Executed on each module
*/
- public void execute(Project module) {
- pi.execute(module);
-
- eventBus.fireEvent(new ProjectAnalysisEvent(module, true));
-
- executeMavenPhase(module);
-
- executeInitializersPhase();
+ public void execute(ProjectDefinition moduleDefinition) {
+ fsLogger.log();
// Index and lock the filesystem
fs.index();
@@ -94,23 +74,6 @@ public final class Phase2Executor {
// 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));
- }
+ analyzersExecutor.execute(analyzerContext);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java
index 3ca92f4bc5b..6a3d9bfcfac 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java
@@ -20,41 +20,25 @@
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
index 00000000000..89f5c7694cc
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObserver.java
@@ -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
index 00000000000..6dc8fa6fd40
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObservers.java
@@ -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
index 00000000000..d5d167bf737
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/package-info.java
@@ -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
index 00000000000..6d2df16d3ab
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/settings/package-info.java
@@ -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
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
index 79af9782d6d..d7f5df2e761 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
@@ -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
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MetricProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MetricProviderTest.java
index 37b6736a89e..1af98413155 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MetricProviderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MetricProviderTest.java
@@ -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());
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java
index 564a6845a04..1fe27bc91b1 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java
@@ -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) {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java
index 065601b9a91..5b97df2c7f5 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java
@@ -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
index ae4a9ec02bb..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/medium/Scan2MediumTest.java
+++ /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();
- }
- }
-
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/ActiveRulesProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/ActiveRulesProviderTest.java
index c2039e71bf2..205fe2e8a8c 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/rule/ActiveRulesProviderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/ActiveRulesProviderTest.java
@@ -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());
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java
index 99b39d19986..6b3102206f3 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java
@@ -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'");
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
index a074f7185df..04ba7b1c251 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
@@ -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");
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileVerifierTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileVerifierTest.java
index 0fd8c58d040..483b6c7e397 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileVerifierTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileVerifierTest.java
@@ -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);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProfileProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProfileProviderTest.java
index 3a980631b1c..789f4a35485 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProfileProviderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProfileProviderTest.java
@@ -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);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/UsedQProfilesTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/UsedQProfilesTest.java
index b3cab37a325..1e9d47db0ec 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/rule/UsedQProfilesTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/UsedQProfilesTest.java
@@ -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(
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/LanguageVerifierTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/LanguageVerifierTest.java
index 8ea87446d82..30b6b571883 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/LanguageVerifierTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/LanguageVerifierTest.java
@@ -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
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java
index 86121955485..0bb4b243226 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java
@@ -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();
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java
index 4ae7bf09d6c..122b9c618de 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java
@@ -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);
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java
index 594a777095d..0de8ac80c56 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java
@@ -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);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java
index cc909035c1a..02f314e6b71 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java
@@ -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();
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java
index d84fdce8563..6255bd6629b 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java
@@ -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();
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java
index 268f007e1b9..e38081b62be 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java
@@ -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);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java
index 5193101ff38..067f1f99d58 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java
@@ -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");
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java
index 1dedd839828..3da4eeba2c0 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java
@@ -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");
- }
- }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionFactoryTest.java
index 35d09f661d6..cda01e16881 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionFactoryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionFactoryTest.java
@@ -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();
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java
index f1500b541c2..7c6eb7ff4f2 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java
@@ -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");
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java
index c232c3344f5..6f4f306a0c5 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java
@@ -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
index 00000000000..69ccd8d1411
--- /dev/null
+++ b/sonar-batch/src/test/resources/org/sonar/batch/medium/simple-project/sonar-project.properties
@@ -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
index 00000000000..b2e6462a3f9
--- /dev/null
+++ b/sonar-batch/src/test/resources/org/sonar/batch/medium/simple-project/sources/Fake.java
@@ -0,0 +1 @@
+Fake
diff --git a/sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java b/sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java
index 25d1a66d4b5..ed2e5abdd7f 100644
--- a/sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java
+++ b/sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java
@@ -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>
diff --git a/sonar-deprecated/src/main/java/org/sonar/api/batch/BatchExtensionDictionnary.java b/sonar-deprecated/src/main/java/org/sonar/api/batch/BatchExtensionDictionnary.java
index bc1deda33bb..c951512e8f6 100644
--- a/sonar-deprecated/src/main/java/org/sonar/api/batch/BatchExtensionDictionnary.java
+++ b/sonar-deprecated/src/main/java/org/sonar/api/batch/BatchExtensionDictionnary.java
@@ -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) {
diff --git a/sonar-plugin-api/pom.xml b/sonar-plugin-api/pom.xml
index 09d12366d3f..165e9fc5eaf 100644
--- a/sonar-plugin-api/pom.xml
+++ b/sonar-plugin-api/pom.xml
@@ -29,6 +29,10 @@
</dependency>
<dependency>
<groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-batch-plugin-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-colorizer</artifactId>
</dependency>
<dependency>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/InstantiationStrategy.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/InstantiationStrategy.java
index dcd215cd4c7..5cfea413fc5 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/InstantiationStrategy.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/InstantiationStrategy.java
@@ -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)
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
index bbe0af3c3d2..ccdec2dbf2f 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
@@ -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.
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
index 4eb61021ca5..1be238923ae 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
@@ -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/internal/DeprecatedDefaultInputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java
new file mode 100644
index 00000000000..fad4e6d43ce
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java
@@ -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/measures/CoreMetrics.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
index 025f27fc511..f94a4345af2 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
@@ -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)
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
index 3d38e52aea8..b6a90add399 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
@@ -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;
@@ -238,6 +238,38 @@ public class Measure implements Serializable {
}
/**
+ * 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
*/
public Integer getIntValue() {
@@ -692,4 +724,5 @@ public class Measure implements Serializable {
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
+
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java
index f11a225e668..c51973b79b7 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java
@@ -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) {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java
index bc809c88884..9ea0288fd0a 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java
@@ -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;
@@ -232,41 +251,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
*/
public Integer getId() {
@@ -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();
+ }
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectFileSystem.java
index 41ed8f6ff8a..944b1278a6a 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectFileSystem.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectFileSystem.java
@@ -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 {
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/AbstractSumChildrenDecoratorTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/AbstractSumChildrenDecoratorTest.java
index 67baa3cbfe0..9f6de72da31 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/AbstractSumChildrenDecoratorTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/AbstractSumChildrenDecoratorTest.java
@@ -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
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/TimeMachineQueryTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/TimeMachineQueryTest.java
index 7831cb2975e..1b4908c728e 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/TimeMachineQueryTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/TimeMachineQueryTest.java
@@ -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/DeprecatedDefaultInputFileTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java
new file mode 100644
index 00000000000..321efa8b681
--- /dev/null
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java
@@ -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-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java b/sonar-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java
index 2fa115a8626..9e375adfd29 100644
--- a/sonar-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java
@@ -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();