public class ComponentsWs implements WebService {
private final AppAction appAction;
- private final SearchViewComponentsAction searchViewComponentsAction;
private final ComponentsWsAction[] actions;
- public ComponentsWs(AppAction appAction, SearchViewComponentsAction searchViewComponentsAction, ComponentsWsAction... actions) {
+ public ComponentsWs(AppAction appAction, ComponentsWsAction... actions) {
this.appAction = appAction;
- this.searchViewComponentsAction = searchViewComponentsAction;
this.actions = actions;
}
action.define(controller);
}
appAction.define(controller);
- searchViewComponentsAction.define(controller);
controller.done();
}
SuggestionsAction.class,
TreeAction.class,
ShowAction.class,
- SearchViewComponentsAction.class,
UpdateKeyAction.class,
BulkUpdateKeyAction.class,
SearchProjectsAction.class,
+++ /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.component.ws;
-
-import com.google.common.collect.Sets;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-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.Param;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.util.Uuids;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.user.UserSession;
-
-import static com.google.common.collect.Sets.newLinkedHashSet;
-import static org.sonar.api.server.ws.WebService.Param.PAGE;
-import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
-import static org.sonar.server.es.SearchOptions.MAX_LIMIT;
-
-public class SearchViewComponentsAction implements RequestHandler {
-
- private static final short MINIMUM_SEARCH_CHARACTERS = 2;
-
- private static final String PARAM_COMPONENT_UUID = "componentId";
-
- private final DbClient dbClient;
- private final UserSession userSession;
- private final ComponentFinder componentFinder;
-
- public SearchViewComponentsAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder) {
- this.dbClient = dbClient;
- this.userSession = userSession;
- this.componentFinder = componentFinder;
- }
-
- void define(WebService.NewController controller) {
- WebService.NewAction action = controller.createAction("search_view_components")
- .setDescription("Search for components. Currently limited to projects in a view or a sub-view")
- .setResponseExample(getClass().getResource("search_view_components-example.json"))
- .setSince("5.1")
- .setInternal(true)
- .setHandler(this);
-
- action
- .createParam(PARAM_COMPONENT_UUID)
- .setRequired(true)
- .setDescription("View or sub view UUID")
- .setExampleValue(Uuids.UUID_EXAMPLE_01);
-
- action
- .createParam(Param.TEXT_QUERY)
- .setRequired(true)
- .setDescription("UTF-8 search query")
- .setExampleValue("sonar");
-
- action.addPagingParams(10, MAX_LIMIT);
- }
-
- @Override
- public void handle(Request request, Response response) {
- String query = request.mandatoryParam(Param.TEXT_QUERY);
- if (query.length() < MINIMUM_SEARCH_CHARACTERS) {
- throw new IllegalArgumentException(String.format("Minimum search is %s characters", MINIMUM_SEARCH_CHARACTERS));
- }
- String componentUuid = request.mandatoryParam(PARAM_COMPONENT_UUID);
-
- JsonWriter json = response.newJsonWriter();
- json.beginObject();
-
- DbSession session = dbClient.openSession(false);
- try {
- ComponentDto componentDto = componentFinder.getByUuid(session, componentUuid);
- userSession.checkComponentUuidPermission(UserRole.USER, componentDto.projectUuid());
-
- Set<Long> projectIds = newLinkedHashSet(dbClient.componentIndexDao().selectProjectIdsFromQueryAndViewOrSubViewUuid(session, query, componentDto.uuid()));
- Collection<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(session, projectIds, userSession.getUserId(), UserRole.USER);
-
- SearchOptions options = new SearchOptions();
- options.setPage(request.mandatoryParamAsInt(PAGE), request.mandatoryParamAsInt(PAGE_SIZE));
- Set<Long> pagedProjectIds = pagedProjectIds(authorizedProjectIds, options);
-
- List<ComponentDto> projects = dbClient.componentDao().selectByIds(session, pagedProjectIds);
-
- options.writeJson(json, authorizedProjectIds.size());
- json.name("components").beginArray();
- for (ComponentDto project : projects) {
- json.beginObject();
- json.prop("uuid", project.uuid());
- json.prop("name", project.name());
- json.endObject();
- }
- json.endArray();
- } finally {
- MyBatis.closeQuietly(session);
- }
-
- json.endObject();
- json.close();
- }
-
- private static Set<Long> pagedProjectIds(Collection<Long> projectIds, SearchOptions options) {
- Set<Long> results = Sets.newLinkedHashSet();
- int index = 0;
- for (Long projectId : projectIds) {
- if (index >= options.getOffset() && results.size() < options.getLimit()) {
- results.add(projectId);
- } else if (results.size() >= options.getLimit()) {
- break;
- }
- index++;
- }
- return results;
- }
-}
+++ /dev/null
-{
- "total": 7,
- "p": 1,
- "ps": 10,
- "components": [
- {
- "uuid": "e638eb68-1f30-4c9e-ae07-c45741f5d4ce",
- "name": "AssertJ - Fluent assertions for java unit testing"
- },
- {
- "uuid": "271d3ba4-5881-4f9c-80df-601f162d55c1",
- "name": "Java Concurrency Stress Tests: Parent"
- },
- {
- "uuid": "3224e429-6693-4a0c-9c5e-9eb73064ac27",
- "name": "Java Microbenchmark Harness Parent"
- },
- {
- "uuid": "166c61d2-420e-489f-a2c1-8a6b71a1db34",
- "name": "SonarQube Java"
- },
- {
- "uuid": "54fb08be-5cfc-482a-b977-56c306011800",
- "name": "JavaScript"
- },
- {
- "uuid": "36025b5c-8654-4620-9e32-aa9b60d38016",
- "name": "SonarQube Java Properties Plugin"
- },
- {
- "uuid": "AVBx-FSivhIeFA9E82uf",
- "name": "Google Cloud Dataflow Java SDK - Parent"
- }
- ]
-}
wsTester = new WsTester(
new ComponentsWs(
new AppAction(dbTester.getDbClient(), userSessionRule, new ComponentFinder(dbTester.getDbClient())),
- mock(SearchViewComponentsAction.class),
mock(SuggestionsAction.class)));
}
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new ComponentsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(12 + 2);
+ assertThat(container.size()).isEqualTo(11 + 2);
}
}
@Rule
public UserSessionRule userSessionRule = UserSessionRule.standalone();
- WebService.Controller controller;
+ private WebService.Controller controller;
@Before
public void setUp() {
WsTester tester = new WsTester(new ComponentsWs(
new AppAction(mock(DbClient.class), userSessionRule, mock(ComponentFinder.class)),
- new SearchViewComponentsAction(mock(DbClient.class), userSessionRule, mock(ComponentFinder.class)),
new SuggestionsAction(mock(DbClient.class), mock(ComponentIndex.class)),
new SearchAction(mock(DbClient.class), mock(ResourceTypes.class), mock(I18n.class), userSessionRule, languages)));
controller = tester.controller("api/components");
assertThat(controller).isNotNull();
assertThat(controller.description()).isNotEmpty();
assertThat(controller.since()).isEqualTo("4.2");
- assertThat(controller.actions()).hasSize(4);
+ assertThat(controller.actions()).hasSize(3);
}
@Test
}
@Test
- public void define_search_view_components_action() {
- WebService.Action action = controller.action("search_view_components");
+ public void define_search_action() {
+ WebService.Action action = controller.action("search");
assertThat(action).isNotNull();
+ assertThat(action.param("qualifiers").isRequired()).isTrue();
+ assertThat(action.responseExampleAsString()).isNotEmpty();
+ assertThat(action.description()).isNotEmpty();
assertThat(action.isInternal()).isTrue();
assertThat(action.isPost()).isFalse();
- assertThat(action.handler()).isNotNull();
- assertThat(action.params()).hasSize(4);
+ assertThat(action.since()).isEqualTo("5.2");
}
-
}
+++ /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.component.ws;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.DbTester;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.component.index.ComponentIndex;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.mockito.Mockito.mock;
-
-public class SearchViewComponentsActionTest {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- @Rule
- public DbTester db = DbTester.create(System2.INSTANCE);
-
- @Rule
- public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
- WsTester ws;
-
- @Before
- public void setUp() {
- ws = new WsTester(
- new ComponentsWs(
- mock(AppAction.class),
- new SearchViewComponentsAction(db.getDbClient(), userSessionRule, new ComponentFinder(db.getDbClient())),
- new SuggestionsAction(db.getDbClient(), mock(ComponentIndex.class))));
- }
-
- @Test
- public void return_projects_from_view() throws Exception {
- db.prepareDbUnit(getClass(), "shared.xml");
- userSessionRule.login("john").addProjectUuidPermissions(UserRole.USER, "EFGH");
-
- WsTester.TestRequest request = newRequest().setParam("componentId", "EFGH").setParam("q", "st");
- request.execute().assertJson(getClass(), "return_projects_from_view.json");
- }
-
- @Test
- public void return_projects_from_subview() throws Exception {
- db.prepareDbUnit(getClass(), "shared.xml");
- userSessionRule.login("john").addComponentUuidPermission(UserRole.USER, "EFGH", "FGHI");
-
- WsTester.TestRequest request = newRequest().setParam("componentId", "FGHI").setParam("q", "st");
- request.execute().assertJson(getClass(), "return_projects_from_subview.json");
- }
-
- @Test
- public void return_only_authorized_projects_from_view() throws Exception {
- db.prepareDbUnit(getClass(), "return_only_authorized_projects_from_view.xml");
- userSessionRule.login("john").addProjectUuidPermissions(UserRole.USER, "EFGH");
-
- WsTester.TestRequest request = newRequest().setParam("componentId", "EFGH").setParam("q", "st");
- request.execute().assertJson(getClass(), "return_only_authorized_projects_from_view.json");
- }
-
- @Test
- public void return_paged_result() throws Exception {
- db.prepareDbUnit(getClass(), "shared.xml");
- userSessionRule.login("john").addProjectUuidPermissions(UserRole.USER, "EFGH");
-
- WsTester.TestRequest request = newRequest().setParam("componentId", "EFGH").setParam("q", "st").setParam(Param.PAGE, "2")
- .setParam(Param.PAGE_SIZE, "1");
- request.execute().assertJson(getClass(), "return_paged_result.json");
- }
-
- @Test
- public void return_only_first_page() throws Exception {
- db.prepareDbUnit(getClass(), "shared.xml");
- userSessionRule.login("john").addProjectUuidPermissions(UserRole.USER, "EFGH");
-
- WsTester.TestRequest request = newRequest().setParam("componentId", "EFGH").setParam("q", "st").setParam(Param.PAGE, "1")
- .setParam(Param.PAGE_SIZE, "1");
- request.execute().assertJson(getClass(), "return_only_first_page.json");
- }
-
- @Test
- public void fail_when_search_param_is_too_short() throws Exception {
- thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Minimum search is 2 characters");
-
- db.prepareDbUnit(getClass(), "shared.xml");
- userSessionRule.login("john").addProjectUuidPermissions(UserRole.USER, "EFGH");
-
- WsTester.TestRequest request = newRequest().setParam("componentId", "EFGH").setParam("q", "s");
- request.execute();
- }
-
- @Test
- public void fail_when_project_uuid_does_not_exists() throws Exception {
- thrown.expect(NotFoundException.class);
- thrown.expectMessage("Component id 'UNKNOWN' not found");
-
- db.prepareDbUnit(getClass(), "shared.xml");
- userSessionRule.login("john").addProjectUuidPermissions(UserRole.USER, "EFGH");
-
- WsTester.TestRequest request = newRequest().setParam("componentId", "UNKNOWN").setParam("q", "st");
- request.execute();
- }
-
- private WsTester.TestRequest newRequest() {
- return ws.newGetRequest("api/components", "search_view_components");
- }
-}
+++ /dev/null
-{
- "total": 1,
- "p": 1,
- "ps": 10,
- "components": [
- {
- "uuid": "JKLM",
- "name": "Struts"
- }
- ]
-}
+++ /dev/null
-<dataset>
-
- <organizations uuid="org1"
- kee="org1_key"
- name="org1_name"
- created_at="1000"
- updated_at="1000"/>
-
- <!-- Only struts is authorized for all user -->
- <group_roles id="1"
- group_id="[null]"
- resource_id="100"
- role="user"
- organization_uuid="org1"/>
-
- <!-- View -->
- <projects organization_uuid="org1"
- uuid="EFGH"
- uuid_path="NOT_USED"
- root_uuid="EFGH"
- project_uuid="EFGH"
- module_uuid="[null]"
- module_uuid_path="."
- copy_component_uuid="[null]"
- enabled="[true]"
- kee="LANGUAGE_VIEW"
- scope="PRJ"
- qualifier="VW"
- name="By Language"
- path="[null]"
- id="11"/>
-
- <projects organization_uuid="org1"
- uuid="GHIJ"
- uuid_path="NOT_USED"
- root_uuid="EFGH"
- project_uuid="EFGH"
- module_uuid="EFGH"
- module_uuid_path=".EFGH."
- copy_component_uuid="KLMN"
- enabled="[true]"
- kee="VIEW2org.elasticsearch:elasticsearch"
- scope="FIL"
- qualifier="TRK"
- name="Elasticsearch"
- path="[null]"
- id="112"/>
-
- <projects organization_uuid="org1"
- uuid="HIJK"
- uuid_path="NOT_USED"
- root_uuid="EFGH"
- project_uuid="EFGH"
- module_uuid="EFGH"
- module_uuid_path=".EFGH."
- copy_component_uuid="JKLM"
- enabled="[true]"
- kee="VIEW2org.struts:struts"
- scope="FIL"
- qualifier="TRK"
- name="Struts"
- path="[null]"
- id="113"/>
-
- <!-- Real projects -->
-
- <projects organization_uuid="org1"
- uuid="JKLM"
- uuid_path="NOT_USED"
- root_uuid="JKLM"
- root_project_uuid="JKLM"
- module_uuid="[null]"
- module_uuid_path="."
- enabled="[true]"
- copy_component_uuid="[null]"
- path="[null]"
- id="100"
- scope="PRJ"
- qualifier="TRK"
- kee="org.struts:struts"
- name="Struts"/>
-
- <projects organization_uuid="org1"
- uuid="KLMN"
- uuid_path="NOT_USED"
- root_uuid="KLMN"
- project_uuid="KLMN"
- module_uuid="[null]"
- module_uuid_path="."
- enabled="[true]"
- copy_component_uuid="[null]"
- path="[null]"
- id="101"
- scope="PRJ"
- qualifier="TRK"
- kee="org.elasticsearch:elasticsearch"
- name="Elasticsearch"/>
-
- <resource_index id="1"
- kee="struts"
- component_uuid="JKLM"
- root_component_uuid="JKLM"
- position="0"
- name_size="6"
- qualifier="TRK"/>
- <resource_index id="2"
- kee="elasticsearch"
- component_uuid="KLMN"
- root_component_uuid="KLMN"
- position="0"
- name_size="13"
- qualifier="TRK"/>
- <resource_index id="3"
- kee="sticsearch"
- component_uuid="KLMN"
- root_component_uuid="KLMN"
- position="1"
- name_size="13"
- qualifier="TRK"/>
-
-</dataset>
+++ /dev/null
-{
- "total": 2,
- "p": 1,
- "ps": 1
-}
+++ /dev/null
-{
- "total": 2,
- "p": 2,
- "ps": 1
-}
+++ /dev/null
-{
- "total": 1,
- "p": 1,
- "ps": 10,
- "components": [
- {
- "uuid": "JKLM",
- "name": "Struts"
- }
- ]
-}
+++ /dev/null
-{
- "total": 2,
- "p": 1,
- "ps": 10,
- "components": [
- {
- "uuid": "JKLM",
- "name": "Struts"
- },
- {
- "uuid": "KLMN",
- "name": "Elasticsearch"
- }
- ]
-}
+++ /dev/null
-<dataset>
-
- <organizations uuid="org1"
- kee="org1_key"
- name="org1_name"
- created_at="1000"
- updated_at="1000"/>
-
- <!-- Projects is authorized for all user -->
- <group_roles id="1"
- group_id="[null]"
- resource_id="100"
- role="user"
- organization_uuid="org1"/>
- <group_roles id="2"
- group_id="[null]"
- resource_id="101"
- role="user"
- organization_uuid="org1"/>
-
- <!-- View with sub view -->
- <projects organization_uuid="org1"
- uuid="EFGH"
- uuid_path="NOT_USED"
- root_uuid="EFGH"
- project_uuid="EFGH"
- module_uuid="[null]"
- module_uuid_path="."
- copy_component_uuid="[null]"
- enabled="[true]"
- kee="LANGUAGE_VIEW"
- scope="PRJ"
- qualifier="VW"
- name="By Language"
- path="[null]"
- id="11"/>
-
- <projects organization_uuid="org1"
- uuid="GHIJ"
- uuid_path="NOT_USED"
- root_uuid="EFGH"
- project_uuid="EFGH"
- module_uuid="EFGH"
- module_uuid_path=".EFGH."
- copy_component_uuid="KLMN"
- enabled="[true]"
- kee="VIEW2org.elasticsearch:elasticsearch"
- scope="FIL"
- qualifier="TRK"
- name="Elasticsearch"
- path="[null]"
- id="112"/>
-
- <!-- Sub view -->
- <projects organization_uuid="org1"
- uuid="FGHI"
- uuid_path="NOT_USED"
- root_uuid="EFGH"
- project_uuid="EFGH"
- module_uuid="EFGH"
- module_uuid_path=".EFGH."
- copy_component_uuid="[null]"
- enabled="[true]"
- kee="JAVA_PROJECTS"
- scope="PRJ"
- qualifier="SVW"
- name="Java projects"
- path="[null]"
- id="13"/>
-
- <projects organization_uuid="org1"
- uuid="HIJK"
- uuid_path="NOT_USED"
- root_uuid="EFGH"
- project_uuid="EFGH"
- module_uuid="FGHI"
- module_uuid_path=".EFGH.FGHI."
- copy_component_uuid="JKLM"
- enabled="[true]"
- kee="VIEW2org.struts:struts"
- scope="FIL"
- qualifier="TRK"
- name="Struts"
- path="[null]"
- id="113"/>
-
- <!-- Real projects -->
-
- <projects organization_uuid="org1"
- uuid="JKLM"
- uuid_path="NOT_USED"
- root_uuid="JKLM"
- project_uuid="JKLM"
- module_uuid="[null]"
- module_uuid_path="."
- enabled="[true]"
- copy_component_uuid="[null]"
- path="[null]"
- id="100"
- scope="PRJ"
- qualifier="TRK"
- kee="org.struts:struts"
- name="Struts"/>
-
- <projects organization_uuid="org1"
- uuid="KLMN"
- uuid_path="NOT_USED"
- root_uuid="KLMN"
- project_uuid="KLMN"
- module_uuid="[null]"
- module_uuid_path="."
- enabled="[true]"
- copy_component_uuid="[null]"
- path="[null]"
- id="101"
- scope="PRJ"
- qualifier="TRK"
- kee="org.elasticsearch:elasticsearch"
- name="Elasticsearch"/>
-
- <resource_index id="1"
- kee="struts"
- component_uuid="JKLM"
- root_component_uuid="JKLM"
- position="0"
- name_size="6"
- qualifier="TRK"/>
- <resource_index id="2"
- kee="elasticsearch"
- component_uuid="KLMN"
- root_component_uuid="KLMN"
- position="0"
- name_size="13"
- qualifier="TRK"/>
- <resource_index id="3"
- kee="sticsearch"
- component_uuid="KLMN"
- root_component_uuid="KLMN"
- position="1"
- name_size="13"
- qualifier="TRK"/>
-
-</dataset>