import org.sonar.api.Plugin;
import org.sonar.api.SonarQubeSide;
import org.sonar.api.SonarRuntime;
+import org.sonar.api.internal.PluginContextImpl;
import org.sonar.api.internal.SonarRuntimeImpl;
import org.sonar.api.utils.Version;
import org.sonar.xoo.lang.CpdTokenizerSensor;
@Test
public void provide_extensions_for_5_4() {
SonarRuntime runtime = SonarRuntimeImpl.forSonarLint(Version.parse("5.4"));
- Plugin.Context context = new Plugin.Context(runtime);
+ Plugin.Context context = new PluginContextImpl.Builder().setSonarRuntime(runtime).build();
new XooPlugin().define(context);
assertThat(context.getExtensions()).hasSize(46).doesNotContain(CpdTokenizerSensor.class);
}
@Test
public void provide_extensions_for_5_5() {
SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.parse("5.5"), SonarQubeSide.SCANNER);
- Plugin.Context context = new Plugin.Context(runtime);
+ Plugin.Context context = new PluginContextImpl.Builder().setSonarRuntime(runtime).build();
new XooPlugin().define(context);
assertThat(context.getExtensions()).hasSize(49).contains(CpdTokenizerSensor.class);
}
@Test
public void provide_extensions_for_6_6() {
SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.parse("6.6"), SonarQubeSide.SCANNER);
- Plugin.Context context = new Plugin.Context(runtime);
+ Plugin.Context context = new PluginContextImpl.Builder().setSonarRuntime(runtime).build();
new XooPlugin().define(context);
assertThat(context.getExtensions()).hasSize(50).contains(CpdTokenizerSensor.class);
}
import org.sonar.api.ExtensionProvider;
import org.sonar.api.Plugin;
import org.sonar.api.SonarRuntime;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.internal.PluginContextImpl;
import org.sonar.api.utils.AnnotationUtils;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.PluginInfo;
Plugin plugin = pluginRepository.getPluginInstance(pluginKey);
container.addExtension(pluginInfo, plugin);
- Plugin.Context context = new Plugin.Context(sonarRuntime);
+ Plugin.Context context = new PluginContextImpl.Builder()
+ .setSonarRuntime(sonarRuntime)
+ .setBootConfiguration(container.getComponentByType(Configuration.class))
+ .build();
plugin.define(context);
for (Object extension : context.getExtensions()) {
if (installExtension(container, pluginInfo, extension, true) != null) {
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import org.sonar.api.config.Configuration;
import org.sonar.api.utils.Version;
import static java.util.Arrays.asList;
* </project>
* </pre>
*
- * <p>Example of test
+ * <p>Example of Test
* <pre>
*{@literal @}Test
* public void test_plugin_extensions_compatible_with_5_6() {
* SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.create(5, 6), SonarQubeSide.SCANNER);
- * Plugin.Context context = new Plugin.Context(runtime);
- * new MyPlugin().define(context);
+ * Plugin.Context context = new PluginContextImpl.Builder().setSonarRuntime(runtime).build();
+ * MyPlugin underTest = new MyPlugin();
+ *
+ * underTest.define(context);
+ *
* assertThat(context.getExtensions()).hasSize(4);
* }
* </pre>
*
* @since 5.5
+ * @see org.sonar.api.internal.PluginContextImpl for unit tests
*/
public interface Plugin {
private final SonarRuntime sonarRuntime;
private final List extensions = new ArrayList();
+ /**
+ * For unit tests only. It's recommended to use {@link org.sonar.api.internal.PluginContextImpl.Builder}
+ * to create instances of {@link Plugin.Context}.
+ * The configuration returned by {@see #getBootConfiguration()} is empty.
+ */
public Context(SonarRuntime sonarRuntime) {
- this.sonarRuntime = sonarRuntime;
+ this.sonarRuntime = requireNonNull(sonarRuntime, "sonarRuntime is null");
}
/**
return extensions;
}
+ /**
+ * The configuration that contains only the few properties required to bootstrap the process, for example:
+ * - conf/sonar.properties and persisted properties on web server and Compute Engine sides. The default values
+ * defined by plugins are ignored.
+ * - command-line arguments on scanner side. Default values or properties persisted in server are ignored.
+ *
+ * @since 7.1
+ */
+ public Configuration getBootConfiguration() {
+ throw new UnsupportedOperationException("Unit tests should create Plugin.Context with org.sonar.api.internal.PluginContextImpl#Builder");
+ }
+
}
/**
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info 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.api.internal;
+
+import org.sonar.api.Plugin;
+import org.sonar.api.SonarRuntime;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.config.internal.MapSettings;
+
+/**
+ * Implementation of {@link Plugin.Context} that plugins could use in their unit tests.
+ *
+ * Example:
+ *
+ * <pre>
+ * import org.sonar.api.internal.SonarRuntimeImpl;
+ * import org.sonar.api.config.internal.MapSettings;
+ *
+ * ...
+ *
+ * SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.create(7, 1), SonarQubeSide.SCANNER);
+ * MapSettings settings = new MapSettings().setProperty("foo", "bar");
+ * Plugin.Context context = new PluginContextImpl.Builder()
+ * .setSonarRuntime(runtime)
+ * .setBootConfiguration(settings.asConfig());
+ * .build();
+ * </pre>
+ *
+ * @since 7.1
+ */
+public class PluginContextImpl extends Plugin.Context {
+
+ private final Configuration bootConfiguration;
+
+ private PluginContextImpl(Builder builder) {
+ super(builder.sonarRuntime);
+ this.bootConfiguration = builder.bootConfiguration != null ? builder.bootConfiguration : new MapSettings().asConfig();
+ }
+
+ @Override
+ public Configuration getBootConfiguration() {
+ return bootConfiguration;
+ }
+
+ public static class Builder {
+ private SonarRuntime sonarRuntime;
+ private Configuration bootConfiguration;
+
+ /**
+ * Required.
+ * @see SonarRuntimeImpl
+ * @return this
+ */
+ public Builder setSonarRuntime(SonarRuntime r) {
+ this.sonarRuntime = r;
+ return this;
+ }
+
+ /**
+ * If not set, then an empty configuration is used.
+ * @return this
+ */
+ public Builder setBootConfiguration(Configuration c) {
+ this.bootConfiguration = c;
+ return this;
+ }
+
+ public Plugin.Context build() {
+ return new PluginContextImpl(this);
+ }
+ }
+}
import java.util.Arrays;
import org.junit.Test;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.internal.PluginContextImpl;
import org.sonar.api.internal.SonarRuntimeImpl;
import org.sonar.api.utils.Version;
@Test
public void test_context() {
SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(VERSION_5_6, SonarQubeSide.SERVER);
- Plugin.Context context = new Plugin.Context(runtime);
+ MapSettings settings = new MapSettings().setProperty("foo", "bar");
+ Plugin.Context context = new PluginContextImpl.Builder()
+ .setSonarRuntime(runtime)
+ .setBootConfiguration(settings.asConfig())
+ .build();
assertThat(context.getSonarQubeVersion()).isEqualTo(VERSION_5_6);
assertThat(context.getExtensions()).isEmpty();
context.addExtensions("one", "two", "three", "four");
assertThat(context.getExtensions()).containsOnly("foo", "bar", "baz", "one", "two", "three", "four");
+
+ assertThat(context.getBootConfiguration().get("foo")).hasValue("bar");
}
}
import org.sonar.api.ExtensionProvider;
import org.sonar.api.Plugin;
import org.sonar.api.SonarRuntime;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.internal.PluginContextImpl;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginRepository;
private final SonarRuntime sonarRuntime;
private final PluginRepository pluginRepository;
private final GlobalAnalysisMode analysisMode;
+ private final Configuration bootConfiguration;
- public ExtensionInstaller(SonarRuntime sonarRuntime, PluginRepository pluginRepository, GlobalAnalysisMode analysisMode) {
+ public ExtensionInstaller(SonarRuntime sonarRuntime, PluginRepository pluginRepository, GlobalAnalysisMode analysisMode,
+ Configuration bootConfiguration) {
this.sonarRuntime = sonarRuntime;
this.pluginRepository = pluginRepository;
this.analysisMode = analysisMode;
+ this.bootConfiguration = bootConfiguration;
}
public ExtensionInstaller install(ComponentContainer container, ExtensionMatcher matcher) {
// plugin extensions
for (PluginInfo pluginInfo : pluginRepository.getPluginInfos()) {
Plugin plugin = pluginRepository.getPluginInstance(pluginInfo.getKey());
- Plugin.Context context = new Plugin.Context(sonarRuntime);
+ Plugin.Context context = new PluginContextImpl.Builder()
+ .setSonarRuntime(sonarRuntime)
+ .setBootConfiguration(bootConfiguration)
+ .build();
+
plugin.define(context);
for (Object extension : context.getExtensions()) {
doInstall(container, matcher, pluginInfo, extension);
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang.ClassUtils;
-import org.junit.Before;
import org.junit.Test;
import org.sonar.api.BatchExtension;
import org.sonar.api.ExtensionProvider;
import org.sonar.api.SonarPlugin;
import org.sonar.api.SonarRuntime;
+import org.sonar.api.config.internal.MapSettings;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.PluginInfo;
public class ExtensionInstallerTest {
- GlobalAnalysisMode mode;
- ScannerPluginRepository pluginRepository = mock(ScannerPluginRepository.class);
+ private MapSettings settings = new MapSettings();
+ private GlobalAnalysisMode mode = mock(GlobalAnalysisMode.class);
+ private ScannerPluginRepository pluginRepository = mock(ScannerPluginRepository.class);
private static SonarPlugin newPluginInstance(final Object... extensions) {
return new SonarPlugin() {
};
}
- @Before
- public void setUp() {
- mode = mock(GlobalAnalysisMode.class);
- }
-
@Test
public void should_filter_extensions_to_install() {
when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo")));
when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(Foo.class, Bar.class));
ComponentContainer container = new ComponentContainer();
- ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, mock(GlobalAnalysisMode.class));
+ ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, mode, settings.asConfig());
installer.install(container, new FooMatcher());
assertThat(container.getComponentByType(Foo.class)).isNotNull();
when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo")));
when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(new FooProvider(), new BarProvider()));
ComponentContainer container = new ComponentContainer();
- ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, mock(GlobalAnalysisMode.class));
+ ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, mode, settings.asConfig());
installer.install(container, new FooMatcher());
when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo")));
when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(new FooBarProvider()));
ComponentContainer container = new ComponentContainer();
- ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, mock(GlobalAnalysisMode.class));
+ ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, mode, settings.asConfig());
installer.install(container, new TrueMatcher());