--- /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.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();
+ }
+
+}
--- /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.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<Language> listMatchingLanguages(@Nullable String query, int pageSize) {
+ Pattern pattern = Pattern.compile(query == null ? MATCH_ALL : MATCH_ALL + query + MATCH_ALL, Pattern.CASE_INSENSITIVE);
+
+ SortedMap<String, Language> 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<Language> 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");
+ }
+
+}
--- /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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.server.language.ws;
+
+import javax.annotation.ParametersAreNonnullByDefault;
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;
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;
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;
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);
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);
--- /dev/null
+{
+ "languages": [
+ {"key": "c", "name": "C"},
+ {"key": "cpp", "name": "C++"},
+ {"key": "java", "name": "Java"},
+ {"key": "js", "name": "JavaScript"},
+ {"key": "python", "name": "Python"}
+ ]
+}
--- /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.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");
+ }
+ }
+}
--- /dev/null
+{
+ "languages": [
+ {"key": "ac", "name": "ArnoldC"},
+ {"key": "lol", "name": "LOLCODE"},
+ {"key": "ook", "name": "Ook!"},
+ {"key": "ws", "name": "Whitespace"}
+ ]
+}
--- /dev/null
+{
+ "languages": [
+ {"key": "ws", "name": "Whitespace"}
+ ]
+}
--- /dev/null
+{
+ "languages": [
+ {"key": "ac", "name": "ArnoldC"},
+ {"key": "lol", "name": "LOLCODE"},
+ {"key": "ook", "name": "Ook!"}
+ ]
+}
--- /dev/null
+{
+ "languages": [
+ {"key": "ac", "name": "ArnoldC"},
+ {"key": "lol", "name": "LOLCODE"}
+ ]
+}