]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6017 Add api/rules/repositories action to list rule repositories (with criteria)
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Tue, 20 Jan 2015 14:56:12 +0000 (15:56 +0100)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Tue, 20 Jan 2015 15:09:51 +0000 (16:09 +0100)
22 files changed:
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/AppAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/CreateAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/DeleteAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWebService.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/TagsAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/UpdateAction.java
server/sonar-server/src/main/resources/org/sonar/server/rule/ws/example-repositories.json [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/DeleteActionTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/RepositoriesActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java
server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_common.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_limited.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_squid.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_ws.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_xoo.json [new file with mode: 0644]

index 5d21aaefe5d363c938abc3cc9ccc84d73994422a..c0e2bfda799eacc3a2a8e79e40db13bbd05a282f 100644 (file)
@@ -264,6 +264,7 @@ import org.sonar.server.rule.index.RuleNormalizer;
 import org.sonar.server.rule.ws.ActiveRuleCompleter;
 import org.sonar.server.rule.ws.AppAction;
 import org.sonar.server.rule.ws.DeleteAction;
+import org.sonar.server.rule.ws.RepositoriesAction;
 import org.sonar.server.rule.ws.RuleMapping;
 import org.sonar.server.rule.ws.RulesWebService;
 import org.sonar.server.rule.ws.SearchAction;
@@ -558,6 +559,7 @@ class ServerComponents {
     pico.addSingleton(TagsAction.class);
     pico.addSingleton(RuleMapping.class);
     pico.addSingleton(ActiveRuleCompleter.class);
+    pico.addSingleton(RepositoriesAction.class);
     pico.addSingleton(AppAction.class);
 
     // languages
index 7ca17abfd905393899fa7306a642fcd217c9d71b..25564e3a618493148ed29fc64e22fc682b27c180 100644 (file)
@@ -28,7 +28,6 @@ import org.sonar.api.server.debt.DebtCharacteristic;
 import org.sonar.api.server.debt.DebtModel;
 import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
 import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.text.JsonWriter;
@@ -45,7 +44,7 @@ import java.util.Map;
 /**
  * @since 4.4
  */
-public class AppAction implements RequestHandler {
+public class AppAction implements RulesAction {
 
   private final Languages languages;
   private final RuleRepositories ruleRepositories;
@@ -148,7 +147,8 @@ public class AppAction implements RequestHandler {
     json.endArray();
   }
 
-  void define(WebService.NewController controller) {
+  @Override
+  public void define(WebService.NewController controller) {
     controller.createAction("app")
       .setDescription("Data required for rendering the page 'Coding Rules'")
       .setInternal(true)
index cf48eba28d86452a46d813cc2bcfb6049f857b7c..20430e3daff5d3b2b60e71e3f56454d7e8dfb576 100644 (file)
@@ -25,7 +25,6 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.KeyValueFormat;
@@ -42,7 +41,7 @@ import java.io.OutputStreamWriter;
 /**
  * @since 4.4
  */
-public class CreateAction implements RequestHandler {
+public class CreateAction implements RulesAction {
 
   public static final String PARAM_CUSTOM_KEY = "custom_key";
   public static final String PARAM_MANUAL_KEY = "manual_key";
@@ -63,7 +62,8 @@ public class CreateAction implements RequestHandler {
     this.mapping = mapping;
   }
 
-  void define(WebService.NewController controller) {
+  @Override
+  public void define(WebService.NewController controller) {
     WebService.NewAction action = controller
       .createAction("create")
       .setDescription("Create a custom rule or a manual rule")
index b81a8bdb6f96f93e1e5c4c29a71884aac90d356d..5520761fc45df85b0795ae7a49978a9eb6ac60dd 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.rule.ws;
 
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.rule.RuleService;
@@ -30,7 +29,7 @@ import org.sonar.server.rule.RuleService;
 /**
  * @since 4.4
  */
-public class DeleteAction implements RequestHandler {
+public class DeleteAction implements RulesAction {
 
   public static final String PARAM_KEY = "key";
 
@@ -40,7 +39,8 @@ public class DeleteAction implements RequestHandler {
     this.service = service;
   }
 
-  void define(WebService.NewController controller) {
+  @Override
+  public void define(WebService.NewController controller) {
     WebService.NewAction action = controller
       .createAction("delete")
       .setDescription("Delete custom rule or manual rule")
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java
new file mode 100644 (file)
index 0000000..55ff234
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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.rule.ws;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+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.server.ws.WebService.NewAction;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.server.rule.RuleRepositories;
+import org.sonar.server.rule.RuleRepositories.Repository;
+
+import javax.annotation.Nullable;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.regex.Pattern;
+
+/**
+ * @since 5.1
+ */
+public class RepositoriesAction implements RulesAction {
+
+  private static final String MATCH_ALL = ".*";
+  private final RuleRepositories repositories;
+
+  public RepositoriesAction(RuleRepositories repositories) {
+    this.repositories = repositories;
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    String query = request.param("q");
+    String languageKey = request.param("language");
+    int pageSize = request.mandatoryParamAsInt("ps");
+
+    JsonWriter json = response.newJsonWriter().beginObject().name("repositories").beginArray();
+    for (Repository repo : listMatchingRepositories(query, languageKey, pageSize)) {
+      json.beginObject().prop("key", repo.key()).prop("name", repo.name()).prop("language", repo.language()).endObject();
+    }
+    json.endArray().endObject().close();
+  }
+
+  private Collection<Repository> listMatchingRepositories(@Nullable String query, @Nullable String languageKey, int pageSize) {
+    Pattern pattern = Pattern.compile(query == null ? MATCH_ALL : MATCH_ALL + query + MATCH_ALL, Pattern.CASE_INSENSITIVE);
+
+    SortedMap<String, Repository> reposByName = Maps.newTreeMap();
+    Collection<Repository> repos = languageKey == null ? repositories.repositories() : repositories.repositoriesForLang(languageKey);
+
+    for (Repository repo : repos) {
+      if (pattern.matcher(repo.key()).matches() || pattern.matcher(repo.name()).matches()) {
+        reposByName.put(repo.name() + " -- " + repo.language(), repo);
+      }
+    }
+    List<Repository> result = Lists.newArrayList(reposByName.values());
+    if (pageSize > 0 && pageSize < result.size()) {
+      result = result.subList(0, pageSize);
+    }
+    return result;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction action = controller.createAction("repositories")
+      .setDescription("List available rule repositories")
+      .setHandler(this)
+      .setResponseExample(Resources.getResource(getClass(), "example-repositories.json"));
+
+    action.createParam("q")
+      .setDescription("A pattern to match repository keys/names against")
+      .setExampleValue("squid");
+    action.createParam("language")
+      .setDescription("A language key; if provided, only repositories for the given language will be returned")
+      .setExampleValue("java");
+    action.createParam("ps")
+      .setDescription("The size of the list to return, 0 for all repositories")
+      .setExampleValue("25")
+      .setDefaultValue("0");
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesAction.java
new file mode 100644 (file)
index 0000000..ef56302
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.rule.ws;
+
+import org.sonar.api.server.ws.RequestHandler;
+import org.sonar.api.server.ws.WebService;
+
+/**
+ * Marker interface for coding rule related actions
+ * @author jblievremont
+ *
+ */
+interface RulesAction extends RequestHandler {
+
+  void define(WebService.NewController controller);
+}
index b4a9ffc9cb4b4a4a05f997f142660c1a8f742347..08b0374f84cd9a5eaf3406e77365555e7844c633 100644 (file)
@@ -23,23 +23,10 @@ import org.sonar.api.server.ws.WebService;
 
 public class RulesWebService implements WebService {
 
-  private final SearchAction search;
-  private final ShowAction show;
-  private final TagsAction tags;
-  private final CreateAction create;
-  private final AppAction app;
-  private final UpdateAction update;
-  private final DeleteAction delete;
+  private final RulesAction[] actions;
 
-  public RulesWebService(SearchAction search, ShowAction show, TagsAction tags, CreateAction create,
-                         AppAction app, UpdateAction update, DeleteAction delete) {
-    this.search = search;
-    this.show = show;
-    this.tags = tags;
-    this.create = create;
-    this.app = app;
-    this.update = update;
-    this.delete = delete;
+  public RulesWebService(RulesAction... actions) {
+    this.actions = actions;
   }
 
   @Override
@@ -48,13 +35,9 @@ public class RulesWebService implements WebService {
       .createController("api/rules")
       .setDescription("Coding rules");
 
-    search.define(controller);
-    show.define(controller);
-    tags.define(controller);
-    app.define(controller);
-    update.define(controller);
-    create.define(controller);
-    delete.define(controller);
+    for (RulesAction action : actions) {
+      action.define(controller);
+    }
 
     controller.done();
   }
index 3adbc00b4b447aaf1453304780e2412e343b4286..f5f24a581ef8e170b5e9b83db0bacd0f6578c824 100644 (file)
@@ -47,7 +47,7 @@ import java.util.Collection;
 /**
  * @since 4.4
  */
-public class SearchAction extends SearchRequestHandler<RuleQuery, Rule> {
+public class SearchAction extends SearchRequestHandler<RuleQuery, Rule> implements RulesAction {
 
   public static final String PARAM_REPOSITORIES = "repositories";
   public static final String PARAM_KEY = "rule_key";
index fb2d98994f6d3fb6f8e097062ecbf8d4190214e3..2387e8db40e65ec02285f487ccb45f8cab118af1 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.rule.ws;
 import com.google.common.io.Resources;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.text.JsonWriter;
@@ -33,7 +32,7 @@ import org.sonar.server.rule.RuleService;
 /**
  * @since 4.4
  */
-public class ShowAction implements RequestHandler {
+public class ShowAction implements RulesAction {
 
   public static final String PARAM_KEY = "key";
   public static final String PARAM_ACTIVES = "actives";
@@ -48,7 +47,8 @@ public class ShowAction implements RequestHandler {
     this.activeRuleCompleter = activeRuleCompleter;
   }
 
-  void define(WebService.NewController controller) {
+  @Override
+  public void define(WebService.NewController controller) {
     WebService.NewAction action = controller
       .createAction("show")
       .setDescription("Get detailed information about a rule")
index 8d4c3d037e47783aacd03e04dc798b9eb266095f..4d20919f6ada7bb1f1a69b80837fa940bb794578 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.server.rule.ws;
 
 import com.google.common.io.Resources;
 import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.NewAction;
@@ -30,7 +29,7 @@ import org.sonar.server.rule.RuleService;
 
 import java.util.Set;
 
-public class TagsAction implements RequestHandler {
+public class TagsAction implements RulesAction {
 
   private final RuleService service;
 
@@ -38,7 +37,8 @@ public class TagsAction implements RequestHandler {
     this.service = service;
   }
 
-  void define(WebService.NewController controller) {
+  @Override
+  public void define(WebService.NewController controller) {
     NewAction action = controller
       .createAction("tags")
       .setDescription("List rule tags")
index 0eb7aee2f2a2468fee7277d6a254dbf54fdd1c8c..8ee0104e5125721059e1a0df6ac4d2519e997aad 100644 (file)
@@ -28,7 +28,6 @@ import org.sonar.api.rule.Severity;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction;
 import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.KeyValueFormat;
@@ -38,7 +37,7 @@ import org.sonar.server.rule.Rule;
 import org.sonar.server.rule.RuleService;
 import org.sonar.server.rule.RuleUpdate;
 
-public class UpdateAction implements RequestHandler {
+public class UpdateAction implements RulesAction {
 
   public static final String PARAM_KEY = "key";
   public static final String PARAM_TAGS = "tags";
@@ -61,7 +60,8 @@ public class UpdateAction implements RequestHandler {
     this.mapping = mapping;
   }
 
-  void define(WebService.NewController controller) {
+  @Override
+  public void define(WebService.NewController controller) {
     WebService.NewAction action = controller
       .createAction("update")
       .setPost(true)
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/example-repositories.json b/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/example-repositories.json
new file mode 100644 (file)
index 0000000..e73c411
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "repositories": [
+    {"key": "clirr", "name": "Clirr", "language": "java"},
+    {"key": "common-c", "name": "Common SonarQube", "language": "c"},
+    {"key": "common-cpp", "name": "Common SonarQube", "language": "cpp"},
+    {"key": "common-cs", "name": "Common SonarQube", "language": "cs"},
+    {"key": "common-java", "name": "Common SonarQube", "language": "java"},
+    {"key": "common-js", "name": "Common SonarQube", "language": "js"},
+    {"key": "common-objc", "name": "Common SonarQube", "language": "objc"},
+    {"key": "common-php", "name": "Common SonarQube", "language": "php"},
+    {"key": "c-cppcheck", "name": "Cppcheck", "language": "c"},
+    {"key": "cpp-cppcheck", "name": "Cppcheck", "language": "cpp"},
+    {"key": "fb-contrib", "name": "fb-contrib", "language": "java"},
+    {"key": "findbugs", "name": "FindBugs", "language": "java"},
+    {"key": "fxcop", "name": "FxCop / Code Analysis", "language": "cs"},
+    {"key": "resharper-cs", "name": "ReSharper", "language": "cs"},
+    {"key": "resharper-vbnet", "name": "ReSharper", "language": "vbnet"},
+    {"key": "c", "name": "SonarQube", "language": "c"},
+    {"key": "cpp", "name": "SonarQube", "language": "cpp"},
+    {"key": "csharpsquid", "name": "SonarQube", "language": "cs"},
+    {"key": "javascript", "name": "SonarQube", "language": "js"},
+    {"key": "objc", "name": "SonarQube", "language": "objc"},
+    {"key": "php", "name": "SonarQube", "language": "php"},
+    {"key": "squid", "name": "SonarQube", "language": "java"},
+    {"key": "stylecop", "name": "StyleCop", "language": "cs"}
+  ]
+}
index c40bde946aea0f6630efc844a2f17972296e53be..c54a13586f5f8cd8bf55ffdedd5249f7206cc149 100644 (file)
@@ -68,9 +68,7 @@ public class AppActionTest {
   @Test
   public void should_generate_app_init_info() throws Exception {
     AppAction app = new AppAction(languages, ruleRepositories, i18n, debtModel, profileLoader);
-    WsTester tester = new WsTester(new RulesWebService(
-      new SearchAction(null, null, null), mock(ShowAction.class), mock(TagsAction.class), mock(CreateAction.class),
-      app, mock(UpdateAction.class), mock(DeleteAction.class)));
+    WsTester tester = new WsTester(new RulesWebService(app));
 
     MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
 
index 5043126e12f1d474b9420cea37bb5b341443e5ae..002da0ff0ca97632bf72597e0581868f43255b63 100644 (file)
@@ -29,7 +29,6 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.server.rule.RuleService;
 import org.sonar.server.ws.WsTester;
 
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
 @RunWith(MockitoJUnitRunner.class)
@@ -42,8 +41,7 @@ public class DeleteActionTest {
 
   @Before
   public void setUp() throws Exception {
-    tester = new WsTester(new RulesWebService(new SearchAction(null, null, null), mock(ShowAction.class), mock(TagsAction.class), mock(CreateAction.class), mock(AppAction.class),
-      mock(UpdateAction.class), new DeleteAction(ruleService)));
+    tester = new WsTester(new RulesWebService(new DeleteAction(ruleService)));
   }
 
   @Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RepositoriesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RepositoriesActionTest.java
new file mode 100644 (file)
index 0000000..7f059be
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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.rule.ws;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.server.rule.RuleRepositories;
+import org.sonar.server.ws.WsTester;
+import org.sonar.server.ws.WsTester.TestRequest;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class RepositoriesActionTest {
+
+  private WsTester tester;
+
+  @Mock
+  private RuleRepositories repositories;
+
+  @Before
+  public void setUp() {
+    tester = new WsTester(new RulesWebService(new RepositoriesAction(repositories)));
+
+    RuleRepositories.Repository repo1 = mock(RuleRepositories.Repository.class);
+    when(repo1.key()).thenReturn("xoo");
+    when(repo1.name()).thenReturn("SonarQube");
+    when(repo1.language()).thenReturn("xoo");
+
+    RuleRepositories.Repository repo2 = mock(RuleRepositories.Repository.class);
+    when(repo2.key()).thenReturn("squid");
+    when(repo2.name()).thenReturn("SonarQube");
+    when(repo2.language()).thenReturn("ws");
+
+    RuleRepositories.Repository repo3 = mock(RuleRepositories.Repository.class);
+    when(repo3.key()).thenReturn("common-ws");
+    when(repo3.name()).thenReturn("SonarQube Common");
+    when(repo3.language()).thenReturn("ws");
+
+    when(repositories.repositories()).thenReturn(ImmutableList.of(repo1, repo2, repo3));
+    when(repositories.repositoriesForLang("xoo")).thenReturn(ImmutableList.of(repo1));
+    when(repositories.repositoriesForLang("ws")).thenReturn(ImmutableList.of(repo2, repo3));
+  }
+
+  @Test
+  public void should_list_repositories() throws Exception {
+
+    tester = new WsTester(new RulesWebService(new RepositoriesAction(repositories)));
+
+    newRequest().execute().assertJson(this.getClass(), "repositories.json");
+    newRequest().setParam("language", "xoo").execute().assertJson(this.getClass(), "repositories_xoo.json");
+    newRequest().setParam("language", "ws").execute().assertJson(this.getClass(), "repositories_ws.json");
+    newRequest().setParam("q", "common").execute().assertJson(this.getClass(), "repositories_common.json");
+    newRequest().setParam("q", "squid").execute().assertJson(this.getClass(), "repositories_squid.json");
+    newRequest().setParam("q", "sonar").execute().assertJson(this.getClass(), "repositories.json");
+    newRequest().setParam("ps", "2").execute().assertJson(this.getClass(), "repositories_limited.json");
+    newRequest().setParam("ps", "3").execute().assertJson(this.getClass(), "repositories.json");
+    newRequest().setParam("ps", "100").execute().assertJson(this.getClass(), "repositories.json");
+  }
+
+  protected TestRequest newRequest() {
+    return tester.newGetRequest("api/rules", "repositories");
+  }
+}
index 97cb91a606b84fc23b10de658fc8ac3e161621d1..e209139529570d665e728d7e235b304ca8da109e 100644 (file)
@@ -92,13 +92,14 @@ public class RulesWebServiceMediumTest {
     WebService.Controller controller = context.controller(API_ENDPOINT);
 
     assertThat(controller).isNotNull();
-    assertThat(controller.actions()).hasSize(7);
+    assertThat(controller.actions()).hasSize(8);
     assertThat(controller.action(API_SEARCH_METHOD)).isNotNull();
     assertThat(controller.action(API_SHOW_METHOD)).isNotNull();
     assertThat(controller.action(API_TAGS_METHOD)).isNotNull();
     assertThat(controller.action("update")).isNotNull();
     assertThat(controller.action("create")).isNotNull();
     assertThat(controller.action("delete")).isNotNull();
+    assertThat(controller.action("repositories")).isNotNull();
     assertThat(controller.action("app")).isNotNull();
   }
 
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories.json
new file mode 100644 (file)
index 0000000..3635fef
--- /dev/null
@@ -0,0 +1,19 @@
+{
+  "repositories": [
+    {
+      "key": "squid",
+      "name": "SonarQube",
+      "language": "ws"
+    },
+    {
+      "key": "xoo",
+      "name": "SonarQube",
+      "language": "xoo"
+    },
+    {
+      "key": "common-ws",
+      "name": "SonarQube Common",
+      "language": "ws"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_common.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_common.json
new file mode 100644 (file)
index 0000000..e572f33
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "repositories": [
+    {
+      "key": "common-ws",
+      "name": "SonarQube Common",
+      "language": "ws"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_limited.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_limited.json
new file mode 100644 (file)
index 0000000..bb30a98
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "repositories": [
+    {
+      "key": "squid",
+      "name": "SonarQube",
+      "language": "ws"
+    },
+    {
+      "key": "xoo",
+      "name": "SonarQube",
+      "language": "xoo"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_squid.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_squid.json
new file mode 100644 (file)
index 0000000..8e8a170
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "repositories": [
+    {
+      "key": "squid",
+      "name": "SonarQube",
+      "language": "ws"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_ws.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_ws.json
new file mode 100644 (file)
index 0000000..df797d1
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "repositories": [
+    {
+      "key": "squid",
+      "name": "SonarQube",
+      "language": "ws"
+    },
+    {
+      "key": "common-ws",
+      "name": "SonarQube Common",
+      "language": "ws"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_xoo.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RepositoriesActionTest/repositories_xoo.json
new file mode 100644 (file)
index 0000000..f15c319
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "repositories": [
+    {
+      "key": "xoo",
+      "name": "SonarQube",
+      "language": "xoo"
+    }
+  ]
+}
\ No newline at end of file