package org.sonar.server.component.ws;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import org.sonar.api.i18n.I18n;
import org.sonar.api.resources.Languages;
import org.sonar.api.resources.ResourceTypes;
import org.sonarqube.ws.client.component.SearchWsRequest;
import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.stream.Collectors.toMap;
import static org.sonar.core.util.Protobuf.setNullable;
+import static org.sonar.core.util.stream.MoreCollectors.toHashSet;
import static org.sonar.server.util.LanguageParamUtils.getExampleValue;
import static org.sonar.server.util.LanguageParamUtils.getLanguageKeys;
-import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext;
import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter;
+import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext;
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;
OrganizationDto organization = getOrganization(dbSession, request);
Paging paging = buildPaging(dbSession, request, organization, query);
List<ComponentDto> components = searchComponents(dbSession, organization, query, paging);
+ Map<String, String> projectKeysByUuids = searchProjectsKeysByUuids(dbSession, components);
- return buildResponse(components, organization, paging);
+ return buildResponse(components, organization, projectKeysByUuids, paging);
}
}
+ private Map<String, String> searchProjectsKeysByUuids(DbSession dbSession, List<ComponentDto> components) {
+ Set<String> projectUuidsToSearch = components.stream()
+ .map(ComponentDto::projectUuid)
+ .collect(toHashSet());
+ List<ComponentDto> projects = dbClient.componentDao().selectByUuids(dbSession, projectUuidsToSearch);
+ return projects.stream().collect(toMap(ComponentDto::uuid, ComponentDto::key));
+ }
+
private static ComponentQuery buildQuery(SearchWsRequest request) {
List<String> qualifiers = request.getQualifiers();
return ComponentQuery.builder()
return userSession.keepAuthorizedComponents(UserRole.USER, componentDtos);
}
- private static SearchWsResponse buildResponse(List<ComponentDto> components, OrganizationDto organization, Paging paging) {
+ private static SearchWsResponse buildResponse(List<ComponentDto> components, OrganizationDto organization, Map<String, String> projectKeysByUuids, Paging paging) {
SearchWsResponse.Builder responseBuilder = SearchWsResponse.newBuilder();
responseBuilder.getPagingBuilder()
.setPageIndex(paging.pageIndex())
.build();
components.stream()
- .map(dto -> dtoToComponent(organization, dto))
+ .map(dto -> dtoToComponent(organization, dto, projectKeysByUuids.get(dto.projectUuid())))
.forEach(responseBuilder::addComponents);
return responseBuilder.build();
}
- private static WsComponents.Component dtoToComponent(OrganizationDto organization, ComponentDto dto) {
+ private static WsComponents.Component dtoToComponent(OrganizationDto organization, ComponentDto dto, String projectKey) {
checkArgument(
organization.getUuid().equals(dto.getOrganizationUuid()),
"No Organization found for uuid '%s'",
.setOrganization(organization.getKey())
.setId(dto.uuid())
.setKey(dto.key())
+ .setProject(projectKey)
.setName(dto.name())
.setQualifier(dto.qualifier());
setNullable(dto.language(), builder::setLanguage);
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.MediaTypes;
+import org.sonarqube.ws.WsComponents.Component;
import org.sonarqube.ws.WsComponents.SearchWsResponse;
import org.sonarqube.ws.client.component.SearchWsRequest;
+import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.api.resources.Qualifiers.DIRECTORY;
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonar.test.JsonAssert.assertJson;
-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;
assertThat(response.getComponentsList()).extracting(Component::getKey).containsOnly(file1.getKey(), file2.getKey());
}
+ @Test
+ public void return_project_key() throws IOException {
+ ComponentDto project = ComponentTesting.newPublicProjectDto(db.getDefaultOrganization());
+ ComponentDto module = ComponentTesting.newModuleDto(project);
+ ComponentDto file1 = newFileDto(module).setKey("file1");
+ ComponentDto file2 = newFileDto(module).setKey("file2");
+ ComponentDto file3 = newFileDto(project).setKey("file3");
+ db.components().insertComponents(project, module, file1, file2, file3);
+
+ SearchWsResponse response = call(new SearchWsRequest().setQualifiers(asList(PROJECT, MODULE, FILE)));
+
+ assertThat(response.getComponentsList()).extracting(Component::getKey, Component::getProject)
+ .containsOnly(tuple(project.getKey(), project.getKey()),
+ tuple(module.getKey(), project.getKey()),
+ tuple(file1.getKey(), project.getKey()),
+ tuple(file2.getKey(), project.getKey()),
+ tuple(file3.getKey(), project.getKey()));
+ }
+
@Test
public void do_not_verify_permissions_if_user_is_root() throws IOException {
OrganizationDto org = db.organizations().insert();