aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java10
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/ws/ShowAction.java45
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java5
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentDtoToWsComponentTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ws/ShowActionTest.java61
-rw-r--r--sonar-ws/src/main/protobuf/ws-components.proto1
6 files changed, 98 insertions, 27 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java
index 63951b30c39..cc5e7aaf032 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java
@@ -20,12 +20,15 @@
package org.sonar.server.component.ws;
import java.util.Objects;
+import java.util.Optional;
import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonarqube.ws.WsComponents;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.emptyToNull;
+import static org.sonar.api.utils.DateUtils.formatDateTime;
import static org.sonar.core.util.Protobuf.setNullable;
class ComponentDtoToWsComponent {
@@ -33,15 +36,15 @@ class ComponentDtoToWsComponent {
// prevent instantiation
}
- static WsComponents.Component.Builder componentDtoToWsComponent(ComponentDto dto, OrganizationDto organizationDto) {
+ static WsComponents.Component.Builder componentDtoToWsComponent(ComponentDto dto, OrganizationDto organizationDto, Optional<SnapshotDto> lastAnalysis) {
checkArgument(
Objects.equals(dto.getOrganizationUuid(), organizationDto.getUuid()),
"OrganizationUuid (%s) of ComponentDto to convert to Ws Component is not the same as the one (%s) of the specified OrganizationDto",
dto.getOrganizationUuid(), organizationDto.getUuid());
- return componentDtoToWsComponent(dto, organizationDto.getKey());
+ return componentDtoToWsComponent(dto, organizationDto.getKey(), lastAnalysis);
}
- private static WsComponents.Component.Builder componentDtoToWsComponent(ComponentDto dto, String organizationDtoKey) {
+ private static WsComponents.Component.Builder componentDtoToWsComponent(ComponentDto dto, String organizationDtoKey, Optional<SnapshotDto> lastAnalysis) {
WsComponents.Component.Builder wsComponent = WsComponents.Component.newBuilder()
.setOrganization(organizationDtoKey)
.setId(dto.uuid())
@@ -51,6 +54,7 @@ class ComponentDtoToWsComponent {
setNullable(emptyToNull(dto.path()), wsComponent::setPath);
setNullable(emptyToNull(dto.description()), wsComponent::setDescription);
setNullable(emptyToNull(dto.language()), wsComponent::setLanguage);
+ lastAnalysis.ifPresent(analysis -> wsComponent.setAnalysisDate(formatDateTime(analysis.getCreatedAt())));
return wsComponent;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ShowAction.java
index b65ae45a1e0..04f1aafca1c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ShowAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ShowAction.java
@@ -20,6 +20,9 @@
package org.sonar.server.component.ws;
import java.util.List;
+import java.util.Optional;
+import java.util.stream.IntStream;
+import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
@@ -27,6 +30,7 @@ import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.component.ComponentFinder.ParamNames;
@@ -54,26 +58,6 @@ public class ShowAction implements ComponentsWsAction {
this.componentFinder = componentFinder;
}
- private static ShowWsResponse buildResponse(ComponentDto component, OrganizationDto organizationDto, List<ComponentDto> orderedAncestors) {
- ShowWsResponse.Builder response = ShowWsResponse.newBuilder();
- response.setComponent(componentDtoToWsComponent(component, organizationDto));
-
- // ancestors are ordered from root to leaf, whereas it's the opposite
- // in WS response
- for (int i = orderedAncestors.size() - 1; i >= 0; i--) {
- ComponentDto ancestor = orderedAncestors.get(i);
- response.addAncestors(componentDtoToWsComponent(ancestor, organizationDto));
- }
-
- return response.build();
- }
-
- private static ShowWsRequest toShowWsRequest(Request request) {
- return new ShowWsRequest()
- .setId(request.param(PARAM_COMPONENT_ID))
- .setKey(request.param(PARAM_COMPONENT));
- }
-
@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction(ACTION_SHOW)
@@ -84,6 +68,7 @@ public class ShowAction implements ComponentsWsAction {
PARAM_COMPONENT_ID, PARAM_COMPONENT))
.setResponseExample(getClass().getResource("show-example.json"))
.setSince("5.4")
+ .setChangelog(new Change("6.4", "Analysis date has been added to the response"))
.setHandler(this);
action.createParam(PARAM_COMPONENT_ID)
@@ -109,9 +94,10 @@ public class ShowAction implements ComponentsWsAction {
DbSession dbSession = dbClient.openSession(false);
try {
ComponentDto component = getComponentByUuidOrKey(dbSession, request);
+ Optional<SnapshotDto> lastAnalysis = dbClient.snapshotDao().selectLastAnalysisByComponentUuid(dbSession, component.projectUuid());
List<ComponentDto> ancestors = dbClient.componentDao().selectAncestors(dbSession, component);
OrganizationDto organizationDto = componentFinder.getOrganization(dbSession, component);
- return buildResponse(component, organizationDto, ancestors);
+ return buildResponse(component, organizationDto, ancestors, lastAnalysis);
} finally {
dbClient.closeSession(dbSession);
}
@@ -122,4 +108,21 @@ public class ShowAction implements ComponentsWsAction {
userSession.checkComponentPermission(UserRole.USER, component);
return component;
}
+
+ private static ShowWsResponse buildResponse(ComponentDto component, OrganizationDto organizationDto, List<ComponentDto> orderedAncestors, Optional<SnapshotDto> lastAnalysis) {
+ ShowWsResponse.Builder response = ShowWsResponse.newBuilder();
+ response.setComponent(componentDtoToWsComponent(component, organizationDto, lastAnalysis));
+
+ // ancestors are ordered from root to leaf, whereas it's the opposite in WS response
+ int size = orderedAncestors.size() - 1;
+ IntStream.rangeClosed(0, size).forEach(
+ index -> response.addAncestors(componentDtoToWsComponent(orderedAncestors.get(size - index), organizationDto, lastAnalysis)));
+ return response.build();
+ }
+
+ private static ShowWsRequest toShowWsRequest(Request request) {
+ return new ShowWsRequest()
+ .setId(request.param(PARAM_COMPONENT_ID))
+ .setKey(request.param(PARAM_COMPONENT));
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java
index b01861db1c7..c5e8be4a337 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java
@@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import javax.annotation.CheckForNull;
import org.sonar.api.i18n.I18n;
@@ -63,8 +64,8 @@ import static org.sonar.db.component.ComponentTreeQuery.Strategy.LEAVES;
import static org.sonar.server.component.ComponentFinder.ParamNames.COMPONENT_ID_AND_COMPONENT;
import static org.sonar.server.component.ws.ComponentDtoToWsComponent.componentDtoToWsComponent;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-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.checkRequest;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.ACTION_TREE;
@@ -213,7 +214,7 @@ public class TreeAction implements ComponentsWsAction {
private static WsComponents.Component.Builder toWsComponent(ComponentDto component, OrganizationDto organizationDto,
Map<String, ComponentDto> referenceComponentsByUuid) {
- WsComponents.Component.Builder wsComponent = componentDtoToWsComponent(component, organizationDto);
+ WsComponents.Component.Builder wsComponent = componentDtoToWsComponent(component, organizationDto, Optional.empty());
ComponentDto referenceComponent = referenceComponentsByUuid.get(component.getCopyResourceUuid());
if (referenceComponent != null) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentDtoToWsComponentTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentDtoToWsComponentTest.java
index d2a2bfc0ba5..d79b53be798 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentDtoToWsComponentTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentDtoToWsComponentTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.component.ws;
+import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -43,7 +44,7 @@ public class ComponentDtoToWsComponentTest {
expectedException.expectMessage("OrganizationUuid (" + organizationDto1.getUuid() + ") of ComponentDto to convert " +
"to Ws Component is not the same as the one (" + organizationDto2.getUuid() + ") of the specified OrganizationDto");
- componentDtoToWsComponent(componentDto, organizationDto2);
+ componentDtoToWsComponent(componentDto, organizationDto2, Optional.empty());
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ShowActionTest.java
index 6dc3dbb8ab1..e384589f0f2 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ShowActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ShowActionTest.java
@@ -22,6 +22,7 @@ package org.sonar.server.component.ws;
import com.google.common.base.Throwables;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Date;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
@@ -40,12 +41,16 @@ import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.MediaTypes;
+import org.sonarqube.ws.WsComponents;
import org.sonarqube.ws.WsComponents.ShowWsResponse;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.utils.DateUtils.formatDateTime;
import static org.sonar.db.component.ComponentTesting.newDirectory;
import static org.sonar.db.component.ComponentTesting.newFileDto;
+import static org.sonar.db.component.ComponentTesting.newModuleDto;
import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonar.db.component.SnapshotTesting.newAnalysis;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_COMPONENT;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_COMPONENT_ID;
@@ -93,6 +98,62 @@ public class ShowActionTest {
ShowWsResponse response = newRequest("project-uuid", null);
assertThat(response.getComponent().getId()).isEqualTo("project-uuid");
+ assertThat(response.getComponent().hasAnalysisDate()).isFalse();
+ }
+
+ @Test
+ public void show_with_ancestors_when_not_project() throws Exception {
+ ComponentDto project = componentDb.insertProject();
+ ComponentDto module = componentDb.insertComponent(newModuleDto(project));
+ ComponentDto directory = componentDb.insertComponent(newDirectory(module, "dir"));
+ ComponentDto file = componentDb.insertComponent(newFileDto(directory));
+ userSession.addProjectUuidPermissions(UserRole.USER, project.uuid());
+
+ ShowWsResponse response = newRequest(null, file.key());
+
+ assertThat(response.getComponent().getKey()).isEqualTo(file.key());
+ assertThat(response.getAncestorsList()).extracting(WsComponents.Component::getKey).containsOnly(directory.key(), module.key(), project.key());
+ }
+
+ @Test
+ public void show_without_ancestors_when_project() throws Exception {
+ ComponentDto project = componentDb.insertProject();
+ componentDb.insertComponent(newModuleDto(project));
+ userSession.addProjectUuidPermissions(UserRole.USER, project.uuid());
+
+ ShowWsResponse response = newRequest(null, project.key());
+
+ assertThat(response.getComponent().getKey()).isEqualTo(project.key());
+ assertThat(response.getAncestorsList()).isEmpty();
+ }
+
+ @Test
+ public void show_with_last_analysis_date() throws Exception {
+ ComponentDto project = componentDb.insertProject();
+ componentDb.insertSnapshot(newAnalysis(project).setCreatedAt(1_000_000_000L).setLast(false));
+ componentDb.insertSnapshot(newAnalysis(project).setCreatedAt(2_000_000_000L).setLast(false));
+ componentDb.insertSnapshot(newAnalysis(project).setCreatedAt(3_000_000_000L).setLast(true));
+ userSession.addProjectUuidPermissions(UserRole.USER, project.uuid());
+
+ ShowWsResponse response = newRequest(null, project.key());
+
+ assertThat(response.getComponent().getAnalysisDate()).isNotEmpty().isEqualTo(formatDateTime(new Date(3_000_000_000L)));
+ }
+
+ @Test
+ public void show_with_ancestors_and_analysis_date() throws Exception {
+ ComponentDto project = componentDb.insertProject();
+ componentDb.insertSnapshot(newAnalysis(project).setCreatedAt(3_000_000_000L).setLast(true));
+ ComponentDto module = componentDb.insertComponent(newModuleDto(project));
+ ComponentDto directory = componentDb.insertComponent(newDirectory(module, "dir"));
+ ComponentDto file = componentDb.insertComponent(newFileDto(directory));
+ userSession.addProjectUuidPermissions(UserRole.USER, project.uuid());
+
+ ShowWsResponse response = newRequest(null, file.key());
+
+ String expectedDate = formatDateTime(new Date(3_000_000_000L));
+ assertThat(response.getAncestorsList()).extracting(WsComponents.Component::getAnalysisDate)
+ .containsOnly(expectedDate, expectedDate, expectedDate);
}
@Test
diff --git a/sonar-ws/src/main/protobuf/ws-components.proto b/sonar-ws/src/main/protobuf/ws-components.proto
index d99095e075c..2c5b2673eb4 100644
--- a/sonar-ws/src/main/protobuf/ws-components.proto
+++ b/sonar-ws/src/main/protobuf/ws-components.proto
@@ -87,4 +87,5 @@ message Component {
optional string path = 9;
optional string language = 10;
optional bool isFavorite = 11;
+ optional string analysisDate = 13;
}