aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2015-03-30 18:40:05 +0200
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2015-04-01 10:44:20 +0200
commit67e2278d37142eed525696714b0b585d03daefe0 (patch)
tree935a5c5dcba5b62e09a26bb04f56b569bf617110 /server
parent8afbf65b0bed14347cae7d577489a1a1c86dea87 (diff)
downloadsonarqube-67e2278d37142eed525696714b0b585d03daefe0.tar.gz
sonarqube-67e2278d37142eed525696714b0b585d03daefe0.zip
SONAR-6300 WS to select the default quality profile for a language
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/QProfileFactory.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultAction.java115
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultActionTest.java181
4 files changed, 298 insertions, 1 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 3742afb7567..eef1ee23140 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
@@ -380,6 +380,7 @@ class ServerComponents {
pico.addSingleton(BuiltInProfiles.class);
pico.addSingleton(QProfileRestoreBuiltInAction.class);
pico.addSingleton(QProfileSearchAction.class);
+ pico.addSingleton(QProfileSetDefaultAction.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/QProfileFactory.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java
index ccc8f8f2d52..c6d99c1eb42 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java
@@ -138,7 +138,7 @@ public class QProfileFactory implements ServerComponent {
return db.qualityProfileDao().getDefaultProfile(language, session);
}
- void setDefault(String profileKey) {
+ public void setDefault(String profileKey) {
DbSession dbSession = db.openSession(false);
try {
setDefault(dbSession, profileKey);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultAction.java
new file mode 100644
index 00000000000..ec88a6c165c
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultAction.java
@@ -0,0 +1,115 @@
+/*
+ * 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.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+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.core.permission.GlobalPermissions;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfile;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.user.UserSession;
+
+import java.util.Arrays;
+
+import static org.apache.commons.lang.StringUtils.isEmpty;
+
+public class QProfileSetDefaultAction implements BaseQProfileWsAction {
+
+ private static final String PARAM_LANGUAGE = "language";
+ private static final String PARAM_PROFILE_NAME = "profileName";
+ private static final String PARAM_PROFILE_KEY = "profileKey";
+
+ private final Languages languages;
+
+ private final QProfileLookup profileLookup;
+
+ private final QProfileFactory profileFactory;
+
+ public QProfileSetDefaultAction(Languages languages, QProfileLookup profileLookup, QProfileFactory profileFactory) {
+ this.languages = languages;
+ this.profileLookup = profileLookup;
+ this.profileFactory = profileFactory;
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ UserSession.get().checkLoggedIn().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+ String language = request.param(PARAM_LANGUAGE);
+ String profileName = request.param(PARAM_PROFILE_NAME);
+ String profileKey = request.param(PARAM_PROFILE_KEY);
+
+ Preconditions.checkArgument(
+ (!isEmpty(language) && !isEmpty(profileName)) ^ !isEmpty(profileKey), "Either profileKey or profileName + language must be set");
+
+ if(profileKey == null) {
+ profileKey = getProfileKeyFromLanguageAndName(language, profileName);
+ }
+
+ profileFactory.setDefault(profileKey);
+
+ response.noContent();
+ }
+
+ private String getProfileKeyFromLanguageAndName(String language, String profileName) {
+ QProfile profile = profileLookup.profile(profileName, language);
+ if (profile == null) {
+ throw new NotFoundException(String.format("Unable to find a profile for language '%s' with name '%s'", language, profileName));
+ }
+ return profile.key();
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ NewAction setDefault = controller.createAction("set_default")
+ .setSince("5.2")
+ .setDescription("Select the default profile for a given language.")
+ .setHandler(this)
+ .setResponseExample(getClass().getResource("example-search.json"));
+
+ setDefault.createParam(PARAM_LANGUAGE)
+ .setDescription("The key of a language supported by the platform. If specified, profileName must be set to select the default profile for the selected language.")
+ .setExampleValue("js")
+ .setPossibleValues(Collections2.transform(Arrays.asList(languages.all()), new Function<Language, String>() {
+ @Override
+ public String apply(Language input) {
+ return input.getKey();
+ }
+ }));
+
+ setDefault.createParam(PARAM_PROFILE_NAME)
+ .setDescription("The name of a quality profile. If specified, language must be set. The matching profile will be used as default for the selected language.")
+ .setExampleValue("sonar-way-js-12345");
+
+ setDefault.createParam(PARAM_PROFILE_KEY)
+ .setDescription("The key of a quality profile. If specified, language and profileName must not be set. The matching profile will be used as default for its language.")
+ .setExampleValue("sonar-way-js-12345");
+ }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultActionTest.java
new file mode 100644
index 00000000000..8dac75022ab
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileSetDefaultActionTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.sonar.server.exceptions.ForbiddenException;
+
+import org.apache.commons.lang.StringUtils;
+import org.assertj.core.api.Fail;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.resources.AbstractLanguage;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.ws.WsTester;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class QProfileSetDefaultActionTest {
+
+ @ClassRule
+ public static DbTester dbTester = new DbTester();
+
+ private DbClient dbClient;
+
+ private QualityProfileDao qualityProfileDao;
+
+ private Language xoo1, xoo2;
+
+ private WsTester tester;
+
+ private DbSession session;
+
+
+ @Before
+ public void setUp() throws Exception {
+ dbTester.truncateTables();
+ qualityProfileDao = new QualityProfileDao(dbTester.myBatis(), mock(System2.class));
+ dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), qualityProfileDao);
+ session = dbClient.openSession(false);
+
+ xoo1 = createLanguage("xoo1");
+ xoo2 = createLanguage("xoo2");
+ createProfiles();
+
+ tester = new WsTester(new QProfilesWs(
+ mock(RuleActivationActions.class),
+ mock(BulkRuleActivationActions.class),
+ mock(ProjectAssociationActions.class),
+ new QProfileSetDefaultAction(new Languages(xoo1, xoo2), new QProfileLookup(dbClient), new QProfileFactory(dbClient))));
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void set_default_profile_using_key() throws Exception {
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+
+ checkDefaultProfile("xoo1", "sonar-way-xoo1-12345");
+ checkDefaultProfile("xoo2", "my-sonar-way-xoo2-34567");
+
+ tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "sonar-way-xoo2-23456").execute().assertNoContent();
+
+ checkDefaultProfile("xoo1", "sonar-way-xoo1-12345");
+ checkDefaultProfile("xoo2", "sonar-way-xoo2-23456");
+ assertThat(dbClient.qualityProfileDao().getByKey(session, "sonar-way-xoo2-23456").isDefault()).isTrue();
+ assertThat(dbClient.qualityProfileDao().getByKey(session, "my-sonar-way-xoo2-34567").isDefault()).isFalse();
+
+ // One more time!
+ tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "sonar-way-xoo2-23456").execute().assertNoContent();
+ checkDefaultProfile("xoo1", "sonar-way-xoo1-12345");
+ checkDefaultProfile("xoo2", "sonar-way-xoo2-23456");
+ }
+
+ @Test
+ public void set_default_profile_using_language_and_name() throws Exception {
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+ tester.newPostRequest("api/qualityprofiles", "set_default").setParam("language", "xoo2").setParam("profileName", "Sonar way").execute().assertNoContent();
+
+ checkDefaultProfile("xoo1", "sonar-way-xoo1-12345");
+ checkDefaultProfile("xoo2", "sonar-way-xoo2-23456");
+ }
+
+ @Test
+ public void fail_to_set_default_profile_using_key() throws Exception {
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+ try {
+ tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "unknown-profile-666").execute();
+ Fail.failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
+ } catch(IllegalArgumentException nfe) {
+ assertThat(nfe).hasMessage("Quality profile not found: unknown-profile-666");
+ checkDefaultProfile("xoo1", "sonar-way-xoo1-12345");
+ checkDefaultProfile("xoo2", "my-sonar-way-xoo2-34567");
+ }
+ }
+
+
+ @Test
+ public void fail_to_set_default_profile_using_language_and_name() throws Exception {
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+ try {
+ tester.newPostRequest("api/qualityprofiles", "set_default").setParam("language", "xoo2").setParam("profileName", "Unknown").execute();
+ Fail.failBecauseExceptionWasNotThrown(NotFoundException.class);
+ } catch(NotFoundException nfe) {
+ assertThat(nfe).hasMessage("Unable to find a profile for language 'xoo2' with name 'Unknown'");
+ checkDefaultProfile("xoo1", "sonar-way-xoo1-12345");
+ checkDefaultProfile("xoo2", "my-sonar-way-xoo2-34567");
+ }
+ }
+
+ @Test
+ public void fail_on_missing_permission() throws Exception {
+ MockUserSession.set().setLogin("obiwan");
+
+ try {
+ tester.newPostRequest("api/qualityprofiles", "set_default").setParam("profileKey", "sonar-way-xoo2-23456").execute().assertNoContent();
+ Fail.failBecauseExceptionWasNotThrown(ForbiddenException.class);
+ } catch(ForbiddenException forbidden) {
+ checkDefaultProfile("xoo1", "sonar-way-xoo1-12345");
+ checkDefaultProfile("xoo2", "my-sonar-way-xoo2-34567");
+ }
+ }
+
+ private void createProfiles() {
+ qualityProfileDao.insert(session,
+ QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way").setDefault(true),
+ QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2.getKey()).setName("Sonar way"),
+ QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2.getKey()).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456").setDefault(true)
+ );
+ session.commit();
+ }
+
+ private void checkDefaultProfile(String language, String key) throws Exception {
+ assertThat(dbClient.qualityProfileDao().getDefaultProfile(language).getKey()).isEqualTo(key);
+ }
+
+ private Language createLanguage(final String key) {
+ return new AbstractLanguage(key, StringUtils.capitalize(key)) {
+ @Override
+ public String[] getFileSuffixes() {
+ return new String[] {key};
+ }
+ };
+ }
+}