]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8576 Make WS api/plugins/installed usable by Scanner/SonarLint
authorJulien HENRY <julien.henry@sonarsource.com>
Mon, 7 Aug 2017 13:44:49 +0000 (15:44 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Thu, 7 Sep 2017 06:33:31 +0000 (08:33 +0200)
server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java
server/sonar-db-dao/src/test/java/org/sonar/db/plugin/PluginDbTester.java [new file with mode: 0644]
server/sonar-db-dao/src/test/java/org/sonar/db/plugin/PluginTesting.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledAction.java
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingAction.java
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginWSCommons.java
server/sonar-server/src/main/resources/org/sonar/server/plugins/ws/example-installed_plugins.json
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledActionTest.java
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginWSCommonsTest.java

index f7b41634a4d4fa270fae817a35bb60a01c1a93bc..8122f1b0c602846f3558dcea0cd50981ec057b3d 100644 (file)
@@ -38,6 +38,7 @@ import org.sonar.db.organization.OrganizationDbTester;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.organization.OrganizationTesting;
 import org.sonar.db.permission.template.PermissionTemplateDbTester;
+import org.sonar.db.plugin.PluginDbTester;
 import org.sonar.db.property.PropertyDbTester;
 import org.sonar.db.qualitygate.QualityGateDbTester;
 import org.sonar.db.qualityprofile.QualityProfileDbTester;
@@ -78,6 +79,7 @@ public class DbTester extends AbstractDbTester<TestDb> {
   private final QualityProfileDbTester qualityProfileDbTester;
   private final MeasureDbTester measureDbTester;
   private final FileSourceTester fileSourceTester;
+  private final PluginDbTester pluginDbTester;
 
   public DbTester(System2 system2, @Nullable String schemaPath) {
     super(TestDb.create(schemaPath));
@@ -99,6 +101,7 @@ public class DbTester extends AbstractDbTester<TestDb> {
     this.qualityProfileDbTester = new QualityProfileDbTester(this);
     this.measureDbTester = new MeasureDbTester(this);
     this.fileSourceTester = new FileSourceTester(this);
+    this.pluginDbTester = new PluginDbTester(this);
   }
 
   public static DbTester create() {
@@ -233,6 +236,10 @@ public class DbTester extends AbstractDbTester<TestDb> {
     return fileSourceTester;
   }
 
+  public PluginDbTester pluginDbTester() {
+    return pluginDbTester;
+  }
+
   @Override
   protected void after() {
     if (session != null) {
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/plugin/PluginDbTester.java b/server/sonar-db-dao/src/test/java/org/sonar/db/plugin/PluginDbTester.java
new file mode 100644 (file)
index 0000000..a278328
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.db.plugin;
+
+import java.util.Arrays;
+import java.util.function.Consumer;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+
+public class PluginDbTester {
+  private final DbClient dbClient;
+  private final DbSession dbSession;
+
+  public PluginDbTester(DbTester db) {
+    this.dbClient = db.getDbClient();
+    this.dbSession = db.getSession();
+  }
+
+  @SafeVarargs
+  public final PluginDto insertPlugin(Consumer<PluginDto>... consumers) {
+    PluginDto pluginDto = PluginTesting.newPluginDto();
+    Arrays.stream(consumers).forEach(c -> c.accept(pluginDto));
+    dbClient.pluginDao().insert(dbSession, pluginDto);
+    dbSession.commit();
+    return pluginDto;
+  }
+
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/plugin/PluginTesting.java b/server/sonar-db-dao/src/test/java/org/sonar/db/plugin/PluginTesting.java
new file mode 100644 (file)
index 0000000..a8be452
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.db.plugin;
+
+import org.sonar.core.util.Uuids;
+
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+import static org.apache.commons.lang.math.RandomUtils.nextLong;
+
+public class PluginTesting {
+
+  private PluginTesting() {
+    // prevent instantiation
+  }
+
+  /**
+   * Create an instance of {@link  PluginDto} with random field values.
+   */
+  public static PluginDto newPluginDto() {
+    String uuid = Uuids.createFast();
+    return new PluginDto()
+      .setUuid(uuid)
+      .setKee(uuid)
+      .setHash(randomAlphanumeric(32))
+      .setCreatedAt(nextLong())
+      .setUpdatedAt(nextLong());
+  }
+
+}
index a8bd9fcd6fa9a311d2cdf5c43d944e6830116aec..a26a9c13cf05dd21e7e4e4a1c2550d99b1b7db52 100644 (file)
@@ -25,19 +25,23 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.SortedSet;
+import java.util.function.Function;
 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.core.platform.PluginInfo;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.plugin.PluginDto;
 import org.sonar.server.plugins.ServerPluginRepository;
 import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.server.user.UserSession;
 import org.sonar.updatecenter.common.Plugin;
 
 import static com.google.common.collect.ImmutableSortedSet.copyOf;
 import static java.lang.String.format;
 import static java.util.Collections.singleton;
+import static java.util.stream.Collectors.toMap;
 import static org.sonar.server.plugins.ws.PluginWSCommons.NAME_KEY_PLUGIN_METADATA_COMPARATOR;
 import static org.sonar.server.plugins.ws.PluginWSCommons.compatiblePluginsByKey;
 
@@ -48,23 +52,22 @@ public class InstalledAction implements PluginsWsAction {
   private static final String ARRAY_PLUGINS = "plugins";
   private static final String FIELD_CATEGORY = "category";
 
-  private final UserSession userSession;
   private final ServerPluginRepository pluginRepository;
   private final PluginWSCommons pluginWSCommons;
   private final UpdateCenterMatrixFactory updateCenterMatrixFactory;
+  private final DbClient dbClient;
 
-  public InstalledAction(UserSession userSession, ServerPluginRepository pluginRepository, PluginWSCommons pluginWSCommons, UpdateCenterMatrixFactory updateCenterMatrixFactory) {
-    this.userSession = userSession;
+  public InstalledAction(ServerPluginRepository pluginRepository, PluginWSCommons pluginWSCommons, UpdateCenterMatrixFactory updateCenterMatrixFactory, DbClient dbClient) {
     this.pluginRepository = pluginRepository;
     this.pluginWSCommons = pluginWSCommons;
     this.updateCenterMatrixFactory = updateCenterMatrixFactory;
+    this.dbClient = dbClient;
   }
 
   @Override
   public void define(WebService.NewController controller) {
     WebService.NewAction action = controller.createAction("installed")
-      .setDescription("Get the list of all the plugins installed on the SonarQube instance, sorted by plugin name.<br/>" +
-        "Require 'Administer System' permission.")
+      .setDescription("Get the list of all the plugins installed on the SonarQube instance, sorted by plugin name.")
       .setSince("5.2")
       .setHandler(this)
       .setResponseExample(Resources.getResource(this.getClass(), "example-installed_plugins.json"));
@@ -79,16 +82,18 @@ public class InstalledAction implements PluginsWsAction {
 
   @Override
   public void handle(Request request, Response response) throws Exception {
-    userSession.checkIsSystemAdministrator();
-
     Collection<PluginInfo> pluginInfoList = searchPluginInfoList();
+    Map<String, PluginDto> pluginDtosByKey;
+    try (DbSession dbSession = dbClient.openSession(false)) {
+      pluginDtosByKey = dbClient.pluginDao().selectAll(dbSession).stream().collect(toMap(PluginDto::getKee, Function.identity()));
+    }
 
     JsonWriter jsonWriter = response.newJsonWriter();
     jsonWriter.setSerializeEmptys(false);
     jsonWriter.beginObject();
 
     List<String> additionalFields = request.paramAsStrings(WebService.Param.FIELDS);
-    writePluginInfoList(jsonWriter, pluginInfoList, additionalFields == null ? Collections.<String>emptyList() : additionalFields);
+    writePluginInfoList(jsonWriter, pluginInfoList, additionalFields == null ? Collections.<String>emptyList() : additionalFields, pluginDtosByKey);
 
     jsonWriter.endObject();
     jsonWriter.close();
@@ -98,10 +103,10 @@ public class InstalledAction implements PluginsWsAction {
     return copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, pluginRepository.getPluginInfos());
   }
 
-  private void writePluginInfoList(JsonWriter jsonWriter, Collection<PluginInfo> pluginInfoList, List<String> additionalFields) {
+  private void writePluginInfoList(JsonWriter jsonWriter, Collection<PluginInfo> pluginInfoList, List<String> additionalFields, Map<String, PluginDto> pluginDtos) {
     Map<String, Plugin> compatiblesPluginsFromUpdateCenter = additionalFields.isEmpty()
       ? Collections.<String, Plugin>emptyMap()
       : compatiblePluginsByKey(updateCenterMatrixFactory);
-    pluginWSCommons.writePluginInfoList(jsonWriter, pluginInfoList, compatiblesPluginsFromUpdateCenter, ARRAY_PLUGINS);
+    pluginWSCommons.writePluginInfoList(jsonWriter, pluginInfoList, compatiblesPluginsFromUpdateCenter, ARRAY_PLUGINS, pluginDtos);
   }
 }
index 510b6ae3b707e0feca67649a014de9bb3f9e4ad1..ac821b5e67a5d9847c1a2aa1205fff78587adaaf 100644 (file)
@@ -59,8 +59,8 @@ public class PendingAction implements PluginsWsAction {
   private final UpdateCenterMatrixFactory updateCenterMatrixFactory;
 
   public PendingAction(UserSession userSession, PluginDownloader pluginDownloader,
-                       ServerPluginRepository installer,
-                       PluginWSCommons pluginWSCommons, UpdateCenterMatrixFactory updateCenterMatrixFactory) {
+    ServerPluginRepository installer,
+    PluginWSCommons pluginWSCommons, UpdateCenterMatrixFactory updateCenterMatrixFactory) {
     this.userSession = userSession;
     this.pluginDownloader = pluginDownloader;
     this.installer = installer;
@@ -108,9 +108,9 @@ public class PendingAction implements PluginsWsAction {
       }
     }
 
-    pluginWSCommons.writePluginInfoList(json, newPlugins, compatiblePluginsByKey, ARRAY_INSTALLING);
-    pluginWSCommons.writePluginInfoList(json, updatedPlugins, compatiblePluginsByKey, ARRAY_UPDATING);
-    pluginWSCommons.writePluginInfoList(json, uninstalledPlugins, compatiblePluginsByKey, ARRAY_REMOVING);
+    pluginWSCommons.writePluginInfoList(json, newPlugins, compatiblePluginsByKey, ARRAY_INSTALLING, null);
+    pluginWSCommons.writePluginInfoList(json, updatedPlugins, compatiblePluginsByKey, ARRAY_UPDATING, null);
+    pluginWSCommons.writePluginInfoList(json, uninstalledPlugins, compatiblePluginsByKey, ARRAY_REMOVING, null);
   }
 
   private enum PluginInfoToKey implements Function<PluginInfo, String> {
index 5e6bc5edc9f56a20362f0f335cb55705d2b36c74..44716a3ab7dea30878c096121083d3e154d4647f 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.plugins.ws;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Ordering;
@@ -34,6 +35,7 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.platform.PluginInfo;
+import org.sonar.db.plugin.PluginDto;
 import org.sonar.server.plugins.UpdateCenterMatrixFactory;
 import org.sonar.updatecenter.common.Artifact;
 import org.sonar.updatecenter.common.Plugin;
@@ -51,6 +53,9 @@ import static org.apache.commons.lang.StringUtils.isNotBlank;
 public class PluginWSCommons {
   static final String PROPERTY_KEY = "key";
   static final String PROPERTY_NAME = "name";
+  static final String PROPERTY_HASH = "hash";
+  static final String PROPERTY_FILENAME = "filename";
+  static final String PROPERTY_SONARLINT_SUPPORTED = "sonarLintSupported";
   static final String PROPERTY_DESCRIPTION = "description";
   static final String PROPERTY_LICENSE = "license";
   static final String PROPERTY_VERSION = "version";
@@ -58,6 +63,7 @@ public class PluginWSCommons {
   static final String PROPERTY_ORGANIZATION_NAME = "organizationName";
   static final String PROPERTY_ORGANIZATION_URL = "organizationUrl";
   static final String PROPERTY_DATE = "date";
+  static final String PROPERTY_UPDATED_AT = "updatedAt";
   static final String PROPERTY_STATUS = "status";
   static final String PROPERTY_HOMEPAGE_URL = "homepageUrl";
   static final String PROPERTY_ISSUE_TRACKER_URL = "issueTrackerUrl";
@@ -81,11 +87,17 @@ public class PluginWSCommons {
   public static final Comparator<PluginUpdate> NAME_KEY_PLUGIN_UPDATE_ORDERING = Ordering.from(NAME_KEY_PLUGIN_ORDERING)
     .onResultOf(PluginUpdateToPlugin.INSTANCE);
 
-  void writePluginInfo(JsonWriter json, PluginInfo pluginInfo, @Nullable String category) {
+  void writePluginInfo(JsonWriter json, PluginInfo pluginInfo, @Nullable String category, @Nullable PluginDto pluginDto) {
     json.beginObject();
 
     json.prop(PROPERTY_KEY, pluginInfo.getKey());
     json.prop(PROPERTY_NAME, pluginInfo.getName());
+    if (pluginDto != null) {
+      json.prop(PROPERTY_FILENAME, pluginInfo.getNonNullJarFile().getName());
+      json.prop(PROPERTY_SONARLINT_SUPPORTED, pluginInfo.isSonarLintSupported());
+      json.prop(PROPERTY_HASH, pluginDto.getHash());
+      json.prop(PROPERTY_UPDATED_AT, pluginDto.getUpdatedAt());
+    }
     json.prop(PROPERTY_DESCRIPTION, pluginInfo.getDescription());
     Version version = pluginInfo.getVersion();
     if (version != null) {
@@ -103,12 +115,18 @@ public class PluginWSCommons {
     json.endObject();
   }
 
-  public void writePluginInfoList(JsonWriter json, Iterable<PluginInfo> plugins, Map<String, Plugin> compatiblePluginsByKey, String propertyName) {
+  public void writePluginInfoList(JsonWriter json, Iterable<PluginInfo> plugins, Map<String, Plugin> compatiblePluginsByKey, String propertyName,
+    @Nullable Map<String, PluginDto> pluginDtos) {
     json.name(propertyName);
     json.beginArray();
     for (PluginInfo pluginInfo : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
+      PluginDto pluginDto = null;
+      if (pluginDtos != null) {
+        pluginDto = pluginDtos.get(pluginInfo.getKey());
+        Preconditions.checkNotNull(pluginDto, "Plugin %s is installed but not in DB", pluginInfo.getKey());
+      }
       Plugin plugin = compatiblePluginsByKey.get(pluginInfo.getKey());
-      writePluginInfo(json, pluginInfo, categoryOrNull(plugin));
+      writePluginInfo(json, pluginInfo, categoryOrNull(plugin), pluginDto);
     }
     json.endArray();
   }
index 4b17325ac9577d7f8d2e5f566cfe6f0a8118c3de..d88f50b376a980a31632e54fd4a09dff6c517e22 100644 (file)
       "organizationUrl": "http://www.sonarsource.com",
       "homepageUrl": "https://redirect.sonarsource.com/plugins/scmgit.html",
       "issueTrackerUrl": "http://jira.sonarsource.com/browse/SONARSCGIT",
-      "implementationBuild": "9ce9d330c313c296fab051317cc5ad4b26319e07"
+      "implementationBuild": "9ce9d330c313c296fab051317cc5ad4b26319e07",
+      "filename": "sonar-scm-git-plugin-1.0.jar",
+      "hash": "abcdef123456",
+      "sonarLintSupported": false,
+      "updatedAt": 123456789
     },
     {
       "key": "java",
       "organizationUrl": "http://www.sonarsource.com",
       "homepageUrl": "https://redirect.sonarsource.com/plugins/java.html",
       "issueTrackerUrl": "http://jira.sonarsource.com/browse/SONARJAVA",
-      "implementationBuild": "65396a609ddface8b311a6a665aca92a7da694f1"
+      "implementationBuild": "65396a609ddface8b311a6a665aca92a7da694f1",
+      "filename": "sonar-java-plugin-3.0.jar",
+      "hash": "abcdef123456",
+      "sonarLintSupported": true,
+      "updatedAt": 123456789
     },
     {
       "key": "scmsvn",
       "organizationUrl": "http://www.sonarsource.com",
       "homepageUrl": "https://redirect.sonarsource.com/plugins/scmsvn.html",
       "issueTrackerUrl": "http://jira.sonarsource.com/browse/SONARSCSVN",
-      "implementationBuild": "213fc8a8b582ff530b12dd4a59a6512be1071234"
+      "implementationBuild": "213fc8a8b582ff530b12dd4a59a6512be1071234",
+      "filename": "sonar-scm-svn-plugin-1.0.jar",
+      "hash": "abcdef123456",
+      "sonarLintSupported": false,
+      "updatedAt": 123456789
     }
   ]
 }
index 44ab6b201732c7285282fdfe50d1ead88dc6ed80..f7e0f39296aaa59f833217f2186571da27f3816f 100644 (file)
@@ -28,11 +28,11 @@ import org.junit.rules.ExpectedException;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.System2;
 import org.sonar.core.platform.PluginInfo;
-import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.db.DbTester;
 import org.sonar.server.plugins.ServerPluginRepository;
 import org.sonar.server.plugins.UpdateCenterMatrixFactory;
-import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.WsTester;
 import org.sonar.updatecenter.common.Plugin;
 import org.sonar.updatecenter.common.UpdateCenter;
@@ -49,25 +49,24 @@ import static org.sonar.test.JsonAssert.assertJson;
 
 public class InstalledActionTest {
   private static final String DUMMY_CONTROLLER_KEY = "dummy";
-  private static final String JSON_EMPTY_PLUGIN_LIST =
-    "{" +
-      "  \"plugins\":" + "[]" +
-      "}";
+  private static final String JSON_EMPTY_PLUGIN_LIST = "{" +
+    "  \"plugins\":" + "[]" +
+    "}";
 
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
 
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+
   private ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class);
   private UpdateCenterMatrixFactory updateCenterMatrixFactory = mock(UpdateCenterMatrixFactory.class, RETURNS_DEEP_STUBS);
   private Request request = mock(Request.class);
   private WsTester.TestResponse response = new WsTester.TestResponse();
-  private InstalledAction underTest = new InstalledAction(userSession, pluginRepository, new PluginWSCommons(), updateCenterMatrixFactory);
+  private InstalledAction underTest = new InstalledAction(pluginRepository, new PluginWSCommons(), updateCenterMatrixFactory, db.getDbClient());
 
   @Test
   public void action_installed_is_defined() {
-    logInAsSystemAdministrator();
     WsTester wsTester = new WsTester();
     WebService.NewController newController = wsTester.context().createController(DUMMY_CONTROLLER_KEY);
 
@@ -83,25 +82,8 @@ public class InstalledActionTest {
     assertThat(action.responseExample()).isNotNull();
   }
 
-  @Test
-  public void request_fails_with_ForbiddenException_when_user_is_not_logged_in() throws Exception {
-    expectedException.expect(ForbiddenException.class);
-
-    underTest.handle(request, response);
-  }
-
-  @Test
-  public void request_fails_with_ForbiddenException_when_user_is_not_system_administrator() throws Exception {
-    userSession.logIn().setNonSystemAdministrator();
-
-    expectedException.expect(ForbiddenException.class);
-
-    underTest.handle(request, response);
-  }
-
   @Test
   public void empty_array_is_returned_when_there_is_not_plugin_installed() throws Exception {
-    logInAsSystemAdministrator();
     underTest.handle(request, response);
 
     assertJson(response.outputAsString()).withStrictArrayOrder().isSimilarTo(JSON_EMPTY_PLUGIN_LIST);
@@ -109,7 +91,6 @@ public class InstalledActionTest {
 
   @Test
   public void empty_array_when_update_center_is_unavailable() throws Exception {
-    logInAsSystemAdministrator();
     when(updateCenterMatrixFactory.getUpdateCenter(false)).thenReturn(Optional.<UpdateCenter>absent());
 
     underTest.handle(request, response);
@@ -119,9 +100,12 @@ public class InstalledActionTest {
 
   @Test
   public void empty_fields_are_not_serialized_to_json() throws Exception {
-    logInAsSystemAdministrator();
     when(pluginRepository.getPluginInfos()).thenReturn(
-      of(new PluginInfo("").setName("")));
+      of(new PluginInfo("").setName("").setJarFile(new File(""))));
+    db.pluginDbTester().insertPlugin(
+      p -> p.setKee(""),
+      p -> p.setHash("abcdA"),
+      p -> p.setUpdatedAt(111111L));
 
     underTest.handle(request, response);
 
@@ -130,7 +114,6 @@ public class InstalledActionTest {
 
   @Test
   public void verify_properties_displayed_in_json_per_plugin() throws Exception {
-    logInAsSystemAdministrator();
     String jarFilename = getClass().getSimpleName() + "/" + "some.jar";
     when(pluginRepository.getPluginInfos()).thenReturn(of(
       new PluginInfo("plugKey")
@@ -143,9 +126,12 @@ public class InstalledActionTest {
         .setHomepageUrl("homepage_url")
         .setIssueTrackerUrl("issueTracker_url")
         .setImplementationBuild("sou_rev_sha1")
-        .setJarFile(new File(getClass().getResource(jarFilename).toURI()))
-      )
-    );
+        .setSonarLintSupported(true)
+        .setJarFile(new File(getClass().getResource(jarFilename).toURI()))));
+    db.pluginDbTester().insertPlugin(
+      p -> p.setKee("plugKey"),
+      p -> p.setHash("abcdplugKey"),
+      p -> p.setUpdatedAt(111111L));
 
     underTest.handle(request, response);
 
@@ -164,16 +150,18 @@ public class InstalledActionTest {
         "      \"organizationUrl\": \"org_url\"," +
         "      \"homepageUrl\": \"homepage_url\"," +
         "      \"issueTrackerUrl\": \"issueTracker_url\"," +
-        "      \"implementationBuild\": \"sou_rev_sha1\"" +
+        "      \"implementationBuild\": \"sou_rev_sha1\"," +
+        "      \"sonarLintSupported\": true," +
+        "      \"filename\": \"some.jar\"," +
+        "      \"hash\": \"abcdplugKey\"," +
+        "      \"updatedAt\": 111111" +
         "    }" +
         "  ]" +
-        "}"
-    );
+        "}");
   }
 
   @Test
   public void category_is_returned_when_in_additional_fields() throws Exception {
-    logInAsSystemAdministrator();
     String jarFilename = getClass().getSimpleName() + "/" + "some.jar";
     when(pluginRepository.getPluginInfos()).thenReturn(of(
       new PluginInfo("plugKey")
@@ -186,17 +174,19 @@ public class InstalledActionTest {
         .setHomepageUrl("homepage_url")
         .setIssueTrackerUrl("issueTracker_url")
         .setImplementationBuild("sou_rev_sha1")
-        .setJarFile(new File(getClass().getResource(jarFilename).toURI()))
-      )
-    );
+        .setJarFile(new File(getClass().getResource(jarFilename).toURI()))));
     UpdateCenter updateCenter = mock(UpdateCenter.class);
     when(updateCenterMatrixFactory.getUpdateCenter(false)).thenReturn(Optional.of(updateCenter));
     when(updateCenter.findAllCompatiblePlugins()).thenReturn(
       Arrays.asList(
         Plugin.factory("plugKey")
-          .setCategory("cat_1")
-      )
-    );
+          .setCategory("cat_1")));
+
+    db.pluginDbTester().insertPlugin(
+      p -> p.setKee("plugKey"),
+      p -> p.setHash("abcdplugKey"),
+      p -> p.setUpdatedAt(111111L));
+
     when(request.paramAsStrings(Param.FIELDS)).thenReturn(singletonList("category"));
 
     underTest.handle(request, response);
@@ -219,21 +209,34 @@ public class InstalledActionTest {
         "      \"implementationBuild\": \"sou_rev_sha1\"" +
         "    }" +
         "  ]" +
-        "}"
-    );
+        "}");
   }
 
   @Test
   public void plugins_are_sorted_by_name_then_key_and_only_one_plugin_can_have_a_specific_name() throws Exception {
-    logInAsSystemAdministrator();
     when(pluginRepository.getPluginInfos()).thenReturn(
       of(
         plugin("A", "name2"),
         plugin("B", "name1"),
         plugin("C", "name0"),
-        plugin("D", "name0")
-      )
-    );
+        plugin("D", "name0")));
+
+    db.pluginDbTester().insertPlugin(
+      p -> p.setKee("A"),
+      p -> p.setHash("abcdA"),
+      p -> p.setUpdatedAt(111111L));
+    db.pluginDbTester().insertPlugin(
+      p -> p.setKee("B"),
+      p -> p.setHash("abcdB"),
+      p -> p.setUpdatedAt(222222L));
+    db.pluginDbTester().insertPlugin(
+      p -> p.setKee("C"),
+      p -> p.setHash("abcdC"),
+      p -> p.setUpdatedAt(333333L));
+    db.pluginDbTester().insertPlugin(
+      p -> p.setKee("D"),
+      p -> p.setHash("abcdD"),
+      p -> p.setUpdatedAt(444444L));
 
     underTest.handle(request, response);
 
@@ -246,19 +249,20 @@ public class InstalledActionTest {
         "    {\"key\": \"B\"}" + "," +
         "    {\"key\": \"A\"}" +
         "  ]" +
-        "}"
-    );
+        "}");
   }
 
   @Test
   public void only_one_plugin_can_have_a_specific_name_and_key() throws Exception {
-    logInAsSystemAdministrator();
     when(pluginRepository.getPluginInfos()).thenReturn(
       of(
         plugin("A", "name2"),
-        plugin("A", "name2")
-      )
-    );
+        plugin("A", "name2")));
+
+    db.pluginDbTester().insertPlugin(
+      p -> p.setKee("A"),
+      p -> p.setHash("abcdA"),
+      p -> p.setUpdatedAt(111111L));
 
     underTest.handle(request, response);
 
@@ -268,17 +272,12 @@ public class InstalledActionTest {
         "  [" +
         "    {\"key\": \"A\"}" +
         "  ]" +
-        "}"
-    );
+        "}");
     assertThat(response.outputAsString()).containsOnlyOnce("name2");
   }
 
   private PluginInfo plugin(String key, String name) {
-    return new PluginInfo(key).setName(name).setVersion(Version.create("1.0"));
-  }
-
-  private void logInAsSystemAdministrator() {
-    userSession.logIn().setSystemAdministrator();
+    return new PluginInfo(key).setName(name).setVersion(Version.create("1.0")).setJarFile(new File("sonar-" + key + "-plugin-1.0.jar"));
   }
 
 }
index 492369c7b91fec7d0d65f4ed7e94a14d22cd18b8..e98d2b3f8d7177cb989892e471539ff46768d5a4 100644 (file)
  */
 package org.sonar.server.plugins.ws;
 
+import java.io.File;
 import org.junit.Test;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.platform.PluginInfo;
+import org.sonar.db.plugin.PluginDto;
 import org.sonar.server.ws.WsTester;
 import org.sonar.updatecenter.common.Plugin;
 import org.sonar.updatecenter.common.PluginUpdate;
@@ -45,7 +47,7 @@ public class PluginWSCommonsTest {
 
   @Test
   public void verify_properties_written_by_writePluginMetadata() {
-    underTest.writePluginInfo(jsonWriter, gitPluginInfo(), null);
+    underTest.writePluginInfo(jsonWriter, gitPluginInfo(), null, null);
 
     jsonWriter.close();
     assertJson(response.outputAsString()).withStrictArrayOrder().isSimilarTo("{" +
@@ -61,9 +63,31 @@ public class PluginWSCommonsTest {
       "}");
   }
 
+  @Test
+  public void verify_properties_written_by_writePluginMetadata_with_dto() {
+    underTest.writePluginInfo(jsonWriter, gitPluginInfo(), null, new PluginDto().setHash("abcdef123456").setUpdatedAt(123456L));
+
+    jsonWriter.close();
+    assertJson(response.outputAsString()).withStrictArrayOrder().isSimilarTo("{" +
+      "  \"key\": \"scmgit\"," +
+      "  \"name\": \"Git\"," +
+      "  \"description\": \"Git SCM Provider.\"," +
+      "  \"version\": \"1.0\"," +
+      "  \"license\": \"GNU LGPL 3\"," +
+      "  \"organizationName\": \"SonarSource\"," +
+      "  \"organizationUrl\": \"http://www.sonarsource.com\"," +
+      "  \"homepageUrl\": \"https://redirect.sonarsource.com/plugins/scmgit.html\"," +
+      "  \"issueTrackerUrl\": \"http://jira.sonarsource.com/browse/SONARSCGIT\"," +
+      "  \"filename\": \"sonar-scm-git-plugin-1.0.jar\"," +
+      "  \"hash\": \"abcdef123456\"," +
+      "  \"sonarLintSupported\": true," +
+      "  \"updatedAt\": 123456" +
+      "}");
+  }
+
   @Test
   public void verify_properties_written_by_writeMetadata() {
-    underTest.writePluginInfo(jsonWriter, gitPluginInfo(), "cat_1");
+    underTest.writePluginInfo(jsonWriter, gitPluginInfo(), "cat_1", null);
 
     jsonWriter.close();
     assertJson(response.outputAsString()).withStrictArrayOrder().isSimilarTo("{" +
@@ -176,8 +200,7 @@ public class PluginWSCommonsTest {
   public void writeUpdate_renders_key_name_and_description_of_requirements() {
     PluginUpdate pluginUpdate = new PluginUpdate();
     pluginUpdate.setRelease(
-      new Release(newPlugin(), version("1.0")).addOutgoingDependency(newRelease())
-      );
+      new Release(newPlugin(), version("1.0")).addOutgoingDependency(newRelease()));
 
     jsonWriter.beginObject();
     underTest.writeUpdate(jsonWriter, pluginUpdate);
@@ -214,7 +237,9 @@ public class PluginWSCommonsTest {
       .setOrganizationName("SonarSource")
       .setOrganizationUrl("http://www.sonarsource.com")
       .setHomepageUrl("https://redirect.sonarsource.com/plugins/scmgit.html")
-      .setIssueTrackerUrl("http://jira.sonarsource.com/browse/SONARSCGIT");
+      .setIssueTrackerUrl("http://jira.sonarsource.com/browse/SONARSCGIT")
+      .setSonarLintSupported(true)
+      .setJarFile(new File("sonar-scm-git-plugin-1.0.jar"));
   }
 
   private Plugin newPlugin() {