aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2017-01-23 18:12:30 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2017-01-24 18:36:49 +0100
commit17cbda842774f2331d65a53cd645ba2dcd2d154a (patch)
treeda8494229f2834ccb9b920b7822dc63ef45959f3
parent4fc7e70ddb24c863a2686b954676790adf071aa7 (diff)
downloadsonarqube-17cbda842774f2331d65a53cd645ba2dcd2d154a.tar.gz
sonarqube-17cbda842774f2331d65a53cd645ba2dcd2d154a.zip
SONAR-7298 Deprecate and rewrite WS api/projects/index in Java
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/ws/IndexAction.java157
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java54
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsModule.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/property/ws/IndexAction.java7
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/ws/DeprecatedRestWebServiceFilter.java3
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/project/ws/index-example.json (renamed from server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-index.json)0
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/project/ws/IndexActionTest.java199
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsModuleTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java65
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/empty.json3
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/return_only_projects_authorized_for_user.json16
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_id.json9
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_key.json9
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_name.json16
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_projects.json23
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_projects_with_modules.json30
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ComponentDao.java10
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ComponentMapper.java2
-rw-r--r--sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml20
-rw-r--r--sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java28
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/server/ws/RailsHandler.java23
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsWsParameters.java1
23 files changed, 529 insertions, 152 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/IndexAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/IndexAction.java
new file mode 100644
index 00000000000..fb9ea3c316e
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/IndexAction.java
@@ -0,0 +1,157 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.server.project.ws;
+
+import com.google.common.io.Resources;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+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.util.stream.Collectors;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.user.UserSession;
+
+import static java.util.Optional.ofNullable;
+import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+import static org.sonarqube.ws.client.project.ProjectsWsParameters.ACTION_INDEX;
+
+/**
+ * This web service is used by old version of SonarLint.
+ */
+public class IndexAction implements ProjectsWsAction {
+
+ private static final String PARAM_KEY = "key";
+ private static final String PARAM_SEARCH = "search";
+ private static final String PARAM_SUB_PROJECTS = "subprojects";
+ private static final String PARAM_FORMAT = "format";
+
+ private final DbClient dbClient;
+ private final UserSession userSession;
+
+ public IndexAction(DbClient dbClient, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction(ACTION_INDEX)
+ .setDescription("This web service is deprecated, please use api/components/search instead")
+ .setSince("2.10")
+ .setDeprecatedSince("6.3")
+ .setHandler(this)
+ .setResponseExample(Resources.getResource(this.getClass(), "index-example.json"));
+ action.createParam(PARAM_KEY)
+ .setDescription("key or id of the project")
+ .setExampleValue(KEY_PROJECT_EXAMPLE_001);
+ action.createParam(PARAM_SEARCH)
+ .setDescription("Substring of project name, case insensitive. Ignored if the parameter key is set")
+ .setExampleValue("Sonar");
+ action.createParam(PARAM_SUB_PROJECTS)
+ .setDescription("Load sub-projects. Ignored if the parameter key is set")
+ .setDefaultValue("false")
+ .setBooleanPossibleValues();
+ action.createParam(PARAM_FORMAT)
+ .setDescription("Only json response format is available")
+ .setPossibleValues("json");
+ addRemovedParameter("desc", action);
+ addRemovedParameter("views", action);
+ addRemovedParameter("libs", action);
+ addRemovedParameter("versions", action);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ List<ComponentDto> projects = getAuthorizedProjects(dbSession, searchProjects(dbSession, request));
+ JsonWriter json = response.newJsonWriter();
+ json.beginArray();
+ for (ComponentDto project : projects) {
+ addProject(json, project);
+ }
+ json.endArray();
+ json.close();
+ }
+ }
+
+ private Optional<ComponentDto> getProjectByKeyOrId(DbSession dbSession, String component) {
+ try {
+ Long componentId = Long.parseLong(component);
+ return ofNullable(dbClient.componentDao().selectById(dbSession, componentId).orNull());
+ } catch (NumberFormatException e) {
+ return ofNullable(dbClient.componentDao().selectByKey(dbSession, component).orNull());
+ }
+ }
+
+ private List<ComponentDto> searchProjects(DbSession dbSession, Request request) {
+ String projectKey = request.param(PARAM_KEY);
+ List<ComponentDto> projects = new ArrayList<>();
+ if (projectKey != null) {
+ getProjectByKeyOrId(dbSession, projectKey).ifPresent(projects::add);
+ } else {
+ String nameQuery = request.param(PARAM_SEARCH);
+ boolean includeModules = request.paramAsBoolean(PARAM_SUB_PROJECTS);
+ projects.addAll(dbClient.componentDao().selectProjectsByNameQuery(dbSession, nameQuery, includeModules));
+ }
+ return projects;
+ }
+
+ private List<ComponentDto> getAuthorizedProjects(DbSession dbSession, List<ComponentDto> projectDtos) {
+ if (projectDtos.isEmpty()) {
+ return Collections.emptyList();
+ }
+ Map<String, Long> projectIdsByUuids = projectDtos.stream().collect(uniqueIndex(ComponentDto::uuid, ComponentDto::getId));
+ Set<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(dbSession,
+ projectDtos.stream().map(ComponentDto::getId).collect(toList()),
+ userSession.getUserId(), USER);
+ return projectDtos.stream()
+ .filter(c -> authorizedProjectIds.contains(projectIdsByUuids.get(c.projectUuid())))
+ .collect(Collectors.toList());
+ }
+
+ private static void addProject(JsonWriter json, ComponentDto project) {
+ json.beginObject()
+ .prop("id", project.getId())
+ .prop("k", project.getKey())
+ .prop("nm", project.name())
+ .prop("sc", project.scope())
+ .prop("qu", project.qualifier())
+ .endObject();
+ }
+
+ private static void addRemovedParameter(String key, WebService.NewAction action) {
+ action.createParam(key)
+ .setDescription("Since 6.3, this parameter has no effect")
+ .setDeprecatedKey("6.3");
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java
index e6a42102996..b15f7362dac 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java
@@ -19,17 +19,12 @@
*/
package org.sonar.server.project.ws;
-import com.google.common.io.Resources;
import java.util.Arrays;
-import org.sonar.api.server.ws.RailsHandler;
import org.sonar.api.server.ws.WebService;
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+import static org.sonarqube.ws.client.project.ProjectsWsParameters.CONTROLLER;
public class ProjectsWs implements WebService {
- public static final String ENDPOINT = "api/projects";
- private static final String FALSE = "false";
- private static final String TRUE = "true";
private final ProjectsWsAction[] actions;
@@ -39,56 +34,11 @@ public class ProjectsWs implements WebService {
@Override
public void define(Context context) {
- NewController controller = context.createController(ENDPOINT)
+ NewController controller = context.createController(CONTROLLER)
.setSince("2.10")
.setDescription("Manage project existence.");
-
- defineIndexAction(controller);
Arrays.stream(actions).forEach(action -> action.define(controller));
controller.done();
}
- private void defineIndexAction(NewController controller) {
- WebService.NewAction action = controller.createAction("index")
- .setDescription("Search for projects")
- .setSince("2.10")
- .setHandler(RailsHandler.INSTANCE)
- .setResponseExample(Resources.getResource(this.getClass(), "projects-example-index.json"));
-
- action.createParam("key")
- .setDescription("id or key of the project")
- .setExampleValue(KEY_PROJECT_EXAMPLE_001);
-
- action.createParam("search")
- .setDescription("Substring of project name, case insensitive")
- .setExampleValue("Sonar");
-
- action.createParam("desc")
- .setDescription("Load project description")
- .setDefaultValue(TRUE)
- .setBooleanPossibleValues();
-
- action.createParam("subprojects")
- .setDescription("Load sub-projects. Ignored if the parameter key is set")
- .setDefaultValue(FALSE)
- .setBooleanPossibleValues();
-
- action.createParam("views")
- .setDescription("Load views and sub-views. Ignored if the parameter key is set")
- .setDefaultValue(FALSE)
- .setBooleanPossibleValues();
-
- action.createParam("libs")
- .setDescription("Load libraries. Ignored if the parameter key is set")
- .setDefaultValue(FALSE)
- .setBooleanPossibleValues();
-
- action.createParam("versions")
- .setDescription("Load version")
- .setDefaultValue(FALSE)
- .setPossibleValues(TRUE, FALSE, "last");
-
- RailsHandler.addFormatParam(action);
- }
-
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsModule.java
index e3e5138bf55..8a06f08e34a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsModule.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsModule.java
@@ -27,6 +27,7 @@ public class ProjectsWsModule extends Module {
add(
ProjectsWs.class,
CreateAction.class,
+ IndexAction.class,
BulkDeleteAction.class,
DeleteAction.class,
GhostsAction.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/property/ws/IndexAction.java b/server/sonar-server/src/main/java/org/sonar/server/property/ws/IndexAction.java
index c4205ff3f54..cdeb026538b 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/property/ws/IndexAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/property/ws/IndexAction.java
@@ -49,8 +49,6 @@ import org.sonar.server.ws.WsAction;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.sonar.api.PropertyType.PROPERTY_SET;
-import static org.sonar.api.server.ws.RailsHandler.PARAM_FORMAT;
-import static org.sonar.api.server.ws.RailsHandler.addJsonOnlyFormatParam;
import static org.sonar.api.web.UserRole.ADMIN;
import static org.sonar.server.setting.ws.SettingsPermissionPredicates.DOT_LICENSE;
import static org.sonar.server.setting.ws.SettingsPermissionPredicates.DOT_SECURED;
@@ -64,6 +62,7 @@ public class IndexAction implements WsAction {
public static final String PARAM_ID = "id";
public static final String PARAM_COMPONENT = "resource";
+ public static final String PARAM_FORMAT = "format";
private final DbClient dbClient;
private final UserSession userSession;
@@ -89,7 +88,9 @@ public class IndexAction implements WsAction {
action.createParam(PARAM_COMPONENT)
.setDescription("Component key or database id")
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
- addJsonOnlyFormatParam(action);
+ action.createParam(PARAM_FORMAT)
+ .setDescription("Only json response format is available")
+ .setPossibleValues("json");
}
@Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ws/DeprecatedRestWebServiceFilter.java b/server/sonar-server/src/main/java/org/sonar/server/ws/DeprecatedRestWebServiceFilter.java
index c3749bd9dc7..2e54e06f42a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/ws/DeprecatedRestWebServiceFilter.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/ws/DeprecatedRestWebServiceFilter.java
@@ -42,7 +42,6 @@ import org.sonar.server.property.ws.IndexAction;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.sonar.api.server.ws.RailsHandler.PARAM_FORMAT;
import static org.sonar.server.property.ws.PropertiesWs.CONTROLLER_PROPERTIES;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_RESET;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_SET;
@@ -172,7 +171,7 @@ public class DeprecatedRestWebServiceFilter extends ServletFilter {
private void handleGet(Optional<String> key, Optional<String> component) {
addParameterIfPresent(IndexAction.PARAM_ID, key);
addParameterIfPresent(IndexAction.PARAM_COMPONENT, component);
- addParameterIfPresent(PARAM_FORMAT, readParam(PARAM_FORMAT));
+ addParameterIfPresent(IndexAction.PARAM_FORMAT, readParam(IndexAction.PARAM_FORMAT));
redirectedPath = CONTROLLER_PROPERTIES + "/index";
redirectedMethod = "GET";
}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-index.json b/server/sonar-server/src/main/resources/org/sonar/server/project/ws/index-example.json
index a5d82ab23c3..a5d82ab23c3 100644
--- a/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-index.json
+++ b/server/sonar-server/src/main/resources/org/sonar/server/project/ws/index-example.json
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java
index 247cd7a1856..52c0c754664 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java
@@ -71,6 +71,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.server.project.ws.DeleteAction.PARAM_ID;
import static org.sonar.server.project.ws.DeleteAction.PARAM_KEY;
+import static org.sonarqube.ws.client.project.ProjectsWsParameters.CONTROLLER;
public class DeleteActionTest {
@@ -278,6 +279,6 @@ public class DeleteActionTest {
}
private WsTester.TestRequest newRequest() {
- return ws.newPostRequest(ProjectsWs.ENDPOINT, ACTION);
+ return ws.newPostRequest(CONTROLLER, ACTION);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/IndexActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/IndexActionTest.java
new file mode 100644
index 00000000000..a3be3e099bd
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/IndexActionTest.java
@@ -0,0 +1,199 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.server.project.ws;
+
+import java.util.Arrays;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.core.util.Protobuf.setNullable;
+import static org.sonar.db.component.ComponentTesting.newModuleDto;
+import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class IndexActionTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+
+ private DbClient dbClient = db.getDbClient();
+
+ private UserDto user;
+
+ private WsActionTester ws = new WsActionTester(new IndexAction(dbClient, userSession));
+
+ @Before
+ public void setUp() {
+ user = db.users().insertUser("john");
+ userSession.login(user);
+ }
+
+ @Test
+ public void search_all_projects() throws Exception {
+ insertProjectsAuthorizedForUser(
+ newProjectDto(db.getDefaultOrganization()).setKey("org.jenkins-ci.plugins:sonar").setName("Jenkins Sonar Plugin"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-ant-task").setName("Sonar Ant Task"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-build-breaker-plugin").setName("Sonar Build Breaker Plugin"));
+
+ String result = call(null, null, null);
+
+ verifyResult(result, "search_projects.json");
+ }
+
+ @Test
+ public void search_projects_with_modules() throws Exception {
+ ComponentDto project1 = newProjectDto(db.getDefaultOrganization()).setKey("org.jenkins-ci.plugins:sonar").setName("Jenkins Sonar Plugin");
+ ComponentDto project2 = newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-ant-task").setName("Sonar Ant Task");
+ insertProjectsAuthorizedForUser(project1, project2);
+ db.components().insertComponents(
+ newModuleDto(project1).setKey("org.jenkins-ci.plugins:sonar-common").setName("Common"),
+ newModuleDto(project2).setKey("org.codehaus.sonar-plugins:sonar-ant-db").setName("Ant DB"));
+
+ String result = call(null, null, true);
+
+ verifyResult(result, "search_projects_with_modules.json");
+ }
+
+ @Test
+ public void search_project_by_key() throws Exception {
+ insertProjectsAuthorizedForUser(
+ newProjectDto(db.getDefaultOrganization()).setKey("org.jenkins-ci.plugins:sonar").setName("Jenkins Sonar Plugin"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-ant-task").setName("Sonar Ant Task"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-build-breaker-plugin").setName("Sonar Build Breaker Plugin"));
+
+ String result = call("org.jenkins-ci.plugins:sonar", null, null);
+
+ verifyResult(result, "search_project_by_key.json");
+ }
+
+ @Test
+ public void search_project_by_id() throws Exception {
+ ComponentDto project = newProjectDto(db.getDefaultOrganization()).setKey("org.jenkins-ci.plugins:sonar").setName("Jenkins Sonar Plugin");
+ insertProjectsAuthorizedForUser(
+ project,
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-ant-task").setName("Sonar Ant Task"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-build-breaker-plugin").setName("Sonar Build Breaker Plugin"));
+
+ String result = call(Long.toString(project.getId()), null, null);
+
+ verifyResult(result, "search_project_by_id.json");
+ }
+
+ @Test
+ public void search_project_by_name() throws Exception {
+ insertProjectsAuthorizedForUser(
+ newProjectDto(db.getDefaultOrganization()).setKey("org.jenkins-ci.plugins:sonar").setName("Jenkins Sonar Plugin"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-ant-task").setName("Sonar Ant Task"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-build-breaker-plugin").setName("Sonar Build Breaker Plugin"));
+
+ String result = call(null, "Plu", null);
+
+ verifyResult(result, "search_project_by_name.json");
+ }
+
+ @Test
+ public void return_empty_list_when_no_project_match_search() throws Exception {
+ insertProjectsAuthorizedForUser(
+ newProjectDto(db.getDefaultOrganization()).setKey("org.jenkins-ci.plugins:sonar").setName("Jenkins Sonar Plugin"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-ant-task").setName("Sonar Ant Task"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-build-breaker-plugin").setName("Sonar Build Breaker Plugin"));
+
+ String result = call(null, "Unknown", null);
+
+ verifyResult(result, "empty.json");
+ }
+
+ @Test
+ public void return_only_projects_authorized_for_user() throws Exception {
+ insertProjectsAuthorizedForUser(
+ newProjectDto(db.getDefaultOrganization()).setKey("org.jenkins-ci.plugins:sonar").setName("Jenkins Sonar Plugin"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-ant-task").setName("Sonar Ant Task"));
+ db.components()
+ .insertComponent(newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-build-breaker-plugin").setName("Sonar Build Breaker Plugin"));
+
+ String result = call(null, null, null);
+
+ verifyResult(result, "return_only_projects_authorized_for_user.json");
+ }
+
+ @Test
+ public void test_example() {
+ insertProjectsAuthorizedForUser(
+ newProjectDto(db.getDefaultOrganization()).setKey("org.jenkins-ci.plugins:sonar").setName("Jenkins Sonar Plugin"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-ant-task").setName("Sonar Ant Task"),
+ newProjectDto(db.getDefaultOrganization()).setKey("org.codehaus.sonar-plugins:sonar-build-breaker-plugin").setName("Sonar Build Breaker Plugin"));
+
+ String result = call(null, null, null);
+
+ assertJson(result).ignoreFields("id").isSimilarTo(ws.getDef().responseExampleAsString());
+ }
+
+ @Test
+ public void define_index_action() {
+ WebService.Action action = ws.getDef();
+ assertThat(action).isNotNull();
+ assertThat(action.responseExampleAsString()).isNotEmpty();
+ assertThat(action.params()).hasSize(8);
+ }
+
+ private String call(@Nullable String key, @Nullable String search, @Nullable Boolean subprojects) {
+ TestRequest httpRequest = ws.newRequest();
+ setNullable(key, e -> httpRequest.setParam("key", e));
+ setNullable(search, e -> httpRequest.setParam("search", e));
+ setNullable(subprojects, e -> httpRequest.setParam("subprojects", Boolean.toString(e)));
+ return httpRequest.execute().getInput();
+ }
+
+ private void insertProjectsAuthorizedForUser(ComponentDto... projects) {
+ db.components().insertComponents(projects);
+ setBrowsePermissionOnUser(projects);
+ db.commit();
+ }
+
+ private void setBrowsePermissionOnUser(ComponentDto... projects) {
+ Arrays.stream(projects).forEach(project -> db.users().insertProjectPermissionOnUser(user, UserRole.USER, project));
+ db.getSession().commit();
+ }
+
+ private void verifyResult(String json, String expectedJsonFile) {
+ assertJson(json).ignoreFields("id").isSimilarTo(getClass().getResource(getClass().getSimpleName() + "/" + expectedJsonFile));
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsModuleTest.java
index c2a2dab4b74..87215ece5d2 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsModuleTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsModuleTest.java
@@ -29,6 +29,6 @@ public class ProjectsWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new ProjectsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(2 + 8);
+ assertThat(container.size()).isEqualTo(2 + 9);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java
deleted file mode 100644
index 214e9f176e4..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.server.project.ws;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.server.ws.RailsHandler;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.db.DbClient;
-import org.sonar.server.component.ComponentCleanerService;
-import org.sonar.server.user.UserSession;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class ProjectsWsTest {
-
- WebService.Controller controller;
- WsTester ws;
-
- @Before
- public void setUp() {
- ws = new WsTester(new ProjectsWs(
- new BulkDeleteAction(mock(ComponentCleanerService.class), mock(DbClient.class), mock(UserSession.class)),
- new GhostsAction(mock(DbClient.class), mock(UserSession.class)),
- new ProvisionedAction(mock(DbClient.class), mock(UserSession.class))));
- controller = ws.controller("api/projects");
- }
-
- @Test
- public void define_controller() {
- assertThat(controller).isNotNull();
- assertThat(controller.description()).isNotEmpty();
- assertThat(controller.since()).isEqualTo("2.10");
- assertThat(controller.actions()).hasSize(4);
- }
-
- @Test
- public void define_index_action() {
- WebService.Action action = controller.action("index");
- assertThat(action).isNotNull();
- assertThat(action.handler()).isInstanceOf(RailsHandler.class);
- assertThat(action.responseExampleAsString()).isNotEmpty();
- assertThat(action.params()).hasSize(8);
- }
-
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/empty.json
new file mode 100644
index 00000000000..41b42e677b9
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/empty.json
@@ -0,0 +1,3 @@
+[
+
+]
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/return_only_projects_authorized_for_user.json b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/return_only_projects_authorized_for_user.json
new file mode 100644
index 00000000000..9bc8440f9b0
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/return_only_projects_authorized_for_user.json
@@ -0,0 +1,16 @@
+[
+ {
+ "id": 4,
+ "k": "org.jenkins-ci.plugins:sonar",
+ "nm": "Jenkins Sonar Plugin",
+ "sc": "PRJ",
+ "qu": "TRK"
+ },
+ {
+ "id": 5,
+ "k": "org.codehaus.sonar-plugins:sonar-ant-task",
+ "nm": "Sonar Ant Task",
+ "sc": "PRJ",
+ "qu": "TRK"
+ }
+]
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_id.json b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_id.json
new file mode 100644
index 00000000000..4c9d99ac462
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_id.json
@@ -0,0 +1,9 @@
+[
+ {
+ "id": "5035",
+ "k": "org.jenkins-ci.plugins:sonar",
+ "nm": "Jenkins Sonar Plugin",
+ "sc": "PRJ",
+ "qu": "TRK"
+ }
+]
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_key.json b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_key.json
new file mode 100644
index 00000000000..4c9d99ac462
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_key.json
@@ -0,0 +1,9 @@
+[
+ {
+ "id": "5035",
+ "k": "org.jenkins-ci.plugins:sonar",
+ "nm": "Jenkins Sonar Plugin",
+ "sc": "PRJ",
+ "qu": "TRK"
+ }
+]
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_name.json b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_name.json
new file mode 100644
index 00000000000..bd36e6832c3
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_project_by_name.json
@@ -0,0 +1,16 @@
+[
+ {
+ "id": 7,
+ "k": "org.jenkins-ci.plugins:sonar",
+ "nm": "Jenkins Sonar Plugin",
+ "sc": "PRJ",
+ "qu": "TRK"
+ },
+ {
+ "id": 9,
+ "k": "org.codehaus.sonar-plugins:sonar-build-breaker-plugin",
+ "nm": "Sonar Build Breaker Plugin",
+ "sc": "PRJ",
+ "qu": "TRK"
+ }
+]
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_projects.json b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_projects.json
new file mode 100644
index 00000000000..a5d82ab23c3
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_projects.json
@@ -0,0 +1,23 @@
+[
+ {
+ "id": "5035",
+ "k": "org.jenkins-ci.plugins:sonar",
+ "nm": "Jenkins Sonar Plugin",
+ "sc": "PRJ",
+ "qu": "TRK"
+ },
+ {
+ "id": "5146",
+ "k": "org.codehaus.sonar-plugins:sonar-ant-task",
+ "nm": "Sonar Ant Task",
+ "sc": "PRJ",
+ "qu": "TRK"
+ },
+ {
+ "id": "15964",
+ "k": "org.codehaus.sonar-plugins:sonar-build-breaker-plugin",
+ "nm": "Sonar Build Breaker Plugin",
+ "sc": "PRJ",
+ "qu": "TRK"
+ }
+]
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_projects_with_modules.json b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_projects_with_modules.json
new file mode 100644
index 00000000000..51b0c2f4872
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/project/ws/IndexActionTest/search_projects_with_modules.json
@@ -0,0 +1,30 @@
+[
+ {
+ "id": 16,
+ "k": "org.codehaus.sonar-plugins:sonar-ant-db",
+ "nm": "Ant DB",
+ "sc": "PRJ",
+ "qu": "BRC"
+ },
+ {
+ "id": 15,
+ "k": "org.jenkins-ci.plugins:sonar-common",
+ "nm": "Common",
+ "sc": "PRJ",
+ "qu": "BRC"
+ },
+ {
+ "id": 13,
+ "k": "org.jenkins-ci.plugins:sonar",
+ "nm": "Jenkins Sonar Plugin",
+ "sc": "PRJ",
+ "qu": "TRK"
+ },
+ {
+ "id": 14,
+ "k": "org.codehaus.sonar-plugins:sonar-ant-task",
+ "nm": "Sonar Ant Task",
+ "sc": "PRJ",
+ "qu": "TRK"
+ }
+]
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentDao.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentDao.java
index e4d2527af9b..2d892055a79 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/ComponentDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentDao.java
@@ -39,15 +39,16 @@ import org.sonar.db.Dao;
import org.sonar.db.DatabaseUtils;
import org.sonar.db.DbSession;
import org.sonar.db.RowNotFoundException;
-import org.sonar.db.WildcardPosition;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Maps.newHashMapWithExpectedSize;
import static java.util.Collections.emptyList;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.isBlank;
+import static org.sonar.db.DatabaseUtils.buildLikeValue;
import static org.sonar.db.DatabaseUtils.executeLargeInputs;
import static org.sonar.db.DatabaseUtils.executeLargeUpdates;
+import static org.sonar.db.WildcardPosition.BEFORE_AND_AFTER;
public class ComponentDao implements Dao {
@@ -239,7 +240,7 @@ public class ComponentDao implements Dao {
if (isBlank(textQuery)) {
return null;
}
- return DatabaseUtils.buildLikeValue(textQuery.toUpperCase(Locale.ENGLISH), WildcardPosition.BEFORE_AND_AFTER);
+ return DatabaseUtils.buildLikeValue(textQuery.toUpperCase(Locale.ENGLISH), BEFORE_AND_AFTER);
}
public List<ComponentDto> selectGhostProjects(DbSession session, int offset, int limit, @Nullable String query) {
@@ -288,6 +289,11 @@ public class ComponentDao implements Dao {
return new HashSet<>(mapper(dbSession).selectComponentsByQualifiers(qualifiers));
}
+ public List<ComponentDto> selectProjectsByNameQuery(DbSession dbSession, @Nullable String nameQuery, boolean includeModules) {
+ String nameQueryForSql = nameQuery == null ? null : buildLikeValue(nameQuery, BEFORE_AND_AFTER).toUpperCase(Locale.ENGLISH);
+ return mapper(dbSession).selectProjectsByNameQuery(nameQueryForSql, includeModules);
+ }
+
private static void addPartialQueryParameterIfNotNull(Map<String, Object> parameters, @Nullable String keyOrNameFilter) {
// TODO rely on resource_index table and match exactly the key
if (keyOrNameFilter != null) {
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentMapper.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentMapper.java
index 101ac0f26c6..7cf6f163b49 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/ComponentMapper.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentMapper.java
@@ -117,6 +117,8 @@ public interface ComponentMapper {
List<ComponentDto> selectComponentsHavingSameKeyOrderedById(String key);
+ List<ComponentDto> selectProjectsByNameQuery(@Param("nameQuery") @Nullable String nameQuery, @Param("includeModules") boolean includeModules);
+
long countGhostProjects(Map<String, Object> parameters);
void selectForIndexing(@Param("projectUuid") @Nullable String projectUuid, ResultHandler handler);
diff --git a/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml
index 5813d2aca3b..3ff8987b017 100644
--- a/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml
+++ b/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml
@@ -425,6 +425,26 @@
</if>
</select>
+ <select id="selectProjectsByNameQuery" resultType="Component">
+ select
+ <include refid="componentColumns"/>
+ from projects p
+ <where>
+ p.enabled=${_true}
+ AND p.copy_component_uuid is null
+ <if test="includeModules == false">
+ AND p.qualifier = 'TRK'
+ </if>
+ <if test="includeModules == true">
+ AND (p.qualifier = 'TRK' OR p.qualifier = 'BRC')
+ </if>
+ <if test="nameQuery != null">
+ AND UPPER(p.name) like #{nameQuery,jdbcType=VARCHAR}
+ </if>
+ </where>
+ ORDER BY p.name
+ </select>
+
<insert id="insert" parameterType="Component" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
INSERT INTO projects (
organization_uuid,
diff --git a/sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java
index 9bbaaf20aa7..e0b62a5dc03 100644
--- a/sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java
@@ -720,9 +720,9 @@ public class ComponentDaoTest {
@Test
public void updateBEnabledToFalse() {
- ComponentDto dto1 = ComponentTesting.newProjectDto(db.getDefaultOrganization(), "U1");
- ComponentDto dto2 = ComponentTesting.newProjectDto(db.getDefaultOrganization(), "U2");
- ComponentDto dto3 = ComponentTesting.newProjectDto(db.getDefaultOrganization(), "U3");
+ ComponentDto dto1 = newProjectDto(db.getDefaultOrganization(), "U1");
+ ComponentDto dto2 = newProjectDto(db.getDefaultOrganization(), "U2");
+ ComponentDto dto3 = newProjectDto(db.getDefaultOrganization(), "U3");
underTest.insert(dbSession, dto1, dto2, dto3);
underTest.updateBEnabledToFalse(dbSession, asList("U1", "U2"));
@@ -1001,6 +1001,28 @@ public class ComponentDaoTest {
assertThat(components).extracting("organizationUuid").containsOnly(organizationDto.getUuid());
}
+ @Test
+ public void select_projects_by_name_query() {
+ OrganizationDto organizationDto = db.organizations().insert();
+ ComponentDto project1 = db.components().insertComponent(newProjectDto(organizationDto).setName("project1"));
+ ComponentDto module1 = db.components().insertComponent(newModuleDto(project1).setName("module1"));
+ ComponentDto subModule1 = db.components().insertComponent(newModuleDto(module1).setName("subModule1"));
+ ComponentDto file = db.components().insertComponent(newFileDto(subModule1).setName("file"));
+ ComponentDto project2 = db.components().insertComponent(newProjectDto(organizationDto).setName("project2"));
+ ComponentDto project3 = db.components().insertComponent(newProjectDto(organizationDto).setName("project3"));
+
+ assertThat(underTest.selectProjectsByNameQuery(dbSession, null, false)).extracting(ComponentDto::uuid)
+ .containsOnly(project1.uuid(), project2.uuid(), project3.uuid());
+ assertThat(underTest.selectProjectsByNameQuery(dbSession, null, true)).extracting(ComponentDto::uuid)
+ .containsOnly(project1.uuid(), project2.uuid(), project3.uuid(), module1.uuid(), subModule1.uuid());
+ assertThat(underTest.selectProjectsByNameQuery(dbSession, "project1", false)).extracting(ComponentDto::uuid).containsOnly(project1.uuid());
+ assertThat(underTest.selectProjectsByNameQuery(dbSession, "ct1", false)).extracting(ComponentDto::uuid).containsOnly(project1.uuid());
+ assertThat(underTest.selectProjectsByNameQuery(dbSession, "pro", false)).extracting(ComponentDto::uuid).containsOnly(project1.uuid(), project2.uuid(), project3.uuid());
+ assertThat(underTest.selectProjectsByNameQuery(dbSession, "jec", false)).extracting(ComponentDto::uuid).containsOnly(project1.uuid(), project2.uuid(), project3.uuid());
+ assertThat(underTest.selectProjectsByNameQuery(dbSession, "1", true)).extracting(ComponentDto::uuid).containsOnly(project1.uuid(), module1.uuid(), subModule1.uuid());
+ assertThat(underTest.selectProjectsByNameQuery(dbSession, "unknown", true)).extracting(ComponentDto::uuid).isEmpty();
+ }
+
private static ComponentTreeQuery.Builder newTreeQuery(String baseUuid) {
return ComponentTreeQuery.builder()
.setBaseUuid(baseUuid)
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/RailsHandler.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/RailsHandler.java
index 5c86c340ecf..63ce01080fb 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/RailsHandler.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/RailsHandler.java
@@ -27,7 +27,6 @@ package org.sonar.api.server.ws;
public class RailsHandler implements RequestHandler {
public static final RequestHandler INSTANCE = new RailsHandler();
- public static final String PARAM_FORMAT = "format";
private RailsHandler() {
// Nothing
@@ -38,26 +37,4 @@ public class RailsHandler implements RequestHandler {
throw new UnsupportedOperationException("This web service is implemented in rails");
}
- public static WebService.NewParam addFormatParam(WebService.NewAction action) {
- return action.createParam(PARAM_FORMAT)
- .setDescription("Response format can be set through:" +
- "<ul>" +
- "<li>Parameter format: xml | json</li>" +
- "<li>Or the 'Accept' property in the HTTP header:" +
- "<ul>" +
- "<li>Accept:text/xml</li>" +
- "<li>Accept:application/json</li>" +
- "</ul></li></ul>" +
- "If nothing is set, json is used.<br/>" +
- "Since 6.1, XML format is deprecated, only JSON format should be used.")
- .setPossibleValues("json", "xml")
- .setDeprecatedSince("6.1");
- }
-
- public static WebService.NewParam addJsonOnlyFormatParam(WebService.NewAction action) {
- return action.createParam(PARAM_FORMAT)
- .setDescription("Only json response format is available")
- .setPossibleValues("json");
- }
-
}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsWsParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsWsParameters.java
index f6ca6e6c0c1..89ce77b8e5e 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsWsParameters.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsWsParameters.java
@@ -24,6 +24,7 @@ public class ProjectsWsParameters {
public static final String CONTROLLER = "api/projects";
public static final String ACTION_CREATE = "create";
+ public static final String ACTION_INDEX = "index";
public static final String PARAM_PROJECT = "project";
public static final String PARAM_NAME = "name";