From 18545dcecf10746158d7f336b6957d8a0ec763c2 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Mon, 12 Sep 2016 17:16:51 +0200 Subject: [PATCH] Refactor the way to load QProfiles from WS --- .../platformlevel/PlatformLevel4.java | 2 - .../qualityprofile/QProfileFactory.java | 26 +++ .../server/qualityprofile/QProfileRef.java | 155 ++++++++++++++ .../qualityprofile/ws/BackupAction.java | 30 +-- .../qualityprofile/ws/ChangeParentAction.java | 52 ++--- .../qualityprofile/ws/ChangelogAction.java | 15 +- .../qualityprofile/ws/DeleteAction.java | 16 +- .../qualityprofile/ws/InheritanceAction.java | 23 +-- .../qualityprofile/ws/QProfileFinder.java | 95 --------- .../ws/QProfileIdentificationParamUtils.java | 79 ------- .../qualityprofile/QProfileFactoryTest.java | 81 ++++++++ .../qualityprofile/ws/BackupActionTest.java | 43 ++-- .../ws/ChangeParentActionMediumTest.java | 32 +-- .../ws/ChangelogActionTest.java | 26 ++- .../ws/QProfileFactoryTest.java | 82 ++++++++ .../qualityprofile/ws/QProfileRefTest.java | 192 ++++++++++++++++++ .../qualityprofile/ws/QProfilesWsTest.java | 7 +- 17 files changed, 631 insertions(+), 325 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRef.java delete mode 100644 server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileFinder.java delete mode 100644 server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileIdentificationParamUtils.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileFactoryTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRefTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index 4d959dd5f1c..156110ecde0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -210,7 +210,6 @@ import org.sonar.server.qualityprofile.ws.OldRestoreAction; import org.sonar.server.qualityprofile.ws.ProfilesWs; import org.sonar.server.qualityprofile.ws.ProjectAssociationActions; import org.sonar.server.qualityprofile.ws.ProjectsAction; -import org.sonar.server.qualityprofile.ws.QProfileFinder; import org.sonar.server.qualityprofile.ws.QProfilesWs; import org.sonar.server.qualityprofile.ws.RenameAction; import org.sonar.server.qualityprofile.ws.RestoreAction; @@ -372,7 +371,6 @@ public class PlatformLevel4 extends PlatformLevel { InheritanceAction.class, ChangeParentAction.class, ChangelogAction.class, - QProfileFinder.class, ChangelogLoader.class, CompareAction.class, ExportAction.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 f2e9ff6b6a0..4b0e60b2d69 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 @@ -38,6 +38,7 @@ import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.Verifications; import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED; +import static org.sonar.server.ws.WsUtils.checkFound; /** * Create, delete, rename and set as default profile. @@ -171,6 +172,31 @@ public class QProfileFactory { db.qualityProfileDao().update(session, profile.setDefault(true)); } + public QualityProfileDto find(QProfileRef ref) { + try (DbSession dbSession = db.openSession(false)) { + return find(ref, dbSession); + } + } + + public QualityProfileDto find(QProfileRef ref, DbSession dbSession) { + if (ref.hasKey()) { + return findByKey(dbSession, ref.getKey()); + } + return findByName(dbSession, ref.getLanguage(), ref.getName()); + } + + private QualityProfileDto findByKey(DbSession dbSession, String profileKey) { + QualityProfileDto profile; + profile = db.qualityProfileDao().selectByKey(dbSession, profileKey); + return checkFound(profile, "Unable to find a profile for with key '%s'", profileKey); + } + + private QualityProfileDto findByName(DbSession dbSession, String language, String profileName) { + QualityProfileDto profile; + profile = db.qualityProfileDao().selectByNameAndLanguage(profileName, language, dbSession); + return checkFound(profile, "Unable to find a profile for language '%s' with name '%s'", language, profileName); + } + QualityProfileDto getByProjectAndLanguage(String projectKey, String language) { DbSession dbSession = db.openSession(false); try { diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRef.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRef.java new file mode 100644 index 00000000000..9dca9c59dd7 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRef.java @@ -0,0 +1,155 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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; + +import javax.annotation.Nullable; +import org.sonar.api.resources.Languages; +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.WebService; +import org.sonar.server.component.ws.LanguageParamUtils; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; +import static org.apache.commons.lang.StringUtils.isEmpty; + +/** + * Reference to a Quality profile. The two exclusive options to reference a profile are: + * + */ +public class QProfileRef { + + public static final String PARAM_LANGUAGE = "language"; + public static final String PARAM_PROFILE_NAME = "profileName"; + public static final String PARAM_PROFILE_KEY = "profileKey"; + + private final String key; + private final String language; + private final String name; + + private QProfileRef(@Nullable String key, @Nullable String language, @Nullable String name) { + this.key = key; + this.language = language; + this.name = name; + } + + /** + * @return {@code true} if key is defined and {@link #getKey()} can be called. If {@code false}, then + * the couple {language, name} is defined and the methods {@link #getLanguage()}/{@link #getName()} + * can be called. + */ + public boolean hasKey() { + return this.key != null; + } + + /** + * @return non-null key + * @throws IllegalStateException if {@link #hasKey()} does not return {@code true} + */ + public String getKey() { + checkState(key != null, "Key is not present. Please call hasKey()."); + return key; + } + + /** + * @return non-null language + * @throws IllegalStateException if {@link #hasKey()} does not return {@code false} + */ + public String getLanguage() { + checkState(language != null, "Language is not present. Please call hasKey()."); + return language; + } + + /** + * @return non-null name + * @throws IllegalStateException if {@link #hasKey()} does not return {@code false} + */ + public String getName() { + checkState(name != null, "Name is not present. Please call hasKey()."); + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + QProfileRef that = (QProfileRef) o; + if (key != null ? !key.equals(that.key) : that.key != null) { + return false; + } + if (language != null ? !language.equals(that.language) : that.language != null) { + return false; + } + return name != null ? name.equals(that.name) : that.name == null; + + } + + @Override + public int hashCode() { + int result = key != null ? key.hashCode() : 0; + result = 31 * result + (language != null ? language.hashCode() : 0); + result = 31 * result + (name != null ? name.hashCode() : 0); + return result; + } + + public static QProfileRef from(Request request) { + String key = request.param(PARAM_PROFILE_KEY); + String lang = request.param(PARAM_LANGUAGE); + String name = request.param(PARAM_PROFILE_NAME); + return from(key, lang, name); + } + + public static QProfileRef from(@Nullable String key, @Nullable String lang, @Nullable String name) { + if (key != null) { + checkArgument(isEmpty(lang) && isEmpty(name), "Either key or couple language/name must be set"); + return fromKey(key); + } + checkArgument(!isEmpty(lang) && !isEmpty(name), "Both profile language and name must be set"); + return fromName(lang, name); + } + + public static QProfileRef fromKey(String key) { + return new QProfileRef(requireNonNull(key), null, null); + } + + public static QProfileRef fromName(String lang, String name) { + return new QProfileRef(null, requireNonNull(lang), requireNonNull(name)); + } + + public static void defineParams(WebService.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"); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BackupAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BackupAction.java index faf3405a1c4..a422f83967a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BackupAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BackupAction.java @@ -21,32 +21,26 @@ package org.sonar.server.qualityprofile.ws; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; -import org.apache.commons.io.IOUtils; 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.Response.Stream; 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.qualityprofile.QualityProfileDto; import org.sonar.server.qualityprofile.QProfileBackuper; import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.qualityprofile.QProfileRef; import org.sonarqube.ws.MediaTypes; public class BackupAction implements QProfileWsAction { private final QProfileBackuper backuper; - - private final DbClient dbClient; - - private QProfileFactory profileFactory; - + private final QProfileFactory profileFactory; private final Languages languages; - public BackupAction(QProfileBackuper backuper, DbClient dbClient, QProfileFactory profileFactory, Languages languages) { + public BackupAction(QProfileBackuper backuper, QProfileFactory profileFactory, Languages languages) { this.backuper = backuper; - this.dbClient = dbClient; this.profileFactory = profileFactory; this.languages = languages; } @@ -59,23 +53,17 @@ public class BackupAction implements QProfileWsAction { .setResponseExample(getClass().getResource("backup-example.xml")) .setHandler(this); - QProfileIdentificationParamUtils.defineProfileParams(backup, languages); + QProfileRef.defineParams(backup, languages); } @Override public void handle(Request request, Response response) throws Exception { Stream stream = response.stream(); stream.setMediaType(MediaTypes.XML); - DbSession dbSession = dbClient.openSession(false); - OutputStreamWriter writer = new OutputStreamWriter(stream.output(), StandardCharsets.UTF_8); - try { - String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, dbSession); - response.setHeader("Content-Disposition", String.format("attachment; filename=%s.xml", profileKey)); - backuper.backup(profileKey, writer); - } finally { - dbSession.close(); - IOUtils.closeQuietly(writer); + try (OutputStreamWriter writer = new OutputStreamWriter(stream.output(), StandardCharsets.UTF_8)) { + QualityProfileDto profile = profileFactory.find(QProfileRef.from(request)); + response.setHeader("Content-Disposition", String.format("attachment; filename=%s.xml", profile.getKee())); + backuper.backup(profile.getKee(), writer); } } - } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangeParentAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangeParentAction.java index c9758089dc4..4ea28a6e67d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangeParentAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangeParentAction.java @@ -19,16 +19,15 @@ */ 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.permission.GlobalPermissions; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; +import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.qualityprofile.QProfileRef; import org.sonar.server.qualityprofile.RuleActivator; import org.sonar.server.user.UserSession; @@ -37,20 +36,14 @@ import static org.apache.commons.lang.StringUtils.isEmpty; public class ChangeParentAction implements QProfileWsAction { 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; private final UserSession userSession; - public ChangeParentAction(DbClient dbClient, RuleActivator ruleActivator, QProfileFactory profileFactory, Languages languages, UserSession userSession) { - this.dbClient = dbClient; + public ChangeParentAction(RuleActivator ruleActivator, QProfileFactory profileFactory, Languages languages, UserSession userSession) { this.ruleActivator = ruleActivator; this.profileFactory = profileFactory; this.languages = languages; @@ -65,7 +58,7 @@ public class ChangeParentAction implements QProfileWsAction { .setDescription("Change a quality profile's parent.") .setHandler(this); - QProfileIdentificationParamUtils.defineProfileParams(inheritance, languages); + QProfileRef.defineParams(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. " + @@ -82,36 +75,15 @@ public class ChangeParentAction implements QProfileWsAction { public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn().checkPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN); - 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); + QualityProfileDto profile = profileFactory.find(QProfileRef.from(request)); String parentKey = request.param(PARAM_PARENT_KEY); - - Preconditions.checkArgument( - isEmpty(parentName) || isEmpty(parentKey), "parentKey and parentName cannot be used simultaneously"); - - if (isEmpty(parentKey)) { - if (!isEmpty(parentName)) { - parentKey = QProfileIdentificationParamUtils.getProfileKeyFromLanguageAndName(language, parentName, profileFactory, session); - } else { - // Empty parent key is treated as "no more parent" - parentKey = null; - } + String parentName = request.param(PARAM_PARENT_NAME); + if (isEmpty(parentKey) && isEmpty(parentName)) { + ruleActivator.setParent(profile.getKey(), null); + } else { + QualityProfileDto parent = profileFactory.find(QProfileRef.from(parentKey, request.param(QProfileRef.PARAM_LANGUAGE), parentName)); + ruleActivator.setParent(profile.getKey(), parent.getKey()); } - - return parentKey; + response.noContent(); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java index 968259448d9..e430c908155 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java @@ -21,6 +21,7 @@ package org.sonar.server.qualityprofile.ws; import java.util.Date; import java.util.Map; +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; @@ -30,6 +31,8 @@ import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.qualityprofile.QProfileChangeQuery; import org.sonar.db.qualityprofile.QualityProfileDto; +import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.qualityprofile.QProfileRef; import static org.sonar.server.es.SearchOptions.MAX_LIMIT; @@ -39,11 +42,13 @@ public class ChangelogAction implements QProfileWsAction { private static final String PARAM_TO = "to"; private final ChangelogLoader changelogLoader; - private final QProfileFinder profileFinder; + private final QProfileFactory profileFactory; + private final Languages languages; - public ChangelogAction(ChangelogLoader changelogLoader, QProfileFinder profileFinder) { + public ChangelogAction(ChangelogLoader changelogLoader, QProfileFactory profileFactory, Languages languages) { this.changelogLoader = changelogLoader; - this.profileFinder = profileFinder; + this.profileFactory = profileFactory; + this.languages = languages; } @Override @@ -55,7 +60,7 @@ public class ChangelogAction implements QProfileWsAction { .setHandler(this) .setResponseExample(getClass().getResource("example-changelog.json")); - profileFinder.defineProfileParams(wsAction); + QProfileRef.defineParams(wsAction, languages); wsAction.addPagingParams(50, MAX_LIMIT); @@ -70,7 +75,7 @@ public class ChangelogAction implements QProfileWsAction { @Override public void handle(Request request, Response response) throws Exception { - QualityProfileDto profile = profileFinder.find(request); + QualityProfileDto profile = profileFactory.find(QProfileRef.from(request)); QProfileChangeQuery query = new QProfileChangeQuery(profile.getKey()); Date since = request.paramAsDateTime(PARAM_SINCE); diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeleteAction.java index 75ddc8cb8ae..999c9446126 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeleteAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeleteAction.java @@ -27,7 +27,9 @@ import org.sonar.api.server.ws.WebService.NewController; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.qualityprofile.QProfileRef; import org.sonar.server.user.UserSession; public class DeleteAction implements QProfileWsAction { @@ -53,7 +55,7 @@ public class DeleteAction implements QProfileWsAction { .setPost(true) .setHandler(this); - QProfileIdentificationParamUtils.defineProfileParams(action, languages); + QProfileRef.defineParams(action, languages); } @Override @@ -61,14 +63,10 @@ public class DeleteAction implements QProfileWsAction { userSession.checkLoggedIn(); userSession.checkPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN); - DbSession session = dbClient.openSession(false); - try { - String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session); - profileFactory.delete(session, profileKey, false); - - session.commit(); - } finally { - session.close(); + try (DbSession dbSession = dbClient.openSession(false)) { + QualityProfileDto profile = profileFactory.find(QProfileRef.from(request), dbSession); + profileFactory.delete(dbSession, profile.getKey(), false); + dbSession.commit(); } response.noContent(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/InheritanceAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/InheritanceAction.java index a6e38d3a113..324a862265e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/InheritanceAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/InheritanceAction.java @@ -32,11 +32,11 @@ import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.qualityprofile.QualityProfileDto; -import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.qualityprofile.QProfile; import org.sonar.server.qualityprofile.QProfileFactory; import org.sonar.server.qualityprofile.QProfileLoader; import org.sonar.server.qualityprofile.QProfileLookup; +import org.sonar.server.qualityprofile.QProfileRef; import org.sonar.server.rule.index.RuleIndexDefinition; import org.sonar.server.search.FacetValue; @@ -45,13 +45,9 @@ import static org.sonar.server.qualityprofile.index.ActiveRuleIndex.COUNT_ACTIVE public class InheritanceAction implements QProfileWsAction { private final DbClient dbClient; - private final QProfileLookup profileLookup; - private final QProfileLoader profileLoader; - private final QProfileFactory profileFactory; - private final Languages languages; public InheritanceAction(DbClient dbClient, QProfileLookup profileLookup, QProfileLoader profileLoader, QProfileFactory profileFactory, Languages languages) { @@ -70,26 +66,21 @@ public class InheritanceAction implements QProfileWsAction { .setHandler(this) .setResponseExample(getClass().getResource("example-inheritance.json")); - QProfileIdentificationParamUtils.defineProfileParams(inheritance, languages); + QProfileRef.defineParams(inheritance, languages); } @Override public void handle(Request request, Response response) throws Exception { - DbSession session = dbClient.openSession(false); + DbSession dbSession = dbClient.openSession(false); try { - String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session); - QualityProfileDto profile = dbClient.qualityProfileDao().selectByKey(session, profileKey); - if (profile == null) { - throw new NotFoundException(String.format("Could not find a quality profile with key %s", profileKey)); - } - - List ancestors = profileLookup.ancestors(profile, session); - List children = dbClient.qualityProfileDao().selectChildren(session, profileKey); + QualityProfileDto profile = profileFactory.find(QProfileRef.from(request), dbSession); + List ancestors = profileLookup.ancestors(profile, dbSession); + List children = dbClient.qualityProfileDao().selectChildren(dbSession, profile.getKey()); Map> profileStats = profileLoader.getAllProfileStats(); writeResponse(response.newJsonWriter(), profile, ancestors, children, profileStats); } finally { - session.close(); + dbSession.close(); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileFinder.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileFinder.java deleted file mode 100644 index b2bd1b2c7b2..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileFinder.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.WebService; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.qualityprofile.QualityProfileDto; -import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.util.LanguageParamUtils; - -import static com.google.common.base.Preconditions.checkArgument; -import static java.lang.String.format; -import static org.apache.commons.lang.StringUtils.isEmpty; - -public class QProfileFinder { - - private final DbClient dbClient; - private final Languages languages; - - public QProfileFinder(DbClient dbClient, Languages languages) { - this.dbClient = dbClient; - this.languages = languages; - } - - public void defineProfileParams(WebService.NewAction action) { - action.createParam(QProfileIdentificationParamUtils.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(QProfileIdentificationParamUtils.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(QProfileIdentificationParamUtils.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 QualityProfileDto find(Request request) { - try (DbSession dbSession = dbClient.openSession(false)) { - return find(request, dbSession); - } - } - - public QualityProfileDto find(Request request, DbSession dbSession) { - String language = request.param(QProfileIdentificationParamUtils.PARAM_LANGUAGE); - String profileName = request.param(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME); - String profileKey = request.param(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY); - - checkArgument( - (!isEmpty(language) && !isEmpty(profileName)) ^ !isEmpty(profileKey), "Either profileKey or profileName + language must be set"); - - if (profileKey != null) { - return findByKey(dbSession, profileKey); - } - return findByName(dbSession, language, profileName); - } - - private QualityProfileDto findByKey(DbSession dbSession, String profileKey) { - QualityProfileDto profile; - profile = dbClient.qualityProfileDao().selectByKey(dbSession, profileKey); - if (profile == null) { - throw new NotFoundException(format("Unable to find a profile for with key '%s'", profileKey)); - } - return profile; - } - - private QualityProfileDto findByName(DbSession dbSession, String language, String profileName) { - QualityProfileDto profile; - profile = dbClient.qualityProfileDao().selectByNameAndLanguage(profileName, language, dbSession); - if (profile == null) { - throw new NotFoundException(format("Unable to find a profile for language '%s' with name '%s'", language, profileName)); - } - return profile; - } -} 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 deleted file mode 100644 index 0a4452c5a6b..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileIdentificationParamUtils.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.db.DbSession; -import org.sonar.db.qualityprofile.QualityProfileDto; -import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.qualityprofile.QProfileFactory; -import org.sonar.server.util.LanguageParamUtils; - -import static org.apache.commons.lang.StringUtils.isEmpty; - -public class QProfileIdentificationParamUtils { - - 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 - } - - 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 getProfileKeyFromParameters(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; - } - - 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)); - } - return profile.getKey(); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryTest.java new file mode 100644 index 00000000000..89ab1c18370 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryTest.java @@ -0,0 +1,81 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.System2; +import org.sonar.db.DbTester; +import org.sonar.db.qualityprofile.QualityProfileDto; +import org.sonar.db.qualityprofile.QualityProfileTesting; +import org.sonar.server.exceptions.NotFoundException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class QProfileFactoryTest { + + @Rule + public DbTester dbTester = DbTester.create(System2.INSTANCE); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private QProfileFactory underTest = new QProfileFactory(dbTester.getDbClient()); + + @Before + public void setUp() throws Exception { + QualityProfileDto dto = QualityProfileTesting.newQualityProfileDto().setKey("sw").setName("Sonar way").setLanguage("js"); + dbTester.getDbClient().qualityProfileDao().insert(dbTester.getSession(), dto); + dbTester.commit(); + } + + @Test + public void find_profile_by_key() { + QualityProfileDto profile = underTest.find(QProfileRef.fromKey("sw")); + assertThat(profile.getKey()).isEqualTo("sw"); + assertThat(profile.getLanguage()).isEqualTo("js"); + assertThat(profile.getName()).isEqualTo("Sonar way"); + } + + @Test + public void find_profile_by_name() { + QualityProfileDto profile = underTest.find(QProfileRef.fromName("js", "Sonar way")); + assertThat(profile.getKey()).isEqualTo("sw"); + assertThat(profile.getLanguage()).isEqualTo("js"); + assertThat(profile.getName()).isEqualTo("Sonar way"); + } + + @Test + public void throw_NFE_if_profile_key_does_not_exist() { + expectedException.expect(NotFoundException.class); + + underTest.find(QProfileRef.fromKey("missing")); + } + + @Test + public void throw_NFE_if_profile_name_does_not_exist() { + expectedException.expect(NotFoundException.class); + + underTest.find(QProfileRef.fromName("js", "Missing")); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/BackupActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/BackupActionTest.java index a8cadafaa6e..c60f27fee73 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/BackupActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/BackupActionTest.java @@ -21,20 +21,16 @@ package org.sonar.server.qualityprofile.ws; import java.io.PrintWriter; import java.io.Writer; -import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; -import org.sonar.api.utils.System2; -import org.sonar.db.DbClient; -import org.sonar.db.DbTester; +import org.sonar.db.qualityprofile.QualityProfileTesting; import org.sonar.server.language.LanguageTesting; import org.sonar.server.qualityprofile.QProfileBackuper; import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.qualityprofile.QProfileRef; import org.sonar.server.ws.WsTester; import org.sonar.server.ws.WsTester.Result; @@ -43,33 +39,24 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class BackupActionTest { - @Rule - public DbTester db = DbTester.create(System2.INSTANCE); + private static final String SOME_PROFILE_KEY = "polop-palap-xoo-12345"; - // TODO Replace with proper DbTester + EsTester medium test once DaoV2 is removed - @Mock - private QProfileBackuper backuper; - - private WsTester tester; - - @Before - public void setUp() { - DbClient dbClient = new DbClient(db.database(), db.myBatis()); - - tester = new WsTester(new QProfilesWs( - mock(RuleActivationActions.class), - mock(BulkRuleActivationActions.class), - mock(ProjectAssociationActions.class), - new BackupAction(backuper, dbClient, new QProfileFactory(dbClient), LanguageTesting.newLanguages("xoo")))); - } + private QProfileBackuper backuper = mock(QProfileBackuper.class); + private QProfileFactory profileFactory = mock(QProfileFactory.class); + private WsTester tester = new WsTester(new QProfilesWs( + mock(RuleActivationActions.class), + mock(BulkRuleActivationActions.class), + mock(ProjectAssociationActions.class), + new BackupAction(backuper, profileFactory, LanguageTesting.newLanguages("xoo")))); @Test public void backup_profile() throws Exception { - String profileKey = "polop-palap-xoo-12345"; + when(profileFactory.find(QProfileRef.fromKey(SOME_PROFILE_KEY))).thenReturn(QualityProfileTesting.newQualityProfileDto().setKey(SOME_PROFILE_KEY)); final String response = ""; doAnswer(new Answer() { @@ -80,11 +67,11 @@ public class BackupActionTest { w.close(); return null; } - }).when(backuper).backup(eq(profileKey), any(Writer.class)); + }).when(backuper).backup(eq(SOME_PROFILE_KEY), any(Writer.class)); - Result result = tester.newGetRequest("api/qualityprofiles", "backup").setParam("profileKey", profileKey).execute(); + Result result = tester.newGetRequest("api/qualityprofiles", "backup").setParam(QProfileRef.PARAM_PROFILE_KEY, SOME_PROFILE_KEY).execute(); assertThat(result.outputAsString()).isEqualTo(response); - result.assertHeader("Content-Disposition", "attachment; filename=polop-palap-xoo-12345.xml"); + result.assertHeader("Content-Disposition", "attachment; filename=" + SOME_PROFILE_KEY + ".xml"); } @Test(expected = IllegalArgumentException.class) diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionMediumTest.java index bc0019df2e0..79f3f866b38 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionMediumTest.java @@ -31,7 +31,6 @@ import org.sonar.api.rule.Severity; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.RowNotFoundException; import org.sonar.db.qualityprofile.ActiveRuleDto; import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.db.rule.RuleDto; @@ -39,6 +38,7 @@ import org.sonar.db.rule.RuleTesting; import org.sonar.server.es.SearchOptions; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.qualityprofile.QProfileName; +import org.sonar.server.qualityprofile.QProfileRef; import org.sonar.server.qualityprofile.QProfileTesting; import org.sonar.server.qualityprofile.RuleActivator; import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; @@ -100,7 +100,7 @@ public class ChangeParentActionMediumTest { // Set parent wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "change_parent") - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey()) + .setParam(QProfileRef.PARAM_PROFILE_KEY, child.getKey()) .setParam("parentKey", parent1.getKey()) .execute(); session.clearCache(); @@ -133,7 +133,7 @@ public class ChangeParentActionMediumTest { // Set parent 2 through WS wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "change_parent") - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey()) + .setParam(QProfileRef.PARAM_PROFILE_KEY, child.getKey()) .setParam("parentKey", parent2.getKey()) .execute(); session.clearCache(); @@ -163,7 +163,7 @@ public class ChangeParentActionMediumTest { // Remove parent through WS wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "change_parent") - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey()) + .setParam(QProfileRef.PARAM_PROFILE_KEY, child.getKey()) .execute(); session.clearCache(); @@ -192,8 +192,8 @@ public class ChangeParentActionMediumTest { // 1. Set parent 1 wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "change_parent") - .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo") - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName()) + .setParam(QProfileRef.PARAM_LANGUAGE, "xoo") + .setParam(QProfileRef.PARAM_PROFILE_NAME, child.getName()) .setParam("parentName", parent1.getName()) .execute(); session.clearCache(); @@ -206,8 +206,8 @@ public class ChangeParentActionMediumTest { // 2. Set parent 2 wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "change_parent") - .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo") - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName()) + .setParam(QProfileRef.PARAM_LANGUAGE, "xoo") + .setParam(QProfileRef.PARAM_PROFILE_NAME, child.getName()) .setParam("parentName", parent2.getName()) .execute(); session.clearCache(); @@ -219,8 +219,8 @@ public class ChangeParentActionMediumTest { // 3. Remove parent wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "change_parent") - .setParam(QProfileIdentificationParamUtils.PARAM_LANGUAGE, "xoo") - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName()) + .setParam(QProfileRef.PARAM_LANGUAGE, "xoo") + .setParam(QProfileRef.PARAM_PROFILE_NAME, child.getName()) .setParam("parentName", "") .execute(); session.clearCache(); @@ -250,7 +250,7 @@ public class ChangeParentActionMediumTest { // Remove parent wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "change_parent") - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKey()) + .setParam(QProfileRef.PARAM_PROFILE_KEY, child.getKey()) .setParam("parentKey", "") .execute(); session.clearCache(); @@ -270,13 +270,13 @@ public class ChangeParentActionMediumTest { assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfileKey(child.getKey()), new SearchOptions()).getIds()).isEmpty(); wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "change_parent") - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKee()) + .setParam(QProfileRef.PARAM_PROFILE_KEY, child.getKee()) .setParam("parentName", "polop") .setParam("parentKey", "palap") .execute(); } - @Test(expected = RowNotFoundException.class) + @Test(expected = IllegalArgumentException.class) public void fail_if_profile_key_and_name_both_set() throws Exception { QualityProfileDto child = createProfile("xoo", "Child"); session.commit(); @@ -285,8 +285,8 @@ public class ChangeParentActionMediumTest { assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfileKey(child.getKey()), new SearchOptions()).getIds()).isEmpty(); wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "change_parent") - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, child.getKee()) - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_NAME, child.getName()) + .setParam(QProfileRef.PARAM_PROFILE_KEY, child.getKee()) + .setParam(QProfileRef.PARAM_PROFILE_NAME, child.getName()) .setParam("parentKey", "palap") .execute(); } @@ -295,7 +295,7 @@ public class ChangeParentActionMediumTest { public void fail_if_missing_permission() throws Exception { userSessionRule.login("anakin"); wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, "change_parent") - .setParam(QProfileIdentificationParamUtils.PARAM_PROFILE_KEY, "polop") + .setParam(QProfileRef.PARAM_PROFILE_KEY, "polop") .setParam("parentKey", "pulup") .execute(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java index c67888895c1..254d01004af 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java @@ -24,19 +24,23 @@ import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.sonar.api.server.ws.Request; +import org.sonar.api.resources.Languages; import org.sonar.api.utils.System2; import org.sonar.db.DbTester; import org.sonar.db.qualityprofile.QProfileChangeQuery; import org.sonar.db.rule.RuleTesting; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.qualityprofile.QProfileRef; import org.sonar.server.qualityprofile.QProfileTesting; import org.sonar.server.ws.WsTester; import static java.util.Arrays.asList; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.sonar.server.qualityprofile.QProfileRef.PARAM_PROFILE_KEY; import static org.sonar.server.qualityprofile.QProfileTesting.XOO_P1_KEY; public class ChangelogActionTest { @@ -48,52 +52,52 @@ public class ChangelogActionTest { private WsTester wsTester; private ChangelogLoader changelogLoader = mock(ChangelogLoader.class); - private QProfileFinder profileFinder = mock(QProfileFinder.class); + private QProfileFactory profileFactory = mock(QProfileFactory.class); @Before public void before() { wsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class), - new ChangelogAction(changelogLoader, profileFinder))); + new ChangelogAction(changelogLoader, profileFactory, new Languages()))); } @Test public void changelog_empty() throws Exception { - when(profileFinder.find(any(Request.class))).thenReturn(QProfileTesting.newXooP1()); + when(profileFactory.find(eq(QProfileRef.fromKey(XOO_P1_KEY)))).thenReturn(QProfileTesting.newXooP1()); when(changelogLoader.load(any(QProfileChangeQuery.class))).thenReturn(new ChangelogLoader.Changelog(0, Collections.emptyList())); - wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY) + wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam(PARAM_PROFILE_KEY, XOO_P1_KEY) .execute().assertJson(getClass(), "changelog_empty.json"); } @Test public void changelog_nominal() throws Exception { - when(profileFinder.find(any(Request.class))).thenReturn(QProfileTesting.newXooP1()); + when(profileFactory.find(eq(QProfileRef.fromKey(XOO_P1_KEY)))).thenReturn(QProfileTesting.newXooP1()); ChangelogLoader.Change change1 = new ChangelogLoader.Change("C1", "ACTIVATED", A_DATE, null, null, null, null, null, null); ChangelogLoader.Change change2 = new ChangelogLoader.Change("C2", "ACTIVATED", A_DATE + 10, null, null, null, null, null, null); List changes = asList(change1, change2); when(changelogLoader.load(any(QProfileChangeQuery.class))).thenReturn(new ChangelogLoader.Changelog(10, changes)); - wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY) + wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam(PARAM_PROFILE_KEY, XOO_P1_KEY) .execute().assertJson(getClass(), "changelog_nominal.json"); } @Test public void changelog_with_all_fields() throws Exception { - when(profileFinder.find(any(Request.class))).thenReturn(QProfileTesting.newXooP1()); + when(profileFactory.find(eq(QProfileRef.fromKey(XOO_P1_KEY)))).thenReturn(QProfileTesting.newXooP1()); ChangelogLoader.Change change1 = new ChangelogLoader.Change("C1", "ACTIVATED", A_DATE, "MAJOR", "marcel", "Marcel", "INHERITED", RuleTesting.XOO_X1, "X One"); change1.getParams().put("foo", "foo_value"); change1.getParams().put("bar", "bar_value"); List changes = asList(change1); when(changelogLoader.load(any(QProfileChangeQuery.class))).thenReturn(new ChangelogLoader.Changelog(10, changes)); - wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", XOO_P1_KEY) + wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam(PARAM_PROFILE_KEY, XOO_P1_KEY) .execute().assertJson(getClass(), "changelog_full.json"); } @Test(expected = NotFoundException.class) public void fail_on_unknown_profile() throws Exception { - when(profileFinder.find(any(Request.class))).thenThrow(new NotFoundException("Profile not found")); + when(profileFactory.find(eq(QProfileRef.fromKey(XOO_P1_KEY)))).thenThrow(new NotFoundException("Profile not found")); - wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam("profileKey", "unknown-profile").execute(); + wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam(PARAM_PROFILE_KEY, XOO_P1_KEY).execute(); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileFactoryTest.java new file mode 100644 index 00000000000..e59d6dfe492 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileFactoryTest.java @@ -0,0 +1,82 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.System2; +import org.sonar.db.DbTester; +import org.sonar.db.qualityprofile.QualityProfileDto; +import org.sonar.db.qualityprofile.QualityProfileTesting; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.qualityprofile.QProfileRef; + +import static org.assertj.core.api.Assertions.assertThat; + +public class QProfileFactoryTest { + + @Rule + public DbTester dbTester = DbTester.create(System2.INSTANCE); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private QProfileFactory underTest = new QProfileFactory(dbTester.getDbClient()); + + @Before + public void setUp() throws Exception { + QualityProfileDto dto = QualityProfileTesting.newQualityProfileDto().setKey("sw").setName("Sonar way").setLanguage("js"); + dbTester.getDbClient().qualityProfileDao().insert(dbTester.getSession(), dto); + dbTester.commit(); + } + + @Test + public void find_profile_by_key() { + QualityProfileDto profile = underTest.find(QProfileRef.fromKey("sw")); + assertThat(profile.getKey()).isEqualTo("sw"); + assertThat(profile.getLanguage()).isEqualTo("js"); + assertThat(profile.getName()).isEqualTo("Sonar way"); + } + + @Test + public void find_profile_by_name() { + QualityProfileDto profile = underTest.find(QProfileRef.fromName("js", "Sonar way")); + assertThat(profile.getKey()).isEqualTo("sw"); + assertThat(profile.getLanguage()).isEqualTo("js"); + assertThat(profile.getName()).isEqualTo("Sonar way"); + } + + @Test + public void throw_NFE_if_profile_key_does_not_exist() { + expectedException.expect(NotFoundException.class); + + underTest.find(QProfileRef.fromKey("missing")); + } + + @Test + public void throw_NFE_if_profile_name_does_not_exist() { + expectedException.expect(NotFoundException.class); + + underTest.find(QProfileRef.fromName("js", "Missing")); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRefTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRefTest.java new file mode 100644 index 00000000000..afde17aa015 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileRefTest.java @@ -0,0 +1,192 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.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.server.ws.internal.SimpleGetRequest; +import org.sonar.server.qualityprofile.QProfileRef; +import org.sonar.server.ws.WsTester; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class QProfileRefTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void create_ref_by_key() { + QProfileRef ref = QProfileRef.fromKey("foo"); + assertThat(ref.hasKey()).isTrue(); + assertThat(ref.getKey()).isEqualTo("foo"); + } + + @Test + public void getLanguage_throws_ISE_if_key_ref() { + QProfileRef ref = QProfileRef.fromKey("foo"); + + expectedException.expect(IllegalStateException.class); + ref.getLanguage(); + } + + @Test + public void getName_throws_ISE_if_key_ref() { + QProfileRef ref = QProfileRef.fromKey("foo"); + + expectedException.expect(IllegalStateException.class); + ref.getName(); + } + + @Test + public void create_ref_by_name() { + QProfileRef ref = QProfileRef.fromName("js", "Sonar way"); + assertThat(ref.hasKey()).isFalse(); + assertThat(ref.getLanguage()).isEqualTo("js"); + assertThat(ref.getName()).isEqualTo("Sonar way"); + } + + @Test + public void getKey_throws_ISE_if_name_ref() { + QProfileRef ref = QProfileRef.fromName("js", "Sonar way"); + + expectedException.expect(IllegalStateException.class); + ref.getKey(); + } + + + @Test + public void create_key_ref_from_ws_request() { + SimpleGetRequest req = new SimpleGetRequest(); + req.setParam("profileKey", "foo"); + + QProfileRef ref = QProfileRef.from(req); + assertThat(ref.getKey()).isEqualTo("foo"); + } + + @Test + public void create_name_ref_from_ws_request() { + SimpleGetRequest req = new SimpleGetRequest(); + req.setParam("language", "js"); + req.setParam("profileName", "Sonar way"); + + QProfileRef ref = QProfileRef.from(req); + assertThat(ref.getLanguage()).isEqualTo("js"); + assertThat(ref.getName()).isEqualTo("Sonar way"); + } + + @Test + public void create_name_ref_throws_IAE_if_language_is_missing() { + SimpleGetRequest req = new SimpleGetRequest(); + req.setParam(QProfileRef.PARAM_PROFILE_KEY, "the key"); + req.setParam(QProfileRef.PARAM_PROFILE_NAME, "the name"); + + expectedException.expect(IllegalArgumentException.class); + QProfileRef.from(req); + } + + @Test + public void throw_IAE_if_request_does_not_define_ref() { + SimpleGetRequest req = new SimpleGetRequest(); + + expectedException.expect(IllegalArgumentException.class); + QProfileRef.from(req); + } + + @Test + public void define_ws_parameters() { + WsTester wsTester = new WsTester(); + WebService.NewController controller = wsTester.context().createController("api/qualityprofiles"); + WebService.NewAction newAction = controller.createAction("do").setHandler((request, response) -> { + }); + + Languages languages = new Languages(new FakeLanguage("java"), new FakeLanguage("js")); + QProfileRef.defineParams(newAction, languages); + + controller.done(); + WebService.Action action = wsTester.controller("api/qualityprofiles").action("do"); + assertThat(action.param("language")).isNotNull(); + assertThat(action.param("language").possibleValues()).containsOnly("java", "js"); + assertThat(action.param("profileKey")).isNotNull(); + assertThat(action.param("profileName")).isNotNull(); + } + + @Test + public void test_equals_and_hashCode_of_key_ref() { + QProfileRef key1 = QProfileRef.fromKey("one"); + QProfileRef key1bis = QProfileRef.fromKey("one"); + QProfileRef key2 = QProfileRef.fromKey("two"); + QProfileRef name = QProfileRef.fromName("js", "one"); + + assertThat(key1.equals(key1)).isTrue(); + assertThat(key1.equals(key1bis)).isTrue(); + assertThat(key1.equals(key2)).isFalse(); + assertThat(key1.equals(name)).isFalse(); + + assertThat(key1.hashCode()).isEqualTo(key1.hashCode()); + assertThat(key1.hashCode()).isEqualTo(key1bis.hashCode()); + } + + @Test + public void test_equals_and_hashCode_of_name_ref() { + QProfileRef name1 = QProfileRef.fromName("js", "one"); + QProfileRef name1bis = QProfileRef.fromName("js", "one"); + QProfileRef name2 = QProfileRef.fromName("js", "two"); + QProfileRef name1OtherLang = QProfileRef.fromName("java", "one"); + QProfileRef key = QProfileRef.fromKey("one"); + + assertThat(name1.equals(name1)).isTrue(); + assertThat(name1.equals(name1bis)).isTrue(); + assertThat(name1.equals(name2)).isFalse(); + assertThat(name1.equals(name1OtherLang)).isFalse(); + assertThat(name1.equals(key)).isFalse(); + + assertThat(name1.hashCode()).isEqualTo(name1.hashCode()); + assertThat(name1.hashCode()).isEqualTo(name1bis.hashCode()); + } + + private static class FakeLanguage implements Language { + private final String key; + + public FakeLanguage(String key) { + this.key = key; + } + + @Override + public String getKey() { + return key; + } + + @Override + public String getName() { + return key; + } + + @Override + public String[] getFileSuffixes() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java index 3ddc714390b..0bc7bdff46c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java @@ -32,6 +32,7 @@ import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.ValidationMessages; import org.sonar.server.language.LanguageTesting; import org.sonar.server.qualityprofile.QProfileExporters; +import org.sonar.server.qualityprofile.QProfileFactory; import org.sonar.server.qualityprofile.QProfileService; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; @@ -67,10 +68,10 @@ public class QProfilesWsTest { new SearchAction(null, languages), new SetDefaultAction(languages, null, null, userSessionRule), new ProjectsAction(null, userSessionRule), - new BackupAction(null, null, null, languages), + new BackupAction(null, null, languages), new RestoreAction(null, languages, userSessionRule), - new ChangelogAction(null, mock(QProfileFinder.class)), - new ChangeParentAction(null, null, null, languages, userSessionRule), + new ChangelogAction(null, mock(QProfileFactory.class), languages), + new ChangeParentAction(null, null, languages, userSessionRule), new CompareAction(null, null, null, languages), new CopyAction(null, languages, userSessionRule), new DeleteAction(languages, null, null, userSessionRule), -- 2.39.5