aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-scanner-engine
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2016-08-06 11:28:40 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2016-08-06 12:52:33 +0200
commit8e6415a4c7444f7c6e03b10e8fa8eb535cc7e505 (patch)
treeaacc9e22f21f755e98a9ac2ad945136ee36f0419 /sonar-scanner-engine
parente55369090f3be4f1e4baa791b05c3f5cf1cef6e1 (diff)
downloadsonarqube-8e6415a4c7444f7c6e03b10e8fa8eb535cc7e505.tar.gz
sonarqube-8e6415a4c7444f7c6e03b10e8fa8eb535cc7e505.zip
SONAR-7654 API to propagate props from scanner to CE
Diffstat (limited to 'sonar-scanner-engine')
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java51
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ContextPropertiesCache.java49
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java6
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java4
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java11
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java94
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ContextPropertiesCacheTest.java66
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java15
8 files changed, 293 insertions, 3 deletions
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java
new file mode 100644
index 00000000000..87b6574e612
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java
@@ -0,0 +1,51 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.scanner.report;
+
+import com.google.common.base.Function;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.scanner.protocol.output.ScannerReportWriter;
+import org.sonar.scanner.repository.ContextPropertiesCache;
+
+import static com.google.common.collect.FluentIterable.from;
+
+public class ContextPropertiesPublisher implements ReportPublisherStep {
+ private final ContextPropertiesCache cache;
+
+ public ContextPropertiesPublisher(ContextPropertiesCache cache) {
+ this.cache = cache;
+ }
+
+ @Override
+ public void publish(ScannerReportWriter writer) {
+ Iterable<ScannerReport.ContextProperty> it = from(cache.getAll().entrySet()).transform(new MapEntryToContextPropertyFunction());
+ writer.writeContextProperties(it);
+ }
+
+ private static final class MapEntryToContextPropertyFunction implements Function<Map.Entry<String, String>, ScannerReport.ContextProperty> {
+ private final ScannerReport.ContextProperty.Builder builder = ScannerReport.ContextProperty.newBuilder();
+
+ public ScannerReport.ContextProperty apply(@Nonnull Map.Entry<String, String> input) {
+ return builder.clear().setKey(input.getKey()).setValue(input.getValue()).build();
+ }
+ }
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ContextPropertiesCache.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ContextPropertiesCache.java
new file mode 100644
index 00000000000..db7a6785c75
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ContextPropertiesCache.java
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.scanner.repository;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.sonar.api.batch.ScannerSide;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+@ScannerSide
+public class ContextPropertiesCache {
+
+ private final Map<String, String> props = new HashMap<>();
+
+ /**
+ * Value is overridden if the key was already stored.
+ * @throws IllegalArgumentException if key is null
+ * @throws IllegalArgumentException if value is null
+ * @since 6.1
+ */
+ public ContextPropertiesCache put(String key, String value) {
+ checkArgument(key != null, "Key of context property must not be null");
+ checkArgument(value != null, "Value of context property must not be null");
+ props.put(key, value);
+ return this;
+ }
+
+ public Map<String, String> getAll() {
+ return props;
+ }
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
index 65a6ff8dada..649e994cb05 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
@@ -60,12 +60,14 @@ import org.sonar.scanner.profiling.PhasesSumUpTimeProfiler;
import org.sonar.scanner.report.ActiveRulesPublisher;
import org.sonar.scanner.report.AnalysisContextReportPublisher;
import org.sonar.scanner.report.ComponentsPublisher;
+import org.sonar.scanner.report.ContextPropertiesPublisher;
import org.sonar.scanner.report.CoveragePublisher;
import org.sonar.scanner.report.MeasuresPublisher;
import org.sonar.scanner.report.MetadataPublisher;
import org.sonar.scanner.report.ReportPublisher;
import org.sonar.scanner.report.SourcePublisher;
import org.sonar.scanner.report.TestExecutionAndCoveragePublisher;
+import org.sonar.scanner.repository.ContextPropertiesCache;
import org.sonar.scanner.repository.DefaultProjectRepositoriesLoader;
import org.sonar.scanner.repository.DefaultQualityProfileLoader;
import org.sonar.scanner.repository.DefaultServerIssuesLoader;
@@ -174,6 +176,10 @@ public class ProjectScanContainer extends ComponentContainer {
// Measures
MeasureCache.class,
+ // context
+ ContextPropertiesCache.class,
+ ContextPropertiesPublisher.class,
+
ProjectSettings.class,
// Report
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java
index f19633527af..ec7b8cfe5b6 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java
@@ -152,4 +152,8 @@ public class DefaultSensorContext implements SensorContext {
return false;
}
+ @Override
+ public void addContextProperty(String key, String value) {
+ sensorStorage.storeProperty(key, value);
+ }
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
index 8487a379085..f50c95e41d2 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
@@ -64,6 +64,7 @@ import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.report.ReportPublisher;
import org.sonar.scanner.report.ScannerReportUtils;
+import org.sonar.scanner.repository.ContextPropertiesCache;
import org.sonar.scanner.scan.measure.MeasureCache;
import org.sonar.scanner.sensor.coverage.CoverageExclusions;
@@ -95,11 +96,14 @@ public class DefaultSensorStorage implements SensorStorage {
private final ReportPublisher reportPublisher;
private final MeasureCache measureCache;
private final SonarCpdBlockIndex index;
+ private final ContextPropertiesCache contextPropertiesCache;
private final Settings settings;
public DefaultSensorStorage(MetricFinder metricFinder, ModuleIssues moduleIssues,
Settings settings,
- CoverageExclusions coverageExclusions, BatchComponentCache componentCache, ReportPublisher reportPublisher, MeasureCache measureCache, SonarCpdBlockIndex index) {
+ CoverageExclusions coverageExclusions, BatchComponentCache componentCache, ReportPublisher reportPublisher,
+ MeasureCache measureCache, SonarCpdBlockIndex index,
+ ContextPropertiesCache contextPropertiesCache) {
this.metricFinder = metricFinder;
this.moduleIssues = moduleIssues;
this.settings = settings;
@@ -108,6 +112,7 @@ public class DefaultSensorStorage implements SensorStorage {
this.reportPublisher = reportPublisher;
this.measureCache = measureCache;
this.index = index;
+ this.contextPropertiesCache = contextPropertiesCache;
}
private Metric findMetricOrFail(String metricKey) {
@@ -294,4 +299,8 @@ public class DefaultSensorStorage implements SensorStorage {
// no op
}
+ @Override
+ public void storeProperty(String key, String value) {
+ contextPropertiesCache.put(key, value);
+ }
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java
new file mode 100644
index 00000000000..337f1b7a924
--- /dev/null
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java
@@ -0,0 +1,94 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.scanner.report;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.scanner.repository.ContextPropertiesCache;
+import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.scanner.protocol.output.ScannerReportWriter;
+
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class ContextPropertiesPublisherTest {
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ ContextPropertiesCache cache = new ContextPropertiesCache();
+ ContextPropertiesPublisher underTest = new ContextPropertiesPublisher(cache);
+
+ @Test
+ public void publish_writes_properties_to_report() {
+ cache.put("foo1", "bar1");
+ cache.put("foo2", "bar2");
+
+ ScannerReportWriter writer = mock(ScannerReportWriter.class);
+ underTest.publish(writer);
+
+ verify(writer).writeContextProperties(argThat(new TypeSafeMatcher<Iterable<ScannerReport.ContextProperty>>() {
+ @Override
+ protected boolean matchesSafely(Iterable<ScannerReport.ContextProperty> props) {
+ Map<String, ScannerReport.ContextProperty> map = Maps.uniqueIndex(props, ContextPropertyToKey.INSTANCE);
+ return map.size() == 2 &&
+ map.get("foo1").getValue().equals("bar1") &&
+ map.get("foo2").getValue().equals("bar2");
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ }
+ }));
+ }
+
+ @Test
+ public void publish_writes_no_properties_to_report() {
+ ScannerReportWriter writer = mock(ScannerReportWriter.class);
+ underTest.publish(writer);
+
+ verify(writer).writeContextProperties(argThat(new TypeSafeMatcher<Iterable<ScannerReport.ContextProperty>>() {
+ @Override
+ protected boolean matchesSafely(Iterable<ScannerReport.ContextProperty> props) {
+ return Iterables.isEmpty(props);
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ }
+ }));
+ }
+
+ private enum ContextPropertyToKey implements Function<ScannerReport.ContextProperty, String> {
+ INSTANCE;
+ @Override
+ public String apply(@Nonnull ScannerReport.ContextProperty input) {
+ return input.getKey();
+ }
+ }
+}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ContextPropertiesCacheTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ContextPropertiesCacheTest.java
new file mode 100644
index 00000000000..94eb23d36d1
--- /dev/null
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ContextPropertiesCacheTest.java
@@ -0,0 +1,66 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.scanner.repository;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.data.MapEntry.entry;
+
+public class ContextPropertiesCacheTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ ContextPropertiesCache underTest = new ContextPropertiesCache();
+
+ @Test
+ public void put_property() {
+ assertThat(underTest.getAll()).isEmpty();
+
+ underTest.put("foo", "bar");
+ assertThat(underTest.getAll()).containsOnly(entry("foo", "bar"));
+ }
+
+ @Test
+ public void put_overrides_existing_value() {
+ underTest.put("foo", "bar");
+ underTest.put("foo", "baz");
+ assertThat(underTest.getAll()).containsOnly(entry("foo", "baz"));
+ }
+
+ @Test
+ public void put_throws_IAE_if_key_is_null() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Key of context property must not be null");
+
+ underTest.put(null, "bar");
+ }
+
+ @Test
+ public void put_throws_IAE_if_value_is_null() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Value of context property must not be null");
+
+ underTest.put("foo", null);
+ }
+}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
index 72bbfafac76..c0d8053ece5 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
@@ -43,10 +43,12 @@ import org.sonar.scanner.index.BatchComponentCache;
import org.sonar.scanner.issue.ModuleIssues;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.report.ReportPublisher;
+import org.sonar.scanner.repository.ContextPropertiesCache;
import org.sonar.scanner.scan.measure.MeasureCache;
import org.sonar.scanner.sensor.coverage.CoverageExclusions;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.data.MapEntry.entry;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
@@ -65,7 +67,7 @@ public class DefaultSensorStorageTest {
private ModuleIssues moduleIssues;
private Project project;
private MeasureCache measureCache;
-
+ private ContextPropertiesCache contextPropertiesCache = new ContextPropertiesCache();
private BatchComponentCache resourceCache;
@Before
@@ -83,7 +85,8 @@ public class DefaultSensorStorageTest {
ReportPublisher reportPublisher = mock(ReportPublisher.class);
when(reportPublisher.getWriter()).thenReturn(new ScannerReportWriter(temp.newFolder()));
underTest = new DefaultSensorStorage(metricFinder,
- moduleIssues, settings, coverageExclusions, resourceCache, reportPublisher, measureCache, mock(SonarCpdBlockIndex.class));
+ moduleIssues, settings, coverageExclusions, resourceCache, reportPublisher, measureCache,
+ mock(SonarCpdBlockIndex.class), contextPropertiesCache);
}
@Test
@@ -159,4 +162,12 @@ public class DefaultSensorStorageTest {
underTest.store(st);
}
+ @Test
+ public void shouldStoreContextProperty() {
+ underTest.storeProperty("foo", "bar");
+
+ assertThat(contextPropertiesCache.getAll()).containsOnly(entry("foo", "bar"));
+
+ }
+
}