aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2015-04-08 11:54:35 +0200
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2015-04-10 11:19:25 +0200
commit5a4027c007014262d0cf9aaa11dcf43b63934bc3 (patch)
tree69e2601a568df2d2f47e51e2dfbd34f4768c6460 /server
parent0aaeb8c595e64a43aa1590d1bb6a4fbafe5e8826 (diff)
downloadsonarqube-5a4027c007014262d0cf9aaa11dcf43b63934bc3.tar.gz
sonarqube-5a4027c007014262d0cf9aaa11dcf43b63934bc3.zip
SONAR-6307 WS to change the parent of a quality profile
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentAction.java102
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileIdentificationParamUtils.java8
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentActionMediumTest.java197
5 files changed, 305 insertions, 5 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
index 23a95ec3bd2..202b1558515 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
@@ -390,6 +390,7 @@ class ServerComponents {
pico.addSingleton(QProfileCreateAction.class);
pico.addSingleton(QProfileImportersAction.class);
pico.addSingleton(QProfileInheritanceAction.class);
+ pico.addSingleton(QProfileChangeParentAction.class);
pico.addSingleton(QProfilesWs.class);
pico.addSingleton(ProfilesWs.class);
pico.addSingleton(RuleActivationActions.class);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
index 8026d90518d..e8c72779dd1 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
@@ -449,7 +449,7 @@ public class RuleActivator implements ServerComponent {
}
}
- void setParent(String key, @Nullable String parentKey) {
+ public void setParent(String key, @Nullable String parentKey) {
DbSession dbSession = db.openSession(false);
try {
setParent(dbSession, key, parentKey);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentAction.java
new file mode 100644
index 00000000000..9c6d01f161e
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentAction.java
@@ -0,0 +1,102 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import com.google.common.base.Preconditions;
+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.NewAction;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.RuleActivator;
+
+import static org.apache.commons.lang.StringUtils.isEmpty;
+
+public class QProfileChangeParentAction implements BaseQProfileWsAction {
+
+ private static final String PARAM_PARENT_KEY = "parentKey";
+
+ private static final String PARAM_PARENT_NAME = "parentName";
+
+ private final DbClient dbClient;
+
+ private final RuleActivator ruleActivator;
+
+ private final QProfileFactory profileFactory;
+
+ private final Languages languages;
+
+ public QProfileChangeParentAction(DbClient dbClient, RuleActivator ruleActivator, QProfileFactory profileFactory, Languages languages) {
+ this.dbClient = dbClient;
+ this.ruleActivator = ruleActivator;
+ this.profileFactory = profileFactory;
+ this.languages = languages;
+ }
+
+ @Override
+ public void define(NewController context) {
+ NewAction inheritance = context.createAction("change_parent")
+ .setSince("5.2")
+ .setDescription("Change a quality profile's parent.")
+ .setHandler(this);
+
+ QProfileIdentificationParamUtils.defineProfileParams(inheritance, languages);
+
+ inheritance.createParam(PARAM_PARENT_KEY)
+ .setDescription("The key of the new parent profile. If this parameter is set, parentName must not be set. If left empty, ")
+ .setExampleValue("sonar-way-java-12345");
+ inheritance.createParam(PARAM_PARENT_NAME)
+ .setDescription("A quality profile name. If this parameter is set, profileKey must not be set and language must be set to disambiguate.")
+ .setExampleValue("Sonar way");
+
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ DbSession session = dbClient.openSession(false);
+ try {
+ String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
+ String parentKey = getParentKeyFromParameters(request, profileFactory, session);
+
+ ruleActivator.setParent(profileKey, parentKey);
+
+ response.noContent();
+ } finally {
+ session.close();
+ }
+ }
+
+ private static String getParentKeyFromParameters(Request request, QProfileFactory profileFactory, DbSession session) {
+ String language = request.param(QProfileIdentificationParamUtils.PARAM_LANGUAGE);
+ String parentName = request.param(PARAM_PARENT_NAME);
+ String parentKey = request.param(PARAM_PARENT_KEY);
+
+ Preconditions.checkArgument(
+ (isEmpty(parentName) || isEmpty(parentKey)), "parentKey and parentName cannot be used simultaneously");
+
+ if (isEmpty(parentKey) && !isEmpty(parentName)) {
+ parentKey = QProfileIdentificationParamUtils.getProfileKeyFromLanguageAndName(language, parentName, profileFactory, session);
+ }
+ return parentKey;
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileIdentificationParamUtils.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileIdentificationParamUtils.java
index a577869ca12..29659c1c360 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileIdentificationParamUtils.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileIdentificationParamUtils.java
@@ -32,9 +32,9 @@ import static org.apache.commons.lang.StringUtils.isEmpty;
public class QProfileIdentificationParamUtils {
- private static final String PARAM_LANGUAGE = "language";
- private static final String PARAM_PROFILE_NAME = "profileName";
- private static final String PARAM_PROFILE_KEY = "profileKey";
+ public static final String PARAM_LANGUAGE = "language";
+ public static final String PARAM_PROFILE_NAME = "profileName";
+ public static final String PARAM_PROFILE_KEY = "profileKey";
private QProfileIdentificationParamUtils() {
// Utility class
@@ -67,7 +67,7 @@ public class QProfileIdentificationParamUtils {
return profileKey;
}
- private static String getProfileKeyFromLanguageAndName(String language, String profileName, QProfileFactory profileFactory, DbSession session) {
+ public static String getProfileKeyFromLanguageAndName(String language, String profileName, QProfileFactory profileFactory, DbSession session) {
QualityProfileDto profile = profileFactory.getByNameAndLanguage(session, profileName, language);
if (profile == null) {
throw new NotFoundException(String.format("Unable to find a profile for language '%s' with name '%s'", language, profileName));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentActionMediumTest.java
new file mode 100644
index 00000000000..c95c3d9ec47
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileChangeParentActionMediumTest.java
@@ -0,0 +1,197 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.qualityprofile.QProfileName;
+import org.sonar.server.qualityprofile.QProfileTesting;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.ws.WsTester;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class QProfileChangeParentActionMediumTest {
+
+ // TODO Replace with DbTester + EsTester once DaoV2 is removed
+ @ClassRule
+ public static ServerTester tester = new ServerTester();
+
+ QProfilesWs ws;
+ DbClient db;
+ DbSession session;
+ WsTester wsTester;
+
+ @Before
+ public void setUp() throws Exception {
+ tester.clearDbAndIndexes();
+ db = tester.get(DbClient.class);
+ ws = tester.get(QProfilesWs.class);
+ wsTester = tester.get(WsTester.class);
+ session = db.openSession(false);
+ MockUserSession.set().setLogin("gandalf").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+ }
+
+ @After
+ public void after() {
+ session.close();
+ }
+
+ @Test
+ public void change_parent_with_keys() throws Exception {
+ QualityProfileDto parent1 = createProfile("xoo", "Parent 1");
+ QualityProfileDto parent2 = createProfile("xoo", "Parent 2");
+ QualityProfileDto child = createProfile("xoo", "Child");
+
+ RuleDto rule1 = createRule("xoo", "rule1");
+ RuleDto rule2 = createRule("xoo", "rule2");
+ createActiveRule(rule1, parent1);
+ createActiveRule(rule2, parent2);
+ session.commit();
+
+ assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
+
+ // 1. Set parent 1
+ wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+ .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey().toString())
+ .setParam("parentKey", parent1.getKey().toString())
+ .execute();
+ session.clearCache();
+
+ // 1. Assert ActiveRule in DAO
+ List<ActiveRuleDto> activeRules1 = db.activeRuleDao().findByProfileKey(session, child.getKey());
+ assertThat(activeRules1).hasSize(1);
+ assertThat(activeRules1.get(0).getKey().ruleKey().rule()).isEqualTo("rule1");
+
+ // 2. Set parent 2
+ wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+ .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey().toString())
+ .setParam("parentKey", parent2.getKey().toString())
+ .execute();
+ session.clearCache();
+
+ // 2. Assert ActiveRule in DAO
+ List<ActiveRuleDto> activeRules2 = db.activeRuleDao().findByProfileKey(session, child.getKey());
+ assertThat(activeRules2).hasSize(1);
+ assertThat(activeRules2.get(0).getKey().ruleKey().rule()).isEqualTo("rule2");
+
+ // 3. Remove parent
+ wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+ .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey().toString())
+ .execute();
+ session.clearCache();
+
+ // 3. Assert ActiveRule in DAO
+ List<ActiveRuleDto> activeRules = db.activeRuleDao().findByProfileKey(session, child.getKey());
+ assertThat(activeRules).isEmpty();
+ }
+
+ @Test
+ public void change_parent_with_names() throws Exception {
+ QualityProfileDto parent1 = createProfile("xoo", "Parent 1");
+ QualityProfileDto parent2 = createProfile("xoo", "Parent 2");
+ QualityProfileDto child = createProfile("xoo", "Child");
+
+ RuleDto rule1 = createRule("xoo", "rule1");
+ RuleDto rule2 = createRule("xoo", "rule2");
+ createActiveRule(rule1, parent1);
+ createActiveRule(rule2, parent2);
+ session.commit();
+
+ assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
+
+ // 1. Set parent 1
+ wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+ .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo")
+ .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName())
+ .setParam("parentName", parent1.getName())
+ .execute();
+ session.clearCache();
+
+ // 1. Assert ActiveRule in DAO
+ List<ActiveRuleDto> activeRules1 = db.activeRuleDao().findByProfileKey(session, child.getKey());
+ assertThat(activeRules1).hasSize(1);
+ assertThat(activeRules1.get(0).getKey().ruleKey().rule()).isEqualTo("rule1");
+
+ // 2. Set parent 2
+ wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+ .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo")
+ .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName())
+ .setParam("parentName", parent2.getName())
+ .execute();
+ session.clearCache();
+
+ // 2. Assert ActiveRule in DAO
+ List<ActiveRuleDto> activeRules2 = db.activeRuleDao().findByProfileKey(session, child.getKey());
+ assertThat(activeRules2).hasSize(1);
+ assertThat(activeRules2.get(0).getKey().ruleKey().rule()).isEqualTo("rule2");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void fail_if_parent_key_and_name_both_set() throws Exception {
+ QualityProfileDto child = createProfile("xoo", "Child");
+ session.commit();
+
+ assertThat(db.activeRuleDao().findByProfileKey(session, child.getKey())).isEmpty();
+
+ wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "change_parent")
+ .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKee())
+ .setParam("parentName", "polop")
+ .setParam("parentKey", "palap")
+ .execute();
+ session.clearCache();
+ }
+
+ private QualityProfileDto createProfile(String lang, String name) {
+ QualityProfileDto profile = QProfileTesting.newDto(new QProfileName(lang, name), "p" + lang + "-" + name.toLowerCase());
+ db.qualityProfileDao().insert(session, profile);
+ return profile;
+ }
+
+ private RuleDto createRule(String lang, String id) {
+ RuleDto rule = RuleDto.createFor(RuleKey.of("blah", id))
+ .setLanguage(lang)
+ .setSeverity(Severity.BLOCKER)
+ .setStatus(RuleStatus.READY);
+ db.ruleDao().insert(session, rule);
+ return rule;
+ }
+
+ private ActiveRuleDto createActiveRule(RuleDto rule, QualityProfileDto profile) {
+ ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
+ .setSeverity(rule.getSeverityString());
+ db.activeRuleDao().insert(session, activeRule);
+ return activeRule;
+ }
+}