aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2017-06-28 14:31:19 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2017-07-04 16:29:36 +0200
commit471e44c5b229e5b52047eaf81554d9ee9da9cd00 (patch)
tree72e3e87e8731b1fcd3e5d9a65fa9b8e98f9e1293
parent597f139942a1f27d5e6f519388851a8fe37b0881 (diff)
downloadsonarqube-471e44c5b229e5b52047eaf81554d9ee9da9cd00.tar.gz
sonarqube-471e44c5b229e5b52047eaf81554d9ee9da9cd00.zip
SONAR-9482 Show ws returns profile related info only
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ShowAction.java92
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/show-example.json4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ShowActionTest.java133
-rw-r--r--sonar-ws/src/main/protobuf/ws-qualityprofiles.proto20
4 files changed, 204 insertions, 45 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ShowAction.java
index 7b4020baf94..eb15750a717 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ShowAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ShowAction.java
@@ -19,20 +19,43 @@
*/
package org.sonar.server.qualityprofile.ws;
+import java.util.Map;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.qualityprofile.ActiveRuleCountQuery;
+import org.sonar.db.qualityprofile.QProfileDto;
import org.sonarqube.ws.QualityProfiles.ShowWsResponse;
-import org.sonarqube.ws.QualityProfiles.ShowWsResponse.CompareToSonarWay;
+import org.sonarqube.ws.QualityProfiles.ShowWsResponse.QualityProfile;
+import static java.util.Collections.singletonList;
+import static org.sonar.api.rule.RuleStatus.DEPRECATED;
+import static org.sonar.api.utils.DateUtils.formatDateTime;
+import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
+import static org.sonar.server.ws.WsUtils.checkFound;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_COMPARE_TO_SONAR_WAY;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE;
public class ShowAction implements QProfileWsAction {
+ private final DbClient dbClient;
+ private final QProfileWsSupport qProfileWsSupport;
+ private final Languages languages;
+
+ public ShowAction(DbClient dbClient, QProfileWsSupport qProfileWsSupport, Languages languages) {
+ this.dbClient = dbClient;
+ this.qProfileWsSupport = qProfileWsSupport;
+ this.languages = languages;
+ }
+
@Override
public void define(WebService.NewController controller) {
NewAction show = controller.createAction("show")
@@ -55,29 +78,50 @@ public class ShowAction implements QProfileWsAction {
@Override
public void handle(Request request, Response response) throws Exception {
- ShowWsResponse showWsResponse = ShowWsResponse.newBuilder()
- .setProfile(ShowWsResponse.QualityProfile.newBuilder()
- .setKey("AU-TpxcA-iU5OvuD2FL3")
- .setName("My Company Profile")
- .setLanguage("cs")
- .setLanguageName("C#")
- .setIsInherited(true)
- .setIsBuiltIn(false)
- .setIsDefault(false)
- .setParentKey("AU-TpxcA-iU5OvuD2FL1")
- .setParentName("Parent Company Profile")
- .setActiveRuleCount(10)
- .setActiveDeprecatedRuleCount(0)
- .setProjectCount(7)
- .setRuleUpdatedAt("2016-12-22T19:10:03+0100")
- .setLastUsed("2016-12-01T19:10:03+0100"))
- .setCompareToSonarWay(CompareToSonarWay.newBuilder()
- .setProfile("iU5OvuD2FLz")
- .setProfileName("Sonar way")
- .setMissingRuleCount(4)
- .build())
- .build();
- writeProtobuf(showWsResponse, request, response);
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ QProfileDto profile = qProfileWsSupport.getProfile(dbSession, QProfileReference.fromKey(request.mandatoryParam(PARAM_PROFILE)));
+ OrganizationDto organization = qProfileWsSupport.getOrganization(dbSession, profile);
+ boolean isDefault = dbClient.defaultQProfileDao().isDefault(dbSession, profile.getOrganizationUuid(), profile.getKee());
+ ActiveRuleCountQuery.Builder builder = ActiveRuleCountQuery.builder().setOrganization(organization);
+ long activeRuleCount = countActiveRulesByQuery(dbSession, profile, builder);
+ long deprecatedActiveRuleCount = countActiveRulesByQuery(dbSession, profile, builder.setRuleStatus(DEPRECATED));
+ long projectCount = countProjectsByOrganizationAndProfiles(dbSession, organization, profile);
+ writeProtobuf(buildResponse(profile, isDefault, getLanguage(profile), activeRuleCount, deprecatedActiveRuleCount, projectCount), request, response);
+ }
+ }
+
+ private long countActiveRulesByQuery(DbSession dbSession, QProfileDto profile, ActiveRuleCountQuery.Builder queryBuilder) {
+ Map<String, Long> result = dbClient.activeRuleDao().countActiveRulesByQuery(dbSession, queryBuilder.setProfiles(singletonList(profile)).build());
+ return result.getOrDefault(profile.getKee(), 0L);
+ }
+
+ private long countProjectsByOrganizationAndProfiles(DbSession dbSession, OrganizationDto organization, QProfileDto profile) {
+ Map<String, Long> projects = dbClient.qualityProfileDao().countProjectsByOrganizationAndProfiles(dbSession, organization, singletonList(profile));
+ return projects.getOrDefault(profile.getKee(), 0L);
+ }
+
+ public Language getLanguage(QProfileDto profile) {
+ Language language = languages.get(profile.getLanguage());
+ checkFound(language, "Quality Profile with key '%s' does not exist", profile.getKee());
+ return language;
+ }
+
+ private static ShowWsResponse buildResponse(QProfileDto profile, boolean isDefault, Language language, long activeRules, long deprecatedActiveRules, long projects) {
+ QualityProfile.Builder profileBuilder = QualityProfile.newBuilder()
+ .setKey(profile.getKee())
+ .setName(profile.getName())
+ .setLanguage(profile.getLanguage())
+ .setLanguageName(language.getName())
+ .setIsBuiltIn(profile.isBuiltIn())
+ .setIsDefault(isDefault)
+ .setIsInherited(profile.getParentKee() != null)
+ .setActiveRuleCount(activeRules)
+ .setActiveDeprecatedRuleCount(deprecatedActiveRules)
+ .setProjectCount(projects);
+ setNullable(profile.getRulesUpdatedAt(), profileBuilder::setRulesUpdatedAt);
+ setNullable(profile.getLastUsed(), last -> profileBuilder.setLastUsed(formatDateTime(last)));
+ setNullable(profile.getUserUpdatedAt(), userUpdatedAt -> profileBuilder.setUserUpdatedAt(formatDateTime(userUpdatedAt)));
+ return ShowWsResponse.newBuilder().setProfile(profileBuilder).build();
}
}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/show-example.json b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/show-example.json
index 60f03aaf168..a628efa37c2 100644
--- a/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/show-example.json
+++ b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/show-example.json
@@ -7,12 +7,10 @@
"isInherited": true,
"isBuiltIn": false,
"isDefault": false,
- "parentKey": "AU-TpxcA-iU5OvuD2FL1",
- "parentName": "Parent Company Profile",
"activeRuleCount": 10,
"activeDeprecatedRuleCount": 0,
"projectCount": 7,
- "ruleUpdatedAt": "2016-12-22T19:10:03+0100",
+ "rulesUpdatedAt": "2016-12-22T19:10:03+0100",
"lastUsed": "2016-12-01T19:10:03+0100"
},
"compareToSonarWay": {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ShowActionTest.java
index b7f9b98f35d..5b90834477b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ShowActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ShowActionTest.java
@@ -22,23 +22,45 @@ package org.sonar.server.qualityprofile.ws;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.DateUtils;
import org.sonar.db.DbTester;
import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
+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.QualityProfiles.ShowWsResponse;
import static java.util.stream.IntStream.range;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.rule.RuleStatus.DEPRECATED;
+import static org.sonar.api.utils.DateUtils.parseDateTime;
import static org.sonar.server.language.LanguageTesting.newLanguage;
import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonarqube.ws.QualityProfiles.ShowWsResponse.QualityProfile;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE;
public class ShowActionTest {
+ private static Language XOO1 = newLanguage("xoo1");
+ private static Language XOO2 = newLanguage("xoo2");
+ private static Languages LANGUAGES = new Languages(XOO1, XOO2);
+
@Rule
public DbTester db = DbTester.create();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
- private WsActionTester ws = new WsActionTester(new ShowAction());
+ private WsActionTester ws = new WsActionTester(
+ new ShowAction(db.getDbClient(), new QProfileWsSupport(db.getDbClient(), userSession, TestDefaultOrganizationProvider.from(db)), LANGUAGES));
@Test
public void test_definition() {
@@ -49,13 +71,11 @@ public class ShowActionTest {
assertThat(action.since()).isEqualTo("6.5");
WebService.Param profile = action.param("profile");
- assertThat(profile).isNotNull();
assertThat(profile.isRequired()).isTrue();
assertThat(profile.isInternal()).isFalse();
assertThat(profile.description()).isNotEmpty();
WebService.Param compareToSonarWay = action.param("compareToSonarWay");
- assertThat(compareToSonarWay).isNotNull();
assertThat(compareToSonarWay.isRequired()).isFalse();
assertThat(compareToSonarWay.isInternal()).isTrue();
assertThat(compareToSonarWay.description()).isNotEmpty();
@@ -63,9 +83,102 @@ public class ShowActionTest {
}
@Test
- public void test_example() {
+ public void profile_info() {
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+
+ ShowWsResponse result = call(ws.newRequest().setParam(PARAM_PROFILE, profile.getKee()));
+
+ assertThat(result.getProfile())
+ .extracting(QualityProfile::getKey, QualityProfile::getName, QualityProfile::getIsBuiltIn, QualityProfile::getLanguage, QualityProfile::getLanguageName,
+ QualityProfile::getIsInherited)
+ .containsExactly(profile.getKee(), profile.getName(), profile.isBuiltIn(), profile.getLanguage(), XOO1.getName(), false);
+ }
+
+ @Test
+ public void default_profile() {
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+ db.qualityProfiles().setAsDefault(profile);
+
+ ShowWsResponse result = call(ws.newRequest().setParam(PARAM_PROFILE, profile.getKee()));
+
+ assertThat(result.getProfile().getIsDefault()).isTrue();
+ }
+
+ @Test
+ public void non_default_profile() {
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+ QProfileDto defaultProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+ db.qualityProfiles().setAsDefault(defaultProfile);
+
+ ShowWsResponse result = call(ws.newRequest().setParam(PARAM_PROFILE, profile.getKee()));
+
+ assertThat(result.getProfile().getIsDefault()).isFalse();
+ }
+
+ @Test
+ public void map_dates() {
+ long time = DateUtils.parseDateTime("2016-12-22T19:10:03+0100").getTime();
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p
+ .setLanguage(XOO1.getKey())
+ .setRulesUpdatedAt("2016-12-21T19:10:03+0100")
+ .setLastUsed(time)
+ .setUserUpdatedAt(time));
+
+ ShowWsResponse result = call(ws.newRequest().setParam(PARAM_PROFILE, profile.getKee()));
+
+ assertThat(result.getProfile().getRulesUpdatedAt()).isEqualTo("2016-12-21T19:10:03+0100");
+ assertThat(parseDateTime(result.getProfile().getLastUsed()).getTime()).isEqualTo(time);
+ assertThat(parseDateTime(result.getProfile().getUserUpdatedAt()).getTime()).isEqualTo(time);
+ }
+
+ @Test
+ public void statistics() {
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+ // Active rules
+ range(0, 10)
+ .mapToObj(i -> db.rules().insertRule(r -> r.setLanguage(XOO1.getKey())).getDefinition())
+ .forEach(r -> db.qualityProfiles().activateRule(profile, r));
+ // Deprecated rules
+ range(0, 3)
+ .mapToObj(i -> db.rules().insertRule(r -> r.setLanguage(XOO1.getKey()).setStatus(DEPRECATED)).getDefinition())
+ .forEach(r -> db.qualityProfiles().activateRule(profile, r));
+ // Projects
+ range(0, 7)
+ .mapToObj(i -> db.components().insertPrivateProject())
+ .forEach(project -> db.qualityProfiles().associateWithProject(project, profile));
+
+ ShowWsResponse result = call(ws.newRequest().setParam(PARAM_PROFILE, profile.getKee()));
+
+ assertThat(result.getProfile())
+ .extracting(QualityProfile::getActiveRuleCount, QualityProfile::getActiveDeprecatedRuleCount, QualityProfile::getProjectCount)
+ .containsExactly(13L, 3L, 7L);
+ }
+
+ @Test
+ public void fail_if_profile_language_is_not_supported() {
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setKee("unknown-profile").setLanguage("kotlin"));
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Quality Profile with key 'unknown-profile' does not exist");
+
+ call(ws.newRequest().setParam(PARAM_PROFILE, profile.getKee()));
+ }
+
+ @Test
+ public void fail_if_profile_does_not_exist() {
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Quality Profile with key 'unknown-profile' does not exist");
+
+ call(ws.newRequest().setParam(PARAM_PROFILE, "unknown-profile"));
+ }
+
+ @Test
+ public void json_example() {
Language cs = newLanguage("cs", "C#");
- QProfileDto parentProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setKee("AU-TpxcA-iU5OvuD2FL1").setName("Parent Company Profile"));
+ QProfileDto parentProfile = db.qualityProfiles().insert(db.getDefaultOrganization(),
+ p -> p.setKee("AU-TpxcA-iU5OvuD2FL1")
+ .setName("Parent Company Profile")
+ .setLanguage(cs.getKey()));
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p
.setKee("AU-TpxcA-iU5OvuD2FL3")
.setName("My Company Profile")
@@ -82,8 +195,14 @@ public class ShowActionTest {
.mapToObj(i -> db.components().insertPrivateProject())
.forEach(project -> db.qualityProfiles().associateWithProject(project, profile));
- String result = ws.newRequest().execute().getInput();
+ ws = new WsActionTester(new ShowAction(db.getDbClient(), new QProfileWsSupport(db.getDbClient(), userSession, TestDefaultOrganizationProvider.from(db)), new Languages(cs)));
+ String result = ws.newRequest().setParam(PARAM_PROFILE, profile.getKee()).execute().getInput();
+
+ assertJson(result).ignoreFields("rulesUpdatedAt", "lastUsed", "userUpdatedAt", "compareToSonarWay").isSimilarTo(ws.getDef().responseExampleAsString());
+ }
- assertJson(result).isSimilarTo(ws.getDef().responseExampleAsString());
+ private ShowWsResponse call(TestRequest request) {
+ TestRequest wsRequest = request.setMediaType(MediaTypes.PROTOBUF);
+ return wsRequest.executeProtobuf(ShowWsResponse.class);
}
}
diff --git a/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto b/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto
index 0dab9b3c06f..0f1ddd6cb0b 100644
--- a/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto
+++ b/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto
@@ -111,17 +111,15 @@ message ShowWsResponse {
optional string language = 3;
optional string languageName = 4;
optional bool isInherited = 5;
- optional string parentKey = 6;
- optional string parentName = 7;
- optional bool isDefault = 8;
- optional int64 activeRuleCount = 9;
- optional int64 activeDeprecatedRuleCount = 12;
- optional int64 projectCount = 10;
- optional string ruleUpdatedAt = 11;
- optional string lastUsed = 13;
- optional string userUpdatedAt = 14;
- optional string organization = 15;
- optional bool isBuiltIn = 16;
+ optional bool isDefault = 6;
+ optional int64 activeRuleCount = 7;
+ optional int64 activeDeprecatedRuleCount = 8;
+ optional int64 projectCount = 9;
+ optional string rulesUpdatedAt = 10;
+ optional string lastUsed = 11;
+ optional string userUpdatedAt = 12;
+ optional string organization = 13;
+ optional bool isBuiltIn = 14;
}
message CompareToSonarWay {