From b3a9a07dd933ce2fa4b41bcfdb28ef58161ee7a8 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Tue, 20 Jan 2015 11:52:13 +0100 Subject: [PATCH] SONAR-6017 Add WS to list supported languages --- .../sonar/server/language/ws/LanguageWs.java | 46 ++++++ .../sonar/server/language/ws/ListAction.java | 96 +++++++++++++ .../server/language/ws/package-info.java | 23 +++ .../server/platform/ServerComponents.java | 10 +- .../server/language/ws/example-list.json | 9 ++ .../server/language/ws/LanguageWsTest.java | 135 ++++++++++++++++++ .../language/ws/LanguageWsTest/list.json | 8 ++ .../ws/LanguageWsTest/list_filtered_key.json | 5 + .../ws/LanguageWsTest/list_filtered_name.json | 7 + .../ws/LanguageWsTest/list_limited.json | 6 + 10 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/language/ws/LanguageWs.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/language/ws/package-info.java create mode 100644 server/sonar-server/src/main/resources/org/sonar/server/language/ws/example-list.json create mode 100644 server/sonar-server/src/test/java/org/sonar/server/language/ws/LanguageWsTest.java create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_filtered_key.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_filtered_name.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_limited.json diff --git a/server/sonar-server/src/main/java/org/sonar/server/language/ws/LanguageWs.java b/server/sonar-server/src/main/java/org/sonar/server/language/ws/LanguageWs.java new file mode 100644 index 00000000000..cc903c6ea7e --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/language/ws/LanguageWs.java @@ -0,0 +1,46 @@ +/* + * 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.language.ws; + +import org.sonar.api.server.ws.WebService; + +/** + * @since 5.1 + */ +public class LanguageWs implements WebService { + + private final ListAction list; + + public LanguageWs(ListAction list) { + this.list = list; + } + + @Override + public void define(Context context) { + NewController languages = context.createController("api/languages") + .setDescription("Programming languages") + .setSince("5.1"); + + list.define(languages); + + languages.done(); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java new file mode 100644 index 00000000000..fcd4326e48c --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java @@ -0,0 +1,96 @@ +/* + * 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.language.ws; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.io.Resources; +import org.sonar.api.resources.Language; +import org.sonar.api.resources.Languages; +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; +import org.sonar.api.utils.text.JsonWriter; + +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 ListAction implements RequestHandler { + + private static final String MATCH_ALL = ".*"; + private final Languages languages; + + public ListAction(Languages languages) { + this.languages = languages; + } + + @Override + public void handle(Request request, Response response) throws Exception { + String query = request.param("q"); + int pageSize = request.mandatoryParamAsInt("ps"); + + JsonWriter json = response.newJsonWriter().beginObject().name("languages").beginArray(); + for (Language language : listMatchingLanguages(query, pageSize)) { + json.beginObject().prop("key", language.getKey()).prop("name", language.getName()).endObject(); + } + json.endArray().endObject().close(); + } + + private Collection listMatchingLanguages(@Nullable String query, int pageSize) { + Pattern pattern = Pattern.compile(query == null ? MATCH_ALL : MATCH_ALL + query + MATCH_ALL, Pattern.CASE_INSENSITIVE); + + SortedMap languagesByName = Maps.newTreeMap(); + for (Language lang : languages.all()) { + if (pattern.matcher(lang.getKey()).matches() || pattern.matcher(lang.getName()).matches()) { + languagesByName.put(lang.getName(), lang); + } + } + List result = Lists.newArrayList(languagesByName.values()); + if (pageSize > 0 && pageSize < result.size()) { + result = result.subList(0, pageSize); + } + return result; + } + + void define(WebService.NewController controller) { + NewAction action = controller.createAction("list") + .setDescription("List supported programming languages") + .setHandler(this) + .setResponseExample(Resources.getResource(getClass(), "example-list.json")); + + action.createParam("q") + .setDescription("A pattern to match language keys/names against") + .setExampleValue("java"); + action.createParam("ps") + .setDescription("The size of the list to return, 0 for all languages") + .setExampleValue("25") + .setDefaultValue("0"); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/language/ws/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/language/ws/package-info.java new file mode 100644 index 00000000000..1f5a4808967 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/language/ws/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.language.ws; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index 57fbf498be7..5d21aaefe5d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -46,7 +46,6 @@ import org.sonar.core.config.Logback; import org.sonar.core.i18n.DefaultI18n; import org.sonar.core.i18n.RuleI18nManager; import org.sonar.core.issue.IssueFilterSerializer; -import org.sonar.server.issue.notification.IssueNotifications; import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.workflow.FunctionExecutor; import org.sonar.core.issue.workflow.IssueWorkflow; @@ -168,6 +167,7 @@ import org.sonar.server.issue.index.IssueIndexer; import org.sonar.server.issue.index.IssueNormalizer; import org.sonar.server.issue.notification.ChangesOnMyIssueNotificationDispatcher; import org.sonar.server.issue.notification.IssueChangesEmailTemplate; +import org.sonar.server.issue.notification.IssueNotifications; import org.sonar.server.issue.notification.NewFalsePositiveNotificationDispatcher; import org.sonar.server.issue.notification.NewIssuesEmailTemplate; import org.sonar.server.issue.notification.NewIssuesNotificationDispatcher; @@ -176,6 +176,8 @@ import org.sonar.server.issue.ws.IssueActionsWriter; import org.sonar.server.issue.ws.IssueShowAction; import org.sonar.server.issue.ws.IssuesWs; import org.sonar.server.issue.ws.SetTagsAction; +import org.sonar.server.language.ws.LanguageWs; +import org.sonar.server.language.ws.ListAction; import org.sonar.server.measure.MeasureFilterEngine; import org.sonar.server.measure.MeasureFilterExecutor; import org.sonar.server.measure.MeasureFilterFactory; @@ -482,7 +484,6 @@ class ServerComponents { void startLevel4Components(ComponentContainer pico) { pico.addSingleton(PluginDownloader.class); pico.addSingleton(ChartFactory.class); - pico.addSingleton(Languages.class); pico.addSingleton(Views.class); pico.addSingleton(ResourceTypes.class); pico.addSingleton(SettingsChangeNotifier.class); @@ -559,6 +560,11 @@ class ServerComponents { pico.addSingleton(ActiveRuleCompleter.class); pico.addSingleton(AppAction.class); + // languages + pico.addSingleton(Languages.class); + pico.addSingleton(LanguageWs.class); + pico.addSingleton(ListAction.class); + // activity pico.addSingleton(ActivitiesWebService.class); pico.addSingleton(org.sonar.server.activity.ws.SearchAction.class); diff --git a/server/sonar-server/src/main/resources/org/sonar/server/language/ws/example-list.json b/server/sonar-server/src/main/resources/org/sonar/server/language/ws/example-list.json new file mode 100644 index 00000000000..0ead938d72f --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/language/ws/example-list.json @@ -0,0 +1,9 @@ +{ + "languages": [ + {"key": "c", "name": "C"}, + {"key": "cpp", "name": "C++"}, + {"key": "java", "name": "Java"}, + {"key": "js", "name": "JavaScript"}, + {"key": "python", "name": "Python"} + ] +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/language/ws/LanguageWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/language/ws/LanguageWsTest.java new file mode 100644 index 00000000000..e2de7c20e7e --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/language/ws/LanguageWsTest.java @@ -0,0 +1,135 @@ +/* + * 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.language.ws; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.resources.AbstractLanguage; +import org.sonar.api.resources.Language; +import org.sonar.api.resources.Languages; +import org.sonar.api.server.ws.WebService.Action; +import org.sonar.api.server.ws.WebService.Controller; +import org.sonar.server.ws.WsTester; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(MockitoJUnitRunner.class) +public class LanguageWsTest { + + private static final String CONTROLLER_LANGUAGES = "api/languages"; + private static final String ACTION_LIST = "list"; + + @Mock + private Languages languages; + + WsTester tester; + + @Before + public void setUp() { + Mockito.when(languages.all()).thenReturn(new Language[] { + new Ook(), + new LolCode(), + new Whitespace(), + new ArnoldC() + }); + tester = new WsTester(new LanguageWs(new ListAction(languages))); + } + + @Test + public void should_be_well_defined() throws Exception { + Controller controller = tester.controller(CONTROLLER_LANGUAGES); + assertThat(controller).isNotNull(); + assertThat(controller.description()).isNotEmpty(); + assertThat(controller.isInternal()).isFalse(); + assertThat(controller.path()).isEqualTo(CONTROLLER_LANGUAGES); + assertThat(controller.since()).isEqualTo("5.1"); + assertThat(controller.actions()).hasSize(1); + + Action list = controller.action(ACTION_LIST); + assertThat(list).isNotNull(); + assertThat(list.description()).isNotEmpty(); + assertThat(list.handler()).isInstanceOf(ListAction.class); + assertThat(list.isInternal()).isFalse(); + assertThat(list.isPost()).isFalse(); + assertThat(list.responseExampleAsString()).isNotEmpty(); + assertThat(list.params()).hasSize(2); + } + + @Test + public void should_list_languages() throws Exception { + tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST).execute().assertJson(this.getClass(), "list.json"); + + tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST) + .setParam("ps", "2") + .execute().assertJson(this.getClass(), "list_limited.json"); + tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST) + .setParam("ps", "4") + .execute().assertJson(this.getClass(), "list.json"); + tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST) + .setParam("ps", "10") + .execute().assertJson(this.getClass(), "list.json"); + + tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST) + .setParam("q", "ws") + .execute().assertJson(this.getClass(), "list_filtered_key.json"); + tester.newGetRequest(CONTROLLER_LANGUAGES, ACTION_LIST) + .setParam("q", "o") + .execute().assertJson(this.getClass(), "list_filtered_name.json"); + } + + static abstract class TestLanguage extends AbstractLanguage { + public TestLanguage(String key, String language) { + super(key, language); + } + + @Override + public String[] getFileSuffixes() { + return new String[0]; + } + } + + static class Ook extends TestLanguage { + public Ook() { + super("ook", "Ook!"); + } + } + + static class LolCode extends TestLanguage { + public LolCode() { + super("lol", "LOLCODE"); + } + } + + static class Whitespace extends TestLanguage { + public Whitespace() { + super("ws", "Whitespace"); + } + } + + static class ArnoldC extends TestLanguage { + public ArnoldC() { + super("ac", "ArnoldC"); + } + } +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list.json b/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list.json new file mode 100644 index 00000000000..32190c0008f --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list.json @@ -0,0 +1,8 @@ +{ + "languages": [ + {"key": "ac", "name": "ArnoldC"}, + {"key": "lol", "name": "LOLCODE"}, + {"key": "ook", "name": "Ook!"}, + {"key": "ws", "name": "Whitespace"} + ] +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_filtered_key.json b/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_filtered_key.json new file mode 100644 index 00000000000..187ce02ada0 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_filtered_key.json @@ -0,0 +1,5 @@ +{ + "languages": [ + {"key": "ws", "name": "Whitespace"} + ] +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_filtered_name.json b/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_filtered_name.json new file mode 100644 index 00000000000..9f167f6f77e --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_filtered_name.json @@ -0,0 +1,7 @@ +{ + "languages": [ + {"key": "ac", "name": "ArnoldC"}, + {"key": "lol", "name": "LOLCODE"}, + {"key": "ook", "name": "Ook!"} + ] +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_limited.json b/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_limited.json new file mode 100644 index 00000000000..513d8b14de4 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/language/ws/LanguageWsTest/list_limited.json @@ -0,0 +1,6 @@ +{ + "languages": [ + {"key": "ac", "name": "ArnoldC"}, + {"key": "lol", "name": "LOLCODE"} + ] +} -- 2.39.5