factor code from AvailablePluginsWsAction and UpdatablePluginsWsAction into PluginWSCommons because there are extremely similar
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.plugins.ws.UpdatesPluginsWsAction;
import org.sonar.server.properties.ProjectSettingsFactory;
import org.sonar.server.qualitygate.QgateProjectFinder;
import org.sonar.server.qualitygate.QualityGates;
pico.addSingleton(PluginWSCommons.class);
pico.addSingleton(InstalledPluginsWsAction.class);
pico.addSingleton(AvailablePluginsWsAction.class);
+ pico.addSingleton(UpdatesPluginsWsAction.class);
pico.addSingleton(PendingPluginsWsAction.class);
pico.addSingleton(UpdatePluginsWsAction.class);
pico.addSingleton(PluginsWs.class);
*/
package org.sonar.server.plugins.ws;
-import com.google.common.base.Function;
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.UpdateCenterMatrixFactory;
-import org.sonar.updatecenter.common.Artifact;
-import org.sonar.updatecenter.common.Plugin;
import org.sonar.updatecenter.common.PluginUpdate;
-import org.sonar.updatecenter.common.Release;
-import javax.annotation.Nullable;
import java.util.List;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
-import static org.sonar.server.plugins.ws.PluginWSCommons.OBJECT_ARTIFACT;
-import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_DATE;
-import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_DESCRIPTION;
-import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_KEY;
-import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_NAME;
-import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_ORGANIZATION_NAME;
-import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_ORGANIZATION_URL;
-import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_STATUS;
-import static org.sonar.server.plugins.ws.PluginWSCommons.PROPERTY_TERMS_AND_CONDITIONS_URL;
-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;
- private static final String OBJECT_UPDATE = "update";
- private static final String OBJECT_RELEASE = "release";
- private static final String ARRAY_REQUIRES = "requires";
private static final String ARRAY_PLUGINS = "plugins";
- private static final String PROPERTY_CATEGORY = "category";
- private static final String PROPERTY_LICENSE = "license";
private final UpdateCenterMatrixFactory updateCenterFactory;
+ private final PluginWSCommons pluginWSCommons;
- public AvailablePluginsWsAction(UpdateCenterMatrixFactory updateCenterFactory) {
+ public AvailablePluginsWsAction(UpdateCenterMatrixFactory updateCenterFactory, PluginWSCommons pluginWSCommons) {
this.updateCenterFactory = updateCenterFactory;
+ this.pluginWSCommons = pluginWSCommons;
}
@Override
jsonWriter.name(ARRAY_PLUGINS);
jsonWriter.beginArray();
for (PluginUpdate pluginUpdate : retrieveAvailablePlugins()) {
- writePluginUpdate(jsonWriter, pluginUpdate);
+ pluginWSCommons.writePluginUpdate(jsonWriter, pluginUpdate);
}
jsonWriter.endArray();
jsonWriter.endObject();
private List<PluginUpdate> retrieveAvailablePlugins() {
return updateCenterFactory.getUpdateCenter(DO_NOT_FORCE_REFRESH).findAvailablePlugins();
}
-
- private void writePluginUpdate(JsonWriter jsonWriter, PluginUpdate pluginUpdate) {
- jsonWriter.beginObject();
- Plugin plugin = pluginUpdate.getPlugin();
-
- writeMetadata(jsonWriter, plugin);
-
- writeRelease(jsonWriter, pluginUpdate.getRelease());
-
- writeUpdate(jsonWriter, pluginUpdate);
-
- jsonWriter.endObject();
- }
-
- private void writeMetadata(JsonWriter jsonWriter, Plugin plugin) {
- jsonWriter.prop(PROPERTY_KEY, plugin.getKey());
- jsonWriter.prop(PROPERTY_NAME, plugin.getName());
- jsonWriter.prop(PROPERTY_CATEGORY, plugin.getCategory());
- jsonWriter.prop(PROPERTY_DESCRIPTION, plugin.getDescription());
- jsonWriter.prop(PROPERTY_LICENSE, plugin.getLicense());
- jsonWriter.prop(PROPERTY_TERMS_AND_CONDITIONS_URL, plugin.getTermsConditionsUrl());
- jsonWriter.prop(PROPERTY_ORGANIZATION_NAME, plugin.getOrganization());
- jsonWriter.prop(PROPERTY_ORGANIZATION_URL, plugin.getOrganizationUrl());
- }
-
- private void writeRelease(JsonWriter jsonWriter, Release release) {
- jsonWriter.name(OBJECT_RELEASE);
- jsonWriter.beginObject();
- jsonWriter.prop(PROPERTY_VERSION, release.getVersion().toString());
- jsonWriter.propDate(PROPERTY_DATE, release.getDate());
- writeArchive(jsonWriter, release);
- jsonWriter.endObject();
- }
-
- private void writeArchive(JsonWriter jsonWriter, Release release) {
- jsonWriter.name(OBJECT_ARTIFACT);
- jsonWriter.beginObject();
- jsonWriter.prop(PROPERTY_NAME, release.getFilename());
- jsonWriter.prop(PROPERTY_URL, release.getDownloadUrl());
- jsonWriter.endObject();
- }
-
- private void writeUpdate(JsonWriter jsonWriter, PluginUpdate pluginUpdate) {
- jsonWriter.name(OBJECT_UPDATE);
- jsonWriter.beginObject();
- jsonWriter.prop(PROPERTY_STATUS, toJSon(pluginUpdate.getStatus()));
-
- jsonWriter.name(ARRAY_REQUIRES);
- jsonWriter.beginArray();
- Release release = pluginUpdate.getRelease();
- for (Plugin child : filter(transform(release.getOutgoingDependencies(), ReleaseToArtifact.INSTANCE), Plugin.class)) {
- jsonWriter.beginObject();
- jsonWriter.prop(PROPERTY_KEY, child.getKey());
- jsonWriter.prop(PROPERTY_NAME, child.getName());
- jsonWriter.prop(PROPERTY_DESCRIPTION, child.getDescription());
- jsonWriter.endObject();
- }
- jsonWriter.endArray();
-
- jsonWriter.endObject();
- }
-
- private static String toJSon(PluginUpdate.Status status) {
- switch (status) {
- case COMPATIBLE:
- return "COMPATIBLE";
- case INCOMPATIBLE:
- return "INCOMPATIBLE";
- case REQUIRE_SONAR_UPGRADE:
- return "REQUIRES_UPGRADE";
- case DEPENDENCIES_REQUIRE_SONAR_UPGRADE:
- return "DEPS_REQUIRE_UPGRADE";
- default:
- throw new IllegalArgumentException("Unsupported value of PluginUpdate.Status " + status);
- }
- }
-
- private enum ReleaseToArtifact implements Function<Release, Artifact> {
- INSTANCE;
-
- @Override
- public Artifact apply(@Nullable Release input) {
- if (input == null) {
- return null;
- }
- return input.getArtifact();
- }
- }
}
*/
package org.sonar.server.plugins.ws;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.collect.Ordering;
import org.sonar.api.platform.PluginMetadata;
import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.updatecenter.common.Artifact;
+import org.sonar.updatecenter.common.Plugin;
+import org.sonar.updatecenter.common.PluginUpdate;
+import org.sonar.updatecenter.common.Release;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
public class PluginWSCommons {
static final String PROPERTY_KEY = "key";
static final String PROPERTY_DESCRIPTION = "description";
static final String PROPERTY_LICENSE = "license";
static final String PROPERTY_VERSION = "version";
+ static final String PROPERTY_CATEGORY = "category";
static final String PROPERTY_ORGANIZATION_NAME = "organizationName";
static final String PROPERTY_ORGANIZATION_URL = "organizationUrl";
static final String PROPERTY_DATE = "date";
static final String OBJECT_ARTIFACT = "artifact";
static final String PROPERTY_URL = "url";
static final String PROPERTY_TERMS_AND_CONDITIONS_URL = "termsAndConditionsUrl";
+ static final String OBJECT_UPDATE = "update";
+ static final String OBJECT_RELEASE = "release";
+ static final String ARRAY_REQUIRES = "requires";
public static final Ordering<PluginMetadata> NAME_KEY_PLUGIN_METADATA_COMPARATOR = Ordering.natural()
.onResultOf(PluginMetadataToName.INSTANCE)
jsonWriter.endObject();
}
+ public void writePluginUpdate(JsonWriter jsonWriter, PluginUpdate pluginUpdate) {
+ jsonWriter.beginObject();
+ Plugin plugin = pluginUpdate.getPlugin();
+
+ writeMetadata(jsonWriter, plugin);
+
+ writeRelease(jsonWriter, pluginUpdate.getRelease());
+
+ writeUpdate(jsonWriter, pluginUpdate);
+
+ jsonWriter.endObject();
+ }
+
+ public void writeMetadata(JsonWriter jsonWriter, Plugin plugin) {
+ jsonWriter.prop(PROPERTY_KEY, plugin.getKey());
+ jsonWriter.prop(PROPERTY_NAME, plugin.getName());
+ jsonWriter.prop(PROPERTY_CATEGORY, plugin.getCategory());
+ jsonWriter.prop(PROPERTY_DESCRIPTION, plugin.getDescription());
+ jsonWriter.prop(PROPERTY_LICENSE, plugin.getLicense());
+ jsonWriter.prop(PROPERTY_TERMS_AND_CONDITIONS_URL, plugin.getTermsConditionsUrl());
+ jsonWriter.prop(PROPERTY_ORGANIZATION_NAME, plugin.getOrganization());
+ jsonWriter.prop(PROPERTY_ORGANIZATION_URL, plugin.getOrganizationUrl());
+ }
+
+ public void writeRelease(JsonWriter jsonWriter, Release release) {
+ jsonWriter.name(OBJECT_RELEASE);
+ jsonWriter.beginObject();
+ jsonWriter.prop(PROPERTY_VERSION, release.getVersion().toString());
+ jsonWriter.propDate(PROPERTY_DATE, release.getDate());
+
+ writeArtifact(jsonWriter, release);
+
+ jsonWriter.endObject();
+ }
+
+ public void writeArtifact(JsonWriter jsonWriter, Release release) {
+ jsonWriter.name(OBJECT_ARTIFACT);
+ jsonWriter.beginObject();
+ jsonWriter.prop(PROPERTY_NAME, release.getFilename());
+ jsonWriter.prop(PROPERTY_URL, release.getDownloadUrl());
+ jsonWriter.endObject();
+ }
+
+ public void writeUpdate(JsonWriter jsonWriter, PluginUpdate pluginUpdate) {
+ jsonWriter.name(OBJECT_UPDATE);
+ jsonWriter.beginObject();
+ jsonWriter.prop(PROPERTY_STATUS, toJSon(pluginUpdate.getStatus()));
+
+ jsonWriter.name(ARRAY_REQUIRES);
+ jsonWriter.beginArray();
+ Release release = pluginUpdate.getRelease();
+ for (Plugin child : filter(transform(release.getOutgoingDependencies(), ReleaseToArtifact.INSTANCE), Plugin.class)) {
+ jsonWriter.beginObject();
+ jsonWriter.prop(PROPERTY_KEY, child.getKey());
+ jsonWriter.prop(PROPERTY_NAME, child.getName());
+ jsonWriter.prop(PROPERTY_DESCRIPTION, child.getDescription());
+ jsonWriter.endObject();
+ }
+ jsonWriter.endArray();
+
+ jsonWriter.endObject();
+ }
+
+ @VisibleForTesting
+ static String toJSon(PluginUpdate.Status status) {
+ switch (status) {
+ case COMPATIBLE:
+ return "COMPATIBLE";
+ case INCOMPATIBLE:
+ return "INCOMPATIBLE";
+ case REQUIRE_SONAR_UPGRADE:
+ return "REQUIRES_UPGRADE";
+ case DEPENDENCIES_REQUIRE_SONAR_UPGRADE:
+ return "DEPS_REQUIRE_UPGRADE";
+ default:
+ throw new IllegalArgumentException("Unsupported value of PluginUpdate.Status " + status);
+ }
+ }
+
+ private enum ReleaseToArtifact implements Function<Release, Artifact> {
+ INSTANCE;
+
+ @Override
+ public Artifact apply(@Nullable Release input) {
+ if (input == null) {
+ return null;
+ }
+ return input.getArtifact();
+ }
+ }
+
private enum PluginMetadataToName implements Function<PluginMetadata, String> {
INSTANCE;
--- /dev/null
+/*
+ * 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.collect.ImmutableSortedSet;
+import com.google.common.collect.Ordering;
+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.UpdateCenterMatrixFactory;
+import org.sonar.updatecenter.common.PluginUpdate;
+
+import javax.annotation.Nullable;
+import java.util.Collection;
+import java.util.Comparator;
+
+import static java.lang.String.CASE_INSENSITIVE_ORDER;
+
+/**
+ * Implementation of the {@code updates} action for the Plugins WebService.
+ */
+public class UpdatesPluginsWsAction implements PluginsWsAction {
+
+ private static final boolean DO_NOT_FORCE_REFRESH = false;
+ private static final String ARRAY_PLUGINS = "plugins";
+ private static final Comparator<PluginUpdate> NAME_KEY_PLUGIN_UPDATE_ORDERING = Ordering.from(CASE_INSENSITIVE_ORDER)
+ .onResultOf(PluginUpdateToName.INSTANCE)
+ .compound(
+ Ordering.from(CASE_INSENSITIVE_ORDER).onResultOf(PluginUpdateToKey.INSTANCE)
+ );
+
+ private final UpdateCenterMatrixFactory updateCenterMatrixFactory;
+ private final PluginWSCommons pluginWSCommons;
+
+ public UpdatesPluginsWsAction(UpdateCenterMatrixFactory updateCenterMatrixFactory,
+ PluginWSCommons pluginWSCommons) {
+ this.updateCenterMatrixFactory = updateCenterMatrixFactory;
+ this.pluginWSCommons = pluginWSCommons;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ controller.createAction("updates")
+ .setDescription("Lists plugins installed on the SonarQube instance for which at least one newer version is available, sorted by plugin name." +
+ "br/>" +
+ "Each newer version is a separate entry in the returned list, with its update/compatibility status." +
+ "<br/>" +
+ "Update status values are: [COMPATIBLE, INCOMPATIBLE, REQUIRES_UPGRADE, DEPS_REQUIRE_UPGRADE]")
+ .setSince("5.2")
+ .setHandler(this)
+ .setResponseExample(Resources.getResource(this.getClass(), "example-updates_plugins.json"));
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ JsonWriter jsonWriter = response.newJsonWriter();
+ jsonWriter.beginObject();
+
+ writePlugins(jsonWriter);
+
+ jsonWriter.close();
+ }
+
+ private void writePlugins(JsonWriter jsonWriter) {
+ jsonWriter.name(ARRAY_PLUGINS);
+ jsonWriter.beginArray();
+ for (PluginUpdate pluginUpdate : retrieveUpdatablePlugins()) {
+ pluginWSCommons.writePluginUpdate(jsonWriter, pluginUpdate);
+ }
+ jsonWriter.endArray();
+ jsonWriter.endObject();
+ }
+
+ private Collection<PluginUpdate> retrieveUpdatablePlugins() {
+ return ImmutableSortedSet.copyOf(
+ NAME_KEY_PLUGIN_UPDATE_ORDERING,
+ updateCenterMatrixFactory.getUpdateCenter(DO_NOT_FORCE_REFRESH).findPluginUpdates()
+ );
+ }
+
+ private enum PluginUpdateToKey implements Function<PluginUpdate, String> {
+ INSTANCE;
+
+ @Override
+ public String apply(@Nullable PluginUpdate input) {
+ if (input == null) {
+ return null;
+ }
+ return input.getPlugin().getKey();
+ }
+ }
+
+ private enum PluginUpdateToName implements Function<PluginUpdate, String> {
+ INSTANCE;
+
+ @Override
+ public String apply(@Nullable PluginUpdate input) {
+ if (input == null) {
+ return null;
+ }
+ return input.getPlugin().getName();
+ }
+ }
+}
--- /dev/null
+{
+ "plugins": [
+ {
+ "key": "abap",
+ "name": "ABAP",
+ "category": "Languages",
+ "description": "Enable analysis and reporting on ABAP projects",
+ "license": "Commercial",
+ "organizationName": "SonarSource",
+ "organizationUrl": "http://www.sonarsource.com",
+ "termsAndConditionsUrl": "http://dist.sonarsource.com/SonarSource_Terms_And_Conditions.pdf",
+ "release": {
+ "version": "3.2",
+ "date": "2015-03-10",
+ "artifact": {
+ "name": "sonar-abap-plugin-3.2.jar",
+ "url": "http://dist.sonarsource.com/abap/download/sonar-abap-plugin-3.2.jar"
+ }
+ },
+ "update": {
+ "status": "COMPATIBLE",
+ "requires": []
+ }
+ },
+ {
+ "key": "android",
+ "name": "Android",
+ "category": "Languages",
+ "description": "Import Android Lint reports.",
+ "license": "GNU LGPL 3",
+ "organizationName": "SonarSource and Jerome Van Der Linden, Stephane Nicolas, Florian Roncari, Thomas Bores",
+ "organizationUrl": "http://www.sonarsource.com",
+ "release": {
+ "version": "1.0",
+ "date": "2014-03-31",
+ "artifact": {
+ "name": "sonar-android-plugin-1.0.jar",
+ "url": "http://repository.codehaus.org/org/codehaus/sonar-plugins/android/sonar-android-plugin/1.0/sonar-android-plugin-1.0.jar"
+ }
+ },
+ "update": {
+ "status": "COMPATIBLE",
+ "requires": [
+ {
+ "key": "java",
+ "name": "Java",
+ "description": "SonarQube rule engine."
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.Before;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.utils.DateUtils;
+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 java.net.URL;
+
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.updatecenter.common.Version.create;
+
+public class AbstractUpdateCenterBasedPluginsWsActionTest {
+ protected static final String DUMMY_CONTROLLER_KEY = "dummy";
+ protected static final String JSON_EMPTY_PLUGIN_LIST =
+ "{" +
+ " \"plugins\":" + "[]" +
+ "}";
+ protected static final Plugin PLUGIN_1 = new Plugin("p_key_1").setName("p_name_1");
+ protected static final Plugin PLUGIN_2 = new Plugin("p_key_2").setName("p_name_2").setDescription("p_desc_2");
+
+ protected static final Plugin FULL_PROPERTIES_PLUGIN = new Plugin("p_key")
+ .setName("p_name")
+ .setCategory("p_category")
+ .setDescription("p_description")
+ .setLicense("p_license")
+ .setOrganization("p_orga_name")
+ .setOrganizationUrl("p_orga_url")
+ .setTermsConditionsUrl("p_t_and_c_url");
+ protected static final Release FULL_PROPERTIES_PLUGIN_RELEASE = release(FULL_PROPERTIES_PLUGIN, "1.12.1")
+ .setDate(DateUtils.parseDate("2015-04-16"))
+ .setDownloadUrl("http://p_file.jar")
+ .addOutgoingDependency(release(PLUGIN_1, "0.3.6"))
+ .addOutgoingDependency(release(PLUGIN_2, "1.0.0"));
+
+ protected UpdateCenterMatrixFactory updateCenterFactory = mock(UpdateCenterMatrixFactory.class);
+ protected UpdateCenter updateCenter = mock(UpdateCenter.class);
+ protected Request request = mock(Request.class);
+ protected WsTester.TestResponse response = new WsTester.TestResponse();
+
+ protected static Release release(Plugin plugin1, String version) {
+ return new Release(plugin1, create(version));
+ }
+
+ protected static PluginUpdate pluginUpdate(Release pluginRelease, PluginUpdate.Status compatible) {
+ return PluginUpdate.createWithStatus(pluginRelease, compatible);
+ }
+
+ protected static URL resource(String s) {
+ Class<AvailablePluginsWsActionTest> clazz = AvailablePluginsWsActionTest.class;
+ return clazz.getResource(clazz.getSimpleName() + "/" + s);
+ }
+
+ @Before
+ public void wireMocksTogether() throws Exception {
+ when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(updateCenter);
+ }
+}
*/
package org.sonar.server.plugins.ws;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.DateUtils;
-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 java.net.URL;
-
import static com.google.common.collect.ImmutableList.of;
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.when;
-import static org.mockito.MockitoAnnotations.initMocks;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonar.updatecenter.common.PluginUpdate.Status.COMPATIBLE;
import static org.sonar.updatecenter.common.PluginUpdate.Status.DEPENDENCIES_REQUIRE_SONAR_UPGRADE;
import static org.sonar.updatecenter.common.PluginUpdate.Status.INCOMPATIBLE;
import static org.sonar.updatecenter.common.PluginUpdate.Status.REQUIRE_SONAR_UPGRADE;
-import static org.sonar.updatecenter.common.Version.create;
-
-public class AvailablePluginsWsActionTest {
- private static final String DUMMY_CONTROLLER_KEY = "dummy";
- private static final String JSON_EMPTY_PLUGIN_LIST =
- "{" +
- " \"plugins\":" + "[]" +
- "}";
- private static final Plugin PLUGIN_1 = new Plugin("p_key_1").setName("p_name_1");
- private static final Plugin PLUGIN_2 = new Plugin("p_key_2").setName("p_name_2").setDescription("p_desc_2");
-
- @Mock
- private UpdateCenterMatrixFactory updateCenterFactory;
- @Mock
- private UpdateCenter updateCenter;
- @InjectMocks
- private AvailablePluginsWsAction underTest;
-
- private Request request = mock(Request.class);
- private WsTester.TestResponse response = new WsTester.TestResponse();
-
- @Before
- public void createAndWireMocksTogether() throws Exception {
- initMocks(this);
- when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(updateCenter);
- }
+
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.PluginUpdate;
+
+public class AvailablePluginsWsActionTest extends AbstractUpdateCenterBasedPluginsWsActionTest {
+
+ private AvailablePluginsWsAction underTest = new AvailablePluginsWsAction(updateCenterFactory, new PluginWSCommons());
@Test
public void action_available_is_defined() throws Exception {
@Test
public void verify_properties_displayed_in_json_per_plugin() throws Exception {
- Plugin plugin = new Plugin("p_key")
- .setName("p_name")
- .setCategory("p_category")
- .setDescription("p_description")
- .setLicense("p_license")
- .setOrganization("p_orga_name")
- .setOrganizationUrl("p_orga_url")
- .setTermsConditionsUrl("p_t_and_c_url");
- Release pluginRelease = release(plugin, "1.12.1")
- .setDate(DateUtils.parseDate("2015-04-16"))
- .setDownloadUrl("http://p_file.jar")
- .addOutgoingDependency(release(PLUGIN_1, "0.3.6"))
- .addOutgoingDependency(release(PLUGIN_2, "1.0.0"));
when(updateCenter.findAvailablePlugins()).thenReturn(of(
- pluginUpdate(pluginRelease, COMPATIBLE)
+ pluginUpdate(FULL_PROPERTIES_PLUGIN_RELEASE, COMPATIBLE)
));
underTest.handle(request, response);
assertJson(response.outputAsString()).isSimilarTo(resource("properties_per_plugin.json"));
}
- private Release release(Plugin plugin1, String version) {
- return new Release(plugin1, create(version));
- }
-
@Test
public void status_COMPATIBLE_is_displayed_COMPATIBLE_in_JSON() throws Exception {
checkStatusDisplayedInJson(COMPATIBLE, "COMPATIBLE");
);
}
- private static PluginUpdate pluginUpdate(Release pluginRelease, PluginUpdate.Status compatible) {
- return PluginUpdate.createWithStatus(pluginRelease, compatible);
- }
-
- private static URL resource(String s) {
- Class<AvailablePluginsWsActionTest> clazz = AvailablePluginsWsActionTest.class;
- return clazz.getResource(clazz.getSimpleName() + "/" + s);
- }
}
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.plugins.DefaultPluginMetadata;
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.Version;
import java.io.File;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.utils.DateUtils.parseDate;
import static org.sonar.core.plugins.DefaultPluginMetadata.create;
+import static org.sonar.server.plugins.ws.PluginWSCommons.toJSon;
import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.COMPATIBLE;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.DEPENDENCIES_REQUIRE_SONAR_UPGRADE;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.INCOMPATIBLE;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.REQUIRE_SONAR_UPGRADE;
public class PluginWSCommonsTest {
- public static final DefaultPluginMetadata GIT_PLUGIN_METADATA = create("scmgit")
+ private static final DefaultPluginMetadata GIT_PLUGIN_METADATA = create("scmgit")
.setName("Git")
.setDescription("Git SCM Provider.")
.setVersion("1.0")
.setHomepage("http://redirect.sonarsource.com/plugins/scmgit.html")
.setIssueTrackerUrl("http://jira.codehaus.org/browse/SONARSCGIT")
.setFile(new File("/home/user/sonar-scm-git-plugin-1.0.jar"));
+ private static final Plugin PLUGIN = new Plugin("p_key")
+ .setName("p_name")
+ .setCategory("p_category")
+ .setDescription("p_description")
+ .setLicense("p_license")
+ .setOrganization("p_orga_name")
+ .setOrganizationUrl("p_orga_url")
+ .setTermsConditionsUrl("p_t_and_c_url");
+ private static final Release RELEASE = new Release(PLUGIN, version("1.0")).setDate(parseDate("2015-04-16"))
+ .setDownloadUrl("http://toto.com/file.jar");
private WsTester.TestResponse response = new WsTester.TestResponse();
private JsonWriter jsonWriter = response.newJsonWriter();
private PluginWSCommons underTest = new PluginWSCommons();
@Test
- public void verify_properties_written_by_writePluginMetadata() throws Exception {
+ public void verify_properties_written_by_writePluginMetadata() {
underTest.writePluginMetadata(jsonWriter, GIT_PLUGIN_METADATA);
jsonWriter.close();
}
@Test
- public void verify_properties_written_by_writeMetadata() throws Exception {
+ public void verify_properties_written_by_writeMetadata() {
jsonWriter.beginObject();
underTest.writeMetadata(jsonWriter, GIT_PLUGIN_METADATA);
jsonWriter.endObject();
}
@Test
- public void writeArtifact_supports_null_file() throws Exception {
+ public void writeArtifact_from_pluginMetadata_supports_null_file() {
jsonWriter.beginObject();
underTest.writeArtifact(jsonWriter, DefaultPluginMetadata.create("key"));
jsonWriter.endObject();
}
@Test
- public void writeArtifact_writes_artifact_object_and_file_name() throws Exception {
+ public void writeArtifact_from_pluginMetadata_writes_artifact_object_and_file_name() {
jsonWriter.beginObject();
underTest.writeArtifact(jsonWriter, GIT_PLUGIN_METADATA);
jsonWriter.endObject();
" }" +
"}");
}
-}
\ No newline at end of file
+
+ @Test
+ public void verify_properties_written_by_writePluginUpdate() {
+ underTest.writePluginUpdate(jsonWriter, PluginUpdate.createForPluginRelease(RELEASE, version("1.0")));
+
+ jsonWriter.close();
+ assertJson(response.outputAsString()).isSimilarTo("{" +
+ " \"key\": \"p_key\"," +
+ " \"name\": \"p_name\"," +
+ " \"description\": \"p_description\"," +
+ " \"category\": \"p_category\"," +
+ " \"license\": \"p_license\"," +
+ " \"organizationName\": \"p_orga_name\"," +
+ " \"organizationUrl\": \"p_orga_url\"," +
+ " \"termsAndConditionsUrl\": \"p_t_and_c_url\"" +
+ " \"release\": {" +
+ " \"version\": \"1.0\"," +
+ " \"date\": \"2015-04-16\"," +
+ " \"artifact\": {" +
+ " \"name\": \"file.jar\"," +
+ " \"url\": \"http://toto.com/file.jar\"" +
+ " }" +
+ " }" +
+ "}");
+ }
+
+ @Test
+ public void verify_properties_written_by_writeMetadata_from_plugin() {
+ jsonWriter.beginObject();
+ underTest.writeMetadata(jsonWriter, PLUGIN);
+ jsonWriter.endObject();
+
+ jsonWriter.close();
+ assertJson(response.outputAsString()).isSimilarTo("{" +
+ " \"key\": \"p_key\"," +
+ " \"name\": \"p_name\"," +
+ " \"description\": \"p_description\"," +
+ " \"category\": \"p_category\"," +
+ " \"license\": \"p_license\"," +
+ " \"organizationName\": \"p_orga_name\"," +
+ " \"organizationUrl\": \"p_orga_url\"," +
+ " \"termsAndConditionsUrl\": \"p_t_and_c_url\"" +
+ "}");
+ }
+
+ @Test
+ public void writeRelease_writes_artifact_object_and_file_name() {
+ jsonWriter.beginObject();
+ underTest.writeRelease(jsonWriter, RELEASE);
+ jsonWriter.endObject();
+
+ jsonWriter.close();
+ assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo("{" +
+ " \"release\": {" +
+ " \"version\": \"1.0\"," +
+ " \"date\": \"2015-04-16\"," +
+ " \"artifact\": {" +
+ " \"name\": \"file.jar\"," +
+ " \"url\": \"http://toto.com/file.jar\"" +
+ " }" +
+ " }" +
+ "}");
+ }
+
+ @Test
+ public void writeArtifact_from_release_writes_artifact_object_and_file_name() {
+ jsonWriter.beginObject();
+ underTest.writeArtifact(jsonWriter, release("p_key").setDownloadUrl("http://toto.com/file.jar"));
+ jsonWriter.endObject();
+
+ jsonWriter.close();
+ assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo("{" +
+ " \"artifact\": {" +
+ " \"name\": \"file.jar\"," +
+ " \"url\": \"http://toto.com/file.jar\"" +
+ " }" +
+ "}");
+ }
+
+ @Test
+ public void status_COMPATIBLE_is_displayed_COMPATIBLE_in_JSON() {
+ assertThat(toJSon(COMPATIBLE)).isEqualTo("COMPATIBLE");
+ }
+
+ @Test
+ public void status_INCOMPATIBLE_is_displayed_INCOMPATIBLE_in_JSON() {
+ assertThat(toJSon(INCOMPATIBLE)).isEqualTo("INCOMPATIBLE");
+ }
+
+ @Test
+ public void status_REQUIRE_SONAR_UPGRADE_is_displayed_REQUIRES_UPGRADE_in_JSON() {
+ assertThat(toJSon(REQUIRE_SONAR_UPGRADE)).isEqualTo("REQUIRES_UPGRADE");
+ }
+
+ @Test
+ public void status_DEPENDENCIES_REQUIRE_SONAR_UPGRADE_is_displayed_DEPS_REQUIRE_UPGRADE_in_JSON() {
+ assertThat(toJSon(DEPENDENCIES_REQUIRE_SONAR_UPGRADE)).isEqualTo("DEPS_REQUIRE_UPGRADE");
+ }
+
+ @Test
+ public void writeUpdate_renders_key_name_and_description_of_outgoing_dependencies() {
+ PluginUpdate pluginUpdate = new PluginUpdate();
+ pluginUpdate.setRelease(
+ new Release(PLUGIN, version("1.0")).addOutgoingDependency(RELEASE)
+ );
+
+ jsonWriter.beginObject();
+ underTest.writeUpdate(jsonWriter, pluginUpdate);
+ jsonWriter.endObject();
+
+ jsonWriter.close();
+ assertJson(response.outputAsString()).isSimilarTo("{" +
+ " \"update\": {" +
+ " \"requires\": [" +
+ " {" +
+ " \"key\": \"p_key\"," +
+ " \"name\": \"p_name\"," +
+ " \"description\": \"p_description\"" +
+ " }" +
+ " ]" +
+ " }" +
+ "}");
+ }
+
+ private static Version version(String version) {
+ return Version.create(version);
+ }
+
+ private static Release release(String key) {
+ return new Release(new Plugin(key), version("1.0"));
+ }
+}
--- /dev/null
+/*
+ * 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.WebService;
+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.Version;
+
+import static com.google.common.collect.ImmutableList.of;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonar.updatecenter.common.PluginUpdate.Status.COMPATIBLE;
+
+public class UpdatesPluginsWsActionTest extends AbstractUpdateCenterBasedPluginsWsActionTest {
+
+ private UpdatesPluginsWsAction underTest = new UpdatesPluginsWsAction(updateCenterFactory, new PluginWSCommons());
+
+ @Test
+ public void action_updatable_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("updates");
+
+ 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_no_plugin_available() throws Exception {
+ underTest.handle(request, response);
+
+ assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(JSON_EMPTY_PLUGIN_LIST);
+ }
+
+ @Test
+ public void verify_properties_displayed_in_json_per_plugin() throws Exception {
+ when(updateCenter.findPluginUpdates()).thenReturn(of(
+ pluginUpdate(FULL_PROPERTIES_PLUGIN_RELEASE, COMPATIBLE)
+ ));
+
+ underTest.handle(request, response);
+
+ assertJson(response.outputAsString()).isSimilarTo(resource("properties_per_plugin.json"));
+ }
+
+ @Test
+ public void status_COMPATIBLE_is_displayed_COMPATIBLE_in_JSON() throws Exception {
+ when(updateCenter.findPluginUpdates()).thenReturn(of(
+ pluginUpdate(release(PLUGIN_1, "1.0.0"), COMPATIBLE)
+ ));
+
+ underTest.handle(request, response);
+
+ assertJson(response.outputAsString()).isSimilarTo(
+ "{" +
+ " \"plugins\": [" +
+ " {" +
+ " \"update\": {" +
+ " \"status\": \"COMPATIBLE\"" +
+ " }" +
+ " }" +
+ " ]" +
+ "}"
+ );
+ }
+
+ @Test
+ public void plugins_are_sorted_by_name_then_key_and_made_unique() throws Exception {
+ when(updateCenter.findPluginUpdates()).thenReturn(of(
+ pluginUpdate("key2", "name2"),
+ pluginUpdate("key1", "name2"),
+ pluginUpdate("key2", "name2"),
+ pluginUpdate("key0", "name0"),
+ pluginUpdate("key1", "name1")
+ ));
+
+ underTest.handle(request, response);
+
+ assertJson(response.outputAsString()).setStrictArrayOrder(true).isSimilarTo(
+ "{" +
+ " \"plugins\": [" +
+ " {" +
+ " \"key\": \"key0\"," +
+ " \"name\": \"name0\"," +
+ " }," +
+ " {" +
+ " \"key\": \"key1\"," +
+ " \"name\": \"name1\"," +
+ " }," +
+ " {" +
+ " \"key\": \"key1\"," +
+ " \"name\": \"name2\"," +
+ " }," +
+ " {" +
+ " \"key\": \"key2\"," +
+ " \"name\": \"name2\"," +
+ " }," +
+ " ]" +
+ "}"
+ );
+ }
+
+ private static PluginUpdate pluginUpdate(String key, String name) {
+ return PluginUpdate.createWithStatus(
+ new Release(new Plugin(key).setName(name), Version.create("1.0")),
+ COMPATIBLE
+ );
+ }
+}
--- /dev/null
+{
+ "plugins": [
+ {
+ "key": "p_key",
+ "name": "p_name",
+ "category": "p_category",
+ "description": "p_description",
+ "license": "p_license",
+ "organizationName": "p_orga_name",
+ "organizationUrl": "p_orga_url",
+ "termsAndConditionsUrl": "p_t_and_c_url",
+ "release": {
+ "version": "1.12.1",
+ "date": "2015-04-16",
+ "artifact": {
+ "name": "p_file.jar",
+ "url": "http://p_file.jar"
+ }
+ },
+ "update": {
+ "status": "COMPATIBLE",
+ "requires": [
+ {
+ "key": "p_key_1",
+ "name": "p_name_1"
+ },
+ {
+ "key": "p_key_2",
+ "name": "p_name_2",
+ "description": "p_desc_2"
+ }
+ ]
+ }
+ }
+ ]
+}