aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2015-04-15 12:18:55 +0200
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2015-04-15 14:29:42 +0200
commit86a26e1a2721c1804556b4928dee3ea23f020339 (patch)
tree1029980872d4fe17ab76a0e77f239acf4f516342
parent1ed423756675550bb540020e7aa087c1751e45d4 (diff)
downloadsonarqube-86a26e1a2721c1804556b4928dee3ea23f020339.tar.gz
sonarqube-86a26e1a2721c1804556b4928dee3ea23f020339.zip
SONAR-6376 add Java Ws /api/plugins/installed
provides the same data as RoR WS /api/updatecenter/installed_plugins but only in JSON format
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java125
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginsWs.java46
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginsWsAction.java28
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/plugins/ws/example-installed_plugins.json17
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java170
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginsWsTest.java54
7 files changed, 446 insertions, 0 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
index 70c8a708587..7085d2a46a2 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
@@ -147,6 +147,8 @@ import org.sonar.server.permission.ws.PermissionsWs;
import org.sonar.server.platform.monitoring.*;
import org.sonar.server.platform.ws.*;
import org.sonar.server.plugins.*;
+import org.sonar.server.plugins.ws.InstalledPluginsWsAction;
+import org.sonar.server.plugins.ws.PluginsWs;
import org.sonar.server.properties.ProjectSettingsFactory;
import org.sonar.server.qualitygate.QgateProjectFinder;
import org.sonar.server.qualitygate.QualityGates;
@@ -679,6 +681,10 @@ class ServerComponents {
DatabaseMonitor.class
));
+ // Plugins WS
+ pico.addSingleton(InstalledPluginsWsAction.class);
+ pico.addSingleton(PluginsWs.class);
+
// Compute engine
pico.addSingleton(ReportQueue.class);
pico.addSingleton(ComputationThreadLauncher.class);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java
new file mode 100644
index 00000000000..dc5345f0191
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java
@@ -0,0 +1,125 @@
+/*
+ * 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.server.plugins.ws;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Ordering;
+import com.google.common.io.Resources;
+import org.sonar.api.platform.PluginMetadata;
+import org.sonar.api.platform.PluginRepository;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+
+import java.util.Collection;
+import java.util.SortedSet;
+
+import static com.google.common.base.Objects.firstNonNull;
+import static com.google.common.collect.Iterables.filter;
+
+/**
+ * Implementation of the {@code installed} action for the Plugins WebService.
+ */
+public class InstalledPluginsWsAction implements PluginsWsAction {
+ private static final String DEFAULT_VERSION = "-";
+ private static final String PROPERTY_KEY = "key";
+ private static final String PROPERTY_NAME = "name";
+ private static final String PROPERTY_VERSION = "version";
+
+ private final PluginRepository pluginRepository;
+
+ private static final Ordering<PluginMetadata> NAME_KEY_PLUGIN_METADATA_COMPARATOR = Ordering.natural()
+ .onResultOf(PluginMetadataToName.INSTANCE)
+ .compound(Ordering.natural().onResultOf(PluginMetadataToKey.INSTANCE));
+
+ public InstalledPluginsWsAction(PluginRepository pluginRepository) {
+ this.pluginRepository = pluginRepository;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ controller.createAction("installed")
+ .setDescription("Get the list of all the plugins installed on the SonarQube instance, sorted by name")
+ .setSince("5.2")
+ .setHandler(this)
+ .setResponseExample(Resources.getResource(this.getClass(), "example-installed_plugins.json"));
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ Collection<PluginMetadata> pluginMetadatas = retrieveAndSortPluginMetadata();
+ writeMetadataList(response, pluginMetadatas);
+ }
+
+ private SortedSet<PluginMetadata> retrieveAndSortPluginMetadata() {
+ return ImmutableSortedSet.copyOf(
+ NAME_KEY_PLUGIN_METADATA_COMPARATOR,
+ filter(pluginRepository.getMetadata(), NotCorePluginsPredicate.INSTANCE)
+ );
+ }
+
+ private void writeMetadataList(Response response, Collection<PluginMetadata> pluginMetadatas) {
+ JsonWriter jsonWriter = response.newJsonWriter();
+ jsonWriter.beginArray();
+ for (PluginMetadata pluginMetadata : pluginMetadatas) {
+ writeMetadata(jsonWriter, pluginMetadata);
+ }
+ jsonWriter.endArray();
+ jsonWriter.close();
+ }
+
+ private void writeMetadata(JsonWriter jsonWriter, PluginMetadata pluginMetadata) {
+ jsonWriter.beginObject();
+ jsonWriter.prop(PROPERTY_KEY, pluginMetadata.getKey());
+ jsonWriter.prop(PROPERTY_NAME, pluginMetadata.getName());
+ jsonWriter.prop(PROPERTY_VERSION, firstNonNull(pluginMetadata.getVersion(), DEFAULT_VERSION));
+ jsonWriter.endObject();
+ }
+
+ private enum NotCorePluginsPredicate implements Predicate<PluginMetadata> {
+ INSTANCE;
+
+ @Override
+ public boolean apply(PluginMetadata input) {
+ return !input.isCore();
+ }
+ }
+
+ private enum PluginMetadataToName implements Function<PluginMetadata, String> {
+ INSTANCE;
+
+ @Override
+ public String apply(PluginMetadata input) {
+ return input.getName();
+ }
+ }
+
+ private enum PluginMetadataToKey implements Function<PluginMetadata, String> {
+ INSTANCE;
+
+ @Override
+ public String apply(PluginMetadata input) {
+ return input.getKey();
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginsWs.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginsWs.java
new file mode 100644
index 00000000000..8826ebaea1f
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginsWs.java
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.sonar.api.server.ws.WebService;
+
+/**
+ * WebService bound to URL {@code api/plugins}.
+ */
+public class PluginsWs implements WebService {
+ private final PluginsWsAction[] actions;
+
+ public PluginsWs(PluginsWsAction... actions) {
+ this.actions = actions;
+ }
+
+ @Override
+ public void define(Context context) {
+ NewController controller = context.createController("api/plugins");
+ controller.setDescription("Plugin management")
+ .setSince("5.2");
+
+ for (PluginsWsAction action : actions) {
+ action.define(controller);
+ }
+
+ controller.done();
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginsWsAction.java
new file mode 100644
index 00000000000..3126d2430b7
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginsWsAction.java
@@ -0,0 +1,28 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.plugins.ws;
+
+import org.sonar.server.ws.WsAction;
+
+/**
+ * Marker interface for the action of the plugins WS implemented by {@link PluginsWs}.
+ */
+public interface PluginsWsAction extends WsAction {
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/plugins/ws/example-installed_plugins.json b/server/sonar-server/src/main/resources/org/sonar/server/plugins/ws/example-installed_plugins.json
new file mode 100644
index 00000000000..ca65c9072da
--- /dev/null
+++ b/server/sonar-server/src/main/resources/org/sonar/server/plugins/ws/example-installed_plugins.json
@@ -0,0 +1,17 @@
+[
+ {
+ "key": "findbugs",
+ "name": "Findbugs",
+ "version": "2.1"
+ },
+ {
+ "key": "l10nfr",
+ "name": "French Pack",
+ "version": "1.10"
+ },
+ {
+ "key": "jira",
+ "name": "JIRA",
+ "version": "1.2"
+ }
+]
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java
new file mode 100644
index 00000000000..55f641c443b
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.server.plugins.ws;
+
+import org.junit.Test;
+import org.sonar.api.platform.PluginMetadata;
+import org.sonar.api.platform.PluginRepository;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.server.ws.WsTester;
+
+import static com.google.common.collect.ImmutableList.of;
+import static java.lang.String.valueOf;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class InstalledPluginsWsActionTest {
+ private static final String DUMMY_CONTROLLER_KEY = "dummy";
+ private static final String JSON_EMPTY_ARRAY = "[]";
+
+ private PluginRepository pluginRepository = mock(PluginRepository.class);
+ private InstalledPluginsWsAction underTest = new InstalledPluginsWsAction(pluginRepository);
+
+ private WsTester wsTester = new WsTester();
+ private Request request = mock(Request.class);
+ private WsTester.TestResponse response = new WsTester.TestResponse();
+ private PluginMetadata corePlugin = corePlugin("core1", 10);
+
+ private static PluginMetadata corePlugin(String key, int version) {
+ return DefaultPluginMetadata.create(key).setName(key).setCore(true).setVersion(valueOf(version));
+ }
+
+ private static PluginMetadata plugin(String key, String name, int version) {
+ return DefaultPluginMetadata.create(key).setName(name).setCore(false).setVersion(valueOf(version));
+ }
+
+ private static PluginMetadata plugin(String key, String name) {
+ return DefaultPluginMetadata.create(key).setName(name).setCore(false).setVersion("1.0");
+ }
+
+ @Test
+ public void action_installed_is_defined() throws Exception {
+ WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
+
+ underTest.define(newController);
+ newController.done();
+
+ WebService.Controller controller = wsTester.controller(DUMMY_CONTROLLER_KEY);
+ assertThat(controller.actions()).extracting("key").containsExactly("installed");
+
+ WebService.Action action = controller.actions().iterator().next();
+ assertThat(action.isPost()).isFalse();
+ assertThat(action.description()).isNotEmpty();
+ assertThat(action.responseExample()).isNotNull();
+ }
+
+ @Test
+ public void empty_array_is_returned_when_there_is_not_plugin_installed() throws Exception {
+ underTest.handle(request, response);
+
+ assertThat(response.outputAsString()).isEqualTo("[]");
+ }
+
+ @Test
+ public void core_plugin_are_not_returned() throws Exception {
+ when(pluginRepository.getMetadata()).thenReturn(of(corePlugin));
+
+ underTest.handle(request, response);
+
+ assertThat(response.outputAsString()).isEqualTo(JSON_EMPTY_ARRAY);
+ }
+
+ @Test
+ public void verify_properties_displayed_in_json_per_plugin() throws Exception {
+ when(pluginRepository.getMetadata()).thenReturn(of(plugin("plugKey", "plugName", 10)));
+
+ underTest.handle(request, response);
+
+ assertJson(response.outputAsString()).isSimilarTo(
+ "[" +
+ "{" +
+ " \"key\": \"plugKey\"," +
+ " \"name\": \"plugName\"," +
+ " \"version\": \"10\"" +
+ "}" +
+ "]"
+ );
+ }
+
+ @Test
+ public void plugins_are_sorted_by_name_then_key_and_only_one_plugin_can_have_a_specific_name() throws Exception {
+ when(pluginRepository.getMetadata()).thenReturn(
+ of(
+ plugin("A", "name2"),
+ plugin("B", "name1"),
+ plugin("C", "name0"),
+ plugin("D", "name0")
+ )
+ );
+
+ underTest.handle(request, response);
+
+ assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+ "[" +
+ "{\"key\": \"C\"}" + "," +
+ "{\"key\": \"D\"}" + "," +
+ "{\"key\": \"B\"}" + "," +
+ "{\"key\": \"A\"}" +
+ "]"
+ );
+ }
+
+ @Test
+ public void only_one_plugin_can_have_a_specific_name_and_key() throws Exception {
+ when(pluginRepository.getMetadata()).thenReturn(
+ of(
+ plugin("A", "name2"),
+ plugin("A", "name2")
+ )
+ );
+
+ underTest.handle(request, response);
+
+ assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+ "[" +
+ "{\"key\": \"A\"}" +
+ "]"
+ );
+ assertThat(response.outputAsString()).containsOnlyOnce("name2");
+ }
+
+ @Test
+ public void dash_is_returned_when_version_is_null() throws Exception {
+ when(pluginRepository.getMetadata()).thenReturn(
+ of(
+ (PluginMetadata) DefaultPluginMetadata.create("key").setCore(false).setVersion(null)
+ )
+ );
+
+ underTest.handle(request, response);
+
+ assertJson(response.outputAsString())
+ .isSimilarTo(
+ "[" +
+ "{\"version\": \"-\"}" +
+ "]"
+ );
+
+ }
+} \ No newline at end of file
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginsWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginsWsTest.java
new file mode 100644
index 00000000000..9c220bb1290
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginsWsTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.server.plugins.ws;
+
+import org.junit.Test;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PluginsWsTest {
+ private WsTester tester = new WsTester(new PluginsWs(new DummyPluginsWsAction()));
+
+ @Test
+ public void defines_controller_and_binds_PluginsWsActions() throws Exception {
+ WebService.Controller controller = tester.controller("api/plugins");
+
+ assertThat(controller).isNotNull();
+ assertThat(controller.since()).isEqualTo("5.2");
+ assertThat(controller.description()).isNotEmpty();
+ assertThat(controller.actions()).extracting("key").containsOnly("dummy");
+ }
+
+ private static class DummyPluginsWsAction implements PluginsWsAction {
+ @Override
+ public void define(WebService.NewController context) {
+ context.createAction("dummy").setHandler(this);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ // not relevant to test
+ }
+ }
+}