diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-08-06 11:28:40 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-08-06 12:52:33 +0200 |
commit | 8e6415a4c7444f7c6e03b10e8fa8eb535cc7e505 (patch) | |
tree | aacc9e22f21f755e98a9ac2ad945136ee36f0419 /sonar-scanner-engine | |
parent | e55369090f3be4f1e4baa791b05c3f5cf1cef6e1 (diff) | |
download | sonarqube-8e6415a4c7444f7c6e03b10e8fa8eb535cc7e505.tar.gz sonarqube-8e6415a4c7444f7c6e03b10e8fa8eb535cc7e505.zip |
SONAR-7654 API to propagate props from scanner to CE
Diffstat (limited to 'sonar-scanner-engine')
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")); + + } + } |