pico.addSingleton(QProfileSearchAction.class);
pico.addSingleton(QProfileSetDefaultAction.class);
pico.addSingleton(QProfileProjectsAction.class);
+ pico.addSingleton(QProfileDeleteAction.class);
pico.addSingleton(QProfilesWs.class);
pico.addSingleton(ProfilesWs.class);
pico.addSingleton(RuleActivationActions.class);
* Session is NOT committed. Profiles marked as "default" for a language can't be deleted,
* except if the parameter <code>force</code> is true.
*/
- void delete(DbSession session, String key, boolean force) {
+ public void delete(DbSession session, String key, boolean force) {
QualityProfileDto profile = db.qualityProfileDao().getNonNullByKey(session, key);
List<QualityProfileDto> descendants = db.qualityProfileDao().findDescendants(session, key);
if (!force) {
}
private void doDelete(DbSession session, QualityProfileDto profile) {
+ db.qualityProfileDao().deleteAllProjectProfileAssociation(profile.getKey(), session);
db.activeRuleDao().deleteByProfileKey(session, profile.getKey());
db.qualityProfileDao().delete(session, profile);
}
--- /dev/null
+/*
+ * 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.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.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.user.UserSession;
+
+public class QProfileDeleteAction implements BaseQProfileWsAction {
+
+ private final Languages languages;
+ private final QProfileFactory profileFactory;
+ private final DbClient dbClient;
+
+ public QProfileDeleteAction(Languages languages, QProfileFactory profileFactory, DbClient dbClient) {
+ this.languages = languages;
+ this.profileFactory = profileFactory;
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ public void define(NewController controller) {
+ NewAction action = controller.createAction("delete")
+ .setDescription("Delete a quality profile and all its descendants. The default quality profile cannot be deleted.")
+ .setSince("5.2")
+ .setPost(true)
+ .setHandler(this);
+
+ QProfileParamUtils.defineProfileParams(action, languages);
+ }
+
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ UserSession.get().checkLoggedIn();
+ UserSession.get().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ String profileKey = QProfileParamUtils.getProfileKey(request, profileFactory, session);
+ profileFactory.delete(session, profileKey, false);
+
+ session.commit();
+ } finally {
+ session.close();
+ }
+
+ response.noContent();
+ }
+}
--- /dev/null
+/*
+ * 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.WebService.NewAction;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfileFactory;
+
+import static org.apache.commons.lang.StringUtils.isEmpty;
+
+public class QProfileParamUtils {
+
+ private static final String PARAM_LANGUAGE = "language";
+ private static final String PARAM_PROFILE_NAME = "profileName";
+ private static final String PARAM_PROFILE_KEY = "profileKey";
+
+ private QProfileParamUtils() {
+ // Utility class
+ }
+
+ public static void defineProfileParams(NewAction action, Languages languages) {
+ action.createParam(PARAM_PROFILE_KEY)
+ .setDescription("A quality profile key. Either this parameter, or a combination of profileName + language must be set.")
+ .setExampleValue("sonar-way-java-12345");
+ action.createParam(PARAM_PROFILE_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");
+ action.createParam(PARAM_LANGUAGE)
+ .setDescription("A quality profile language. If this parameter is set, profileKey must not be set and profileName must be set to disambiguate.")
+ .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
+ .setExampleValue("js");
+ }
+
+ public static String getProfileKey(Request request, QProfileFactory profileFactory, DbSession session) {
+ 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, session);
+ }
+ return profileKey;
+ }
+
+ private 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));
+ }
+ return profile.getKey();
+ }
+
+}
--- /dev/null
+/*
+ * 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.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.utils.System2;
+import org.sonar.core.component.ComponentDto;
+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.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.db.ActiveRuleDao;
+import org.sonar.server.rule.db.RuleDao;
+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 QProfileDeleteActionTest {
+
+ @ClassRule
+ public static DbTester dbTester = new DbTester();
+
+ private DbClient dbClient;
+
+ private QualityProfileDao qualityProfileDao;
+
+ private ComponentDao componentDao;
+
+ 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));
+ componentDao = new ComponentDao();
+
+ dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), qualityProfileDao, new ActiveRuleDao(qualityProfileDao, new RuleDao()));
+ session = dbClient.openSession(false);
+
+ xoo1 = LanguageTesting.newLanguage("xoo1");
+ xoo2 = LanguageTesting.newLanguage("xoo2");
+
+ tester = new WsTester(new QProfilesWs(
+ mock(RuleActivationActions.class),
+ mock(BulkRuleActivationActions.class),
+ mock(ProjectAssociationActions.class),
+ new QProfileDeleteAction(new Languages(xoo1, xoo2), new QProfileFactory(dbClient), dbClient)));
+ }
+
+ @After
+ public void teadDown() {
+ session.close();
+ }
+
+ @Test
+ public void delete_nominal_with_key() throws Exception {
+ String profileKey = "sonar-way-xoo1-12345";
+
+ ComponentDto project = ComponentTesting.newProjectDto("polop");
+ componentDao.insert(session, project);
+ qualityProfileDao.insert(session, QualityProfileDto.createFor(profileKey).setLanguage(xoo1.getKey()).setName("Sonar way"));
+ qualityProfileDao.insertProjectProfileAssociation(project.uuid(), profileKey, session);
+ session.commit();
+
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+ tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileKey", "sonar-way-xoo1-12345").execute().assertNoContent();
+
+ assertThat(qualityProfileDao.getByKey(session, "sonar-way-xoo1-12345")).isNull();
+ assertThat(qualityProfileDao.selectProjects("Sonar way", xoo1.getName())).isEmpty();
+ }
+
+ @Test
+ public void delete_nominal_with_language_and_name() throws Exception {
+ String profileKey = "sonar-way-xoo1-12345";
+
+ ComponentDto project = ComponentTesting.newProjectDto("polop");
+ componentDao.insert(session, project);
+ qualityProfileDao.insert(session, QualityProfileDto.createFor(profileKey).setLanguage(xoo1.getKey()).setName("Sonar way"));
+ qualityProfileDao.insertProjectProfileAssociation(project.uuid(), profileKey, session);
+ session.commit();
+
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+ tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Sonar way").setParam("language", xoo1.getKey()).execute().assertNoContent();
+
+ assertThat(qualityProfileDao.getByKey(session, "sonar-way-xoo1-12345")).isNull();
+ assertThat(qualityProfileDao.selectProjects("Sonar way", xoo1.getName())).isEmpty();
+ }
+
+ @Test(expected = ForbiddenException.class)
+ public void fail_on_missing_permission() throws Exception {
+ MockUserSession.set().setLogin("obiwan");
+ tester.newPostRequest("api/qualityprofiles", "delete").execute();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void fail_on_missing_arguments() throws Exception {
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+ tester.newPostRequest("api/qualityprofiles", "delete").execute();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void fail_on_missing_language() throws Exception {
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+ tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Polop").execute();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void fail_on_missing_name() throws Exception {
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+ tester.newPostRequest("api/qualityprofiles", "delete").setParam("language", xoo1.getKey()).execute();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void fail_on_too_many_arguments() throws Exception {
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+ tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Polop").setParam("language", xoo1.getKey()).setParam("profileKey", "polop").execute();
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void fail_on_unexisting_profile() throws Exception {
+ MockUserSession.set().setLogin("obiwan").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+ tester.newPostRequest("api/qualityprofiles", "delete").setParam("profileName", "Polop").setParam("language", xoo1.getKey()).execute();
+ }
+}