]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8648 add organization parameter to api/components/search 1579/head
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 27 Jan 2017 08:28:59 +0000 (09:28 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 30 Jan 2017 13:53:24 +0000 (14:53 +0100)
server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchAction.java
server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsTest.java
server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchActionTest.java
sonar-db/src/main/java/org/sonar/db/component/ComponentDao.java
sonar-db/src/main/java/org/sonar/db/component/ComponentMapper.java
sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml
sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/component/SearchWsRequest.java

index 3538aaca55d51662cb5a888f32850a076d208bf1..25427abe3da812ae5e7186427655e61aa0008b28 100644 (file)
  */
 package org.sonar.server.component.ws;
 
-import com.google.common.base.Function;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
-import javax.annotation.Nonnull;
 import org.sonar.api.i18n.I18n;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.resources.ResourceTypes;
@@ -39,12 +38,14 @@ import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentQuery;
 import org.sonar.db.organization.OrganizationDto;
+import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.user.UserSession;
+import org.sonar.server.ws.WsUtils;
 import org.sonarqube.ws.WsComponents;
 import org.sonarqube.ws.WsComponents.SearchWsResponse;
 import org.sonarqube.ws.client.component.SearchWsRequest;
 
-import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkArgument;
 import static org.sonar.api.web.UserRole.USER;
 import static org.sonar.core.util.Protobuf.setNullable;
 import static org.sonar.core.util.stream.Collectors.uniqueIndex;
@@ -55,6 +56,7 @@ import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.n
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.ACTION_SEARCH;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
 
 public class SearchAction implements ComponentsWsAction {
@@ -63,13 +65,16 @@ public class SearchAction implements ComponentsWsAction {
   private final I18n i18n;
   private final UserSession userSession;
   private final Languages languages;
+  private final DefaultOrganizationProvider defaultOrganizationProvider;
 
-  public SearchAction(DbClient dbClient, ResourceTypes resourceTypes, I18n i18n, UserSession userSession, Languages languages) {
+  public SearchAction(DbClient dbClient, ResourceTypes resourceTypes, I18n i18n, UserSession userSession,
+    Languages languages, DefaultOrganizationProvider defaultOrganizationProvider) {
     this.dbClient = dbClient;
     this.resourceTypes = resourceTypes;
     this.i18n = i18n;
     this.userSession = userSession;
     this.languages = languages;
+    this.defaultOrganizationProvider = defaultOrganizationProvider;
   }
 
   @Override
@@ -81,6 +86,13 @@ public class SearchAction implements ComponentsWsAction {
       .addSearchQuery("sona", "component names", "component keys")
       .setResponseExample(getClass().getResource("search-components-example.json"))
       .setHandler(this);
+    action
+      .createParam(PARAM_ORGANIZATION)
+      .setDescription("Organization key")
+      .setRequired(false)
+      .setInternal(true)
+      .setExampleValue("my-org")
+      .setSince("6.3");
     action
       .createParam(PARAM_LANGUAGE)
       .setDescription("Language key. If provided, only components for the given language are returned.")
@@ -96,24 +108,9 @@ public class SearchAction implements ComponentsWsAction {
     writeProtobuf(searchWsResponse, wsRequest, wsResponse);
   }
 
-  private SearchWsResponse doHandle(SearchWsRequest request) {
-    try (DbSession dbSession = dbClient.openSession(false)) {
-      ComponentQuery query = buildQuery(request);
-      Paging paging = buildPaging(dbSession, request, query);
-      List<ComponentDto> components = searchComponents(dbSession, query, paging);
-
-      Set<String> organizationUuids = components.stream()
-        .map(ComponentDto::getOrganizationUuid)
-        .collect(Collectors.toSet());
-      Map<String, OrganizationDto> organizationsByUuid = dbClient.organizationDao().selectByUuids(dbSession, organizationUuids)
-        .stream()
-        .collect(Collectors.uniqueIndex(OrganizationDto::getUuid));
-      return buildResponse(components, organizationsByUuid, paging);
-    }
-  }
-
   private static SearchWsRequest toSearchWsRequest(Request request) {
     return new SearchWsRequest()
+      .setOrganization(request.param(PARAM_ORGANIZATION))
       .setQualifiers(request.mandatoryParamAsStrings(PARAM_QUALIFIERS))
       .setLanguage(request.param(PARAM_LANGUAGE))
       .setQuery(request.param(Param.TEXT_QUERY))
@@ -121,8 +118,43 @@ public class SearchAction implements ComponentsWsAction {
       .setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE));
   }
 
-  private List<ComponentDto> searchComponents(DbSession dbSession, ComponentQuery query, Paging paging) {
-    List<ComponentDto> componentDtos = dbClient.componentDao().selectByQuery(dbSession, query, paging.offset(), paging.pageSize());
+  private SearchWsResponse doHandle(SearchWsRequest request) {
+    try (DbSession dbSession = dbClient.openSession(false)) {
+      ComponentQuery query = buildQuery(request);
+      OrganizationDto organization = getOrganization(dbSession, request);
+      Paging paging = buildPaging(dbSession, request, organization, query);
+      List<ComponentDto> components = searchComponents(dbSession, organization, query, paging);
+
+      return buildResponse(components, organization, paging);
+    }
+  }
+
+  private static ComponentQuery buildQuery(SearchWsRequest request) {
+    List<String> qualifiers = request.getQualifiers();
+    return ComponentQuery.builder()
+      .setNameOrKeyQuery(request.getQuery())
+      .setLanguage(request.getLanguage())
+      .setQualifiers(qualifiers.toArray(new String[qualifiers.size()]))
+      .build();
+  }
+
+  private OrganizationDto getOrganization(DbSession dbSession, SearchWsRequest request) {
+    String organizationKey = Optional.ofNullable(request.getOrganization())
+      .orElseGet(defaultOrganizationProvider.get()::getKey);
+    return WsUtils.checkFoundWithOptional(
+      dbClient.organizationDao().selectByKey(dbSession, organizationKey),
+      "No organizationDto with key '%s'", organizationKey);
+  }
+
+  private Paging buildPaging(DbSession dbSession, SearchWsRequest request, OrganizationDto organization, ComponentQuery query) {
+    int total = dbClient.componentDao().countByQuery(dbSession, organization.getUuid(), query);
+    return Paging.forPageIndex(request.getPage())
+      .withPageSize(request.getPageSize())
+      .andTotal(total);
+  }
+
+  private List<ComponentDto> searchComponents(DbSession dbSession, OrganizationDto organization, ComponentQuery query, Paging paging) {
+    List<ComponentDto> componentDtos = dbClient.componentDao().selectByQuery(dbSession, organization.getUuid(), query, paging.offset(), paging.pageSize());
     return filterAuthorizedComponents(dbSession, componentDtos);
   }
 
@@ -136,7 +168,7 @@ public class SearchAction implements ComponentsWsAction {
       .collect(Collectors.toList());
   }
 
-  private static SearchWsResponse buildResponse(List<ComponentDto> components, Map<String, OrganizationDto> organizationsByUuid, Paging paging) {
+  private static SearchWsResponse buildResponse(List<ComponentDto> components, OrganizationDto organization, Paging paging) {
     SearchWsResponse.Builder responseBuilder = SearchWsResponse.newBuilder();
     responseBuilder.getPagingBuilder()
       .setPageIndex(paging.pageIndex())
@@ -145,50 +177,26 @@ public class SearchAction implements ComponentsWsAction {
       .build();
 
     components.stream()
-      .map(new ComponentDToComponentResponseFunction(organizationsByUuid)::apply)
+      .map(dto -> dtoToComponent(organization, dto))
       .forEach(responseBuilder::addComponents);
 
     return responseBuilder.build();
   }
 
-  private Paging buildPaging(DbSession dbSession, SearchWsRequest request, ComponentQuery query) {
-    int total = dbClient.componentDao().countByQuery(dbSession, query);
-    return Paging.forPageIndex(request.getPage())
-      .withPageSize(request.getPageSize())
-      .andTotal(total);
+  private static WsComponents.Component dtoToComponent(OrganizationDto organization, ComponentDto dto) {
+    checkArgument(
+      organization.getUuid().equals(dto.getOrganizationUuid()),
+      "No Organization found for uuid '%s'",
+      dto.getOrganizationUuid());
+
+    WsComponents.Component.Builder builder = WsComponents.Component.newBuilder()
+      .setOrganization(organization.getKey())
+      .setId(dto.uuid())
+      .setKey(dto.key())
+      .setName(dto.name())
+      .setQualifier(dto.qualifier());
+    setNullable(dto.language(), builder::setLanguage);
+    return builder.build();
   }
 
-  private static ComponentQuery buildQuery(SearchWsRequest request) {
-    List<String> qualifiers = request.getQualifiers();
-    return ComponentQuery.builder()
-      .setNameOrKeyQuery(request.getQuery())
-      .setLanguage(request.getLanguage())
-      .setQualifiers(qualifiers.toArray(new String[qualifiers.size()]))
-      .build();
-  }
-
-  private static class ComponentDToComponentResponseFunction implements Function<ComponentDto, WsComponents.Component> {
-    private final Map<String, OrganizationDto> organizationsByUuid;
-
-    private ComponentDToComponentResponseFunction(Map<String, OrganizationDto> organizationsByUuid) {
-      this.organizationsByUuid = organizationsByUuid;
-    }
-
-    @Override
-    public WsComponents.Component apply(@Nonnull ComponentDto dto) {
-      OrganizationDto organization = checkNotNull(
-        organizationsByUuid.get(dto.getOrganizationUuid()),
-        "No Organization found for uuid '%s'",
-        dto.getOrganizationUuid());
-
-      WsComponents.Component.Builder builder = WsComponents.Component.newBuilder()
-        .setOrganization(organization.getKey())
-        .setId(dto.uuid())
-        .setKey(dto.key())
-        .setName(dto.name())
-        .setQualifier(dto.qualifier());
-      setNullable(dto.language(), builder::setLanguage);
-      return builder.build();
-    }
-  }
 }
index 8e937c36ffe9c0b8f6e3540b06f592d45b814400..b93c6051c371ca6c67694d3bd3cd9a109468641c 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.db.DbClient;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.component.index.ComponentIndex;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.WsTester;
 
@@ -52,7 +53,7 @@ public class ComponentsWsTest {
     WsTester tester = new WsTester(new ComponentsWs(
       new AppAction(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)));
+      new SearchAction(mock(DbClient.class), mock(ResourceTypes.class), mock(I18n.class), userSessionRule, languages, TestDefaultOrganizationProvider.fromUuid("foo"))));
     controller = tester.controller("api/components");
   }
 
index 24ee4f44ea095f1094cb47673c853c6e78eadeed..064ed90b9216be5f1db744f27bdae1e707df52df 100644 (file)
@@ -40,6 +40,7 @@ import org.sonar.db.component.ResourceTypesRule;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.i18n.I18nRule;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.TestRequest;
 import org.sonar.server.ws.WsActionTester;
@@ -68,6 +69,7 @@ import static org.sonar.test.JsonAssert.assertJson;
 import static org.sonarqube.ws.MediaTypes.PROTOBUF;
 import static org.sonarqube.ws.WsComponents.Component;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
 
 public class SearchActionTest {
@@ -80,6 +82,7 @@ public class SearchActionTest {
 
   private I18nRule i18n = new I18nRule();
 
+  private TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
   private ResourceTypesRule resourceTypes = new ResourceTypesRule();
   private Languages languages = mock(Languages.class);
   private UserDto user;
@@ -90,12 +93,35 @@ public class SearchActionTest {
   public void setUp() {
     resourceTypes.setAllQualifiers(PROJECT, MODULE, DIRECTORY, FILE);
     when(languages.all()).thenReturn(javaLanguage());
-    ws = new WsActionTester(new SearchAction(db.getDbClient(), resourceTypes, i18n, userSession, languages));
+    ws = new WsActionTester(new SearchAction(db.getDbClient(), resourceTypes, i18n, userSession, languages, defaultOrganizationProvider));
 
     user = db.users().insertUser("john");
     userSession.login(user);
   }
 
+  @Test
+  public void verify_definition() {
+    WebService.Action action = ws.getDef();
+
+    assertThat(action.description()).isEqualTo("Search for components");
+    assertThat(action.since()).isEqualTo("6.3");
+    assertThat(action.isPost()).isFalse();
+    assertThat(action.isInternal()).isFalse();
+    assertThat(action.responseExampleAsString()).isNotEmpty();
+
+    assertThat(action.params()).hasSize(6);
+
+    WebService.Param qualifiers = action.param("qualifiers");
+    assertThat(qualifiers.isRequired()).isTrue();
+
+    WebService.Param organization = action.param("organization");
+    assertThat(organization.isRequired()).isFalse();
+    assertThat(organization.description()).isEqualTo("Organization key");
+    assertThat(organization.isInternal()).isTrue();
+    assertThat(organization.exampleValue()).isEqualTo("my-org");
+    assertThat(organization.since()).isEqualTo("6.3");
+  }
+
   @Test
   public void search_by_key_query() throws IOException {
     insertProjectsAuthorizedForUser(
@@ -129,7 +155,7 @@ public class SearchActionTest {
     }
     insertProjectsAuthorizedForUser(componentDtoList.toArray(new ComponentDto[] {}));
 
-    SearchWsResponse response = call(new SearchWsRequest().setPage(2).setPageSize(3).setQualifiers(singletonList(PROJECT)));
+    SearchWsResponse response = call(new SearchWsRequest().setOrganization(organizationDto.getKey()).setPage(2).setPageSize(3).setQualifiers(singletonList(PROJECT)));
 
     assertThat(response.getComponentsList()).extracting(Component::getKey).containsExactly("project-key-4", "project-key-5", "project-key-6");
   }
@@ -141,7 +167,7 @@ public class SearchActionTest {
       newProjectDto(organizationDto).setKey("java-project").setLanguage("java"),
       newProjectDto(organizationDto).setKey("cpp-project").setLanguage("cpp"));
 
-    SearchWsResponse response = call(new SearchWsRequest().setLanguage("java").setQualifiers(singletonList(PROJECT)));
+    SearchWsResponse response = call(new SearchWsRequest().setOrganization(organizationDto.getKey()).setLanguage("java").setQualifiers(singletonList(PROJECT)));
 
     assertThat(response.getComponentsList()).extracting(Component::getKey).containsOnly("java-project");
   }
@@ -190,24 +216,12 @@ public class SearchActionTest {
 
     String response = ws.newRequest()
       .setMediaType(MediaTypes.JSON)
+      .setParam(PARAM_ORGANIZATION, organizationDto.getKey())
       .setParam(PARAM_QUALIFIERS, Joiner.on(",").join(PROJECT, MODULE, DIRECTORY, FILE))
       .execute().getInput();
     assertJson(response).isSimilarTo(ws.getDef().responseExampleAsString());
   }
 
-  @Test
-  public void test_definition() {
-    WebService.Action action = ws.getDef();
-
-    assertThat(action).isNotNull();
-    assertThat(action.param("qualifiers").isRequired()).isTrue();
-    assertThat(action.responseExampleAsString()).isNotEmpty();
-    assertThat(action.description()).isNotEmpty();
-    assertThat(action.isInternal()).isFalse();
-    assertThat(action.isPost()).isFalse();
-    assertThat(action.since()).isEqualTo("6.3");
-  }
-
   private void insertProjectsAuthorizedForUser(ComponentDto... projects) {
     db.components().insertComponents(projects);
     setBrowsePermissionOnUser(projects);
@@ -222,6 +236,7 @@ public class SearchActionTest {
   private SearchWsResponse call(SearchWsRequest wsRequest) {
     TestRequest request = ws.newRequest()
       .setMediaType(PROTOBUF);
+    setNullable(wsRequest.getOrganization(), p -> request.setParam(PARAM_ORGANIZATION, p));
     setNullable(wsRequest.getLanguage(), p -> request.setParam(PARAM_LANGUAGE, p));
     setNullable(wsRequest.getQualifiers(), p -> request.setParam(PARAM_QUALIFIERS, Joiner.on(",").join(p)));
     setNullable(wsRequest.getQuery(), p -> request.setParam(TEXT_QUERY, p));
index 9880e51467ffa9faa9fe5353dfb299919f23f317..d475e9ead20b82e2865869e312f6942fe85f2b4a 100644 (file)
@@ -77,17 +77,37 @@ public class ComponentDao implements Dao {
   }
 
   public List<ComponentDto> selectByQuery(DbSession session, ComponentQuery query, int offset, int limit) {
-    if (query.getComponentIds() != null && query.getComponentIds().isEmpty()) {
+    return selectByQueryImpl(session, null, query, offset, limit);
+  }
+
+  public List<ComponentDto> selectByQuery(DbSession dbSession, String organizationUuid, ComponentQuery query, int offset, int limit) {
+    requireNonNull(organizationUuid, "organizationUuid can't be null");
+    return selectByQueryImpl(dbSession, organizationUuid, query, offset, limit);
+  }
+
+  private static List<ComponentDto> selectByQueryImpl(DbSession session, @Nullable String organizationUuid, ComponentQuery query, int offset, int limit) {
+    Set<Long> componentIds = query.getComponentIds();
+    if (componentIds != null && componentIds.isEmpty()) {
       return emptyList();
     }
-    return mapper(session).selectByQuery(query, new RowBounds(offset, limit));
+    return mapper(session).selectByQuery(organizationUuid, query, new RowBounds(offset, limit));
   }
 
   public int countByQuery(DbSession session, ComponentQuery query) {
-    if (query.getComponentIds() != null && query.getComponentIds().isEmpty()) {
+    return countByQueryImpl(session, null, query);
+  }
+
+  public int countByQuery(DbSession session, String organizationUuid, ComponentQuery query) {
+    requireNonNull(organizationUuid, "organizationUuid can't be null");
+    return countByQueryImpl(session, organizationUuid, query);
+  }
+
+  private static int countByQueryImpl(DbSession session, @Nullable String organizationUuid, ComponentQuery query) {
+    Set<Long> componentIds = query.getComponentIds();
+    if (componentIds != null && componentIds.isEmpty()) {
       return 0;
     }
-    return mapper(session).countByQuery(query);
+    return mapper(session).countByQuery(organizationUuid, query);
   }
 
   public List<ComponentDto> selectSubProjectsByComponentUuids(DbSession session, Collection<String> keys) {
@@ -342,5 +362,4 @@ public class ComponentDao implements Dao {
   private static ComponentMapper mapper(DbSession session) {
     return session.getMapper(ComponentMapper.class);
   }
-
 }
index 9c3bb96b7e5ba08a546e06fece66075c3317e1b5..2cddadffbd43ba201728beb7b31efddb22410061 100644 (file)
@@ -65,9 +65,9 @@ public interface ComponentMapper {
    */
   int countComponentByOrganizationAndId(@Param("organizationUuid") String organizationUuid, @Param("componentId") long componentId);
 
-  List<ComponentDto> selectByQuery(@Param("query") ComponentQuery query, RowBounds rowBounds);
+  List<ComponentDto> selectByQuery(@Nullable @Param("organizationUuid") String organizationUuid, @Param("query") ComponentQuery query, RowBounds rowBounds);
 
-  int countByQuery(@Param("query") ComponentQuery query);
+  int countByQuery(@Nullable @Param("organizationUuid") String organizationUuid, @Param("query") ComponentQuery query);
 
   List<ComponentDto> selectDescendants(@Param("query") ComponentTreeQuery query, @Param("baseUuid") String baseUuid, @Param("baseUuidPath") String baseUuidPath);
 
index a9e91ccca50481eacad8b779fd5f5d61ede3fe11..b8a97b3df49c20ece469f090485cb5deecea8910 100644 (file)
     where
       p.enabled=${_true}
       AND p.copy_component_uuid is null
+      <if test="organizationUuid!=null">
+        and p.organization_uuid=#{organizationUuid,jdbcType=VARCHAR}
+      </if>
       <if test="query.qualifiers!=null">
       AND p.qualifier in
         <foreach collection="query.qualifiers" item="qualifier" open="(" close=")" separator=",">
index 632d98a3d8f55a300edb56cdcc6c81d29a15f0cb..646a54be31a467d72913981c5b51509541c70c7b 100644 (file)
@@ -66,9 +66,10 @@ public class ComponentDaoTest {
   private static final String FILE_2_UUID = "file-2-uuid";
   private static final String FILE_3_UUID = "file-3-uuid";
   private static final String A_VIEW_UUID = "view-uuid";
+  private static final ComponentQuery ALL_PROJECTS_COMPONENT_QUERY = ComponentQuery.builder().setQualifiers("TRK").build();
 
   @Rule
-  public ExpectedException thrown = ExpectedException.none();
+  public ExpectedException expectedException = ExpectedException.none();
   @Rule
   public DbTester db = DbTester.create(System2.INSTANCE);
 
@@ -144,7 +145,7 @@ public class ComponentDaoTest {
 
   @Test
   public void selectOrFailByUuid_fails_when_component_not_found() {
-    thrown.expect(RowNotFoundException.class);
+    expectedException.expect(RowNotFoundException.class);
 
     db.prepareDbUnit(getClass(), "shared.xml");
 
@@ -175,7 +176,7 @@ public class ComponentDaoTest {
 
   @Test
   public void selectOrFailByKey_fails_when_component_not_found() {
-    thrown.expect(RowNotFoundException.class);
+    expectedException.expect(RowNotFoundException.class);
 
     db.prepareDbUnit(getClass(), "shared.xml");
 
@@ -345,8 +346,8 @@ public class ComponentDaoTest {
 
   @Test
   public void fail_with_IAE_select_component_keys_by_qualifiers_on_empty_qualifier() throws Exception {
-    thrown.expect(IllegalArgumentException.class);
-    thrown.expectMessage("Qualifiers cannot be empty");
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Qualifiers cannot be empty");
 
     db.prepareDbUnit(getClass(), "shared.xml");
     underTest.selectComponentsByQualifiers(dbSession, Collections.<String>emptySet());
@@ -807,7 +808,23 @@ public class ComponentDaoTest {
   }
 
   @Test
-  public void select_by_query_with_paging_query_and_qualifiers() {
+  public void selectByQuery_with_organization_throws_NPE_of_organizationUuid_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("organizationUuid can't be null");
+
+    underTest.selectByQuery(dbSession, null, ALL_PROJECTS_COMPONENT_QUERY, 1, 1);
+  }
+
+  @Test
+  public void countByQuery_with_organization_throws_NPE_of_organizationUuid_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("organizationUuid can't be null");
+
+    underTest.countByQuery(dbSession, null, ALL_PROJECTS_COMPONENT_QUERY);
+  }
+
+  @Test
+  public void selectByQuery_with_paging_query_and_qualifiers() {
     OrganizationDto organizationDto = db.organizations().insert();
     componentDb.insertProjectAndSnapshot(newProjectDto(organizationDto).setName("aaaa-name"));
     componentDb.insertProjectAndSnapshot(newView(organizationDto));
@@ -827,7 +844,44 @@ public class ComponentDaoTest {
   }
 
   @Test
-  public void select_by_query_name_with_special_characters() {
+  public void selectByQuery_with_organization_filters_on_specified_organization() {
+    OrganizationDto organization1 = db.organizations().insert();
+    OrganizationDto organization2 = db.organizations().insert();
+    ComponentDto project1 = componentDb.insertProject(organization1);
+    ComponentDto project2 = componentDb.insertProject(organization2);
+
+    assertThat(underTest.selectByQuery(dbSession, ALL_PROJECTS_COMPONENT_QUERY, 0, 2))
+      .extracting(ComponentDto::uuid)
+      .containsOnly(project1.uuid(), project2.uuid());
+    assertThat(underTest.selectByQuery(dbSession, organization1.getUuid(), ALL_PROJECTS_COMPONENT_QUERY, 0, 2))
+      .extracting(ComponentDto::uuid)
+      .containsOnly(project1.uuid());
+    assertThat(underTest.selectByQuery(dbSession, organization2.getUuid(), ALL_PROJECTS_COMPONENT_QUERY, 0, 2))
+      .extracting(ComponentDto::uuid)
+      .containsOnly(project2.uuid());
+    assertThat(underTest.selectByQuery(dbSession, "non existent organization uuid", ALL_PROJECTS_COMPONENT_QUERY, 0, 2))
+      .isEmpty();
+  }
+
+  @Test
+  public void countByQuery_with_organization_filters_on_specified_organization() {
+    OrganizationDto organization1 = db.organizations().insert();
+    OrganizationDto organization2 = db.organizations().insert();
+    ComponentDto project1 = componentDb.insertProject(organization1);
+    ComponentDto project2 = componentDb.insertProject(organization2);
+
+    assertThat(underTest.countByQuery(dbSession, ALL_PROJECTS_COMPONENT_QUERY))
+      .isEqualTo(2);
+    assertThat(underTest.countByQuery(dbSession, organization1.getUuid(), ALL_PROJECTS_COMPONENT_QUERY))
+      .isEqualTo(1);
+    assertThat(underTest.countByQuery(dbSession, organization2.getUuid(), ALL_PROJECTS_COMPONENT_QUERY))
+      .isEqualTo(1);
+    assertThat(underTest.countByQuery(dbSession, "non existent organization uuid", ALL_PROJECTS_COMPONENT_QUERY))
+      .isEqualTo(0);
+  }
+
+  @Test
+  public void selectByQuery_name_with_special_characters() {
     componentDb.insertProjectAndSnapshot(newProjectDto(db.getDefaultOrganization()).setName("project-\\_%/-name"));
 
     ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("-\\_%/-").setQualifiers(Qualifiers.PROJECT).build();
@@ -838,7 +892,7 @@ public class ComponentDaoTest {
   }
 
   @Test
-  public void select_by_query_key_with_special_characters() {
+  public void selectByQuery_key_with_special_characters() {
     componentDb.insertProjectAndSnapshot(newProjectDto(db.organizations().insert()).setKey("project-_%-key"));
 
     ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("project-_%-key").setQualifiers(Qualifiers.PROJECT).build();
@@ -849,7 +903,7 @@ public class ComponentDaoTest {
   }
 
   @Test
-  public void select_by_query_filter_on_language() {
+  public void selectByQuery_filter_on_language() {
     componentDb.insertComponent(newProjectDto(db.getDefaultOrganization()).setKey("java-project-key").setLanguage("java"));
     componentDb.insertComponent(newProjectDto(db.getDefaultOrganization()).setKey("cpp-project-key").setLanguage("cpp"));
 
@@ -861,7 +915,7 @@ public class ComponentDaoTest {
   }
 
   @Test
-  public void select_by_query_on_empty_list_of_component_id() {
+  public void selectByQuery_on_empty_list_of_component_id() {
     ComponentQuery dbQuery = ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT).setComponentIds(emptySet()).build();
     List<ComponentDto> result = underTest.selectByQuery(dbSession, dbQuery, 0, 10);
     int count = underTest.countByQuery(dbSession, dbQuery);
@@ -871,7 +925,7 @@ public class ComponentDaoTest {
   }
 
   @Test
-  public void select_by_query_on_component_ids() {
+  public void selectByQuery_on_component_ids() {
     OrganizationDto organizationDto = db.organizations().insert();
     ComponentDto sonarqube = componentDb.insertComponent(newProjectDto(organizationDto));
     ComponentDto jdk8 = componentDb.insertComponent(newProjectDto(organizationDto));
index 80d5acb65cb209baaa60d8891dc288d67a27c420..00910b0366ddbf2ba122b5b63339f6019b33203e 100644 (file)
@@ -26,12 +26,22 @@ import javax.annotation.Nullable;
 import static java.util.Objects.requireNonNull;
 
 public class SearchWsRequest {
+  private String organization;
   private List<String> qualifiers;
   private Integer page;
   private Integer pageSize;
   private String query;
   private String language;
 
+  public String getOrganization() {
+    return organization;
+  }
+
+  public SearchWsRequest setOrganization(String organization) {
+    this.organization = organization;
+    return this;
+  }
+
   public List<String> getQualifiers() {
     return qualifiers;
   }