import static java.util.Comparator.comparing;
import static java.util.Objects.requireNonNull;
import static java.util.function.Function.identity;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_03;
import static org.sonar.server.measure.ws.ComponentDtoToWsComponent.dbToWsComponent;
import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.dbToWsMeasure;
import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_002;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_KEYS;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_KEYS;
public class SearchAction implements MeasuresWsAction {
- static final String PARAM_COMPONENT_IDS = "componentIds";
- static final String PARAM_COMPONENT_KEYS = "componentKeys";
private final DbClient dbClient;
.setInternal(true)
.setDescription("Search for component measures ordered by component names.<br>" +
"At most %d components can be provided.<br>" +
- "Either '%s' or '%s' must be provided, not both.<br>" +
"Requires one of the following permissions:" +
"<ul>" +
" <li>'Administer System'</li>" +
" <li>'Administer' rights on the provided components</li>" +
" <li>'Browse' on the provided components</li>" +
"</ul>",
- SearchRequest.MAX_NB_COMPONENTS, PARAM_COMPONENT_IDS, PARAM_COMPONENT_KEYS)
- .setSince("6.1")
+ SearchRequest.MAX_NB_COMPONENTS)
+ .setSince("6.2")
.setResponseExample(getClass().getResource("search-example.json"))
.setHandler(this);
createMetricKeysParameter(action);
- action.createParam(PARAM_COMPONENT_IDS)
- .setDescription("Comma-separated list of component ids")
- .setExampleValue(String.join(",", UUID_EXAMPLE_01, UUID_EXAMPLE_02, UUID_EXAMPLE_03));
-
action.createParam(PARAM_COMPONENT_KEYS)
.setDescription("Comma-separated list of component keys")
- .setExampleValue(String.join(",", KEY_PROJECT_EXAMPLE_001, KEY_FILE_EXAMPLE_001, KEY_PROJECT_EXAMPLE_002, KEY_FILE_EXAMPLE_002));
-
+ .setExampleValue(String.join(",", KEY_PROJECT_EXAMPLE_001, KEY_FILE_EXAMPLE_001, KEY_PROJECT_EXAMPLE_002, KEY_FILE_EXAMPLE_002))
+ .setRequired(true);
}
@Override
private SearchRequest createRequest() {
request = SearchRequest.builder()
.setMetricKeys(httpRequest.mandatoryParamAsStrings(PARAM_METRIC_KEYS))
- .setComponentIds(httpRequest.paramAsStrings(PARAM_COMPONENT_IDS))
.setComponentKeys(httpRequest.paramAsStrings(PARAM_COMPONENT_KEYS))
.build();
private List<ComponentDto> searchComponents() {
requireNonNull(request);
- if (request.hasComponentIds()) {
- List<ComponentDto> componentsByUuid = searchByComponentUuids(dbSession, request.getComponentIds());
- List<String> componentUuids = componentsByUuid.stream().map(ComponentDto::uuid).collect(Collectors.toList());
- checkArgument(componentsByUuid.size() == request.getComponentIds().size(), "The following component ids are not found: %s",
- String.join(", ", difference(request.getComponentIds(), componentUuids)));
- return componentsByUuid;
- } else {
- List<ComponentDto> componentsByKey = searchByComponentKeys(dbSession, request.getComponentKeys());
- List<String> componentKeys = componentsByKey.stream().map(ComponentDto::key).collect(Collectors.toList());
- checkArgument(componentsByKey.size() == request.getComponentKeys().size(), "The following component keys are not found: %s",
- String.join(", ", difference(request.getComponentKeys(), componentKeys)));
- return componentsByKey;
- }
- }
-
- private List<ComponentDto> searchByComponentUuids(DbSession dbSession, List<String> componentUuids) {
- return dbClient.componentDao().selectByUuids(dbSession, componentUuids);
+ List<ComponentDto> componentsByKey = searchByComponentKeys(dbSession, request.getComponentKeys());
+ List<String> componentKeys = componentsByKey.stream().map(ComponentDto::key).collect(Collectors.toList());
+ checkArgument(componentsByKey.size() == request.getComponentKeys().size(), "The following component keys are not found: %s",
+ String.join(", ", difference(request.getComponentKeys(), componentKeys)));
+ return componentsByKey;
}
private List<ComponentDto> searchByComponentKeys(DbSession dbSession, List<String> componentKeys) {
package org.sonar.server.measure.ws;
+import com.google.common.base.Joiner;
import com.google.common.base.Throwables;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.WsMeasures.Measure;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
import static org.sonar.db.metric.MetricTesting.newMetricDto;
-import static org.sonar.server.measure.ws.SearchAction.PARAM_COMPONENT_IDS;
-import static org.sonar.server.measure.ws.SearchAction.PARAM_COMPONENT_KEYS;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.MediaTypes.PROTOBUF;
+import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_KEYS;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_KEYS;
public class SearchActionTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
+
ComponentDbTester componentDb = new ComponentDbTester(db);
DbClient dbClient = db.getDbClient();
DbSession dbSession = db.getSession();
@Test
public void json_example() {
- insertJsonExampleData();
+ List<String> componentKeys = insertJsonExampleData();
String result = ws.newRequest()
- .setParam(PARAM_COMPONENT_IDS, "project-id,AVIwDXE-bJbJqrw6wFv5,AVIwDXE-bJbJqrw6wFv8,AVIwDXE_bJbJqrw6wFwJ")
+ .setParam(PARAM_COMPONENT_KEYS, Joiner.on(",").join(componentKeys))
.setParam(PARAM_METRIC_KEYS, "ncloc, complexity, new_violations")
.execute()
.getInput();
ComponentDto dbComponent = componentDb.insertComponent(newProjectDto());
insertComplexityMetric();
- SearchWsResponse result = callByComponentUuids(singletonList(dbComponent.uuid()), singletonList("complexity"));
+ SearchWsResponse result = call(singletonList(dbComponent.key()), singletonList("complexity"));
assertThat(result.getComponentsCount()).isEqualTo(1);
SearchWsResponse.Component wsComponent = result.getComponents(0);
- assertThat(wsComponent.getId()).isEqualTo(dbComponent.uuid());
assertThat(wsComponent.getKey()).isEqualTo(dbComponent.key());
assertThat(wsComponent.getName()).isEqualTo(dbComponent.name());
}
- @Test
- public void search_by_component_uuid() {
- ComponentDto project = componentDb.insertProject();
- insertComplexityMetric();
-
- SearchWsResponse result = callByComponentUuids(singletonList(project.uuid()), singletonList("complexity"));
-
- assertThat(result.getComponentsCount()).isEqualTo(1);
- assertThat(result.getComponents(0).getId()).isEqualTo(project.uuid());
- }
-
@Test
public void search_by_component_key() {
ComponentDto project = componentDb.insertProject();
insertComplexityMetric();
- SearchWsResponse result = callByComponentKeys(singletonList(project.key()), singletonList("complexity"));
+ SearchWsResponse result = call(singletonList(project.key()), singletonList("complexity"));
assertThat(result.getComponentsCount()).isEqualTo(1);
- assertThat(result.getComponents(0).getId()).isEqualTo(project.uuid());
+ assertThat(result.getComponents(0).getKey()).isEqualTo(project.key());
}
@Test
newMeasureDto(coverage, directoryDto, projectSnapshot).setValue(42.0d));
db.commit();
- SearchWsResponse result = callByComponentUuids(newArrayList(directoryDto.uuid(), file.uuid()), newArrayList("ncloc", "coverage", "new_violations"));
+ SearchWsResponse result = call(newArrayList(directoryDto.key(), file.key()), newArrayList("ncloc", "coverage", "new_violations"));
// directory is not eligible for best value
assertThat(result.getMeasuresList().stream()
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("The 'metricKeys' parameter is missing");
- callByComponentUuids(singletonList(project.uuid()), null);
+ call(singletonList(project.uuid()), null);
}
@Test
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Metric keys must be provided");
- callByComponentUuids(singletonList(project.uuid()), emptyList());
+ call(singletonList(project.uuid()), emptyList());
}
@Test
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("The following metrics are not found: ncloc, violations");
- callByComponentUuids(singletonList(project.uuid()), newArrayList("violations", "complexity", "ncloc"));
+ call(singletonList(project.key()), newArrayList("violations", "complexity", "ncloc"));
}
@Test
insertComplexityMetric();
expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Either component ids or component keys must be provided, not both");
-
- call(null, null, singletonList("complexity"));
- }
-
- @Test
- public void fail_if_empty_component_uuid() {
- insertComplexityMetric();
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Either component ids or component keys must be provided, not both");
+ expectedException.expectMessage("Component keys must be provided");
- callByComponentUuids(emptyList(), singletonList("complexity"));
+ call(null, singletonList("complexity"));
}
@Test
insertComplexityMetric();
expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Either component ids or component keys must be provided, not both");
-
- callByComponentKeys(emptyList(), singletonList("complexity"));
- }
-
- @Test
- public void fail_if_unknown_component_uuid() {
- insertComplexityMetric();
- ComponentDto project = componentDb.insertProject();
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("The following component ids are not found: ANOTHER_PROJECT_ID, YOUR_PROJECT_ID");
+ expectedException.expectMessage("Component keys must be provided");
- callByComponentUuids(newArrayList("YOUR_PROJECT_ID", project.uuid(), "ANOTHER_PROJECT_ID"), singletonList("complexity"));
+ call(emptyList(), singletonList("complexity"));
}
@Test
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("The following component keys are not found: ANOTHER_PROJECT_KEY, YOUR_PROJECT_KEY");
- callByComponentKeys(newArrayList("YOUR_PROJECT_KEY", project.key(), "ANOTHER_PROJECT_KEY"), singletonList("complexity"));
- }
-
- @Test
- public void fail_if_component_id_and_key() {
- ComponentDto project = componentDb.insertProject();
- ComponentDto anotherProject = componentDb.insertProject();
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Either component ids or component keys must be provided, not both");
-
- call(singletonList(project.uuid()), singletonList(anotherProject.key()), singletonList("complexity"));
+ call(newArrayList("YOUR_PROJECT_KEY", project.key(), "ANOTHER_PROJECT_KEY"), singletonList("complexity"));
}
@Test
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("101 components provided, more than maximum authorized (100)");
- callByComponentUuids(uuids, singletonList("complexity"));
+ call(uuids, singletonList("complexity"));
}
@Test
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("101 components provided, more than maximum authorized (100)");
- callByComponentKeys(keys, singletonList("complexity"));
+ call(keys, singletonList("complexity"));
}
@Test
assertThat(result.key()).isEqualTo("search");
assertThat(result.isPost()).isFalse();
assertThat(result.isInternal()).isTrue();
- assertThat(result.since()).isEqualTo("6.1");
- assertThat(result.params()).hasSize(3);
+ assertThat(result.since()).isEqualTo("6.2");
+ assertThat(result.params()).hasSize(2);
assertThat(result.responseExampleAsString()).isNotEmpty();
assertThat(result.description()).isEqualToIgnoringWhitespace("" +
"Search for component measures ordered by component names.<br>" +
"At most 100 components can be provided.<br>" +
- "Either 'componentIds' or 'componentKeys' must be provided, not both.<br>" +
"Requires one of the following permissions:" +
"<ul>" +
" <li>'Administer System'</li>" +
"</ul>");
}
- private SearchWsResponse callByComponentUuids(@Nullable List<String> uuids, @Nullable List<String> metrics) {
- return call(uuids, null, metrics);
- }
-
- private SearchWsResponse callByComponentKeys(@Nullable List<String> keys, @Nullable List<String> metrics) {
- return call(null, keys, metrics);
- }
-
- private SearchWsResponse call(@Nullable List<String> uuids, @Nullable List<String> keys, @Nullable List<String> metrics) {
+ private SearchWsResponse call(@Nullable List<String> keys, @Nullable List<String> metrics) {
TestRequest request = ws.newRequest()
.setMediaType(PROTOBUF);
- if (uuids != null) {
- request.setParam(PARAM_COMPONENT_IDS, String.join(",", uuids));
- }
if (keys != null) {
request.setParam(PARAM_COMPONENT_KEYS, String.join(",", keys));
}
return metric;
}
- private void insertJsonExampleData() {
+ private List<String> insertJsonExampleData() {
+ List<String> componentKeys = new ArrayList<>();
ComponentDto project = newProjectDto("project-id")
.setKey("MY_PROJECT")
.setName("My Project")
.setDescription("My Project Description")
.setQualifier(Qualifiers.PROJECT);
+ componentKeys.add(project.key());
componentDb.insertComponent(project);
SnapshotDto projectSnapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)
.setPeriodDate(1, parseDateTime("2016-01-11T10:49:50+0100").getTime())
.setLanguage("java")
.setQualifier(Qualifiers.FILE)
.setPath("src/main/java/com/sonarsource/markdown/impl/ElementImpl.java"));
- componentDb.insertComponent(newFileDto(project, null)
+ componentKeys.add(file1.key());
+ ComponentDto file = newFileDto(project, null)
.setUuid("AVIwDXE_bJbJqrw6wFwJ")
.setKey("com.sonarsource:java-markdown:src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java")
.setName("ElementImplTest.java")
.setLanguage("java")
.setQualifier(Qualifiers.UNIT_TEST_FILE)
- .setPath("src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java"));
+ .setPath("src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java");
+ componentKeys.add(file.key());
+ componentDb.insertComponent(file);
ComponentDto dir = componentDb.insertComponent(newDirectory(project, "src/main/java/com/sonarsource/markdown/impl")
.setUuid("AVIwDXE-bJbJqrw6wFv8")
.setKey("com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl")
.setQualifier(Qualifiers.DIRECTORY));
+ componentKeys.add(dir.key());
MetricDto complexity = insertComplexityMetric();
dbClient.measureDao().insert(dbSession,
.setVariation(3, 255.0d));
db.commit();
+ return componentKeys;
}
}
import java.util.List;
import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.requireNonNull;
public class SearchRequest {
public static final int MAX_NB_COMPONENTS = 100;
private final List<String> metricKeys;
- private final List<String> componentIds;
private final List<String> componentKeys;
public SearchRequest(Builder builder) {
metricKeys = builder.metricKeys;
- componentIds = builder.componentIds;
componentKeys = builder.componentKeys;
}
return metricKeys;
}
- public boolean hasComponentIds() {
- return componentIds != null;
- }
-
- public List<String> getComponentIds() {
- return requireNonNull(componentIds, "No component id in request");
- }
-
- public boolean hasComponentKeys() {
- return componentKeys != null;
- }
-
public List<String> getComponentKeys() {
- return requireNonNull(componentKeys, "No component key in request");
+ return componentKeys;
}
public static Builder builder() {
public static class Builder {
private List<String> metricKeys;
- private List<String> componentIds;
private List<String> componentKeys;
private Builder() {
return this;
}
- public Builder setComponentIds(List<String> componentIds) {
- this.componentIds = componentIds;
- return this;
- }
-
public Builder setComponentKeys(List<String> componentKeys) {
this.componentKeys = componentKeys;
return this;
public SearchRequest build() {
checkArgument(metricKeys != null && !metricKeys.isEmpty(), "Metric keys must be provided");
- checkArgument(
- (componentIds != null && !componentIds.isEmpty())
- ^ (componentKeys != null && !componentKeys.isEmpty()),
- "Either component ids or component keys must be provided, not both");
- int nbComponents = componentIds == null ? componentKeys.size() : componentIds.size();
- checkArgument((componentIds != null && componentIds.size() < MAX_NB_COMPONENTS)
- || (componentKeys != null && componentKeys.size() < MAX_NB_COMPONENTS),
- "%s components provided, more than maximum authorized (%s)",
- nbComponents,
- MAX_NB_COMPONENTS);
+ checkArgument(componentKeys != null && !componentKeys.isEmpty(), "Component keys must be provided");
+ int nbComponents = componentKeys.size();
+ checkArgument(nbComponents < MAX_NB_COMPONENTS,
+ "%s components provided, more than maximum authorized (%s)", nbComponents, MAX_NB_COMPONENTS);
return new SearchRequest(this);
}
}