]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6383 add java WS listing pending plugin installs and removals 229/head
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 17 Apr 2015 09:07:08 +0000 (11:07 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 20 Apr 2015 12:51:30 +0000 (14:51 +0200)
once backing components have been updated to read plugin's jarfile manifests, more information will be added to the JSON response

server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/plugins/ws/example-pending_plugins.json [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java [new file with mode: 0644]

index 3f15d12f4d5444e4e6eeb92868459948c2909c7b..392d42946727c50b0be1e707b2e8ba37b80d09e7 100644 (file)
@@ -218,6 +218,7 @@ import org.sonar.server.plugins.UpdateCenterClient;
 import org.sonar.server.plugins.UpdateCenterMatrixFactory;
 import org.sonar.server.plugins.ws.AvailablePluginsWsAction;
 import org.sonar.server.plugins.ws.InstalledPluginsWsAction;
+import org.sonar.server.plugins.ws.PendingPluginsWsAction;
 import org.sonar.server.plugins.ws.PluginsWs;
 import org.sonar.server.properties.ProjectSettingsFactory;
 import org.sonar.server.qualitygate.QgateProjectFinder;
@@ -888,6 +889,7 @@ class ServerComponents {
     // Plugins WS
     pico.addSingleton(InstalledPluginsWsAction.class);
     pico.addSingleton(AvailablePluginsWsAction.class);
+    pico.addSingleton(PendingPluginsWsAction.class);
     pico.addSingleton(PluginsWs.class);
 
     // Compute engine
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java
new file mode 100644 (file)
index 0000000..5280ee0
--- /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.server.plugins.ws;
+
+import com.google.common.io.Resources;
+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 org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.ServerPluginJarsInstaller;
+
+import static com.google.common.collect.ImmutableSortedSet.copyOf;
+import static java.lang.String.CASE_INSENSITIVE_ORDER;
+
+/**
+ * Implementation of the {@code pending} action for the Plugins WebService.
+ */
+public class PendingPluginsWsAction implements PluginsWsAction {
+
+  private static final String ARRAY_INSTALLING = "installing";
+  private static final String ARRAY_REMOVING = "removing";
+  private static final String OBJECT_ARTIFACT = "artifact";
+  private static final String PROPERTY_NAME = "name";
+
+  private final PluginDownloader pluginDownloader;
+  private final ServerPluginJarsInstaller serverPluginJarsInstaller;
+
+  public PendingPluginsWsAction(PluginDownloader pluginDownloader, ServerPluginJarsInstaller serverPluginJarsInstaller) {
+    this.pluginDownloader = pluginDownloader;
+    this.serverPluginJarsInstaller = serverPluginJarsInstaller;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    controller.createAction("pending")
+        .setDescription("Get the list of plugins which will either be installed or removed at the next startup of the SonarQube instance, sorted by archive name")
+        .setSince("5.2")
+        .setHandler(this)
+        .setResponseExample(Resources.getResource(this.getClass(), "example-pending_plugins.json"));
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    JsonWriter jsonWriter = response.newJsonWriter();
+
+    jsonWriter.beginObject();
+
+    writeInstalling(jsonWriter);
+
+    writeRemoving(jsonWriter);
+
+    jsonWriter.endObject();
+    jsonWriter.close();
+  }
+
+  private void writeInstalling(JsonWriter jsonWriter) {
+    jsonWriter.name(ARRAY_INSTALLING);
+    jsonWriter.beginArray();
+    for (String fileName : copyOf(CASE_INSENSITIVE_ORDER, pluginDownloader.getDownloads())) {
+      writeArchive(jsonWriter, fileName);
+    }
+    jsonWriter.endArray();
+  }
+
+  private void writeRemoving(JsonWriter jsonWriter) {
+    jsonWriter.name(ARRAY_REMOVING);
+    jsonWriter.beginArray();
+    for (String fileName : copyOf(CASE_INSENSITIVE_ORDER, serverPluginJarsInstaller.getUninstalls())) {
+      writeArchive(jsonWriter, fileName);
+    }
+    jsonWriter.endArray();
+  }
+
+  private void writeArchive(JsonWriter jsonWriter, String fileName) {
+    jsonWriter.beginObject();
+    jsonWriter.name(OBJECT_ARTIFACT);
+    jsonWriter.beginObject();
+    jsonWriter.prop(PROPERTY_NAME, fileName);
+    jsonWriter.endObject();
+    jsonWriter.endObject();
+  }
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/plugins/ws/example-pending_plugins.json b/server/sonar-server/src/main/resources/org/sonar/server/plugins/ws/example-pending_plugins.json
new file mode 100644 (file)
index 0000000..bddbe32
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "installing":
+  [
+    {
+      "artifact": {
+        "name": "findbugs-2.1.jar"
+      }
+    },
+    {
+      "artifact": {
+        "name": "jira-2.6.jar"
+      }
+    }
+  ],
+  "removing":
+  [
+    {
+      "artifact": {
+        "name": "pmd-2.1.jar"
+      }
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java
new file mode 100644 (file)
index 0000000..9932fbf
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * 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.WebService;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.ServerPluginJarsInstaller;
+import org.sonar.server.ws.WsTester;
+
+import static com.google.common.collect.ImmutableList.of;
+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 PendingPluginsWsActionTest {
+
+  private static final String DUMMY_CONTROLLER_KEY = "dummy";
+
+  private PluginDownloader pluginDownloader = mock(PluginDownloader.class);
+  private ServerPluginJarsInstaller serverPluginJarsInstaller = mock(ServerPluginJarsInstaller.class);
+  private PendingPluginsWsAction underTest = new PendingPluginsWsAction(pluginDownloader, serverPluginJarsInstaller);
+
+  private Request request = mock(Request.class);
+  private WsTester.TestResponse response = new WsTester.TestResponse();
+
+  @Test
+  public void action_pending_is_defined() throws Exception {
+    WsTester wsTester = new WsTester();
+    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("pending");
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isFalse();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNotNull();
+  }
+
+  @Test
+  public void empty_arrays_are_returned_when_there_nothing_pending() throws Exception {
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+      "{" +
+        "  \"installing\": []," +
+        "  \"removing\": []" +
+        "}"
+      );
+  }
+
+  @Test
+  public void verify_properties_displayed_in_json_per_installing_plugin() throws Exception {
+    when(pluginDownloader.getDownloads()).thenReturn(of("installed_file.jar"));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(
+      "{" +
+        "  \"installing\": " +
+        "  [" +
+        "    {" +
+        "      \"artifact\": {" +
+        "        \"name\": \"installed_file.jar\"" +
+        "      }" +
+        "    }" +
+        "  ]," +
+        "  \"removing\": []" +
+        "}"
+      );
+  }
+
+  @Test
+  public void verify_properties_displayed_in_json_per_removing_plugin() throws Exception {
+    when(serverPluginJarsInstaller.getUninstalls()).thenReturn(of("removed_file.jar"));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).isSimilarTo(
+      "{" +
+        "  \"installing\": []," +
+        "  \"removing\": " +
+        "  [" +
+        "    {" +
+        "      \"artifact\": {" +
+        "        \"name\": \"removed_file.jar\"" +
+        "      }" +
+        "    }" +
+        "  ]" +
+        "}"
+      );
+  }
+
+  @Test
+  public void installing_plugin_are_sorted_and_unique() throws Exception {
+    when(pluginDownloader.getDownloads()).thenReturn(of("file2.jar", "file0.jar", "file0.jar", "file1.jar"));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+      "{" +
+        "  \"installing\": " +
+        "  [" +
+        "    {" +
+        "      \"artifact\": {" +
+        "        \"name\": \"file0.jar\"" +
+        "      }" +
+        "    }," +
+        "    {" +
+        "      \"artifact\": {" +
+        "        \"name\": \"file1.jar\"" +
+        "      }" +
+        "    }," +
+        "    {" +
+        "      \"artifact\": {" +
+        "        \"name\": \"file2.jar\"" +
+        "      }" +
+        "    }" +
+        "  ]," +
+        "  \"removing\": []" +
+        "}"
+      );
+  }
+
+  @Test
+  public void removing_plugin_are_sorted_and_unique() throws Exception {
+    when(serverPluginJarsInstaller.getUninstalls()).thenReturn(of("file2.jar", "file0.jar", "file0.jar", "file1.jar"));
+
+    underTest.handle(request, response);
+
+    assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+      "{" +
+        "  \"installing\": []," +
+        "  \"removing\": " +
+        "  [" +
+        "    {" +
+        "      \"artifact\": {" +
+        "        \"name\": \"file0.jar\"" +
+        "      }" +
+        "    }," +
+        "    {" +
+        "      \"artifact\": {" +
+        "        \"name\": \"file1.jar\"" +
+        "      }" +
+        "    }," +
+        "    {" +
+        "      \"artifact\": {" +
+        "        \"name\": \"file2.jar\"" +
+        "      }" +
+        "    }" +
+        "  ]" +
+        "}"
+      );
+  }
+}