Skip to content

Commit

Permalink
SONAR-6017 Add api/rules/repositories action to list rule repositorie…
Browse files Browse the repository at this point in the history
…s (with criteria)
  • Loading branch information
jblievremont committed Jan 20, 2015
1 parent b3a9a07 commit 0d24e18
Show file tree
Hide file tree
Showing 22 changed files with 353 additions and 49 deletions.
Expand Up @@ -264,6 +264,7 @@
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;
Expand Down Expand Up @@ -558,6 +559,7 @@ void startLevel4Components(ComponentContainer pico) {
pico.addSingleton(TagsAction.class);
pico.addSingleton(RuleMapping.class);
pico.addSingleton(ActiveRuleCompleter.class);
pico.addSingleton(RepositoriesAction.class);
pico.addSingleton(AppAction.class);

// languages
Expand Down
Expand Up @@ -28,7 +28,6 @@
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;
Expand All @@ -45,7 +44,7 @@
/**
* @since 4.4
*/
public class AppAction implements RequestHandler {
public class AppAction implements RulesAction {

private final Languages languages;
private final RuleRepositories ruleRepositories;
Expand Down Expand Up @@ -148,7 +147,8 @@ private void addCharacteristics(JsonWriter json) {
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)
Expand Down
Expand Up @@ -25,7 +25,6 @@
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;
Expand All @@ -42,7 +41,7 @@
/**
* @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";
Expand All @@ -63,7 +62,8 @@ public CreateAction(RuleService service, RuleMapping mapping) {
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")
Expand Down
Expand Up @@ -22,15 +22,14 @@

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;

/**
* @since 4.4
*/
public class DeleteAction implements RequestHandler {
public class DeleteAction implements RulesAction {

public static final String PARAM_KEY = "key";

Expand All @@ -40,7 +39,8 @@ public DeleteAction(RuleService service) {
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")
Expand Down
@@ -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");
}

}
@@ -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);
}
Expand Up @@ -23,23 +23,10 @@

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
Expand All @@ -48,13 +35,9 @@ public void define(Context context) {
.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();
}
Expand Down
Expand Up @@ -47,7 +47,7 @@
/**
* @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";
Expand Down
Expand Up @@ -22,7 +22,6 @@
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;
Expand All @@ -33,7 +32,7 @@
/**
* @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";
Expand All @@ -48,7 +47,8 @@ public ShowAction(RuleService service, ActiveRuleCompleter activeRuleCompleter,
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")
Expand Down
Expand Up @@ -21,7 +21,6 @@

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;
Expand All @@ -30,15 +29,16 @@

import java.util.Set;

public class TagsAction implements RequestHandler {
public class TagsAction implements RulesAction {

private final RuleService service;

public TagsAction(RuleService service) {
this.service = service;
}

void define(WebService.NewController controller) {
@Override
public void define(WebService.NewController controller) {
NewAction action = controller
.createAction("tags")
.setDescription("List rule tags")
Expand Down
Expand Up @@ -28,7 +28,6 @@
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;
Expand All @@ -38,7 +37,7 @@
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";
Expand All @@ -61,7 +60,8 @@ public UpdateAction(RuleService service, RuleMapping mapping) {
this.mapping = mapping;
}

void define(WebService.NewController controller) {
@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller
.createAction("update")
.setPost(true)
Expand Down
@@ -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"}
]
}

0 comments on commit 0d24e18

Please sign in to comment.