@@ -382,6 +382,7 @@ class ServerComponents { | |||
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); |
@@ -100,7 +100,7 @@ public class QProfileFactory implements ServerComponent { | |||
* 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) { | |||
@@ -117,6 +117,7 @@ public class QProfileFactory implements ServerComponent { | |||
} | |||
private void doDelete(DbSession session, QualityProfileDto profile) { | |||
db.qualityProfileDao().deleteAllProjectProfileAssociation(profile.getKey(), session); | |||
db.activeRuleDao().deleteByProfileKey(session, profile.getKey()); | |||
db.qualityProfileDao().delete(session, profile); | |||
} |
@@ -0,0 +1,75 @@ | |||
/* | |||
* 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(); | |||
} | |||
} |
@@ -0,0 +1,78 @@ | |||
/* | |||
* 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(); | |||
} | |||
} |
@@ -0,0 +1,162 @@ | |||
/* | |||
* 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(); | |||
} | |||
} |