--- /dev/null
+/*
+ * 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");
+ }
+
+}
*/
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;
@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);
- }
-
}
add(
ProjectsWs.class,
CreateAction.class,
+ IndexAction.class,
BulkDeleteAction.class,
DeleteAction.class,
GhostsAction.class,
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;
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;
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
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;
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";
}
--- /dev/null
+[
+ {
+ "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"
+ }
+]
+++ /dev/null
-[
- {
- "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"
- }
-]
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 {
}
private WsTester.TestRequest newRequest() {
- return ws.newPostRequest(ProjectsWs.ENDPOINT, ACTION);
+ return ws.newPostRequest(CONTROLLER, ACTION);
}
}
--- /dev/null
+/*
+ * 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));
+ }
+}
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);
}
}
+++ /dev/null
-/*
- * 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);
- }
-
-}
--- /dev/null
+[
+ {
+ "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"
+ }
+]
--- /dev/null
+[
+ {
+ "id": "5035",
+ "k": "org.jenkins-ci.plugins:sonar",
+ "nm": "Jenkins Sonar Plugin",
+ "sc": "PRJ",
+ "qu": "TRK"
+ }
+]
--- /dev/null
+[
+ {
+ "id": "5035",
+ "k": "org.jenkins-ci.plugins:sonar",
+ "nm": "Jenkins Sonar Plugin",
+ "sc": "PRJ",
+ "qu": "TRK"
+ }
+]
--- /dev/null
+[
+ {
+ "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"
+ }
+]
--- /dev/null
+[
+ {
+ "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"
+ }
+]
--- /dev/null
+[
+ {
+ "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"
+ }
+]
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 {
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) {
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) {
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);
</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,
@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"));
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)
public class RailsHandler implements RequestHandler {
public static final RequestHandler INSTANCE = new RailsHandler();
- public static final String PARAM_FORMAT = "format";
private RailsHandler() {
// Nothing
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");
- }
-
}
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";