]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5931 Publish new measure API
authorJulien HENRY <julien.henry@sonarsource.com>
Wed, 14 Jan 2015 16:14:00 +0000 (17:14 +0100)
committerJulien HENRY <julien.henry@sonarsource.com>
Thu, 15 Jan 2015 08:08:58 +0000 (09:08 +0100)
58 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/BranchCoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/LineCoverageDecorator.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java [deleted file]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/LineCoverageDecoratorTest.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssueOnDirPerFileSensor.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java
sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/DeprecatedSensorContext.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java
sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java
sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdapter.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan2/AnalysisPublisher.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan2/MeasureCache.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanContainer.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanExecutor.java
sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObserver.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObservers.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorContext.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageConstants.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageExclusions.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/sensor/package-info.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorContextTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/sensor/coverage/CoverageExclusionsTest.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilter.java [deleted file]
sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilters.java [deleted file]
sonar-core/src/main/java/org/sonar/core/measure/package-info.java [deleted file]
sonar-core/src/test/java/org/sonar/core/measure/MeasurementFiltersTest.java [deleted file]
sonar-deprecated/src/main/java/org/sonar/api/checks/NoSonarFilter.java
sonar-deprecated/src/test/java/org/sonar/api/checks/NoSonarFilterTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/maven/DependsUponMavenPlugin.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/Sensor.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/Measure.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/NewMeasure.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java

index 68275cb247a12eccf3e6d83ac73ee76502f0d392..fb1eb26c69d59a3de4937aa882d7ecfff4a1bae0 100644 (file)
@@ -52,7 +52,6 @@ import org.sonar.plugins.core.security.ApplyProjectRolesDecorator;
 import org.sonar.plugins.core.sensors.BranchCoverageDecorator;
 import org.sonar.plugins.core.sensors.CommentDensityDecorator;
 import org.sonar.plugins.core.sensors.CoverageDecorator;
-import org.sonar.plugins.core.sensors.CoverageMeasurementFilter;
 import org.sonar.plugins.core.sensors.DirectoriesDecorator;
 import org.sonar.plugins.core.sensors.FileHashSensor;
 import org.sonar.plugins.core.sensors.FilesDecorator;
@@ -369,7 +368,6 @@ public final class CorePlugin extends SonarPlugin {
       OverallLineCoverageDecorator.class,
       OverallCoverageDecorator.class,
       OverallBranchCoverageDecorator.class,
-      CoverageMeasurementFilter.class,
       ApplyProjectRolesDecorator.class,
       CommentDensityDecorator.class,
       DirectoriesDecorator.class,
index 951c1d383a180e38ddd929dffe3487ffb0a93480..529883fc749b5eafae679a5d8374df3c027383ca 100644 (file)
  */
 package org.sonar.plugins.core.sensors;
 
-import com.google.common.collect.ImmutableList;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
+import org.sonar.batch.sensor.coverage.CoverageConstants;
 
-import java.util.List;
+import java.util.Collection;
 
 public final class BranchCoverageDecorator extends AbstractCoverageDecorator {
   @DependsUpon
-  public List<Metric> dependsUponMetrics() {
-    return ImmutableList.<Metric>of(CoreMetrics.UNCOVERED_CONDITIONS, CoreMetrics.CONDITIONS_TO_COVER,
-      CoreMetrics.NEW_UNCOVERED_CONDITIONS, CoreMetrics.NEW_CONDITIONS_TO_COVER);
+  public Collection<Metric> dependsUponMetrics() {
+    return CoverageConstants.BRANCH_COVERAGE_METRICS;
   }
 
   @Override
index 2d37d02dec9580dd1ea1c171b584615d69629a88..46b02d4e0f801ef1d55bd8ee182f1af6a181baf6 100644 (file)
  */
 package org.sonar.plugins.core.sensors;
 
-import com.google.common.collect.ImmutableList;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
+import org.sonar.batch.sensor.coverage.CoverageConstants;
 
 import java.util.Collection;
 
 public final class CoverageDecorator extends AbstractCoverageDecorator {
   @DependsUpon
   public Collection<Metric> usedMetrics() {
-    return ImmutableList.<Metric>of(CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.NEW_LINES_TO_COVER,
-      CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS,
-      CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS);
+    return CoverageConstants.COVERAGE_METRICS;
   }
 
   @Override
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java
deleted file mode 100644 (file)
index e236c62..0000000
+++ /dev/null
@@ -1,104 +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.plugins.core.sensors;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
-import com.google.common.collect.ImmutableSet;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.Settings;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.utils.WildcardPattern;
-import org.sonar.core.measure.MeasurementFilter;
-
-import java.util.Collection;
-import java.util.Iterator;
-
-public class CoverageMeasurementFilter implements MeasurementFilter {
-
-  private static final Logger LOG = LoggerFactory.getLogger(CoverageMeasurementFilter.class);
-
-  private final Settings settings;
-  private final ImmutableSet<Metric> coverageMetrics;
-  private Collection<WildcardPattern> resourcePatterns;
-
-  public CoverageMeasurementFilter(Settings settings,
-    CoverageDecorator coverageDecorator,
-    LineCoverageDecorator lineCoverageDecorator,
-    BranchCoverageDecorator branchCoverageDecorator) {
-    this.settings = settings;
-    this.coverageMetrics = ImmutableSet.<Metric>builder()
-      .addAll(coverageDecorator.generatedMetrics())
-      .addAll(coverageDecorator.usedMetrics())
-      .addAll(lineCoverageDecorator.generatedMetrics())
-      .addAll(lineCoverageDecorator.dependsUponMetrics())
-      .addAll(branchCoverageDecorator.generatedMetrics())
-      .addAll(branchCoverageDecorator.dependsUponMetrics())
-      .build();
-
-    initPatterns();
-  }
-
-  @Override
-  public boolean accept(Resource resource, Measure measure) {
-    if (isCoverageMetric(measure.getMetric())) {
-      return !hasMatchingPattern(resource);
-    } else {
-      return true;
-    }
-  }
-
-  private boolean isCoverageMetric(Metric metric) {
-    return this.coverageMetrics.contains(metric);
-  }
-
-  private boolean hasMatchingPattern(Resource resource) {
-    boolean found = false;
-    Iterator<WildcardPattern> iterator = resourcePatterns.iterator();
-    while (!found && iterator.hasNext()) {
-      found = resource.matchFilePattern(iterator.next().toString());
-    }
-    return found;
-  }
-
-  @VisibleForTesting
-  final void initPatterns() {
-    Builder<WildcardPattern> builder = ImmutableList.builder();
-    for (String pattern : settings.getStringArray(CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY)) {
-      builder.add(WildcardPattern.create(pattern));
-    }
-    resourcePatterns = builder.build();
-    log("Excluded sources for coverage: ", resourcePatterns);
-  }
-
-  private void log(String title, Collection<WildcardPattern> patterns) {
-    if (!patterns.isEmpty()) {
-      LOG.info(title);
-      for (WildcardPattern pattern : patterns) {
-        LOG.info("  " + pattern);
-      }
-    }
-  }
-}
index feaf04176cf0a2b3cfbdb7f50d0f44978df274f1..11ff93f0634bd86d4bf657aed145b61568473bda 100644 (file)
  */
 package org.sonar.plugins.core.sensors;
 
-import com.google.common.collect.ImmutableList;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
+import org.sonar.batch.sensor.coverage.CoverageConstants;
 
-import java.util.List;
+import java.util.Collection;
 
 public final class LineCoverageDecorator extends AbstractCoverageDecorator {
   @DependsUpon
-  public List<Metric> dependsUponMetrics() {
-    return ImmutableList.<Metric>of(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES,
-      CoreMetrics.NEW_LINES_TO_COVER);
+  public Collection<Metric> dependsUponMetrics() {
+    return CoverageConstants.LINE_COVERAGE_METRICS;
   }
 
   @Override
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java
deleted file mode 100644 (file)
index 85ca73d..0000000
+++ /dev/null
@@ -1,76 +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.plugins.core.sensors;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.config.Settings;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Resource;
-import org.sonar.core.config.ExclusionProperties;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class CoverageMeasurementFilterTest {
-
-  private Settings settings;
-
-  private CoverageMeasurementFilter filter;
-
-  @Before
-  public void createFilter() {
-    settings = new Settings(new PropertyDefinitions(ExclusionProperties.all()));
-    filter = new CoverageMeasurementFilter(settings, new CoverageDecorator(), new LineCoverageDecorator(), new BranchCoverageDecorator());
-  }
-
-  @Test
-  public void shouldNotFilterNonCoverageMetrics() {
-    Measure otherMeasure = mock(Measure.class);
-    when(otherMeasure.getMetric()).thenReturn(CoreMetrics.LINES);
-    assertThat(filter.accept(mock(Resource.class), otherMeasure)).isTrue();
-  }
-
-  @Test
-  public void shouldFilterFileBasedOnPattern() {
-    Resource resource = File.create("src/org/polop/File.php", "org/polop/File.php", null, false);
-    Measure coverageMeasure = mock(Measure.class);
-    when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.LINES_TO_COVER);
-
-    settings.setProperty("sonar.coverage.exclusions", "src/org/polop/*");
-    filter.initPatterns();
-    assertThat(filter.accept(resource, coverageMeasure)).isFalse();
-  }
-
-  @Test
-  public void shouldNotFilterFileBasedOnPattern() {
-    Resource resource = File.create("src/org/polop/File.php", "org/polop/File.php", null, false);
-    Measure coverageMeasure = mock(Measure.class);
-    when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.COVERAGE);
-
-    settings.setProperty("sonar.coverage.exclusions", "src/org/other/*");
-    filter.initPatterns();
-    assertThat(filter.accept(resource, coverageMeasure)).isTrue();
-  }
-}
index 87dd7f9ae6d8a0ef1c17f76401a2e5540a580f91..e2956df168399962653fa6e38300df46cc353d53 100644 (file)
@@ -24,15 +24,12 @@ import org.junit.Test;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Scopes;
 
-import java.util.List;
-
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.anyDouble;
-import static org.mockito.Mockito.eq;
+import static org.mockito.Matchers.anyDouble;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -49,9 +46,8 @@ public class LineCoverageDecoratorTest {
 
   @Test
   public void should_depend_on_coverage_metrics() {
-    List<Metric> metrics = decorator.dependsUponMetrics();
-
-    assertThat(metrics).containsOnly(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.NEW_LINES_TO_COVER);
+    assertThat(decorator.dependsUponMetrics()).containsOnly(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES,
+      CoreMetrics.NEW_LINES_TO_COVER);
   }
 
   @Test
index 471a5835639dc1b2dc2c27b73abe7a06dc8419db..a890b63ac9d0c126f0d66b3b50c41f9ecce59efe 100644 (file)
@@ -28,8 +28,7 @@ import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.batch.sensor.measure.NewMeasure;
 import org.sonar.xoo.Xoo;
 
 import java.io.File;
@@ -88,7 +87,7 @@ public class MeasureSensor implements Sensor {
     if (metric == null) {
       throw new IllegalStateException("Unknow metric with key: " + metricKey);
     }
-    Measure<Serializable> newMeasure = context.newMeasure()
+    NewMeasure<Serializable> newMeasure = context.newMeasure()
       .forMetric(metric)
       .onFile(xooFile);
     if (Boolean.class.equals(metric.valueType())) {
@@ -111,9 +110,7 @@ public class MeasureSensor implements Sensor {
   public void describe(SensorDescriptor descriptor) {
     descriptor
       .name("Xoo Measure Sensor")
-      .provides(CoreMetrics.LINES)
-      .onlyOnLanguages(Xoo.KEY)
-      .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+      .onlyOnLanguages(Xoo.KEY);
   }
 
   @Override
index fbff5f756419d5b5f06423ef2f4ad1711ba2e5e4..8d14771bab48190f7d5e29e032f87aba5d2a85cd 100644 (file)
@@ -87,8 +87,7 @@ public class SymbolReferencesSensor implements Sensor {
   public void describe(SensorDescriptor descriptor) {
     descriptor
       .name("Xoo Symbol Reference Sensor")
-      .onlyOnLanguages(Xoo.KEY)
-      .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+      .onlyOnLanguages(Xoo.KEY);
   }
 
   @Override
index d72b50b4089bad9f12a91305421155d950f7e712..004c186b2089502db27bdc58ab5957c8bc761ea9 100644 (file)
@@ -85,8 +85,7 @@ public class SyntaxHighlightingSensor implements Sensor {
   public void describe(SensorDescriptor descriptor) {
     descriptor
       .name("Xoo Highlighting Sensor")
-      .onlyOnLanguages(Xoo.KEY)
-      .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+      .onlyOnLanguages(Xoo.KEY);
   }
 
   @Override
index 04dc7be446f3507d3442258e9486f4feb2027667..886104c14a01b911f9c41ffb322bd5dac9ece81b 100644 (file)
@@ -35,8 +35,7 @@ public class CreateIssueByInternalKeySensor implements Sensor {
     descriptor
       .name("CreateIssueByInternalKeySensor")
       .onlyOnLanguages(Xoo.KEY)
-      .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY)
-      .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+      .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY);
   }
 
   @Override
index 548b596c3005c4a65f2d4d09678098d78e81f6d1..66a31686e03eafff5288cd1b3feff417578a8a89 100644 (file)
@@ -36,8 +36,7 @@ public class OneIssueOnDirPerFileSensor implements Sensor {
     descriptor
       .name("One Issue On Dir Per File")
       .onlyOnLanguages(Xoo.KEY)
-      .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY)
-      .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+      .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY);
   }
 
   @Override
index 081bb1a0a2bee41ec49eef6730b2e00fa8b018b8..3e0b9f48ee50f5c1b122115e6b42d382b5f94ad8 100644 (file)
@@ -24,7 +24,6 @@ import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.SensorDescriptor;
 import org.sonar.api.batch.sensor.issue.Issue.Severity;
-import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.xoo.Xoo;
 
@@ -38,10 +37,8 @@ public class OneIssuePerLineSensor implements Sensor {
   public void describe(SensorDescriptor descriptor) {
     descriptor
       .name("One Issue Per Line")
-      .dependsOn(CoreMetrics.LINES)
       .onlyOnLanguages(Xoo.KEY)
-      .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY)
-      .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+      .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY);
   }
 
   @Override
index 1fa2a1b6450e881ff3cf6895848609e45f742147..3d18e06c5a91a6bf78403b19c74d17f913df8b9a 100644 (file)
@@ -40,7 +40,7 @@ import org.sonar.api.utils.SonarException;
 import org.sonar.batch.duplication.DuplicationCache;
 import org.sonar.batch.duplication.DuplicationUtils;
 import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.core.measure.MeasurementFilters;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
 
 import java.util.Arrays;
 import java.util.Collection;
@@ -54,7 +54,6 @@ public class DefaultDecoratorContext implements DecoratorContext {
   private static final String SAVE_MEASURE_METHOD = "saveMeasure";
   private SonarIndex sonarIndex;
   private Resource resource;
-  private MeasurementFilters measurementFilters;
   private boolean readOnly = false;
 
   private List<DecoratorContext> childrenContexts;
@@ -63,18 +62,19 @@ public class DefaultDecoratorContext implements DecoratorContext {
   private MeasureCache measureCache;
   private MetricFinder metricFinder;
   private final DuplicationCache duplicationCache;
+  private final CoverageExclusions coverageFilter;
 
   public DefaultDecoratorContext(Resource resource,
     SonarIndex index,
     List<DecoratorContext> childrenContexts,
-    MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder, DuplicationCache duplicationCache) {
+    MeasureCache measureCache, MetricFinder metricFinder, DuplicationCache duplicationCache, CoverageExclusions coverageFilter) {
     this.sonarIndex = index;
     this.resource = resource;
     this.childrenContexts = childrenContexts;
-    this.measurementFilters = measurementFilters;
     this.measureCache = measureCache;
     this.metricFinder = metricFinder;
     this.duplicationCache = duplicationCache;
+    this.coverageFilter = coverageFilter;
   }
 
   public void init() {
@@ -178,7 +178,7 @@ public class DefaultDecoratorContext implements DecoratorContext {
       throw new SonarException("Unknown metric: " + measure.getMetricKey());
     }
     measure.setMetric(metric);
-    if (measurementFilters.accept(resource, measure)) {
+    if (coverageFilter.accept(resource, measure)) {
       List<Measure> metricMeasures = measuresByMetric.get(measure.getMetricKey());
 
       boolean add = true;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
deleted file mode 100644 (file)
index eeecd48..0000000
+++ /dev/null
@@ -1,285 +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;
-
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.Event;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.batch.SonarIndex;
-import org.sonar.api.batch.fs.InputDir;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputPath;
-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.Directory;
-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;
-import java.util.Set;
-
-public class DefaultSensorContext implements SensorContext {
-
-  private static final Logger LOG = LoggerFactory.getLogger(DefaultSensorContext.class);
-
-  private SonarIndex index;
-  private Project project;
-  private MeasurementFilters filters;
-
-  public DefaultSensorContext(SonarIndex index, Project project, MeasurementFilters filters) {
-    this.index = index;
-    this.project = project;
-    this.filters = filters;
-  }
-
-  public Project getProject() {
-    return project;
-  }
-
-  @Override
-  public boolean index(Resource resource) {
-    // SONAR-5006
-    if (indexedByCore(resource)) {
-      logWarning();
-      return true;
-    }
-    return index.index(resource);
-  }
-
-  private boolean indexedByCore(Resource resource) {
-    return StringUtils.equals(Qualifiers.DIRECTORY, resource.getQualifier()) ||
-      StringUtils.equals(Qualifiers.FILE, resource.getQualifier());
-  }
-
-  @Override
-  public boolean index(Resource resource, Resource parentReference) {
-    // SONAR-5006
-    if (indexedByCore(resource)) {
-      logWarning();
-      return true;
-    }
-    return index.index(resource, parentReference);
-  }
-
-  private void logWarning() {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Plugins are no more responsible for indexing physical resources like directories and files. This is now handled by the platform.", new SonarException(
-        "Plugin should not index physical resources"));
-    }
-  }
-
-  @Override
-  public boolean isExcluded(Resource reference) {
-    return index.isExcluded(reference);
-  }
-
-  @Override
-  public boolean isIndexed(Resource reference, boolean acceptExcluded) {
-    return index.isIndexed(reference, acceptExcluded);
-  }
-
-  @Override
-  public Resource getParent(Resource reference) {
-    return index.getParent(reference);
-  }
-
-  @Override
-  public Collection<Resource> getChildren(Resource reference) {
-    return index.getChildren(reference);
-  }
-
-  @Override
-  public <G extends Serializable> Measure<G> getMeasure(Metric<G> metric) {
-    return index.getMeasure(project, metric);
-  }
-
-  @Override
-  public <M> M getMeasures(MeasuresFilter<M> filter) {
-    return index.getMeasures(project, filter);
-  }
-
-  @Override
-  public Measure saveMeasure(Measure measure) {
-    return index.addMeasure(project, measure);
-  }
-
-  @Override
-  public Measure saveMeasure(Metric metric, Double value) {
-    return index.addMeasure(project, new Measure(metric, value));
-  }
-
-  @Override
-  public <G extends Serializable> Measure<G> getMeasure(Resource resource, Metric<G> metric) {
-    return index.getMeasure(resource, metric);
-  }
-
-  @Override
-  public String saveResource(Resource resource) {
-    Resource persistedResource = index.addResource(resource);
-    if (persistedResource != null) {
-      return persistedResource.getEffectiveKey();
-    }
-    return null;
-  }
-
-  public boolean saveResource(Resource resource, Resource parentReference) {
-    return index.index(resource, parentReference);
-  }
-
-  @Override
-  public Resource getResource(Resource resource) {
-    return index.getResource(resource);
-  }
-
-  @Override
-  public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) {
-    return index.getMeasures(resource, filter);
-  }
-
-  @Override
-  public Measure saveMeasure(Resource resource, Metric metric, Double value) {
-    return saveMeasure(resource, new Measure(metric, value));
-  }
-
-  @Override
-  public Measure saveMeasure(Resource resource, Measure measure) {
-    if (filters.accept(resource, measure)) {
-      return index.addMeasure(resourceOrProject(resource), measure);
-    } else {
-      return measure;
-    }
-  }
-
-  @Override
-  public void saveViolation(Violation violation, boolean force) {
-    if (violation.getResource() == null) {
-      violation.setResource(resourceOrProject(violation.getResource()));
-    }
-    index.addViolation(violation, force);
-  }
-
-  @Override
-  public void saveViolation(Violation violation) {
-    saveViolation(violation, false);
-  }
-
-  @Override
-  public void saveViolations(Collection<Violation> violations) {
-    if (violations != null) {
-      for (Violation violation : violations) {
-        saveViolation(violation);
-      }
-    }
-  }
-
-  @Override
-  public Dependency saveDependency(Dependency dependency) {
-    return index.addDependency(dependency);
-  }
-
-  @Override
-  public Set<Dependency> getDependencies() {
-    return index.getDependencies();
-  }
-
-  @Override
-  public Collection<Dependency> getIncomingDependencies(Resource to) {
-    return index.getIncomingEdges(resourceOrProject(to));
-  }
-
-  @Override
-  public Collection<Dependency> getOutgoingDependencies(Resource from) {
-    return index.getOutgoingEdges(resourceOrProject(from));
-  }
-
-  @Override
-  public void saveSource(Resource reference, String source) {
-    // useless since 4.2.
-  }
-
-  @Override
-  public void saveLink(ProjectLink link) {
-    index.addLink(link);
-  }
-
-  @Override
-  public void deleteLink(String key) {
-    index.deleteLink(key);
-  }
-
-  @Override
-  public List<Event> getEvents(Resource resource) {
-    return index.getEvents(resource);
-  }
-
-  @Override
-  public Event createEvent(Resource resource, String name, String description, String category, Date date) {
-    return index.addEvent(resource, name, description, category, date);
-  }
-
-  @Override
-  public void deleteEvent(Event event) {
-    index.deleteEvent(event);
-  }
-
-  private Resource resourceOrProject(Resource resource) {
-    if (resource == null) {
-      return project;
-    }
-    Resource indexedResource = getResource(resource);
-    return indexedResource != null ? indexedResource : resource;
-  }
-
-  @Override
-  public Measure saveMeasure(InputFile inputFile, Metric metric, Double value) {
-    return saveMeasure(getResource(inputFile), metric, value);
-  }
-
-  @Override
-  public Measure saveMeasure(InputFile inputFile, Measure measure) {
-    return saveMeasure(getResource(inputFile), measure);
-  }
-
-  @Override
-  public Resource getResource(InputPath inputPath) {
-    Resource r;
-    if (inputPath instanceof InputDir) {
-      r = Directory.create(((InputDir) inputPath).relativePath());
-    } else if (inputPath instanceof InputFile) {
-      r = File.create(((InputFile) inputPath).relativePath());
-    } else {
-      throw new IllegalArgumentException("Unknow input path type: " + inputPath);
-    }
-    return getResource(r);
-  }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DeprecatedSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DeprecatedSensorContext.java
new file mode 100644 (file)
index 0000000..35d3296
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * 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;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.Event;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.SonarIndex;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputDir;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputPath;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.sensor.SensorStorage;
+import org.sonar.api.config.Settings;
+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.Directory;
+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.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.sensor.DefaultSensorContext;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+public class DeprecatedSensorContext extends DefaultSensorContext implements SensorContext {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DeprecatedSensorContext.class);
+
+  private final SonarIndex index;
+  private final Project project;
+  private final CoverageExclusions coverageFilter;
+
+  public DeprecatedSensorContext(SonarIndex index, Project project, Settings settings, FileSystem fs, ActiveRules activeRules,
+    ComponentDataCache componentDataCache, CoverageExclusions coverageFilter,
+    BlockCache blockCache, DuplicationCache duplicationCache, SensorStorage sensorStorage) {
+    super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache, sensorStorage);
+    this.index = index;
+    this.project = project;
+    this.coverageFilter = coverageFilter;
+  }
+
+  public Project getProject() {
+    return project;
+  }
+
+  @Override
+  public boolean index(Resource resource) {
+    // SONAR-5006
+    if (indexedByCore(resource)) {
+      logWarning();
+      return true;
+    }
+    return index.index(resource);
+  }
+
+  private boolean indexedByCore(Resource resource) {
+    return StringUtils.equals(Qualifiers.DIRECTORY, resource.getQualifier()) ||
+      StringUtils.equals(Qualifiers.FILE, resource.getQualifier());
+  }
+
+  @Override
+  public boolean index(Resource resource, Resource parentReference) {
+    // SONAR-5006
+    if (indexedByCore(resource)) {
+      logWarning();
+      return true;
+    }
+    return index.index(resource, parentReference);
+  }
+
+  private void logWarning() {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Plugins are no more responsible for indexing physical resources like directories and files. This is now handled by the platform.", new SonarException(
+        "Plugin should not index physical resources"));
+    }
+  }
+
+  @Override
+  public boolean isExcluded(Resource reference) {
+    return index.isExcluded(reference);
+  }
+
+  @Override
+  public boolean isIndexed(Resource reference, boolean acceptExcluded) {
+    return index.isIndexed(reference, acceptExcluded);
+  }
+
+  @Override
+  public Resource getParent(Resource reference) {
+    return index.getParent(reference);
+  }
+
+  @Override
+  public Collection<Resource> getChildren(Resource reference) {
+    return index.getChildren(reference);
+  }
+
+  @Override
+  public <G extends Serializable> Measure<G> getMeasure(Metric<G> metric) {
+    return index.getMeasure(project, metric);
+  }
+
+  @Override
+  public <M> M getMeasures(MeasuresFilter<M> filter) {
+    return index.getMeasures(project, filter);
+  }
+
+  @Override
+  public Measure saveMeasure(Measure measure) {
+    return index.addMeasure(project, measure);
+  }
+
+  @Override
+  public Measure saveMeasure(Metric metric, Double value) {
+    return index.addMeasure(project, new Measure(metric, value));
+  }
+
+  @Override
+  public <G extends Serializable> Measure<G> getMeasure(Resource resource, Metric<G> metric) {
+    return index.getMeasure(resource, metric);
+  }
+
+  @Override
+  public String saveResource(Resource resource) {
+    Resource persistedResource = index.addResource(resource);
+    if (persistedResource != null) {
+      return persistedResource.getEffectiveKey();
+    }
+    return null;
+  }
+
+  public boolean saveResource(Resource resource, Resource parentReference) {
+    return index.index(resource, parentReference);
+  }
+
+  @Override
+  public Resource getResource(Resource resource) {
+    return index.getResource(resource);
+  }
+
+  @Override
+  public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) {
+    return index.getMeasures(resource, filter);
+  }
+
+  @Override
+  public Measure saveMeasure(Resource resource, Metric metric, Double value) {
+    return saveMeasure(resource, new Measure(metric, value));
+  }
+
+  @Override
+  public Measure saveMeasure(Resource resource, Measure measure) {
+    Resource resourceOrProject = resourceOrProject(resource);
+    if (coverageFilter.accept(resourceOrProject, measure)) {
+      return index.addMeasure(resourceOrProject, measure);
+    } else {
+      return measure;
+    }
+  }
+
+  @Override
+  public void saveViolation(Violation violation, boolean force) {
+    if (violation.getResource() == null) {
+      violation.setResource(resourceOrProject(violation.getResource()));
+    }
+    index.addViolation(violation, force);
+  }
+
+  @Override
+  public void saveViolation(Violation violation) {
+    saveViolation(violation, false);
+  }
+
+  @Override
+  public void saveViolations(Collection<Violation> violations) {
+    if (violations != null) {
+      for (Violation violation : violations) {
+        saveViolation(violation);
+      }
+    }
+  }
+
+  @Override
+  public Dependency saveDependency(Dependency dependency) {
+    return index.addDependency(dependency);
+  }
+
+  @Override
+  public Set<Dependency> getDependencies() {
+    return index.getDependencies();
+  }
+
+  @Override
+  public Collection<Dependency> getIncomingDependencies(Resource to) {
+    return index.getIncomingEdges(resourceOrProject(to));
+  }
+
+  @Override
+  public Collection<Dependency> getOutgoingDependencies(Resource from) {
+    return index.getOutgoingEdges(resourceOrProject(from));
+  }
+
+  @Override
+  public void saveSource(Resource reference, String source) {
+    // useless since 4.2.
+  }
+
+  @Override
+  public void saveLink(ProjectLink link) {
+    index.addLink(link);
+  }
+
+  @Override
+  public void deleteLink(String key) {
+    index.deleteLink(key);
+  }
+
+  @Override
+  public List<Event> getEvents(Resource resource) {
+    return index.getEvents(resource);
+  }
+
+  @Override
+  public Event createEvent(Resource resource, String name, String description, String category, Date date) {
+    return index.addEvent(resource, name, description, category, date);
+  }
+
+  @Override
+  public void deleteEvent(Event event) {
+    index.deleteEvent(event);
+  }
+
+  private Resource resourceOrProject(Resource resource) {
+    if (resource == null) {
+      return project;
+    }
+    Resource indexedResource = getResource(resource);
+    return indexedResource != null ? indexedResource : resource;
+  }
+
+  @Override
+  public Measure saveMeasure(InputFile inputFile, Metric metric, Double value) {
+    return saveMeasure(getResource(inputFile), metric, value);
+  }
+
+  @Override
+  public Measure saveMeasure(InputFile inputFile, Measure measure) {
+    return saveMeasure(getResource(inputFile), measure);
+  }
+
+  @Override
+  public Resource getResource(InputPath inputPath) {
+    Resource r;
+    if (inputPath instanceof InputDir) {
+      r = Directory.create(((InputDir) inputPath).relativePath());
+    } else if (inputPath instanceof InputFile) {
+      r = File.create(((InputFile) inputPath).relativePath());
+    } else {
+      throw new IllegalArgumentException("Unknow input path type: " + inputPath);
+    }
+    return getResource(r);
+  }
+}
index 32bebf6182ee3ff6e1e8fe1f08c14271b0f5545d..e0a0e34851434e997f41210dce3063f03636b9f5 100644 (file)
@@ -29,6 +29,7 @@ import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
 import org.sonar.batch.scan.SensorWrapper;
 import org.sonar.batch.scan2.AnalyzerOptimizer;
+import org.sonar.batch.sensor.DefaultSensorContext;
 
 import javax.annotation.Nullable;
 
@@ -43,7 +44,7 @@ public class BatchExtensionDictionnary extends org.sonar.api.batch.BatchExtensio
   private SensorContext context;
   private AnalyzerOptimizer analyzerOptimizer;
 
-  public BatchExtensionDictionnary(ComponentContainer componentContainer, SensorContext context, AnalyzerOptimizer analyzerOptimizer) {
+  public BatchExtensionDictionnary(ComponentContainer componentContainer, DefaultSensorContext context, AnalyzerOptimizer analyzerOptimizer) {
     super(componentContainer);
     this.context = context;
     this.analyzerOptimizer = analyzerOptimizer;
index 9e3a3d1b133234ac117e363ff43852a0ed92630d..64886cc15298bcdb59e243b32d3be890ea347aea 100644 (file)
@@ -31,8 +31,10 @@ import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.Event;
 import org.sonar.api.batch.SonarIndex;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.measure.Metric;
 import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.MeasuresFilter;
 import org.sonar.api.measures.MeasuresFilters;
@@ -51,7 +53,6 @@ import org.sonar.api.utils.SonarException;
 import org.sonar.batch.ProjectTree;
 import org.sonar.batch.issue.ModuleIssues;
 import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.batch.scan2.DefaultSensorContext;
 import org.sonar.core.component.ComponentKeys;
 
 import javax.annotation.CheckForNull;
@@ -59,6 +60,7 @@ import javax.annotation.Nullable;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
@@ -72,6 +74,31 @@ public class DefaultIndex extends SonarIndex {
 
   private static final Logger LOG = LoggerFactory.getLogger(DefaultIndex.class);
 
+  private static final List<Metric> INTERNAL_METRICS = Arrays.<Metric>asList(
+    // Computed by DsmDecorator
+    CoreMetrics.DEPENDENCY_MATRIX,
+    CoreMetrics.DIRECTORY_CYCLES,
+    CoreMetrics.DIRECTORY_EDGES_WEIGHT,
+    CoreMetrics.DIRECTORY_FEEDBACK_EDGES,
+    CoreMetrics.DIRECTORY_TANGLE_INDEX,
+    CoreMetrics.DIRECTORY_TANGLES,
+    CoreMetrics.FILE_CYCLES,
+    CoreMetrics.FILE_EDGES_WEIGHT,
+    CoreMetrics.FILE_FEEDBACK_EDGES,
+    CoreMetrics.FILE_TANGLE_INDEX,
+    CoreMetrics.FILE_TANGLES,
+    // Computed by ScmActivitySensor
+    CoreMetrics.SCM_AUTHORS_BY_LINE,
+    CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE,
+    CoreMetrics.SCM_REVISIONS_BY_LINE,
+    // Computed by core duplication plugin
+    CoreMetrics.DUPLICATIONS_DATA,
+    CoreMetrics.DUPLICATION_LINES_DATA,
+    CoreMetrics.DUPLICATED_FILES,
+    CoreMetrics.DUPLICATED_LINES,
+    CoreMetrics.DUPLICATED_BLOCKS
+    );
+
   private final ResourceCache resourceCache;
   private final MetricFinder metricFinder;
 
@@ -228,7 +255,7 @@ public class DefaultIndex extends SonarIndex {
       if (metric == null) {
         throw new SonarException("Unknown metric: " + measure.getMetricKey());
       }
-      if (!isTechnicalProjectCopy(resource) && !measure.isFromCore() && DefaultSensorContext.INTERNAL_METRICS.contains(metric)) {
+      if (!isTechnicalProjectCopy(resource) && !measure.isFromCore() && INTERNAL_METRICS.contains(metric)) {
         LOG.debug("Metric " + metric.key() + " is an internal metric computed by SonarQube. Please update your plugin.");
         return measure;
       }
index b9216a859f7c7d121d365f8bdaf3661c6e4ed778..7bc120b37d68a7a1f87098fb2782186836fef719 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.batch.mediumtest;
 
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.fs.InputDir;
@@ -28,6 +29,7 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.sensor.dependency.Dependency;
 import org.sonar.api.batch.sensor.duplication.DuplicationGroup;
 import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.batch.sensor.symbol.Symbol;
 import org.sonar.api.batch.sensor.test.TestCaseCoverage;
 import org.sonar.api.batch.sensor.test.TestCaseExecution;
@@ -51,6 +53,7 @@ import org.sonar.core.source.SnapshotDataTypes;
 
 import javax.annotation.CheckForNull;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -64,7 +67,7 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
   private static final Logger LOG = LoggerFactory.getLogger(TaskResult.class);
 
   private List<Issue> issues = new ArrayList<>();
-  private List<Measure> measures = new ArrayList<>();
+  private List<org.sonar.api.batch.sensor.measure.Measure> measures = new ArrayList<>();
   private Map<String, List<DuplicationGroup>> duplications = new HashMap<>();
   private Map<String, InputFile> inputFiles = new HashMap<>();
   private Map<String, InputDir> inputDirs = new HashMap<>();
@@ -81,11 +84,10 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
       issues.add(issue);
     }
 
-    for (Measure measure : container.getComponentByType(MeasureCache.class).all()) {
-      measures.add(measure);
-    }
-
     storeFs(container);
+
+    storeMeasures(container);
+
     storeComponentData(container);
     storeDuplication(container);
     // storeTestCases(container);
@@ -94,6 +96,24 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
 
   }
 
+  private void storeMeasures(ProjectScanContainer container) {
+    InputPathCache inputFileCache = container.getComponentByType(InputPathCache.class);
+    for (Entry<Measure> measureEntry : container.getComponentByType(MeasureCache.class).entries()) {
+      String componentKey = measureEntry.key()[0].toString();
+      InputFile file = inputFileCache.getFile(StringUtils.substringBeforeLast(componentKey, ":"), StringUtils.substringAfterLast(componentKey, ":"));
+      Measure oldMeasure = measureEntry.value();
+      DefaultMeasure<Serializable> newMeasure = new DefaultMeasure<>()
+        .forMetric(oldMeasure.getMetric());
+      if (file != null) {
+        newMeasure.onFile(file);
+      } else {
+        newMeasure.onProject();
+      }
+      newMeasure.withValue(oldMeasure.value());
+      measures.add(newMeasure);
+    }
+  }
+
   private void storeCoveragePerTest(ProjectScanContainer container) {
     TestCaseCoverageCache testCaseCoverageCache = container.getComponentByType(TestCaseCoverageCache.class);
     for (Entry<TestCaseCoverage> entry : testCaseCoverageCache.entries()) {
@@ -170,7 +190,7 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
     return issues;
   }
 
-  public List<Measure> measures() {
+  public List<org.sonar.api.batch.sensor.measure.Measure> measures() {
     return measures;
   }
 
index b867e0fc0104c084f09f65c899277346078fbdd6..01ae1e452d896b1744f69067e7ac103c11786e5e 100644 (file)
@@ -35,7 +35,7 @@ import org.sonar.batch.DefaultDecoratorContext;
 import org.sonar.batch.duplication.DuplicationCache;
 import org.sonar.batch.events.EventBus;
 import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.core.measure.MeasurementFilters;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
 
 import java.util.Collection;
 import java.util.List;
@@ -46,13 +46,13 @@ public class DecoratorsExecutor implements BatchComponent {
   private SonarIndex index;
   private EventBus eventBus;
   private Project project;
-  private MeasurementFilters measurementFilters;
+  private CoverageExclusions coverageFilter;
   private MeasureCache measureCache;
   private MetricFinder metricFinder;
   private final DuplicationCache duplicationCache;
 
   public DecoratorsExecutor(BatchExtensionDictionnary batchExtDictionnary,
-    Project project, SonarIndex index, EventBus eventBus, MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder,
+    Project project, SonarIndex index, EventBus eventBus, CoverageExclusions coverageFilter, MeasureCache measureCache, MetricFinder metricFinder,
     DuplicationCache duplicationCache) {
     this.measureCache = measureCache;
     this.metricFinder = metricFinder;
@@ -61,7 +61,7 @@ public class DecoratorsExecutor implements BatchComponent {
     this.index = index;
     this.eventBus = eventBus;
     this.project = project;
-    this.measurementFilters = measurementFilters;
+    this.coverageFilter = coverageFilter;
   }
 
   public void execute() {
@@ -79,7 +79,7 @@ public class DecoratorsExecutor implements BatchComponent {
       childrenContexts.add(childContext.end());
     }
 
-    DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, measurementFilters, measureCache, metricFinder, duplicationCache);
+    DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, measureCache, metricFinder, duplicationCache, coverageFilter);
     context.init();
     if (executeDecorators) {
       for (Decorator decorator : decorators) {
index af680789d8021b77592be79267c31b67d199496c..98598f57f33b87b44a933685cd79d87ddb863324 100644 (file)
@@ -31,8 +31,8 @@ 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.DeprecatedSensorContext;
 import org.sonar.batch.ProjectTree;
 import org.sonar.batch.ResourceFilters;
 import org.sonar.batch.bootstrap.BatchExtensionDictionnary;
@@ -97,8 +97,10 @@ import org.sonar.batch.scan.filesystem.StatusDetectionFactory;
 import org.sonar.batch.scan.maven.MavenPluginsConfigurator;
 import org.sonar.batch.scan.report.JsonReport;
 import org.sonar.batch.scan2.AnalyzerOptimizer;
+import org.sonar.batch.sensor.DefaultSensorContext;
+import org.sonar.batch.sensor.DefaultSensorStorage;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
 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);
@@ -174,11 +176,12 @@ public class ModuleScanContainer extends ComponentContainer {
       AnalyzerOptimizer.class,
 
       DefaultSensorContext.class,
-      SensorContextAdapter.class,
+      DefaultSensorStorage.class,
+      DeprecatedSensorContext.class,
       BatchExtensionDictionnary.class,
       DefaultTimeMachine.class,
       IssueFilters.class,
-      MeasurementFilters.class,
+      CoverageExclusions.class,
       ResourceFilters.class,
 
       // rules
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdapter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdapter.java
deleted file mode 100644 (file)
index a8d57e8..0000000
+++ /dev/null
@@ -1,267 +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.scan;
-
-import org.sonar.api.batch.Sensor;
-import org.sonar.api.batch.SonarIndex;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputDir;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputPath;
-import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.batch.sensor.test.TestCaseCoverage;
-import org.sonar.api.batch.sensor.test.TestCaseExecution;
-import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.config.Settings;
-import org.sonar.api.design.Dependency;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.measures.Formula;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.PersistenceMode;
-import org.sonar.api.measures.SumChildDistributionFormula;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.resources.Scopes;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.test.MutableTestCase;
-import org.sonar.api.test.MutableTestPlan;
-import org.sonar.api.test.MutableTestable;
-import org.sonar.api.test.Testable;
-import org.sonar.batch.duplication.BlockCache;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.scan2.BaseSensorContext;
-import org.sonar.core.component.ComponentKeys;
-
-/**
- * Implements {@link SensorContext} but forward everything to {@link org.sonar.api.batch.SensorContext} for backward compatibility.
- * Will be dropped once old {@link Sensor} API is dropped.
- *
- */
-public class SensorContextAdapter extends BaseSensorContext {
-
-  private static final String USES = "USES";
-  private final org.sonar.api.batch.SensorContext sensorContext;
-  private final MetricFinder metricFinder;
-  private final Project project;
-  private final ResourcePerspectives perspectives;
-  private final SonarIndex sonarIndex;
-
-  public SensorContextAdapter(org.sonar.api.batch.SensorContext sensorContext, MetricFinder metricFinder, Project project,
-    ResourcePerspectives perspectives,
-    Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache, BlockCache blockCache,
-    DuplicationCache duplicationCache, SonarIndex sonarIndex) {
-    super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache);
-    this.sensorContext = sensorContext;
-    this.metricFinder = metricFinder;
-    this.project = project;
-    this.perspectives = perspectives;
-    this.sonarIndex = sonarIndex;
-  }
-
-  private Metric findMetricOrFail(String metricKey) {
-    Metric m = (Metric) metricFinder.findByKey(metricKey);
-    if (m == null) {
-      throw new IllegalStateException("Unknow metric with key: " + metricKey);
-    }
-    return m;
-  }
-
-  @Override
-  public void store(Measure newMeasure) {
-    DefaultMeasure measure = (DefaultMeasure) newMeasure;
-    org.sonar.api.measures.Metric m = findMetricOrFail(measure.metric().key());
-    org.sonar.api.measures.Measure measureToSave = new org.sonar.api.measures.Measure(m);
-    setValueAccordingToMetricType(newMeasure, m, measureToSave);
-    measureToSave.setFromCore(measure.isFromCore());
-    if (newMeasure.inputFile() != null) {
-      Formula formula = newMeasure.metric() instanceof org.sonar.api.measures.Metric ?
-        ((org.sonar.api.measures.Metric) newMeasure.metric()).getFormula() : null;
-      if (formula instanceof SumChildDistributionFormula
-        && !Scopes.isHigherThanOrEquals(Scopes.FILE, ((SumChildDistributionFormula) formula).getMinimumScopeToPersist())) {
-        measureToSave.setPersistenceMode(PersistenceMode.MEMORY);
-      }
-      sensorContext.saveMeasure(newMeasure.inputFile(), measureToSave);
-    } else {
-      sensorContext.saveMeasure(measureToSave);
-    }
-  }
-
-  private void setValueAccordingToMetricType(Measure<?> measure, org.sonar.api.measures.Metric<?> m, org.sonar.api.measures.Measure measureToSave) {
-    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:
-        throw new UnsupportedOperationException("Unsupported type :" + m.getType());
-    }
-  }
-
-  @Override
-  public void store(Issue issue) {
-    Resource r;
-    InputPath inputPath = issue.inputPath();
-    if (inputPath != null) {
-      if (inputPath instanceof InputDir) {
-        r = Directory.create(inputPath.relativePath());
-      } else {
-        r = File.create(inputPath.relativePath());
-      }
-    } else {
-      r = project;
-    }
-    Issuable issuable = perspectives.as(Issuable.class, r);
-    if (issuable == null) {
-      return;
-    }
-    issuable.addIssue(toDefaultIssue(project.getKey(), ComponentKeys.createEffectiveKey(project, r), issue));
-  }
-
-  public static DefaultIssue toDefaultIssue(String projectKey, String componentKey, Issue issue) {
-    Severity overridenSeverity = issue.overridenSeverity();
-    return new org.sonar.core.issue.DefaultIssueBuilder()
-      .componentKey(componentKey)
-      .projectKey(projectKey)
-      .ruleKey(RuleKey.of(issue.ruleKey().repository(), issue.ruleKey().rule()))
-      .effortToFix(issue.effortToFix())
-      .line(issue.line())
-      .message(issue.message())
-      .severity(overridenSeverity != null ? overridenSeverity.name() : null)
-      .build();
-  }
-
-  @Override
-  public void store(TestCaseExecution testCase) {
-    File testRes = getTestResource(((DefaultTestCaseExecution) testCase).testFile());
-    MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes);
-    if (testPlan != null) {
-      testPlan
-        .addTestCase(testCase.name())
-        .setDurationInMs(testCase.durationInMs())
-        .setType(testCase.type().name())
-        .setStatus(org.sonar.api.test.TestCase.Status.valueOf(testCase.status().name()))
-        .setMessage(testCase.message())
-        .setStackTrace(testCase.stackTrace());
-    }
-  }
-
-  @Override
-  public void store(TestCaseCoverage testCaseCoverage) {
-    File testRes = getTestResource(testCaseCoverage.testFile());
-    File mainRes = getMainResource(testCaseCoverage.coveredFile());
-    Testable testAbleFile = perspectives.as(MutableTestable.class, mainRes);
-    if (testAbleFile != null) {
-      MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes);
-      if (testPlan != null) {
-        for (MutableTestCase mutableTestCase : testPlan.testCasesByName(testCaseCoverage.testName())) {
-          mutableTestCase.setCoverageBlock(testAbleFile, testCaseCoverage.coveredLines());
-        }
-      } else {
-        throw new IllegalStateException("Unable to get MutableTestPlan perspective from " + testRes);
-      }
-    } else {
-      throw new IllegalStateException("Unable to get MutableTestable perspective from " + mainRes);
-    }
-  }
-
-  private File getTestResource(InputFile testFile) {
-    File testRes = File.create(testFile.relativePath());
-    testRes.setQualifier(Qualifiers.UNIT_TEST_FILE);
-    // Reload
-    testRes = sensorContext.getResource(testRes);
-    if (testRes == null) {
-      throw new IllegalArgumentException("Provided input file is not indexed or not a test file: " + testFile);
-    }
-    return testRes;
-  }
-
-  private File getMainResource(InputFile mainFile) {
-    File mainRes = File.create(mainFile.relativePath());
-    // Reload
-    mainRes = sensorContext.getResource(mainRes);
-    if (mainRes == null) {
-      throw new IllegalArgumentException("Provided input file is not indexed or not a main file: " + mainRes);
-    }
-    return mainRes;
-  }
-
-  private File getFile(InputFile file) {
-    if (file.type() == InputFile.Type.MAIN) {
-      return getMainResource(file);
-    } else {
-      return getTestResource(file);
-    }
-  }
-
-  @Override
-  public void store(org.sonar.api.batch.sensor.dependency.Dependency dep) {
-    File fromResource = getFile(dep.from());
-    File toResource = getFile(dep.to());
-    if (sonarIndex.getEdge(fromResource, toResource) != null) {
-      throw new IllegalStateException("Dependency between " + dep.from() + " and " + dep.to() + " was already saved.");
-    }
-    Directory fromParent = fromResource.getParent();
-    Directory toParent = toResource.getParent();
-    Dependency parentDep = null;
-    if (!fromParent.equals(toParent)) {
-      parentDep = sonarIndex.getEdge(fromParent, toParent);
-      if (parentDep != null) {
-        parentDep.setWeight(parentDep.getWeight() + 1);
-      } else {
-        parentDep = new Dependency(fromParent, toParent).setUsage(USES).setWeight(1);
-        parentDep = sensorContext.saveDependency(parentDep);
-      }
-    }
-    sensorContext.saveDependency(new Dependency(fromResource, toResource)
-      .setUsage(USES)
-      .setWeight(dep.weight())
-      .setParent(parentDep));
-  }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalysisPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalysisPublisher.java
deleted file mode 100644 (file)
index 6216688..0000000
+++ /dev/null
@@ -1,189 +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.scan2;
-
-import org.apache.commons.io.Charsets;
-import org.apache.commons.io.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputPath;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.ZipUtils;
-import org.sonar.api.utils.text.JsonWriter;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.Properties;
-
-public final class AnalysisPublisher {
-
-  private static final Logger LOG = LoggerFactory.getLogger(AnalysisPublisher.class);
-  private final Settings settings;
-  private final FileSystem fs;
-  private final MeasureCache measureCache;
-  private final ProjectDefinition def;
-  private final IssueCache issueCache;
-
-  public AnalysisPublisher(ProjectDefinition def, Settings settings, FileSystem fs,
-    MeasureCache measureCache,
-    IssueCache analyzerIssueCache) {
-    this.def = def;
-    this.settings = settings;
-    this.fs = fs;
-    this.measureCache = measureCache;
-    this.issueCache = analyzerIssueCache;
-  }
-
-  public void execute() {
-    if (settings.getBoolean("sonar.skipPublish")) {
-      LOG.debug("Publishing of results is skipped");
-      return;
-    }
-    File exportDir = prepareExportDir();
-
-    exportAnalysisProperties(exportDir);
-
-    exportSourceFiles(exportDir);
-
-    exportMeasures(exportDir);
-
-    exportIssues(exportDir);
-
-    createZip(exportDir);
-
-  }
-
-  private void createZip(File exportDir) {
-    File exportZip = new File(fs.workDir(), def.getKey() + "-export.zip");
-    try {
-      ZipUtils.zipDir(exportDir, exportZip);
-      FileUtils.deleteDirectory(exportDir);
-    } catch (IOException e) {
-      throw unableToExport(e);
-    }
-    LOG.info("Results packaged in " + exportZip);
-  }
-
-  private IllegalStateException unableToExport(IOException e) {
-    return new IllegalStateException("Unable to export result of analyzis", e);
-  }
-
-  private void exportIssues(File exportDir) {
-    File issuesFile = new File(exportDir, "issues.json");
-    try (Writer issueWriter = new OutputStreamWriter(new FileOutputStream(issuesFile), Charsets.UTF_8)) {
-      JsonWriter jsonWriter = JsonWriter.of(issueWriter);
-      jsonWriter
-        .beginObject().name("issues")
-        .beginArray();
-      for (Issue issue : issueCache.byModule(def.getKey())) {
-        jsonWriter.beginObject()
-          .prop("repository", issue.ruleKey().repository())
-          .prop("rule", issue.ruleKey().rule());
-        InputPath inputPath = issue.inputPath();
-        if (inputPath != null) {
-          jsonWriter.prop("path", inputPath.relativePath());
-        }
-        jsonWriter.prop("message", issue.message())
-          .prop("effortToFix", issue.effortToFix())
-          .prop("line", issue.line());
-        Severity overridenSeverity = issue.overridenSeverity();
-        if (overridenSeverity != null) {
-          jsonWriter.prop("severity", overridenSeverity.name());
-        }
-        jsonWriter.endObject();
-      }
-      jsonWriter.endArray()
-        .endObject()
-        .close();
-    } catch (IOException e) {
-      throw unableToExport(e);
-    }
-  }
-
-  private void exportMeasures(File exportDir) {
-    File measuresFile = new File(exportDir, "measures.json");
-    try (Writer measureWriter = new OutputStreamWriter(new FileOutputStream(measuresFile), Charsets.UTF_8)) {
-      JsonWriter jsonWriter = JsonWriter.of(measureWriter);
-      jsonWriter
-        .beginObject().name("measures")
-        .beginArray();
-      for (Measure<?> measure : measureCache.byModule(def.getKey())) {
-        jsonWriter.beginObject()
-          .prop("metricKey", measure.metric().key());
-        InputFile inputFile = measure.inputFile();
-        if (inputFile != null) {
-          jsonWriter.prop("filePath", inputFile.relativePath());
-        }
-        jsonWriter.prop("value", String.valueOf(measure.value()))
-          .endObject();
-      }
-      jsonWriter.endArray()
-        .endObject()
-        .close();
-    } catch (IOException e) {
-      throw unableToExport(e);
-    }
-  }
-
-  private void exportSourceFiles(File exportDir) {
-    File sourceDir = new File(exportDir, "sources");
-    for (InputFile inputFile : fs.inputFiles(fs.predicates().all())) {
-      File dest = new File(sourceDir, inputFile.relativePath());
-      try {
-        FileUtils.copyFile(inputFile.file(), dest);
-      } catch (IOException e) {
-        throw unableToExport(e);
-      }
-    }
-  }
-
-  private void exportAnalysisProperties(File exportDir) {
-    File propsFile = new File(exportDir, "analysis.properties");
-    Properties props = new Properties();
-    props.putAll(settings.getProperties());
-    try (Writer writer = new OutputStreamWriter(new FileOutputStream(propsFile), Charsets.UTF_8)) {
-      props.store(writer, "SonarQube batch");
-    } catch (IOException e) {
-      throw unableToExport(e);
-    }
-  }
-
-  private File prepareExportDir() {
-    File exportDir = new File(fs.workDir(), "export");
-    try {
-      if (exportDir.exists()) {
-        FileUtils.forceDelete(exportDir);
-      }
-      FileUtils.forceMkdir(exportDir);
-    } catch (IOException e) {
-      throw unableToExport(e);
-    }
-    return exportDir;
-  }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java
deleted file mode 100644 (file)
index 09b9e5b..0000000
+++ /dev/null
@@ -1,179 +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.scan2;
-
-import com.google.common.base.Preconditions;
-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.rule.ActiveRules;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorStorage;
-import org.sonar.api.batch.sensor.dependency.Dependency;
-import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
-import org.sonar.api.batch.sensor.duplication.DuplicationBuilder;
-import org.sonar.api.batch.sensor.duplication.DuplicationGroup;
-import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder;
-import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplicationBuilder;
-import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder;
-import org.sonar.api.batch.sensor.test.Coverage;
-import org.sonar.api.batch.sensor.test.TestCaseCoverage;
-import org.sonar.api.batch.sensor.test.TestCaseExecution;
-import org.sonar.api.batch.sensor.test.internal.DefaultCoverage;
-import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseCoverage;
-import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
-import org.sonar.api.config.Settings;
-import org.sonar.batch.duplication.BlockCache;
-import org.sonar.batch.duplication.DefaultTokenBuilder;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.highlighting.DefaultHighlightingBuilder;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.scan.SensorContextAdapter;
-import org.sonar.batch.symbol.DefaultSymbolTableBuilder;
-import org.sonar.duplications.internal.pmd.PmdBlockChunker;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * Common bits between {@link DefaultSensorContext} and {@link SensorContextAdapter}
- * @author julien
- *
- */
-public abstract class BaseSensorContext implements SensorContext, SensorStorage {
-
-  private final Settings settings;
-  private final FileSystem fs;
-  private final ActiveRules activeRules;
-  private final ComponentDataCache componentDataCache;
-  private final BlockCache blockCache;
-  private final DuplicationCache duplicationCache;
-
-  protected BaseSensorContext(Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache,
-    BlockCache blockCache, DuplicationCache duplicationCache) {
-    this.settings = settings;
-    this.fs = fs;
-    this.activeRules = activeRules;
-    this.componentDataCache = componentDataCache;
-    this.blockCache = blockCache;
-    this.duplicationCache = duplicationCache;
-  }
-
-  @Override
-  public Settings settings() {
-    return settings;
-  }
-
-  @Override
-  public FileSystem fileSystem() {
-    return fs;
-  }
-
-  @Override
-  public ActiveRules activeRules() {
-    return activeRules;
-  }
-
-  @Override
-  public <G extends Serializable> Measure<G> newMeasure() {
-    return (Measure<G>) new DefaultMeasure(this);
-  }
-
-  @Override
-  public Issue newIssue() {
-    return new DefaultIssue(this);
-  }
-
-  @Override
-  public HighlightingBuilder highlightingBuilder(InputFile inputFile) {
-    return new DefaultHighlightingBuilder(((DefaultInputFile) inputFile).key(), componentDataCache);
-  }
-
-  @Override
-  public SymbolTableBuilder symbolTableBuilder(InputFile inputFile) {
-    return new DefaultSymbolTableBuilder(((DefaultInputFile) inputFile).key(), componentDataCache);
-  }
-
-  @Override
-  public DuplicationTokenBuilder duplicationTokenBuilder(InputFile inputFile) {
-    PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language()));
-
-    return new DefaultTokenBuilder(inputFile, blockCache, blockChunker);
-  }
-
-  @Override
-  public DuplicationBuilder duplicationBuilder(InputFile inputFile) {
-    return new DefaultDuplicationBuilder(inputFile);
-  }
-
-  @Override
-  public void saveDuplications(InputFile inputFile, List<DuplicationGroup> duplications) {
-    Preconditions.checkState(!duplications.isEmpty(), "Empty duplications");
-    String effectiveKey = ((DefaultInputFile) inputFile).key();
-    for (DuplicationGroup duplicationGroup : duplications) {
-      Preconditions.checkState(effectiveKey.equals(duplicationGroup.originBlock().resourceKey()), "Invalid duplication group");
-    }
-    duplicationCache.put(effectiveKey, duplications);
-  }
-
-  private int getBlockSize(String languageKey) {
-    int blockSize = settings.getInt("sonar.cpd." + languageKey + ".minimumLines");
-    if (blockSize == 0) {
-      blockSize = getDefaultBlockSize(languageKey);
-    }
-    return blockSize;
-  }
-
-  private static int getDefaultBlockSize(String languageKey) {
-    if ("cobol".equals(languageKey)) {
-      return 30;
-    } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) {
-      return 20;
-    } else {
-      return 10;
-    }
-  }
-
-  @Override
-  public Coverage newCoverage() {
-    return new DefaultCoverage(this);
-  }
-
-  @Override
-  public TestCaseExecution newTestCaseExecution() {
-    return new DefaultTestCaseExecution(this);
-  }
-
-  @Override
-  public TestCaseCoverage newTestCaseCoverage() {
-    return new DefaultTestCaseCoverage(this);
-  }
-
-  @Override
-  public Dependency newDependency() {
-    return new DefaultDependency(this);
-  }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java
deleted file mode 100644 (file)
index cb70fa2..0000000
+++ /dev/null
@@ -1,182 +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.scan2;
-
-import com.google.common.base.Strings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputPath;
-import org.sonar.api.batch.measure.Metric;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.internal.DefaultActiveRule;
-import org.sonar.api.batch.sensor.dependency.Dependency;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.batch.sensor.test.TestCaseCoverage;
-import org.sonar.api.batch.sensor.test.TestCaseExecution;
-import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
-import org.sonar.api.config.Settings;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.utils.MessageException;
-import org.sonar.batch.dependency.DependencyCache;
-import org.sonar.batch.duplication.BlockCache;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.issue.IssueFilters;
-import org.sonar.batch.scan.SensorContextAdapter;
-import org.sonar.batch.test.TestCaseCoverageCache;
-import org.sonar.batch.test.TestCaseExecutionCache;
-import org.sonar.core.component.ComponentKeys;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.List;
-
-public class DefaultSensorContext extends BaseSensorContext {
-
-  private static final Logger LOG = LoggerFactory.getLogger(DefaultSensorContext.class);
-
-  public static final List<Metric> INTERNAL_METRICS = Arrays.<Metric>asList(
-    // Computed by DsmDecorator
-    CoreMetrics.DEPENDENCY_MATRIX,
-    CoreMetrics.DIRECTORY_CYCLES,
-    CoreMetrics.DIRECTORY_EDGES_WEIGHT,
-    CoreMetrics.DIRECTORY_FEEDBACK_EDGES,
-    CoreMetrics.DIRECTORY_TANGLE_INDEX,
-    CoreMetrics.DIRECTORY_TANGLES,
-    CoreMetrics.FILE_CYCLES,
-    CoreMetrics.FILE_EDGES_WEIGHT,
-    CoreMetrics.FILE_FEEDBACK_EDGES,
-    CoreMetrics.FILE_TANGLE_INDEX,
-    CoreMetrics.FILE_TANGLES,
-    // Computed by ScmActivitySensor
-    CoreMetrics.SCM_AUTHORS_BY_LINE,
-    CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE,
-    CoreMetrics.SCM_REVISIONS_BY_LINE,
-    // Computed by core duplication plugin
-    CoreMetrics.DUPLICATIONS_DATA,
-    CoreMetrics.DUPLICATION_LINES_DATA,
-    CoreMetrics.DUPLICATED_FILES,
-    CoreMetrics.DUPLICATED_LINES,
-    CoreMetrics.DUPLICATED_BLOCKS
-    );
-  private final MeasureCache measureCache;
-  private final IssueCache issueCache;
-  private final ProjectDefinition def;
-  private final ActiveRules activeRules;
-  private final IssueFilters issueFilters;
-  private final TestCaseExecutionCache testCaseExecutionCache;
-  private final TestCaseCoverageCache coveragePerTestCache;
-  private final DependencyCache dependencyCache;
-
-  public DefaultSensorContext(ProjectDefinition def, MeasureCache measureCache, IssueCache issueCache,
-    Settings settings, FileSystem fs, ActiveRules activeRules, IssueFilters issueFilters, ComponentDataCache componentDataCache,
-    BlockCache blockCache, DuplicationCache duplicationCache, TestCaseExecutionCache testCaseCache, TestCaseCoverageCache coveragePerTestCache, DependencyCache dependencyCache) {
-    super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache);
-    this.def = def;
-    this.measureCache = measureCache;
-    this.issueCache = issueCache;
-    this.activeRules = activeRules;
-    this.issueFilters = issueFilters;
-    this.testCaseExecutionCache = testCaseCache;
-    this.coveragePerTestCache = coveragePerTestCache;
-    this.dependencyCache = dependencyCache;
-  }
-
-  @Override
-  public void store(Measure newMeasure) {
-    DefaultMeasure<Serializable> measure = (DefaultMeasure<Serializable>) newMeasure;
-    if (!measure.isFromCore() && INTERNAL_METRICS.contains(measure.metric())) {
-      throw new IllegalArgumentException("Metric " + measure.metric().key() + " is an internal metric computed by SonarQube. Please remove or update offending plugin.");
-    }
-    InputFile inputFile = measure.inputFile();
-    if (inputFile != null) {
-      measureCache.put(def.getKey(), ComponentKeys.createEffectiveKey(def.getKey(), inputFile), measure);
-    } else {
-      measureCache.put(def.getKey(), def.getKey(), measure);
-    }
-  }
-
-  @Override
-  public void store(Issue issue) {
-    String resourceKey;
-    InputPath inputPath = issue.inputPath();
-    if (inputPath != null) {
-      resourceKey = ComponentKeys.createEffectiveKey(def.getKey(), inputPath);
-    } else {
-      resourceKey = def.getKey();
-    }
-    RuleKey ruleKey = issue.ruleKey();
-    DefaultActiveRule activeRule = (DefaultActiveRule) activeRules.find(ruleKey);
-    if (activeRule == null) {
-      // rule does not exist or is not enabled -> ignore the issue
-      LOG.debug("Rule {} does not exists or is not enabled. Issue {} is ignored.", issue.ruleKey(), issue);
-      return;
-    }
-    if (Strings.isNullOrEmpty(activeRule.name()) && Strings.isNullOrEmpty(issue.message())) {
-      throw MessageException.of(String.format("The rule '%s' has no name and the related issue has no message.", ruleKey));
-    }
-
-    updateIssue((DefaultIssue) issue, activeRule);
-
-    if (!issueFilters.accept(SensorContextAdapter.toDefaultIssue(def.getKey(), resourceKey, issue))) {
-      LOG.debug("Issue {} was excluded by some filters.", issue);
-      return;
-    }
-    issueCache.put(def.getKey(), resourceKey, (DefaultIssue) issue);
-  }
-
-  private void updateIssue(DefaultIssue issue, DefaultActiveRule activeRule) {
-    if (Strings.isNullOrEmpty(issue.message())) {
-      issue.message(activeRule.name());
-    }
-  }
-
-  @Override
-  public void store(TestCaseExecution testCaseExecution) {
-    if (testCaseExecutionCache.contains(((DefaultTestCaseExecution) testCaseExecution).testFile(), testCaseExecution.name())) {
-      throw new IllegalArgumentException("There is already a test case with the same name: " + testCaseExecution.name());
-    }
-    testCaseExecutionCache.put(((DefaultTestCaseExecution) testCaseExecution).testFile(), testCaseExecution);
-  }
-
-  @Override
-  public void store(TestCaseCoverage testCaseCoverage) {
-    if (coveragePerTestCache.getCoverage(testCaseCoverage.testFile(), testCaseCoverage.testName(), testCaseCoverage.coveredFile()) != null) {
-      throw new IllegalArgumentException("Test coverage already registered for this combination of test file, test name and main file: " + testCaseCoverage);
-    }
-    coveragePerTestCache.put(testCaseCoverage);
-  }
-
-  @Override
-  public void store(Dependency dep) {
-    if (dependencyCache.get(def.getKey(), dep.from(), dep.to()) != null) {
-      throw new IllegalStateException("Dependency between " + dep.from() + " and " + dep.to() + " was already saved.");
-    }
-    dependencyCache.put(def.getKey(), dep);
-  }
-
-}
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
deleted file mode 100644 (file)
index e0c9d5a..0000000
+++ /dev/null
@@ -1,75 +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.scan2;
-
-import com.google.common.base.Preconditions;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.batch.index.Cache;
-import org.sonar.batch.index.Cache.Entry;
-import org.sonar.batch.index.Caches;
-import org.sonar.batch.scan.filesystem.InputPathCache;
-
-/**
- * Cache of all measures. This cache is shared amongst all project modules.
- */
-public class MeasureCache implements BatchComponent {
-
-  // project key -> component key -> metric key -> measure
-  private final Cache<DefaultMeasure> cache;
-
-  public MeasureCache(Caches caches, MetricFinder metricFinder, InputPathCache inputPathCache) {
-    caches.registerValueCoder(DefaultMeasure.class, new DefaultMeasureValueCoder(metricFinder, inputPathCache));
-    cache = caches.createCache("measures");
-  }
-
-  public Iterable<Entry<DefaultMeasure>> entries() {
-    return cache.entries();
-  }
-
-  public Iterable<DefaultMeasure> byModule(String projectKey) {
-    return cache.values(projectKey);
-  }
-
-  public DefaultMeasure byMetric(String projectKey, String resourceKey, String metricKey) {
-    return cache.get(projectKey, resourceKey, metricKey);
-  }
-
-  public MeasureCache put(String projectKey, String resourceKey, DefaultMeasure<?> measure) {
-    Preconditions.checkNotNull(projectKey);
-    Preconditions.checkNotNull(resourceKey);
-    Preconditions.checkNotNull(measure);
-    cache.put(projectKey, resourceKey, measure.metric().key(), measure);
-    return this;
-  }
-
-  public boolean contains(String projectKey, String resourceKey, DefaultMeasure<?> measure) {
-    Preconditions.checkNotNull(projectKey);
-    Preconditions.checkNotNull(resourceKey);
-    Preconditions.checkNotNull(measure);
-    return cache.containsKey(projectKey, resourceKey, measure.metric().key());
-  }
-
-  public Iterable<DefaultMeasure> 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
deleted file mode 100644 (file)
index 5d3cb48..0000000
+++ /dev/null
@@ -1,146 +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.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.scan.filesystem.FileExclusions;
-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.events.EventBus;
-import org.sonar.batch.issue.IssuableFactory;
-import org.sonar.batch.issue.IssueFilters;
-import org.sonar.batch.issue.ModuleIssues;
-import org.sonar.batch.issue.ignore.EnforceIssuesFilter;
-import org.sonar.batch.issue.ignore.IgnoreIssuesFilter;
-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.rule.ActiveRulesProvider;
-import org.sonar.batch.rule.ModuleQProfiles;
-import org.sonar.batch.rule.QProfileVerifier;
-import org.sonar.batch.scan.LanguageVerifier;
-import org.sonar.batch.scan.ModuleSettings;
-import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
-import org.sonar.batch.scan.filesystem.DeprecatedFileFilters;
-import org.sonar.batch.scan.filesystem.ExclusionFilters;
-import org.sonar.batch.scan.filesystem.FileIndexer;
-import org.sonar.batch.scan.filesystem.FileSystemLogger;
-import org.sonar.batch.scan.filesystem.InputFileBuilderFactory;
-import org.sonar.batch.scan.filesystem.LanguageDetectionFactory;
-import org.sonar.batch.scan.filesystem.ModuleFileSystemInitializer;
-import org.sonar.batch.scan.filesystem.ModuleInputFileCache;
-import org.sonar.batch.scan.filesystem.StatusDetectionFactory;
-
-public class ModuleScanContainer extends ComponentContainer {
-  private static final Logger LOG = LoggerFactory.getLogger(ModuleScanContainer.class);
-  private final ProjectDefinition moduleDefinition;
-
-  public ModuleScanContainer(ProjectScanContainer parent, ProjectDefinition moduleDefinition) {
-    super(parent);
-    this.moduleDefinition = moduleDefinition;
-  }
-
-  @Override
-  protected void doBeforeStart() {
-    LOG.info("-------------  Scan {}", moduleDefinition.getName());
-    addCoreComponents();
-    addExtensions();
-  }
-
-  private void addCoreComponents() {
-    add(
-      moduleDefinition,
-      ModuleSettings.class,
-
-      EventBus.class,
-      ModuleScanExecutor.class,
-      ModuleScanExecutor.getPhaseClasses(),
-      moduleDefinition.getContainerExtensions(),
-
-      // file system
-      ModuleInputFileCache.class,
-      FileExclusions.class,
-      ExclusionFilters.class,
-      DeprecatedFileFilters.class,
-      InputFileBuilderFactory.class,
-      StatusDetectionFactory.class,
-      LanguageDetectionFactory.class,
-      FileIndexer.class,
-      LanguageVerifier.class,
-      FileSystemLogger.class,
-      DefaultModuleFileSystem.class,
-      ModuleFileSystemInitializer.class,
-      QProfileVerifier.class,
-
-      AnalyzerOptimizer.class,
-
-      DefaultSensorContext.class,
-      BatchExtensionDictionnary.class,
-      IssueFilters.class,
-
-      // rules
-      ModuleQProfiles.class,
-      new ActiveRulesProvider(),
-      CheckFactory.class,
-
-      // issues
-      IssuableFactory.class,
-      ModuleIssues.class,
-
-      // Measures
-      DefaultFileLinesContextFactory.class,
-
-      // issue exclusions
-      IssueInclusionPatternInitializer.class,
-      IssueExclusionPatternInitializer.class,
-      IssueExclusionsRegexpScanner.class,
-      IssueExclusionsLoader.class,
-      EnforceIssuesFilter.class,
-      IgnoreIssuesFilter.class,
-
-      AnalysisPublisher.class);
-  }
-
-  private void addExtensions() {
-    ExtensionInstaller installer = getComponentByType(ExtensionInstaller.class);
-    installer.install(this, new ExtensionMatcher() {
-      @Override
-      public boolean accept(Object extension) {
-        return ExtensionUtils.isType(extension, BatchComponent.class)
-          && ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_PROJECT);
-      }
-    });
-  }
-
-  @Override
-  protected void doAfterStart() {
-    getComponentByType(ModuleScanExecutor.class).execute();
-  }
-
-}
index 088125818df0ec616a670dae7d5d216e2d5200f2..943f93e1db05ddbb34edeea149f08b1eaf1259a6 100644 (file)
@@ -37,19 +37,16 @@ public final class ModuleScanExecutor {
   private final QProfileVerifier profileVerifier;
   private final IssueExclusionsLoader issueExclusionsLoader;
 
-  private AnalysisPublisher analyzisPublisher;
-
   public ModuleScanExecutor(SensorsExecutor analyzersExecutor,
     SensorContext analyzerContext,
     FileSystemLogger fsLogger, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
-    IssueExclusionsLoader issueExclusionsLoader, AnalysisPublisher analyzisPublisher) {
+    IssueExclusionsLoader issueExclusionsLoader) {
     this.analyzersExecutor = analyzersExecutor;
     this.analyzerContext = analyzerContext;
     this.fsLogger = fsLogger;
     this.fs = fs;
     this.profileVerifier = profileVerifier;
     this.issueExclusionsLoader = issueExclusionsLoader;
-    this.analyzisPublisher = analyzisPublisher;
   }
 
   public static Collection<Class> getPhaseClasses() {
@@ -73,8 +70,5 @@ public final class ModuleScanExecutor {
 
     analyzersExecutor.execute(analyzerContext);
 
-    // Export results
-    analyzisPublisher.execute();
-
   }
 }
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
deleted file mode 100644 (file)
index 5f79666..0000000
+++ /dev/null
@@ -1,169 +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.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.scan.filesystem.PathResolver;
-import org.sonar.batch.bootstrap.ExtensionInstaller;
-import org.sonar.batch.bootstrap.ExtensionMatcher;
-import org.sonar.batch.bootstrap.ExtensionUtils;
-import org.sonar.batch.dependency.DependencyCache;
-import org.sonar.batch.duplication.BlockCache;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.index.Caches;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.languages.DefaultLanguagesReferential;
-import org.sonar.batch.profiling.PhasesSumUpTimeProfiler;
-import org.sonar.batch.referential.DefaultProjectReferentialsLoader;
-import org.sonar.batch.referential.ProjectReferentialsLoader;
-import org.sonar.batch.referential.ProjectReferentialsProvider;
-import org.sonar.batch.scan.ProjectReactorBuilder;
-import org.sonar.batch.scan.ProjectSettings;
-import org.sonar.batch.scan.filesystem.InputPathCache;
-import org.sonar.batch.scan.maven.FakeMavenPluginExecutor;
-import org.sonar.batch.scan.maven.MavenPluginExecutor;
-import org.sonar.batch.test.TestCaseCoverageCache;
-import org.sonar.batch.test.TestCaseExecutionCache;
-
-public class ProjectScanContainer extends ComponentContainer {
-  public ProjectScanContainer(ComponentContainer taskContainer) {
-    super(taskContainer);
-  }
-
-  @Override
-  protected void doBeforeStart() {
-    projectBootstrap();
-    addBatchComponents();
-    fixMavenExecutor();
-    addBatchExtensions();
-    Settings settings = getComponentByType(Settings.class);
-    if (settings != null && settings.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY)) {
-      add(PhasesSumUpTimeProfiler.class);
-    }
-  }
-
-  private void projectBootstrap() {
-    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) {
-      throw new IllegalStateException(bootstrapper + " has returned null as ProjectReactor");
-    }
-    add(reactor);
-    if (getComponentByType(ProjectReferentialsLoader.class) == null) {
-      add(DefaultProjectReferentialsLoader.class);
-    }
-  }
-
-  private void addBatchComponents() {
-    add(
-      new ProjectReferentialsProvider(),
-      ProjectSettings.class,
-      Caches.class,
-      ResourceCache.class,
-
-      // lang
-      Languages.class,
-      DefaultLanguagesReferential.class,
-
-      // Measures
-      MeasureCache.class,
-
-      // file system
-      InputPathCache.class,
-      PathResolver.class,
-
-      // issues
-      IssueCache.class,
-
-      // Syntax highlighting and symbols
-      ComponentDataCache.class,
-
-      // Duplications
-      BlockCache.class,
-      DuplicationCache.class,
-
-      // Tests
-      TestCaseExecutionCache.class,
-      TestCaseCoverageCache.class,
-
-      // Dependencies
-      DependencyCache.class,
-
-      ScanTaskObservers.class);
-  }
-
-  private void fixMavenExecutor() {
-    if (getComponentByType(MavenPluginExecutor.class) == null) {
-      add(FakeMavenPluginExecutor.class);
-    }
-  }
-
-  private void addBatchExtensions() {
-    getComponentByType(ExtensionInstaller.class).install(this, new BatchExtensionFilter());
-  }
-
-  @Override
-  protected void doAfterStart() {
-    ProjectReactor tree = getComponentByType(ProjectReactor.class);
-    scanRecursively(tree.getRoot());
-
-    getComponentByType(ScanTaskObservers.class).notifyEndOfScanTask();
-  }
-
-  private void scanRecursively(ProjectDefinition module) {
-    for (ProjectDefinition subModules : module.getSubProjects()) {
-      scanRecursively(subModules);
-    }
-    scan(module);
-  }
-
-  @VisibleForTesting
-  void scan(ProjectDefinition module) {
-    new ModuleScanContainer(this, module).execute();
-  }
-
-  static class BatchExtensionFilter implements ExtensionMatcher {
-    @Override
-    public boolean accept(Object extension) {
-      return ExtensionUtils.isType(extension, BatchComponent.class)
-        && ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_BATCH);
-    }
-  }
-}
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
deleted file mode 100644 (file)
index 636ed9f..0000000
+++ /dev/null
@@ -1,28 +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.scan2;
-
-import org.sonar.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
deleted file mode 100644 (file)
index 6dc8fa6..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.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/sensor/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorContext.java
new file mode 100644 (file)
index 0000000..e02fe9e
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * 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.sensor;
+
+import com.google.common.base.Preconditions;
+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.rule.ActiveRules;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorStorage;
+import org.sonar.api.batch.sensor.dependency.Dependency;
+import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
+import org.sonar.api.batch.sensor.duplication.DuplicationBuilder;
+import org.sonar.api.batch.sensor.duplication.DuplicationGroup;
+import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder;
+import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplicationBuilder;
+import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
+import org.sonar.api.batch.sensor.measure.NewMeasure;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder;
+import org.sonar.api.batch.sensor.test.Coverage;
+import org.sonar.api.batch.sensor.test.TestCaseCoverage;
+import org.sonar.api.batch.sensor.test.TestCaseExecution;
+import org.sonar.api.batch.sensor.test.internal.DefaultCoverage;
+import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseCoverage;
+import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
+import org.sonar.api.config.Settings;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DefaultTokenBuilder;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.highlighting.DefaultHighlightingBuilder;
+import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.symbol.DefaultSymbolTableBuilder;
+import org.sonar.duplications.internal.pmd.PmdBlockChunker;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * Common bits between {@link ExperimentalSensorStorage} and {@link SensorContextAdapter}
+ * @author julien
+ *
+ */
+public class DefaultSensorContext implements SensorContext {
+
+  private final Settings settings;
+  private final FileSystem fs;
+  private final ActiveRules activeRules;
+  private final ComponentDataCache componentDataCache;
+  private final BlockCache blockCache;
+  private final DuplicationCache duplicationCache;
+  private final SensorStorage sensorStorage;
+
+  public DefaultSensorContext(Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache,
+    BlockCache blockCache, DuplicationCache duplicationCache, SensorStorage sensorStorage) {
+    this.settings = settings;
+    this.fs = fs;
+    this.activeRules = activeRules;
+    this.componentDataCache = componentDataCache;
+    this.blockCache = blockCache;
+    this.duplicationCache = duplicationCache;
+    this.sensorStorage = sensorStorage;
+  }
+
+  @Override
+  public Settings settings() {
+    return settings;
+  }
+
+  @Override
+  public FileSystem fileSystem() {
+    return fs;
+  }
+
+  @Override
+  public ActiveRules activeRules() {
+    return activeRules;
+  }
+
+  @Override
+  public <G extends Serializable> NewMeasure<G> newMeasure() {
+    return new DefaultMeasure(sensorStorage);
+  }
+
+  @Override
+  public Issue newIssue() {
+    return new DefaultIssue(sensorStorage);
+  }
+
+  @Override
+  public HighlightingBuilder highlightingBuilder(InputFile inputFile) {
+    return new DefaultHighlightingBuilder(((DefaultInputFile) inputFile).key(), componentDataCache);
+  }
+
+  @Override
+  public SymbolTableBuilder symbolTableBuilder(InputFile inputFile) {
+    return new DefaultSymbolTableBuilder(((DefaultInputFile) inputFile).key(), componentDataCache);
+  }
+
+  @Override
+  public DuplicationTokenBuilder duplicationTokenBuilder(InputFile inputFile) {
+    PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language()));
+
+    return new DefaultTokenBuilder(inputFile, blockCache, blockChunker);
+  }
+
+  @Override
+  public DuplicationBuilder duplicationBuilder(InputFile inputFile) {
+    return new DefaultDuplicationBuilder(inputFile);
+  }
+
+  @Override
+  public void saveDuplications(InputFile inputFile, List<DuplicationGroup> duplications) {
+    Preconditions.checkState(!duplications.isEmpty(), "Empty duplications");
+    String effectiveKey = ((DefaultInputFile) inputFile).key();
+    for (DuplicationGroup duplicationGroup : duplications) {
+      Preconditions.checkState(effectiveKey.equals(duplicationGroup.originBlock().resourceKey()), "Invalid duplication group");
+    }
+    duplicationCache.put(effectiveKey, duplications);
+  }
+
+  private int getBlockSize(String languageKey) {
+    int blockSize = settings.getInt("sonar.cpd." + languageKey + ".minimumLines");
+    if (blockSize == 0) {
+      blockSize = getDefaultBlockSize(languageKey);
+    }
+    return blockSize;
+  }
+
+  private static int getDefaultBlockSize(String languageKey) {
+    if ("cobol".equals(languageKey)) {
+      return 30;
+    } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) {
+      return 20;
+    } else {
+      return 10;
+    }
+  }
+
+  @Override
+  public Coverage newCoverage() {
+    return new DefaultCoverage(sensorStorage);
+  }
+
+  @Override
+  public TestCaseExecution newTestCaseExecution() {
+    return new DefaultTestCaseExecution(sensorStorage);
+  }
+
+  @Override
+  public TestCaseCoverage newTestCaseCoverage() {
+    return new DefaultTestCaseCoverage(sensorStorage);
+  }
+
+  @Override
+  public Dependency newDependency() {
+    return new DefaultDependency(sensorStorage);
+  }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java
new file mode 100644 (file)
index 0000000..c1c3e2b
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * 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.sensor;
+
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputDir;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputPath;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.sensor.SensorStorage;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.issue.Issue.Severity;
+import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.batch.sensor.test.TestCaseCoverage;
+import org.sonar.api.batch.sensor.test.TestCaseExecution;
+import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
+import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.config.Settings;
+import org.sonar.api.design.Dependency;
+import org.sonar.api.issue.Issuable;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.measures.Formula;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.PersistenceMode;
+import org.sonar.api.measures.SumChildDistributionFormula;
+import org.sonar.api.resources.Directory;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.test.MutableTestCase;
+import org.sonar.api.test.MutableTestPlan;
+import org.sonar.api.test.MutableTestable;
+import org.sonar.api.test.Testable;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.index.DefaultIndex;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
+import org.sonar.core.component.ComponentKeys;
+
+public class DefaultSensorStorage implements SensorStorage {
+
+  private static final String USES = "USES";
+  private final MetricFinder metricFinder;
+  private final Project project;
+  private final ResourcePerspectives perspectives;
+  private final DefaultIndex sonarIndex;
+  private final CoverageExclusions coverageExclusions;
+
+  public DefaultSensorStorage(MetricFinder metricFinder, Project project,
+    ResourcePerspectives perspectives,
+    Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache, BlockCache blockCache,
+    DuplicationCache duplicationCache, DefaultIndex sonarIndex, CoverageExclusions coverageExclusions) {
+    this.metricFinder = metricFinder;
+    this.project = project;
+    this.perspectives = perspectives;
+    this.sonarIndex = sonarIndex;
+    this.coverageExclusions = coverageExclusions;
+  }
+
+  private Metric findMetricOrFail(String metricKey) {
+    Metric m = (Metric) metricFinder.findByKey(metricKey);
+    if (m == null) {
+      throw new IllegalStateException("Unknow metric with key: " + metricKey);
+    }
+    return m;
+  }
+
+  @Override
+  public void store(Measure newMeasure) {
+    DefaultMeasure measure = (DefaultMeasure) newMeasure;
+    org.sonar.api.measures.Metric m = findMetricOrFail(measure.metric().key());
+    org.sonar.api.measures.Measure measureToSave = new org.sonar.api.measures.Measure(m);
+    setValueAccordingToMetricType(newMeasure, m, measureToSave);
+    measureToSave.setFromCore(measure.isFromCore());
+    if (newMeasure.inputFile() != null) {
+      Formula formula = newMeasure.metric() instanceof org.sonar.api.measures.Metric ?
+        ((org.sonar.api.measures.Metric) newMeasure.metric()).getFormula() : null;
+      if (formula instanceof SumChildDistributionFormula
+        && !Scopes.isHigherThanOrEquals(Scopes.FILE, ((SumChildDistributionFormula) formula).getMinimumScopeToPersist())) {
+        measureToSave.setPersistenceMode(PersistenceMode.MEMORY);
+      }
+      File sonarFile = getFile(newMeasure.inputFile());
+      if (coverageExclusions.accept(sonarFile, measureToSave)) {
+        sonarIndex.addMeasure(sonarFile, measureToSave);
+      }
+    } else {
+      sonarIndex.addMeasure(project, measureToSave);
+    }
+  }
+
+  private void setValueAccordingToMetricType(Measure<?> measure, org.sonar.api.measures.Metric<?> m, org.sonar.api.measures.Measure measureToSave) {
+    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:
+        throw new UnsupportedOperationException("Unsupported type :" + m.getType());
+    }
+  }
+
+  @Override
+  public void store(Issue issue) {
+    Resource r;
+    InputPath inputPath = issue.inputPath();
+    if (inputPath != null) {
+      if (inputPath instanceof InputDir) {
+        r = Directory.create(inputPath.relativePath());
+      } else {
+        r = File.create(inputPath.relativePath());
+      }
+    } else {
+      r = project;
+    }
+    Issuable issuable = perspectives.as(Issuable.class, r);
+    if (issuable == null) {
+      return;
+    }
+    issuable.addIssue(toDefaultIssue(project.getKey(), ComponentKeys.createEffectiveKey(project, r), issue));
+  }
+
+  public static DefaultIssue toDefaultIssue(String projectKey, String componentKey, Issue issue) {
+    Severity overridenSeverity = issue.overridenSeverity();
+    return new org.sonar.core.issue.DefaultIssueBuilder()
+      .componentKey(componentKey)
+      .projectKey(projectKey)
+      .ruleKey(RuleKey.of(issue.ruleKey().repository(), issue.ruleKey().rule()))
+      .effortToFix(issue.effortToFix())
+      .line(issue.line())
+      .message(issue.message())
+      .severity(overridenSeverity != null ? overridenSeverity.name() : null)
+      .build();
+  }
+
+  @Override
+  public void store(TestCaseExecution testCase) {
+    File testRes = getTestResource(((DefaultTestCaseExecution) testCase).testFile());
+    MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes);
+    if (testPlan != null) {
+      testPlan
+        .addTestCase(testCase.name())
+        .setDurationInMs(testCase.durationInMs())
+        .setType(testCase.type().name())
+        .setStatus(org.sonar.api.test.TestCase.Status.valueOf(testCase.status().name()))
+        .setMessage(testCase.message())
+        .setStackTrace(testCase.stackTrace());
+    }
+  }
+
+  @Override
+  public void store(TestCaseCoverage testCaseCoverage) {
+    File testRes = getTestResource(testCaseCoverage.testFile());
+    File mainRes = getMainResource(testCaseCoverage.coveredFile());
+    Testable testAbleFile = perspectives.as(MutableTestable.class, mainRes);
+    if (testAbleFile != null) {
+      MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes);
+      if (testPlan != null) {
+        for (MutableTestCase mutableTestCase : testPlan.testCasesByName(testCaseCoverage.testName())) {
+          mutableTestCase.setCoverageBlock(testAbleFile, testCaseCoverage.coveredLines());
+        }
+      } else {
+        throw new IllegalStateException("Unable to get MutableTestPlan perspective from " + testRes);
+      }
+    } else {
+      throw new IllegalStateException("Unable to get MutableTestable perspective from " + mainRes);
+    }
+  }
+
+  private File getTestResource(InputFile testFile) {
+    File testRes = File.create(testFile.relativePath());
+    testRes.setQualifier(Qualifiers.UNIT_TEST_FILE);
+    // Reload
+    testRes = sonarIndex.getResource(testRes);
+    if (testRes == null) {
+      throw new IllegalArgumentException("Provided input file is not indexed or not a test file: " + testFile);
+    }
+    return testRes;
+  }
+
+  private File getMainResource(InputFile mainFile) {
+    File mainRes = File.create(mainFile.relativePath());
+    // Reload
+    mainRes = sonarIndex.getResource(mainRes);
+    if (mainRes == null) {
+      throw new IllegalArgumentException("Provided input file is not indexed or not a main file: " + mainRes);
+    }
+    return mainRes;
+  }
+
+  private File getFile(InputFile file) {
+    if (file.type() == InputFile.Type.MAIN) {
+      return getMainResource(file);
+    } else {
+      return getTestResource(file);
+    }
+  }
+
+  @Override
+  public void store(org.sonar.api.batch.sensor.dependency.Dependency dep) {
+    File fromResource = getFile(dep.from());
+    File toResource = getFile(dep.to());
+    if (sonarIndex.getEdge(fromResource, toResource) != null) {
+      throw new IllegalStateException("Dependency between " + dep.from() + " and " + dep.to() + " was already saved.");
+    }
+    Directory fromParent = fromResource.getParent();
+    Directory toParent = toResource.getParent();
+    Dependency parentDep = null;
+    if (!fromParent.equals(toParent)) {
+      parentDep = sonarIndex.getEdge(fromParent, toParent);
+      if (parentDep != null) {
+        parentDep.setWeight(parentDep.getWeight() + 1);
+      } else {
+        parentDep = new Dependency(fromParent, toParent).setUsage(USES).setWeight(1);
+        parentDep = sonarIndex.addDependency(parentDep);
+      }
+    }
+    sonarIndex.addDependency(new Dependency(fromResource, toResource)
+      .setUsage(USES)
+      .setWeight(dep.weight())
+      .setParent(parentDep));
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageConstants.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageConstants.java
new file mode 100644 (file)
index 0000000..46aa717
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.sensor.coverage;
+
+import com.google.common.collect.ImmutableList;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Metric;
+
+import java.util.Collection;
+
+public class CoverageConstants {
+
+  public static final Collection<Metric> COVERAGE_METRICS = ImmutableList.<Metric>of(CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.NEW_LINES_TO_COVER,
+    CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS,
+    CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS);
+
+  public static final Collection<Metric> LINE_COVERAGE_METRICS = ImmutableList.<Metric>of(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES,
+    CoreMetrics.NEW_LINES_TO_COVER);
+
+  public static final Collection<Metric> BRANCH_COVERAGE_METRICS = ImmutableList.<Metric>of(CoreMetrics.UNCOVERED_CONDITIONS, CoreMetrics.CONDITIONS_TO_COVER,
+    CoreMetrics.NEW_UNCOVERED_CONDITIONS, CoreMetrics.NEW_CONDITIONS_TO_COVER);
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageExclusions.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageExclusions.java
new file mode 100644 (file)
index 0000000..1545c06
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.sensor.coverage;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+import com.google.common.collect.ImmutableSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.utils.WildcardPattern;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+public class CoverageExclusions {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CoverageExclusions.class);
+
+  private final Settings settings;
+  private final ImmutableSet<Metric> coverageMetrics;
+  private Collection<WildcardPattern> resourcePatterns;
+
+  public CoverageExclusions(Settings settings) {
+    this.settings = settings;
+    this.coverageMetrics = ImmutableSet.<Metric>builder()
+      .add(CoreMetrics.COVERAGE)
+      .addAll(CoverageConstants.COVERAGE_METRICS)
+      .add(CoreMetrics.LINE_COVERAGE)
+      .addAll(CoverageConstants.LINE_COVERAGE_METRICS)
+      .add(CoreMetrics.BRANCH_COVERAGE)
+      .addAll(CoverageConstants.BRANCH_COVERAGE_METRICS)
+      .build();
+
+    initPatterns();
+  }
+
+  public boolean accept(Resource resource, Measure measure) {
+    if (isCoverageMetric(measure.getMetric())) {
+      return !hasMatchingPattern(resource);
+    } else {
+      return true;
+    }
+  }
+
+  private boolean isCoverageMetric(Metric metric) {
+    return this.coverageMetrics.contains(metric);
+  }
+
+  private boolean hasMatchingPattern(Resource resource) {
+    boolean found = false;
+    Iterator<WildcardPattern> iterator = resourcePatterns.iterator();
+    while (!found && iterator.hasNext()) {
+      found = resource.matchFilePattern(iterator.next().toString());
+    }
+    return found;
+  }
+
+  @VisibleForTesting
+  final void initPatterns() {
+    Builder<WildcardPattern> builder = ImmutableList.builder();
+    for (String pattern : settings.getStringArray(CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY)) {
+      builder.add(WildcardPattern.create(pattern));
+    }
+    resourcePatterns = builder.build();
+    log("Excluded sources for coverage: ", resourcePatterns);
+  }
+
+  private void log(String title, Collection<WildcardPattern> patterns) {
+    if (!patterns.isEmpty()) {
+      LOG.info(title);
+      for (WildcardPattern pattern : patterns) {
+        LOG.info("  " + pattern);
+      }
+    }
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/package-info.java
new file mode 100644 (file)
index 0000000..de8138f
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.sensor;
index b0c2e3076d649178d99ec5cdbb25d7958a9945eb..1509a65ffeae93807c7e263b3bc0e5d0e464df8e 100644 (file)
@@ -22,10 +22,10 @@ package org.sonar.batch.bootstrap;
 import org.junit.Test;
 import org.sonar.api.BatchExtension;
 import org.sonar.api.batch.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
 import org.sonar.batch.scan2.AnalyzerOptimizer;
+import org.sonar.batch.sensor.DefaultSensorContext;
 
 import java.util.Collection;
 
@@ -41,7 +41,7 @@ public class BatchExtensionDictionnaryTest {
     for (BatchExtension extension : extensions) {
       iocContainer.addSingleton(extension);
     }
-    return new BatchExtensionDictionnary(iocContainer, mock(SensorContext.class), mock(AnalyzerOptimizer.class));
+    return new BatchExtensionDictionnary(iocContainer, mock(DefaultSensorContext.class), mock(AnalyzerOptimizer.class));
   }
 
   @Test
index 6787ae5710fcd4a7ac93fa931f834dbd594dc8cd..f11c843c541328c5f9f2be1b3a8d0b09556755b5 100644 (file)
@@ -25,6 +25,9 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.measures.CoreMetrics;
 import org.sonar.batch.mediumtest.BatchMediumTester;
 import org.sonar.batch.mediumtest.TaskResult;
 import org.sonar.xoo.XooPlugin;
@@ -92,10 +95,10 @@ public class MeasuresMediumTest {
 
     assertThat(result.measures()).hasSize(2);
 
-    // assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
-    // .forMetric(CoreMetrics.LINES)
-    // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
-    // .withValue(20));
+    assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
+      .forMetric(CoreMetrics.LINES)
+      .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+      .withValue(20));
 
   }
 
index b7aacbcd2d14081a7b237424760589731f6c387c..4a6e1a79cef698e307c9017861f98edeb35b82aa 100644 (file)
@@ -27,6 +27,9 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.measures.CoreMetrics;
 import org.sonar.batch.mediumtest.BatchMediumTester;
 import org.sonar.batch.mediumtest.TaskResult;
 import org.sonar.xoo.XooPlugin;
@@ -80,15 +83,15 @@ public class ScmMediumTest {
 
     assertThat(result.measures()).hasSize(5);
 
-    // assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
-    // .forMetric(CoreMetrics.LINES)
-    // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
-    // .withValue(5));
-    //
-    // assertThat(result.measures()).contains(new DefaultMeasure<String>()
-    // .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
-    // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
-    // .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
+    assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
+      .forMetric(CoreMetrics.LINES)
+      .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+      .withValue(5));
+
+    assertThat(result.measures()).contains(new DefaultMeasure<String>()
+      .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
+      .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+      .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
   }
 
   @Test
@@ -136,15 +139,15 @@ public class ScmMediumTest {
 
     assertThat(result.measures()).hasSize(5);
 
-    // assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
-    // .forMetric(CoreMetrics.LINES)
-    // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
-    // .withValue(5));
-    //
-    // assertThat(result.measures()).contains(new DefaultMeasure<String>()
-    // .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
-    // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
-    // .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
+    assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
+      .forMetric(CoreMetrics.LINES)
+      .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+      .withValue(5));
+
+    assertThat(result.measures()).contains(new DefaultMeasure<String>()
+      .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
+      .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+      .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
   }
 
   @Test
@@ -167,15 +170,15 @@ public class ScmMediumTest {
 
     assertThat(result.measures()).hasSize(5);
 
-    // assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
-    // .forMetric(CoreMetrics.LINES)
-    // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
-    // .withValue(5));
-    //
-    // assertThat(result.measures()).contains(new DefaultMeasure<String>()
-    // .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
-    // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
-    // .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
+    assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
+      .forMetric(CoreMetrics.LINES)
+      .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+      .withValue(5));
+
+    assertThat(result.measures()).contains(new DefaultMeasure<String>()
+      .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
+      .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+      .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
   }
 
   private File prepareProject() throws IOException {
index 1fd1c4e081c8d202a676f0cd664fb8ef5875098b..3f4717111466e60a6a384afc6f8274c8f93f579e 100644 (file)
@@ -33,7 +33,7 @@ import org.sonar.batch.DefaultDecoratorContext;
 import org.sonar.batch.duplication.DuplicationCache;
 import org.sonar.batch.events.EventBus;
 import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.core.measure.MeasurementFilters;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.fail;
@@ -67,7 +67,7 @@ public class DecoratorsExecutorTest {
     doThrow(new SonarException()).when(decorator).decorate(any(Resource.class), any(DecoratorContext.class));
 
     DecoratorsExecutor executor = new DecoratorsExecutor(mock(BatchExtensionDictionnary.class), new Project("key"), mock(SonarIndex.class),
-      mock(EventBus.class), mock(MeasurementFilters.class), mock(MeasureCache.class), mock(MetricFinder.class), mock(DuplicationCache.class));
+      mock(EventBus.class), mock(CoverageExclusions.class), mock(MeasureCache.class), mock(MetricFinder.class), mock(DuplicationCache.class));
     try {
       executor.executeDecorator(decorator, mock(DefaultDecoratorContext.class), File.create("src/org/foo/Bar.java", "org/foo/Bar.java", null, false));
       fail("Exception has not been thrown");
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java
deleted file mode 100644 (file)
index a5610c6..0000000
+++ /dev/null
@@ -1,348 +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.scan;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.batch.SonarIndex;
-import org.sonar.api.batch.fs.InputDir;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultFileSystem;
-import org.sonar.api.batch.fs.internal.DefaultInputDir;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
-import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.config.Settings;
-import org.sonar.api.design.Dependency;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.PersistenceMode;
-import org.sonar.api.resources.Directory;
-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.duplication.BlockCache;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.index.ComponentDataCache;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class SensorContextAdapterTest {
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  private ActiveRules activeRules;
-  private DefaultFileSystem fs;
-  private SensorContextAdapter adaptor;
-  private SensorContext sensorContext;
-  private Settings settings;
-  private ResourcePerspectives resourcePerspectives;
-  private Project project;
-  private SonarIndex sonarIndex;
-
-  @Before
-  public void prepare() {
-    activeRules = new ActiveRulesBuilder().build();
-    fs = new DefaultFileSystem();
-    MetricFinder metricFinder = mock(MetricFinder.class);
-    when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
-    when(metricFinder.findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
-    sensorContext = mock(SensorContext.class);
-    settings = new Settings();
-    resourcePerspectives = mock(ResourcePerspectives.class);
-    ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
-    BlockCache blockCache = mock(BlockCache.class);
-    project = new Project("myProject");
-    sonarIndex = mock(SonarIndex.class);
-    adaptor = new SensorContextAdapter(sensorContext, metricFinder, project,
-      resourcePerspectives, settings, fs, activeRules, componentDataCache, blockCache, mock(DuplicationCache.class), sonarIndex);
-  }
-
-  @Test
-  public void shouldProvideComponents() {
-    assertThat(adaptor.activeRules()).isEqualTo(activeRules);
-    assertThat(adaptor.fileSystem()).isEqualTo(fs);
-    assertThat(adaptor.settings()).isEqualTo(settings);
-
-    assertThat(adaptor.newIssue()).isNotNull();
-    assertThat(adaptor.newMeasure()).isNotNull();
-  }
-
-  @Test
-  public void shouldFailIfUnknowMetric() {
-    InputFile file = new DefaultInputFile("foo", "src/Foo.php");
-
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("Unknow metric with key: lines");
-
-    adaptor.store(new DefaultMeasure()
-      .onFile(file)
-      .forMetric(CoreMetrics.LINES)
-      .withValue(10));
-  }
-
-  @Test
-  public void shouldSaveFileMeasureToSensorContext() {
-    InputFile file = new DefaultInputFile("foo", "src/Foo.php");
-
-    ArgumentCaptor<org.sonar.api.measures.Measure> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
-    when(sensorContext.saveMeasure(eq(file), argumentCaptor.capture())).thenReturn(null);
-
-    adaptor.store(new DefaultMeasure()
-      .onFile(file)
-      .forMetric(CoreMetrics.NCLOC)
-      .withValue(10));
-
-    org.sonar.api.measures.Measure m = argumentCaptor.getValue();
-    assertThat(m.getValue()).isEqualTo(10.0);
-    assertThat(m.getMetric()).isEqualTo(CoreMetrics.NCLOC);
-  }
-
-  @Test
-  public void shouldSetAppropriatePersistenceMode() {
-    // Metric FUNCTION_COMPLEXITY_DISTRIBUTION is only persisted on directories.
-
-    InputFile file = new DefaultInputFile("foo", "src/Foo.php");
-
-    ArgumentCaptor<org.sonar.api.measures.Measure> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
-    when(sensorContext.saveMeasure(eq(file), argumentCaptor.capture())).thenReturn(null);
-
-    adaptor.store(new DefaultMeasure()
-      .onFile(file)
-      .forMetric(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION)
-      .withValue("foo"));
-
-    org.sonar.api.measures.Measure m = argumentCaptor.getValue();
-    assertThat(m.getData()).isEqualTo("foo");
-    assertThat(m.getMetric()).isEqualTo(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
-    assertThat(m.getPersistenceMode()).isEqualTo(PersistenceMode.MEMORY);
-
-  }
-
-  @Test
-  public void shouldSaveProjectMeasureToSensorContext() {
-
-    ArgumentCaptor<org.sonar.api.measures.Measure> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
-    when(sensorContext.saveMeasure(argumentCaptor.capture())).thenReturn(null);
-
-    adaptor.store(new DefaultMeasure()
-      .onProject()
-      .forMetric(CoreMetrics.NCLOC)
-      .withValue(10));
-
-    org.sonar.api.measures.Measure m = argumentCaptor.getValue();
-    assertThat(m.getValue()).isEqualTo(10.0);
-    assertThat(m.getMetric()).isEqualTo(CoreMetrics.NCLOC);
-  }
-
-  @Test
-  public void shouldAddIssueOnFile() {
-    InputFile file = new DefaultInputFile("foo", "src/Foo.php");
-
-    ArgumentCaptor<Issue> argumentCaptor = ArgumentCaptor.forClass(Issue.class);
-
-    Issuable issuable = mock(Issuable.class);
-    when(resourcePerspectives.as(Issuable.class, File.create("src/Foo.php"))).thenReturn(issuable);
-
-    when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
-
-    adaptor.store(new DefaultIssue()
-      .onFile(file)
-      .ruleKey(RuleKey.of("foo", "bar"))
-      .message("Foo")
-      .atLine(3)
-      .effortToFix(10.0));
-
-    Issue issue = argumentCaptor.getValue();
-    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
-    assertThat(issue.message()).isEqualTo("Foo");
-    assertThat(issue.line()).isEqualTo(3);
-    assertThat(issue.severity()).isNull();
-    assertThat(issue.effortToFix()).isEqualTo(10.0);
-  }
-
-  @Test
-  public void shouldAddIssueOnDirectory() {
-    InputDir dir = new DefaultInputDir("foo", "src");
-
-    ArgumentCaptor<Issue> argumentCaptor = ArgumentCaptor.forClass(Issue.class);
-
-    Issuable issuable = mock(Issuable.class);
-    when(resourcePerspectives.as(Issuable.class, Directory.create("src"))).thenReturn(issuable);
-
-    when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
-
-    adaptor.store(new DefaultIssue()
-      .onDir(dir)
-      .ruleKey(RuleKey.of("foo", "bar"))
-      .message("Foo")
-      .effortToFix(10.0));
-
-    Issue issue = argumentCaptor.getValue();
-    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
-    assertThat(issue.message()).isEqualTo("Foo");
-    assertThat(issue.line()).isNull();
-    assertThat(issue.severity()).isNull();
-    assertThat(issue.effortToFix()).isEqualTo(10.0);
-  }
-
-  @Test
-  public void shouldAddIssueOnProject() {
-    ArgumentCaptor<Issue> argumentCaptor = ArgumentCaptor.forClass(Issue.class);
-
-    Issuable issuable = mock(Issuable.class);
-    when(resourcePerspectives.as(Issuable.class, (Resource) project)).thenReturn(issuable);
-
-    when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
-
-    adaptor.store(new DefaultIssue()
-      .onProject()
-      .ruleKey(RuleKey.of("foo", "bar"))
-      .message("Foo")
-      .overrideSeverity(Severity.BLOCKER)
-      .effortToFix(10.0));
-
-    Issue issue = argumentCaptor.getValue();
-    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
-    assertThat(issue.message()).isEqualTo("Foo");
-    assertThat(issue.line()).isNull();
-    assertThat(issue.severity()).isEqualTo("BLOCKER");
-    assertThat(issue.effortToFix()).isEqualTo(10.0);
-  }
-
-  @Test
-  public void shouldStoreDependencyInSameFolder() {
-
-    File foo = File.create("src/Foo.java");
-    File bar = File.create("src/Bar.java");
-    when(sensorContext.getResource(foo)).thenReturn(foo);
-    when(sensorContext.getResource(bar)).thenReturn(bar);
-
-    adaptor.store(new DefaultDependency()
-      .from(new DefaultInputFile("foo", "src/Foo.java").setType(Type.MAIN))
-      .to(new DefaultInputFile("foo", "src/Bar.java").setType(Type.MAIN))
-      .weight(3));
-
-    ArgumentCaptor<Dependency> argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
-
-    verify(sensorContext).saveDependency(argumentCaptor.capture());
-    assertThat(argumentCaptor.getValue().getFrom()).isEqualTo(foo);
-    assertThat(argumentCaptor.getValue().getTo()).isEqualTo(bar);
-    assertThat(argumentCaptor.getValue().getWeight()).isEqualTo(3);
-    assertThat(argumentCaptor.getValue().getUsage()).isEqualTo("USES");
-  }
-
-  @Test
-  public void throw_if_attempt_to_save_same_dep_twice() {
-
-    File foo = File.create("src/Foo.java");
-    File bar = File.create("src/Bar.java");
-    when(sensorContext.getResource(foo)).thenReturn(foo);
-    when(sensorContext.getResource(bar)).thenReturn(bar);
-    when(sonarIndex.getEdge(foo, bar)).thenReturn(new Dependency(foo, bar));
-
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("Dependency between [moduleKey=foo, relative=src/Foo.java, abs=null] and [moduleKey=foo, relative=src/Bar.java, abs=null] was already saved.");
-
-    adaptor.store(new DefaultDependency()
-      .from(new DefaultInputFile("foo", "src/Foo.java").setType(Type.MAIN))
-      .to(new DefaultInputFile("foo", "src/Bar.java").setType(Type.MAIN))
-      .weight(3));
-  }
-
-  @Test
-  public void shouldStoreDependencyInDifferentFolder() {
-
-    File foo = File.create("src1/Foo.java");
-    File bar = File.create("src2/Bar.java");
-    when(sensorContext.getResource(foo)).thenReturn(foo);
-    when(sensorContext.getResource(bar)).thenReturn(bar);
-
-    adaptor.store(new DefaultDependency()
-      .from(new DefaultInputFile("foo", "src1/Foo.java").setType(Type.MAIN))
-      .to(new DefaultInputFile("foo", "src2/Bar.java").setType(Type.MAIN))
-      .weight(3));
-
-    ArgumentCaptor<Dependency> argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
-
-    verify(sensorContext, times(2)).saveDependency(argumentCaptor.capture());
-    assertThat(argumentCaptor.getAllValues()).hasSize(2);
-    Dependency value1 = argumentCaptor.getAllValues().get(0);
-    assertThat(value1.getFrom()).isEqualTo(Directory.create("src1"));
-    assertThat(value1.getTo()).isEqualTo(Directory.create("src2"));
-    assertThat(value1.getWeight()).isEqualTo(1);
-    assertThat(value1.getUsage()).isEqualTo("USES");
-
-    Dependency value2 = argumentCaptor.getAllValues().get(1);
-    assertThat(value2.getFrom()).isEqualTo(foo);
-    assertThat(value2.getTo()).isEqualTo(bar);
-    assertThat(value2.getWeight()).isEqualTo(3);
-    assertThat(value2.getUsage()).isEqualTo("USES");
-  }
-
-  @Test
-  public void shouldIncrementParentWeight() {
-
-    File foo = File.create("src1/Foo.java");
-    File bar = File.create("src2/Bar.java");
-    Directory src1 = Directory.create("src1");
-    Directory src2 = Directory.create("src2");
-    when(sensorContext.getResource(foo)).thenReturn(foo);
-    when(sensorContext.getResource(bar)).thenReturn(bar);
-    Dependency parentDep = new Dependency(src1, src2).setWeight(4);
-    when(sonarIndex.getEdge(src1, src2)).thenReturn(parentDep);
-
-    adaptor.store(new DefaultDependency()
-      .from(new DefaultInputFile("foo", "src1/Foo.java").setType(Type.MAIN))
-      .to(new DefaultInputFile("foo", "src2/Bar.java").setType(Type.MAIN))
-      .weight(3));
-
-    ArgumentCaptor<Dependency> argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
-
-    verify(sensorContext).saveDependency(argumentCaptor.capture());
-
-    assertThat(parentDep.getWeight()).isEqualTo(5);
-
-    Dependency value = argumentCaptor.getValue();
-    assertThat(value.getFrom()).isEqualTo(foo);
-    assertThat(value.getTo()).isEqualTo(bar);
-    assertThat(value.getWeight()).isEqualTo(3);
-    assertThat(value.getUsage()).isEqualTo("USES");
-  }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorContextTest.java b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorContextTest.java
new file mode 100644 (file)
index 0000000..b51dccd
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.sensor;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
+import org.sonar.api.batch.sensor.SensorStorage;
+import org.sonar.api.config.Settings;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.ComponentDataCache;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DefaultSensorContextTest {
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  private ActiveRules activeRules;
+  private DefaultFileSystem fs;
+  private DefaultSensorContext adaptor;
+  private Settings settings;
+  private SensorStorage sensorStorage;
+
+  @Before
+  public void prepare() {
+    activeRules = new ActiveRulesBuilder().build();
+    fs = new DefaultFileSystem();
+    MetricFinder metricFinder = mock(MetricFinder.class);
+    when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
+    when(metricFinder.findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
+    settings = new Settings();
+    ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
+    BlockCache blockCache = mock(BlockCache.class);
+    sensorStorage = mock(SensorStorage.class);
+    adaptor = new DefaultSensorContext(settings, fs, activeRules, componentDataCache, blockCache, mock(DuplicationCache.class), sensorStorage);
+  }
+
+  @Test
+  public void shouldProvideComponents() {
+    assertThat(adaptor.activeRules()).isEqualTo(activeRules);
+    assertThat(adaptor.fileSystem()).isEqualTo(fs);
+    assertThat(adaptor.settings()).isEqualTo(settings);
+
+    assertThat(adaptor.newIssue()).isNotNull();
+    assertThat(adaptor.newMeasure()).isNotNull();
+  }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java
new file mode 100644 (file)
index 0000000..c977124
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * 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.sensor;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.ArgumentCaptor;
+import org.sonar.api.batch.fs.InputDir;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputFile.Type;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.DefaultInputDir;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
+import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
+import org.sonar.api.batch.sensor.issue.Issue.Severity;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.config.Settings;
+import org.sonar.api.design.Dependency;
+import org.sonar.api.issue.Issuable;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.PersistenceMode;
+import org.sonar.api.resources.Directory;
+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.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.index.DefaultIndex;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class DefaultSensorStorageTest {
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  private ActiveRules activeRules;
+  private DefaultFileSystem fs;
+  private DefaultSensorStorage sensorStorage;
+  private Settings settings;
+  private ResourcePerspectives resourcePerspectives;
+  private Project project;
+  private DefaultIndex sonarIndex;
+
+  @Before
+  public void prepare() {
+    activeRules = new ActiveRulesBuilder().build();
+    fs = new DefaultFileSystem();
+    MetricFinder metricFinder = mock(MetricFinder.class);
+    when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
+    when(metricFinder.findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
+    settings = new Settings();
+    resourcePerspectives = mock(ResourcePerspectives.class);
+    ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
+    BlockCache blockCache = mock(BlockCache.class);
+    project = new Project("myProject");
+    sonarIndex = mock(DefaultIndex.class);
+    CoverageExclusions coverageExclusions = mock(CoverageExclusions.class);
+    when(coverageExclusions.accept(any(Resource.class), any(Measure.class))).thenReturn(true);
+    sensorStorage = new DefaultSensorStorage(metricFinder, project,
+      resourcePerspectives, settings, fs, activeRules, componentDataCache, blockCache, mock(DuplicationCache.class), sonarIndex, coverageExclusions);
+  }
+
+  @Test
+  public void shouldFailIfUnknowMetric() {
+    InputFile file = new DefaultInputFile("foo", "src/Foo.php");
+
+    thrown.expect(IllegalStateException.class);
+    thrown.expectMessage("Unknow metric with key: lines");
+
+    sensorStorage.store(new DefaultMeasure()
+      .onFile(file)
+      .forMetric(CoreMetrics.LINES)
+      .withValue(10));
+  }
+
+  @Test
+  public void shouldSaveFileMeasureToSensorContext() {
+    InputFile file = new DefaultInputFile("foo", "src/Foo.php");
+
+    ArgumentCaptor<org.sonar.api.measures.Measure> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
+    File sonarFile = File.create("src/Foo.php");
+    when(sonarIndex.addMeasure(eq(sonarFile), argumentCaptor.capture())).thenReturn(null);
+    when(sonarIndex.getResource(sonarFile)).thenReturn(sonarFile);
+    sensorStorage.store(new DefaultMeasure()
+      .onFile(file)
+      .forMetric(CoreMetrics.NCLOC)
+      .withValue(10));
+
+    org.sonar.api.measures.Measure m = argumentCaptor.getValue();
+    assertThat(m.getValue()).isEqualTo(10.0);
+    assertThat(m.getMetric()).isEqualTo(CoreMetrics.NCLOC);
+  }
+
+  @Test
+  public void shouldSetAppropriatePersistenceMode() {
+    // Metric FUNCTION_COMPLEXITY_DISTRIBUTION is only persisted on directories.
+
+    InputFile file = new DefaultInputFile("foo", "src/Foo.php");
+
+    ArgumentCaptor<org.sonar.api.measures.Measure> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
+    File sonarFile = File.create("src/Foo.php");
+
+    when(sonarIndex.addMeasure(eq(sonarFile), argumentCaptor.capture())).thenReturn(null);
+
+    when(sonarIndex.getResource(sonarFile)).thenReturn(sonarFile);
+
+    sensorStorage.store(new DefaultMeasure()
+      .onFile(file)
+      .forMetric(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION)
+      .withValue("foo"));
+
+    org.sonar.api.measures.Measure m = argumentCaptor.getValue();
+    assertThat(m.getData()).isEqualTo("foo");
+    assertThat(m.getMetric()).isEqualTo(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
+    assertThat(m.getPersistenceMode()).isEqualTo(PersistenceMode.MEMORY);
+
+  }
+
+  @Test
+  public void shouldSaveProjectMeasureToSensorContext() {
+
+    ArgumentCaptor<org.sonar.api.measures.Measure> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
+    when(sonarIndex.addMeasure(eq(project), argumentCaptor.capture())).thenReturn(null);
+
+    sensorStorage.store(new DefaultMeasure()
+      .onProject()
+      .forMetric(CoreMetrics.NCLOC)
+      .withValue(10));
+
+    org.sonar.api.measures.Measure m = argumentCaptor.getValue();
+    assertThat(m.getValue()).isEqualTo(10.0);
+    assertThat(m.getMetric()).isEqualTo(CoreMetrics.NCLOC);
+  }
+
+  @Test
+  public void shouldAddIssueOnFile() {
+    InputFile file = new DefaultInputFile("foo", "src/Foo.php");
+
+    ArgumentCaptor<Issue> argumentCaptor = ArgumentCaptor.forClass(Issue.class);
+
+    Issuable issuable = mock(Issuable.class);
+    when(resourcePerspectives.as(Issuable.class, File.create("src/Foo.php"))).thenReturn(issuable);
+
+    when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
+
+    sensorStorage.store(new DefaultIssue()
+      .onFile(file)
+      .ruleKey(RuleKey.of("foo", "bar"))
+      .message("Foo")
+      .atLine(3)
+      .effortToFix(10.0));
+
+    Issue issue = argumentCaptor.getValue();
+    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
+    assertThat(issue.message()).isEqualTo("Foo");
+    assertThat(issue.line()).isEqualTo(3);
+    assertThat(issue.severity()).isNull();
+    assertThat(issue.effortToFix()).isEqualTo(10.0);
+  }
+
+  @Test
+  public void shouldAddIssueOnDirectory() {
+    InputDir dir = new DefaultInputDir("foo", "src");
+
+    ArgumentCaptor<Issue> argumentCaptor = ArgumentCaptor.forClass(Issue.class);
+
+    Issuable issuable = mock(Issuable.class);
+    when(resourcePerspectives.as(Issuable.class, Directory.create("src"))).thenReturn(issuable);
+
+    when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
+
+    sensorStorage.store(new DefaultIssue()
+      .onDir(dir)
+      .ruleKey(RuleKey.of("foo", "bar"))
+      .message("Foo")
+      .effortToFix(10.0));
+
+    Issue issue = argumentCaptor.getValue();
+    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
+    assertThat(issue.message()).isEqualTo("Foo");
+    assertThat(issue.line()).isNull();
+    assertThat(issue.severity()).isNull();
+    assertThat(issue.effortToFix()).isEqualTo(10.0);
+  }
+
+  @Test
+  public void shouldAddIssueOnProject() {
+    ArgumentCaptor<Issue> argumentCaptor = ArgumentCaptor.forClass(Issue.class);
+
+    Issuable issuable = mock(Issuable.class);
+    when(resourcePerspectives.as(Issuable.class, (Resource) project)).thenReturn(issuable);
+
+    when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
+
+    sensorStorage.store(new DefaultIssue()
+      .onProject()
+      .ruleKey(RuleKey.of("foo", "bar"))
+      .message("Foo")
+      .overrideSeverity(Severity.BLOCKER)
+      .effortToFix(10.0));
+
+    Issue issue = argumentCaptor.getValue();
+    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
+    assertThat(issue.message()).isEqualTo("Foo");
+    assertThat(issue.line()).isNull();
+    assertThat(issue.severity()).isEqualTo("BLOCKER");
+    assertThat(issue.effortToFix()).isEqualTo(10.0);
+  }
+
+  @Test
+  public void shouldStoreDependencyInSameFolder() {
+
+    File foo = File.create("src/Foo.java");
+    File bar = File.create("src/Bar.java");
+    when(sonarIndex.getResource(foo)).thenReturn(foo);
+    when(sonarIndex.getResource(bar)).thenReturn(bar);
+
+    sensorStorage.store(new DefaultDependency()
+      .from(new DefaultInputFile("foo", "src/Foo.java").setType(Type.MAIN))
+      .to(new DefaultInputFile("foo", "src/Bar.java").setType(Type.MAIN))
+      .weight(3));
+
+    ArgumentCaptor<Dependency> argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
+
+    verify(sonarIndex).addDependency(argumentCaptor.capture());
+    assertThat(argumentCaptor.getValue().getFrom()).isEqualTo(foo);
+    assertThat(argumentCaptor.getValue().getTo()).isEqualTo(bar);
+    assertThat(argumentCaptor.getValue().getWeight()).isEqualTo(3);
+    assertThat(argumentCaptor.getValue().getUsage()).isEqualTo("USES");
+  }
+
+  @Test
+  public void throw_if_attempt_to_save_same_dep_twice() {
+
+    File foo = File.create("src/Foo.java");
+    File bar = File.create("src/Bar.java");
+    when(sonarIndex.getResource(foo)).thenReturn(foo);
+    when(sonarIndex.getResource(bar)).thenReturn(bar);
+    when(sonarIndex.getEdge(foo, bar)).thenReturn(new Dependency(foo, bar));
+
+    thrown.expect(IllegalStateException.class);
+    thrown.expectMessage("Dependency between [moduleKey=foo, relative=src/Foo.java, abs=null] and [moduleKey=foo, relative=src/Bar.java, abs=null] was already saved.");
+
+    sensorStorage.store(new DefaultDependency()
+      .from(new DefaultInputFile("foo", "src/Foo.java").setType(Type.MAIN))
+      .to(new DefaultInputFile("foo", "src/Bar.java").setType(Type.MAIN))
+      .weight(3));
+  }
+
+  @Test
+  public void shouldStoreDependencyInDifferentFolder() {
+
+    File foo = File.create("src1/Foo.java");
+    File bar = File.create("src2/Bar.java");
+    when(sonarIndex.getResource(foo)).thenReturn(foo);
+    when(sonarIndex.getResource(bar)).thenReturn(bar);
+
+    sensorStorage.store(new DefaultDependency()
+      .from(new DefaultInputFile("foo", "src1/Foo.java").setType(Type.MAIN))
+      .to(new DefaultInputFile("foo", "src2/Bar.java").setType(Type.MAIN))
+      .weight(3));
+
+    ArgumentCaptor<Dependency> argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
+
+    verify(sonarIndex, times(2)).addDependency(argumentCaptor.capture());
+    assertThat(argumentCaptor.getAllValues()).hasSize(2);
+    Dependency value1 = argumentCaptor.getAllValues().get(0);
+    assertThat(value1.getFrom()).isEqualTo(Directory.create("src1"));
+    assertThat(value1.getTo()).isEqualTo(Directory.create("src2"));
+    assertThat(value1.getWeight()).isEqualTo(1);
+    assertThat(value1.getUsage()).isEqualTo("USES");
+
+    Dependency value2 = argumentCaptor.getAllValues().get(1);
+    assertThat(value2.getFrom()).isEqualTo(foo);
+    assertThat(value2.getTo()).isEqualTo(bar);
+    assertThat(value2.getWeight()).isEqualTo(3);
+    assertThat(value2.getUsage()).isEqualTo("USES");
+  }
+
+  @Test
+  public void shouldIncrementParentWeight() {
+
+    File foo = File.create("src1/Foo.java");
+    File bar = File.create("src2/Bar.java");
+    Directory src1 = Directory.create("src1");
+    Directory src2 = Directory.create("src2");
+    when(sonarIndex.getResource(foo)).thenReturn(foo);
+    when(sonarIndex.getResource(bar)).thenReturn(bar);
+    Dependency parentDep = new Dependency(src1, src2).setWeight(4);
+    when(sonarIndex.getEdge(src1, src2)).thenReturn(parentDep);
+
+    sensorStorage.store(new DefaultDependency()
+      .from(new DefaultInputFile("foo", "src1/Foo.java").setType(Type.MAIN))
+      .to(new DefaultInputFile("foo", "src2/Bar.java").setType(Type.MAIN))
+      .weight(3));
+
+    ArgumentCaptor<Dependency> argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
+
+    verify(sonarIndex).addDependency(argumentCaptor.capture());
+
+    assertThat(parentDep.getWeight()).isEqualTo(5);
+
+    Dependency value = argumentCaptor.getValue();
+    assertThat(value.getFrom()).isEqualTo(foo);
+    assertThat(value.getTo()).isEqualTo(bar);
+    assertThat(value.getWeight()).isEqualTo(3);
+    assertThat(value.getUsage()).isEqualTo("USES");
+  }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/sensor/coverage/CoverageExclusionsTest.java b/sonar-batch/src/test/java/org/sonar/batch/sensor/coverage/CoverageExclusionsTest.java
new file mode 100644 (file)
index 0000000..ec592a7
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.sensor.coverage;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Resource;
+import org.sonar.core.config.ExclusionProperties;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class CoverageExclusionsTest {
+
+  private Settings settings;
+
+  private CoverageExclusions filter;
+
+  @Before
+  public void createFilter() {
+    settings = new Settings(new PropertyDefinitions(ExclusionProperties.all()));
+    filter = new CoverageExclusions(settings);
+  }
+
+  @Test
+  public void shouldNotFilterNonCoverageMetrics() {
+    Measure otherMeasure = mock(Measure.class);
+    when(otherMeasure.getMetric()).thenReturn(CoreMetrics.LINES);
+    assertThat(filter.accept(mock(Resource.class), otherMeasure)).isTrue();
+  }
+
+  @Test
+  public void shouldFilterFileBasedOnPattern() {
+    Resource resource = File.create("src/org/polop/File.php", "org/polop/File.php", null, false);
+    Measure coverageMeasure = mock(Measure.class);
+    when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.LINES_TO_COVER);
+
+    settings.setProperty("sonar.coverage.exclusions", "src/org/polop/*");
+    filter.initPatterns();
+    assertThat(filter.accept(resource, coverageMeasure)).isFalse();
+  }
+
+  @Test
+  public void shouldNotFilterFileBasedOnPattern() {
+    Resource resource = File.create("src/org/polop/File.php", "org/polop/File.php", null, false);
+    Measure coverageMeasure = mock(Measure.class);
+    when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.COVERAGE);
+
+    settings.setProperty("sonar.coverage.exclusions", "src/org/other/*");
+    filter.initPatterns();
+    assertThat(filter.accept(resource, coverageMeasure)).isTrue();
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilter.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilter.java
deleted file mode 100644 (file)
index 324c7e4..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.core.measure;
-
-import org.sonar.api.BatchExtension;
-
-import org.sonar.api.resources.Resource;
-import org.sonar.api.measures.Measure;
-
-/**
- * Allows to define filter {@link Measure}s when they are saved on {@link Resource}s
- * @since 4.0
- *
- */
-public interface MeasurementFilter extends BatchExtension {
-
-  /**
-   *
-   * @param resource
-   * @param measure
-   * @return <code>true</code> if the given measure can be saved for the given resource
-   */
-  boolean accept(Resource resource, Measure measure);
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilters.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilters.java
deleted file mode 100644 (file)
index fa69974..0000000
+++ /dev/null
@@ -1,55 +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.core.measure;
-
-import com.google.common.collect.ImmutableList;
-import org.sonar.api.BatchExtension;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.Resource;
-
-import java.util.Iterator;
-import java.util.List;
-
-/**
- *
- * @since 4.0
- *
- */
-public class MeasurementFilters implements BatchExtension {
-
-  private List<MeasurementFilter> filters;
-
-  public MeasurementFilters() {
-    this.filters = ImmutableList.of();
-  }
-
-  public MeasurementFilters(MeasurementFilter[] filters) {
-    this.filters = ImmutableList.copyOf(filters);
-  }
-
-  public boolean accept(Resource resource, Measure measure) {
-    boolean accept = true;
-    Iterator<MeasurementFilter> iteratorFilter = filters.iterator();
-    while(accept && iteratorFilter.hasNext()) {
-      accept &= iteratorFilter.next().accept(resource, measure);
-    }
-    return accept;
-  }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/package-info.java b/sonar-core/src/main/java/org/sonar/core/measure/package-info.java
deleted file mode 100644 (file)
index 036a513..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.core.measure;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-core/src/test/java/org/sonar/core/measure/MeasurementFiltersTest.java b/sonar-core/src/test/java/org/sonar/core/measure/MeasurementFiltersTest.java
deleted file mode 100644 (file)
index cc0f102..0000000
+++ /dev/null
@@ -1,67 +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.core.measure;
-
-import org.assertj.core.util.Arrays;
-import org.junit.Test;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.Resource;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.*;
-
-public class MeasurementFiltersTest {
-
-  private MeasurementFilters filters;
-
-  @Test
-  public void shouldAcceptEverythingWithEmptyFilters() {
-    filters = new MeasurementFilters();
-    Resource resource = mock(Resource.class);
-    Measure measure = mock(Measure.class);
-    assertThat(filters.accept(resource, measure)).isTrue();
-  }
-
-  @Test
-  public void shouldAcceptIfAllFiltersAccept() {
-    Resource resource = mock(Resource.class);
-    Measure measure = mock(Measure.class);
-    MeasurementFilter filter1 = mock(MeasurementFilter.class);
-    when(filter1.accept(resource, measure)).thenReturn(true);
-    MeasurementFilter filter2 = mock(MeasurementFilter.class);
-    when(filter2.accept(resource, measure)).thenReturn(true);
-
-    filters = new MeasurementFilters(Arrays.array(filter1, filter2));
-    assertThat(filters.accept(resource, measure)).isTrue();
-  }
-
-  @Test
-  public void shouldNnotAcceptIfOneFilterDoesntAccept() {
-    Resource resource = mock(Resource.class);
-    Measure measure = mock(Measure.class);
-    MeasurementFilter filter1 = mock(MeasurementFilter.class);
-    when(filter1.accept(resource, measure)).thenReturn(false);
-    MeasurementFilter filter2 = mock(MeasurementFilter.class);
-
-    filters = new MeasurementFilters(Arrays.array(filter1, filter2));
-    assertThat(filters.accept(resource, measure)).isFalse();
-    verifyZeroInteractions(filter2);
-  }
-}
index 7626ce1e01836a389d9506907987c73f1d35c6a7..16aa183e3a5f2748d54354ac09976b58903ae597 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.api.checks;
 
 import com.google.common.collect.Maps;
 import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.SonarIndex;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.issue.batch.IssueFilterChain;
 import org.sonar.api.resources.Resource;
@@ -37,16 +37,16 @@ import java.util.Set;
 public class NoSonarFilter implements org.sonar.api.issue.batch.IssueFilter {
 
   private final Map<String, Set<Integer>> noSonarLinesByKey = Maps.newHashMap();
-  private SensorContext context;
+  private SonarIndex sonarIndex;
 
-  public NoSonarFilter(SensorContext context) {
-    this.context = context;
+  public NoSonarFilter(SonarIndex sonarIndex) {
+    this.sonarIndex = sonarIndex;
   }
 
   public void addResource(Resource model, Set<Integer> noSonarLines) {
     if (model != null && noSonarLines != null) {
       // Reload resource to handle backward compatibility of resource keys
-      Resource resource = context.getResource(model);
+      Resource resource = sonarIndex.getResource(model);
       if (resource != null) {
         noSonarLinesByKey.put(resource.getEffectiveKey(), noSonarLines);
       }
index 5be333666438f4b93fd7c3fd43b3c5d76f982c0b..1521ca67b52aad2d43ee947bd4202a7030da58b5 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.api.checks;
 
 import org.junit.Before;
 import org.junit.Test;
-import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.SonarIndex;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.issue.batch.IssueFilterChain;
 import org.sonar.api.resources.File;
@@ -37,8 +37,8 @@ import static org.mockito.Mockito.when;
 
 public class NoSonarFilterTest {
 
-  private SensorContext sensorContext = mock(SensorContext.class);
-  NoSonarFilter filter = new NoSonarFilter(sensorContext);
+  private SonarIndex sonarIndex = mock(SonarIndex.class);
+  NoSonarFilter filter = new NoSonarFilter(sonarIndex);
   private File javaFile;
   IssueFilterChain chain = mock(IssueFilterChain.class);
 
@@ -47,7 +47,7 @@ public class NoSonarFilterTest {
     when(chain.accept(isA(Issue.class))).thenReturn(true);
     javaFile = new File("org.foo.Bar");
     javaFile.setEffectiveKey("struts:org.apache.Action");
-    when(sensorContext.getResource(javaFile)).thenReturn(javaFile);
+    when(sonarIndex.getResource(javaFile)).thenReturn(javaFile);
   }
 
   @Test
index a21d421e6acf4a8c4ca6aefe4206340ffa23ade4..b75209e1538845150add6173f54ae7547ee58b91 100644 (file)
@@ -40,7 +40,7 @@ import java.util.Set;
 /**
  * @since 1.10
  */
-public interface SensorContext {
+public interface SensorContext extends org.sonar.api.batch.sensor.SensorContext {
 
   /**
    * Indexes a resource as a direct child of project. This method does nothing and returns true if the resource already indexed.
index 0e590c84593bc30cadea6456becbf2ccd4d982e4..e83df0c84e6db0c5ec4f4b00512145f2965d8a59 100644 (file)
@@ -33,7 +33,9 @@ import org.sonar.api.resources.Project;
  * </p>
  * 
  * @since 1.10
+ * @deprecated since 5.1 SQ platform don't want any dependency on Maven
  */
+@Deprecated
 @SupportedEnvironment("maven")
 public interface DependsUponMavenPlugin extends BatchExtension {
 
index a0be6e447ab49ece9cccb8f16612deb0b7edc502..01f0e109e53f7bea625ee965067afed49a53cd93 100644 (file)
@@ -31,7 +31,7 @@ import org.sonar.api.BatchExtension;
  * For example the Cobertura Sensor parses Cobertura report and saves the first-level of measures on files.
  * </p>
  *
- * @since 5.0
+ * @since 5.1
  */
 public interface Sensor extends BatchExtension {
 
index 805d9db24177fa800bbfa44521398722ee176690..b32be9c7ab0d7272c085b03968af64191f9b6b4d 100644 (file)
@@ -29,6 +29,7 @@ import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder;
 import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
 import org.sonar.api.batch.sensor.issue.Issue;
 import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.measure.NewMeasure;
 import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder;
 import org.sonar.api.batch.sensor.test.Coverage;
 import org.sonar.api.batch.sensor.test.TestCaseCoverage;
@@ -40,7 +41,7 @@ import java.util.List;
 
 /**
  * See {@link Sensor#execute(SensorContext)}
- * @since 5.0
+ * @since 5.1
  */
 public interface SensorContext {
 
@@ -62,9 +63,9 @@ public interface SensorContext {
   // ----------- MEASURES --------------
 
   /**
-   * Fluent builder to create a new {@link Measure}. Don't forget to call {@link Measure#save()} once all parameters are provided.
+   * Fluent builder to create a new {@link Measure}. Don't forget to call {@link NewMeasure#save()} once all parameters are provided.
    */
-  <G extends Serializable> Measure<G> newMeasure();
+  <G extends Serializable> NewMeasure<G> newMeasure();
 
   // ----------- ISSUES --------------
 
index 86a0abdffadb2729a4490750db8371240993c65b..c59f7a7be7658d55b32efcef7c6a4ce0ef049611 100644 (file)
@@ -27,21 +27,12 @@ import javax.annotation.CheckForNull;
 import java.io.Serializable;
 
 /**
- * Builder to create new Measure.
- * @since 5.0
+ * Measure on File, Directory or Project.
+ * Should not be implemented by client.
+ * @since 5.1
  */
 public interface Measure<G extends Serializable> {
 
-  /**
-   * The file the measure belongs to.
-   */
-  Measure<G> onFile(InputFile file);
-
-  /**
-   * Tell that the measure is global to the project.
-   */
-  Measure<G> onProject();
-
   /**
    * The file the measure belong to.
    * @return null if measure is on project
@@ -49,29 +40,14 @@ public interface Measure<G extends Serializable> {
   @CheckForNull
   InputFile inputFile();
 
-  /**
-   * Set the metric this measure belong to.
-   */
-  Measure<G> forMetric(Metric<G> metric);
-
   /**
    * The metric this measure belong to.
    */
   Metric<G> metric();
 
-  /**
-   * Value of the measure.
-   */
-  Measure<G> withValue(G value);
-
   /**
    * Value of the measure.
    */
   G value();
 
-  /**
-   * Save the measure. It is not permitted so save several measures of the same metric on the same file/project.
-   */
-  void save();
-
 }
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/NewMeasure.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/NewMeasure.java
new file mode 100644 (file)
index 0000000..cf8bccb
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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.sensor.measure;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.measure.Metric;
+
+import java.io.Serializable;
+
+/**
+ * Builder to create new Measure.
+ * Should not be implemented by client.
+ * @since 5.1
+ */
+public interface NewMeasure<G extends Serializable> {
+
+  /**
+   * The file the measure belongs to.
+   */
+  NewMeasure<G> onFile(InputFile file);
+
+  /**
+   * Tell that the measure is global to the project.
+   */
+  NewMeasure<G> onProject();
+
+  /**
+   * Set the metric this measure belong to.
+   */
+  NewMeasure<G> forMetric(Metric<G> metric);
+
+  /**
+   * Value of the measure.
+   */
+  NewMeasure<G> withValue(G value);
+
+  /**
+   * Save the measure. It is not permitted so save several measures of the same metric on the same file/project.
+   */
+  void save();
+
+}
index 167f9e6af98385e859984b06d27617a8fdd44cba..a6e4a0021fa01b46e001f43359e0278819670f74 100644 (file)
@@ -27,13 +27,14 @@ import org.sonar.api.batch.measure.Metric;
 import org.sonar.api.batch.sensor.SensorStorage;
 import org.sonar.api.batch.sensor.internal.DefaultStorable;
 import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.measure.NewMeasure;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 
 import java.io.Serializable;
 
-public class DefaultMeasure<G extends Serializable> extends DefaultStorable implements Measure<G> {
+public class DefaultMeasure<G extends Serializable> extends DefaultStorable implements Measure<G>, NewMeasure<G> {
 
   private boolean onProject = false;
   private InputFile file;
@@ -102,7 +103,7 @@ public class DefaultMeasure<G extends Serializable> extends DefaultStorable impl
     Preconditions.checkNotNull(this.value, "Measure value can't be null");
     Preconditions.checkNotNull(this.metric, "Measure metric can't be null");
     Preconditions.checkState(this.metric.valueType().equals(this.value.getClass()), "Measure value should be of type " + this.metric.valueType());
-    storage.store((Measure<Serializable>) this);
+    storage.store(this);
   }
 
   @Override
index c6f68aaedce932651085d0e8987671e78b20c777..bb89c172a07afe4588edcef957a2ea1f66c95fe0 100644 (file)
@@ -29,7 +29,9 @@ import java.util.List;
 
 /**
  * @since 2.5
+ * @deprecated since 5.1 use {@link org.sonar.api.batch.measure.MetricFinder} on batch side
  */
+@Deprecated
 public interface MetricFinder extends TaskComponent, ServerComponent {
 
   @CheckForNull