]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6382 add Java ws to update a plugin 244/head
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 21 Apr 2015 15:59:53 +0000 (17:59 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 23 Apr 2015 07:45:09 +0000 (09:45 +0200)
updates a plugin to its latest compatible version

server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/AvailablePluginsWsAction.java
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatePluginsWsAction.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatePluginsWsActionTest.java [new file with mode: 0644]

index 1385f7d6877615d3b964e9c1868e6356fe72f24c..b338e2e650223dd8395e9565641bbd3392fa2b77 100644 (file)
@@ -221,6 +221,7 @@ import org.sonar.server.plugins.ws.InstalledPluginsWsAction;
 import org.sonar.server.plugins.ws.PendingPluginsWsAction;
 import org.sonar.server.plugins.ws.PluginWSCommons;
 import org.sonar.server.plugins.ws.PluginsWs;
+import org.sonar.server.plugins.ws.UpdatePluginsWsAction;
 import org.sonar.server.properties.ProjectSettingsFactory;
 import org.sonar.server.qualitygate.QgateProjectFinder;
 import org.sonar.server.qualitygate.QualityGates;
@@ -381,7 +382,6 @@ import org.sonar.server.ws.ListingWs;
 import org.sonar.server.ws.WebServiceEngine;
 
 import javax.annotation.Nullable;
-
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
@@ -890,6 +890,7 @@ class ServerComponents {
     pico.addSingleton(InstalledPluginsWsAction.class);
     pico.addSingleton(AvailablePluginsWsAction.class);
     pico.addSingleton(PendingPluginsWsAction.class);
+    pico.addSingleton(UpdatePluginsWsAction.class);
     pico.addSingleton(PluginsWs.class);
 
     // Compute engine
index cc465f64426b6d98d6b5d4b815c4367c00525d2f..33b8c0c43eb146103ddf19e25dce996e60c591fb 100644 (file)
@@ -48,6 +48,9 @@ import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_TERMS_AND_CON
 import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_URL;
 import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_VERSION;
 
+/**
+ * Implementation of the {@code available} action for the Plugins WebService.
+ */
 public class AvailablePluginsWsAction implements PluginsWsAction {
 
   private static final boolean DO_NOT_FORCE_REFRESH = false;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatePluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UpdatePluginsWsAction.java
new file mode 100644 (file)
index 0000000..c013dac
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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.Predicate;
+import com.google.common.collect.Iterables;
+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.plugins.PluginDownloader;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.updatecenter.common.PluginUpdate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import static java.lang.String.format;
+
+/**
+ * Implementation of the {@code update} action for the Plugins WebService.
+ */
+public class UpdatePluginsWsAction implements PluginsWsAction {
+
+  public static final String PARAM_KEY = "key";
+  public static final PluginUpdate MISSING_PLUGIN = null;
+
+  private final UpdateCenterMatrixFactory updateCenterFactory;
+  private final PluginDownloader pluginDownloader;
+
+  public UpdatePluginsWsAction(UpdateCenterMatrixFactory updateCenterFactory, PluginDownloader pluginDownloader) {
+    this.updateCenterFactory = updateCenterFactory;
+    this.pluginDownloader = pluginDownloader;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("update")
+      .setPost(true)
+      .setDescription("Updates a plugin specified by its key to the latest version compatible with the SonarQube instance")
+      .setHandler(this);
+
+    action.createParam(PARAM_KEY)
+      .setRequired(true)
+      .setDescription("The key identifying the plugin to update");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    String key = request.mandatoryParam(PARAM_KEY);
+    PluginUpdate pluginUpdate = findPluginUpdateByKey(key);
+    pluginDownloader.download(key, pluginUpdate.getRelease().getVersion());
+    response.noContent();
+  }
+
+  @Nonnull
+  private PluginUpdate findPluginUpdateByKey(String key) {
+    PluginUpdate pluginUpdate = Iterables.find(
+      updateCenterFactory.getUpdateCenter(false).findPluginUpdates(),
+      new PluginKeyPredicate(key),
+      MISSING_PLUGIN
+      );
+    if (pluginUpdate == MISSING_PLUGIN) {
+      throw new IllegalArgumentException(
+        format("No plugin with key '%s' or plugin '%s' is already in latest compatible version", key, key));
+    }
+    return pluginUpdate;
+  }
+
+  private static class PluginKeyPredicate implements Predicate<PluginUpdate> {
+    private final String key;
+
+    public PluginKeyPredicate(String key) {
+      this.key = key;
+    }
+
+    @Override
+    public boolean apply(@Nullable PluginUpdate input) {
+      return input != null && key.equals(input.getPlugin().getKey());
+    }
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatePluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UpdatePluginsWsActionTest.java
new file mode 100644 (file)
index 0000000..ee2aa10
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * 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.collect.ImmutableList;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+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.UpdateCenterMatrixFactory;
+import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.Plugin;
+import org.sonar.updatecenter.common.PluginUpdate;
+import org.sonar.updatecenter.common.Release;
+import org.sonar.updatecenter.common.UpdateCenter;
+import org.sonar.updatecenter.common.Version;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class UpdatePluginsWsActionTest {
+  private static final String DUMMY_CONTROLLER_KEY = "dummy";
+  private static final String CONTROLLER_KEY = "api/plugins";
+  private static final String ACTION_KEY = "update";
+  private static final String KEY_PARAM = "key";
+  private static final String PLUGIN_KEY = "pluginKey";
+
+  private UpdateCenterMatrixFactory updateCenterFactory = mock(UpdateCenterMatrixFactory.class);
+  private UpdateCenter updateCenter = mock(UpdateCenter.class);
+  private PluginDownloader pluginDownloader = mock(PluginDownloader.class);
+  private UpdatePluginsWsAction underTest = new UpdatePluginsWsAction(updateCenterFactory, pluginDownloader);
+
+  private WsTester wsTester = new WsTester(new PluginsWs(underTest));
+  private Request invalidRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY);
+  private Request validRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY).setParam(KEY_PARAM, PLUGIN_KEY);
+  private WsTester.TestResponse response = new WsTester.TestResponse();
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Before
+  public void setUp() throws Exception {
+    when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(updateCenter);
+  }
+
+  @Test
+  public void action_update_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(ACTION_KEY);
+
+    WebService.Action action = controller.actions().iterator().next();
+    assertThat(action.isPost()).isTrue();
+    assertThat(action.description()).isNotEmpty();
+    assertThat(action.responseExample()).isNull();
+
+    assertThat(action.params()).hasSize(1);
+    WebService.Param key = action.param(KEY_PARAM);
+    assertThat(key).isNotNull();
+    assertThat(key.isRequired()).isTrue();
+    assertThat(key.description()).isNotNull();
+  }
+
+  @Test
+  public void IAE_is_raised_when_key_param_is_not_provided() throws Exception {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Parameter 'key' is missing");
+
+    underTest.handle(invalidRequest, response);
+  }
+
+  @Test
+  public void IAE_is_raised_when_there_is_no_plugin_update_for_the_key() throws Exception {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("No plugin with key 'pluginKey'");
+
+    underTest.handle(validRequest, response);
+  }
+
+  @Test
+  public void if_plugin_has_an_update_download_is_triggered_with_latest_version_from_updatecenter() throws Exception {
+    Version version = Version.create("1.0");
+    when(updateCenter.findPluginUpdates()).thenReturn(ImmutableList.of(
+      PluginUpdate.createWithStatus(new Release(new Plugin(PLUGIN_KEY), version), PluginUpdate.Status.COMPATIBLE)
+      ));
+
+    underTest.handle(validRequest, response);
+
+    verify(pluginDownloader).download(PLUGIN_KEY, version);
+    assertThat(response.outputAsString()).isEmpty();
+  }
+
+}