From f0231f6e3aa917119ac4cbf1fc9abaf885873223 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Tue, 1 Jul 2014 00:10:10 +0200 Subject: [PATCH] SONAR-5007 refactor Q profile exporters --- .../server/platform/ServerComponents.java | 4 + .../qualityprofile/QProfileExporters.java | 107 ++++++++++++ .../server/qualityprofile/QProfileLoader.java | 133 +++++++++++++++ .../QProfileRepositoryExporter.java | 52 +----- .../qualityprofile/QProfileService.java | 82 +-------- .../server/qualityprofile/QProfiles.java | 6 +- .../server/qualityprofile/RuleActivation.java | 7 - .../server/rule/ws/ActiveRuleCompleter.java | 14 +- .../org/sonar/server/rule/ws/AppAction.java | 10 +- .../app/controllers/profiles_controller.rb | 46 ++--- .../WEB-INF/app/helpers/profiles_helper.rb | 4 +- .../webapp/WEB-INF/app/models/internal.rb | 16 +- .../app/views/profiles/_create_form.html.erb | 2 +- .../WEB-INF/app/views/profiles/index.html.erb | 2 +- .../app/views/profiles/permalinks.html.erb | 2 +- .../QProfileBackuperMediumTest.java | 18 +- .../qualityprofile/QProfileExportersTest.java | 160 ++++++++++++++++++ .../QProfileRepositoryExporterTest.java | 113 +------------ .../QProfileServiceMediumTest.java | 8 +- .../sonar/server/rule/ws/AppActionTest.java | 7 +- 20 files changed, 488 insertions(+), 305 deletions(-) create mode 100644 sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java create mode 100644 sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileLoader.java create mode 100644 sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java diff --git a/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index f3921481144..79b4fa8d66a 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -178,7 +178,9 @@ import org.sonar.server.qualitygate.ws.QGatesWs; import org.sonar.server.qualityprofile.BuiltInProfiles; import org.sonar.server.qualityprofile.QProfileBackuper; import org.sonar.server.qualityprofile.QProfileCopier; +import org.sonar.server.qualityprofile.QProfileExporters; import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.qualityprofile.QProfileLoader; import org.sonar.server.qualityprofile.QProfileLookup; import org.sonar.server.qualityprofile.QProfileOperations; import org.sonar.server.qualityprofile.QProfileProjectLookup; @@ -432,6 +434,8 @@ class ServerComponents { pico.addSingleton(RuleActivationActions.class); pico.addSingleton(BulkRuleActivationActions.class); pico.addSingleton(RuleActivator.class); + pico.addSingleton(QProfileLoader.class); + pico.addSingleton(QProfileExporters.class); pico.addSingleton(QProfileService.class); pico.addSingleton(RuleActivatorContextFactory.class); pico.addSingleton(QProfileFactory.class); diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java new file mode 100644 index 00000000000..d8a224f8957 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java @@ -0,0 +1,107 @@ +/* + * 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; + +import org.apache.commons.lang.ArrayUtils; +import org.sonar.api.ServerComponent; +import org.sonar.api.profiles.ProfileExporter; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; +import org.sonar.api.rules.RulePriority; +import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.server.exceptions.NotFoundException; + +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class QProfileExporters implements ServerComponent { + + private final QProfileLoader loader; + private final RuleFinder ruleFinder; + private final ProfileExporter[] exporters; + + public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder, ProfileExporter[] exporters) { + this.loader = loader; + this.ruleFinder = ruleFinder; + this.exporters = exporters; + } + + public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder) { + this(loader, ruleFinder, new ProfileExporter[0]); + } + + public List exportersForLanguage(String language) { + List result = new ArrayList(); + for (ProfileExporter exporter : exporters) { + if (exporter.getSupportedLanguages() == null || exporter.getSupportedLanguages().length == 0 || ArrayUtils.contains(exporter.getSupportedLanguages(), language)) { + result.add(exporter); + } + } + return result; + } + + public String mimeType(String exporterKey) { + ProfileExporter exporter = findExporter(exporterKey); + return exporter.getMimeType(); + } + + public void export(String profileKey, String exporterKey, Writer writer) { + ProfileExporter exporter = findExporter(exporterKey); + QualityProfileDto profile = loader.getByKey(profileKey); + if (profile == null) { + throw new NotFoundException("Unknown Quality profile: " + profileKey); + } + exporter.exportProfile(wrap(profile), writer); + } + + /** + * Only for ruby on rails + */ + public String export(String profileKey, String tool) { + StringWriter writer = new StringWriter(); + export(profileKey, tool, writer); + return writer.toString(); + } + + private RulesProfile wrap(QualityProfileDto profile) { + RulesProfile target = new RulesProfile(profile.getName(), profile.getLanguage()); + for (ActiveRule activeRule : loader.findActiveRulesByProfile(profile.getKey())) { + Rule rule = ruleFinder.findByKey(activeRule.key().ruleKey()); + org.sonar.api.rules.ActiveRule wrappedActiveRule = target.activateRule(rule, RulePriority.valueOf(activeRule.severity())); + for (Map.Entry entry : activeRule.params().entrySet()) { + wrappedActiveRule.setParameter(entry.getKey(), entry.getValue()); + } + } + return target; + } + + private ProfileExporter findExporter(String exporterKey) { + for (ProfileExporter e : exporters) { + if (exporterKey.equals(e.getKey())) { + return e; + } + } + throw new NotFoundException("Unknown quality profile exporter: " + exporterKey); + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileLoader.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileLoader.java new file mode 100644 index 00000000000..d55b8cdc7f8 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileLoader.java @@ -0,0 +1,133 @@ +/* + * 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; + +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import org.sonar.api.ServerComponent; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.qualityprofile.db.ActiveRuleKey; +import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.server.db.DbClient; +import org.sonar.server.qualityprofile.index.ActiveRuleIndex; +import org.sonar.server.rule.index.RuleIndex; +import org.sonar.server.rule.index.RuleQuery; +import org.sonar.server.search.FacetValue; +import org.sonar.server.search.IndexClient; +import org.sonar.server.search.QueryOptions; + +import javax.annotation.CheckForNull; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class QProfileLoader implements ServerComponent { + + private final DbClient db; + private final IndexClient index; + + public QProfileLoader(DbClient db, IndexClient index) { + this.db = db; + this.index = index; + } + + /** + * Returns all Quality profiles as DTOs. This is a temporary solution as long as + * profiles are not indexed and declared as a business object + */ + public List findAll() { + DbSession dbSession = db.openSession(false); + try { + return db.qualityProfileDao().findAll(dbSession); + } finally { + dbSession.close(); + } + } + + @CheckForNull + public QualityProfileDto getByKey(String key) { + DbSession dbSession = db.openSession(false); + try { + return db.qualityProfileDao().getByKey(dbSession, key); + } finally { + dbSession.close(); + } + } + + @CheckForNull + public QualityProfileDto getByLangAndName(String lang, String name) { + DbSession dbSession = db.openSession(false); + try { + return db.qualityProfileDao().getByNameAndLanguage(name, lang, dbSession); + } finally { + dbSession.close(); + } + } + + @CheckForNull + public ActiveRule getActiveRule(ActiveRuleKey key) { + return index.get(ActiveRuleIndex.class).getByKey(key); + } + + public List findActiveRulesByRule(RuleKey key) { + return index.get(ActiveRuleIndex.class).findByRule(key); + } + + public List findActiveRulesByProfile(String key) { + return index.get(ActiveRuleIndex.class).findByProfile(key); + } + + public long countActiveRulesByProfile(String key) { + return index.get(ActiveRuleIndex.class).countByQualityProfileKey(key); + } + + public Map countAllActiveRules() { + Map counts = new HashMap(); + for (Map.Entry entry : index.get(ActiveRuleIndex.class).countAllByQualityProfileKey().entrySet()) { + counts.put(entry.getKey(), entry.getValue()); + } + return counts; + } + + public Multimap getStatsByProfile(String key) { + return index.get(ActiveRuleIndex.class).getStatsByProfileKey(key); + } + + public Map> getAllProfileStats() { + List keys = Lists.newArrayList(); + for (QualityProfileDto profile : this.findAll()) { + keys.add(profile.getKey()); + } + return index.get(ActiveRuleIndex.class).getStatsByProfileKeys(keys); + } + + public long countDeprecatedActiveRulesByProfile(String key) { + return index.get(RuleIndex.class).search( + new RuleQuery() + .setQProfileKey(key) + .setActivation(true) + .setStatuses(Lists.newArrayList(RuleStatus.DEPRECATED)), + new QueryOptions().setLimit(0)).getTotal(); + } + + +} diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java index d3bdcf5d466..ac29bc80f02 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java @@ -27,8 +27,6 @@ import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.ibatis.session.SqlSession; import org.sonar.api.ServerComponent; -import org.sonar.api.database.DatabaseSession; -import org.sonar.api.profiles.ProfileExporter; import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.rules.ActiveRule; @@ -38,13 +36,9 @@ import org.sonar.api.utils.ValidationMessages; import org.sonar.core.qualityprofile.db.ActiveRuleDao; import org.sonar.core.qualityprofile.db.ActiveRuleDto; import org.sonar.core.qualityprofile.db.ActiveRuleParamDto; -import org.sonar.jpa.session.DatabaseSessionFactory; import org.sonar.server.exceptions.BadRequestException; -import org.sonar.server.exceptions.NotFoundException; import java.io.StringReader; -import java.io.StringWriter; -import java.io.Writer; import java.util.ArrayList; import java.util.List; @@ -55,24 +49,19 @@ import static com.google.common.collect.Lists.newArrayList; */ public class QProfileRepositoryExporter implements ServerComponent { - private final DatabaseSessionFactory sessionFactory; private final ActiveRuleDao activeRuleDao; - private final List exporters; private final List importers; /** * Used by pico when no plugin provide profile exporter / importer */ - public QProfileRepositoryExporter(DatabaseSessionFactory sessionFactory, ActiveRuleDao activeRuleDao) { - this(sessionFactory, activeRuleDao, Lists.newArrayList(), Lists.newArrayList()); + public QProfileRepositoryExporter(ActiveRuleDao activeRuleDao) { + this(activeRuleDao, Lists.newArrayList()); } - public QProfileRepositoryExporter(DatabaseSessionFactory sessionFactory, ActiveRuleDao activeRuleDao, - List importers, List exporters) { - this.sessionFactory = sessionFactory; + public QProfileRepositoryExporter(ActiveRuleDao activeRuleDao, List importers) { this.activeRuleDao = activeRuleDao; this.importers = importers; - this.exporters = exporters; } public QProfileResult importXml(QProfile profile, String pluginKey, String xml, SqlSession session) { @@ -85,22 +74,6 @@ public class QProfileRepositoryExporter implements ServerComponent { return result; } - public String exportToXml(QProfile profile, String pluginKey) { - DatabaseSession session = sessionFactory.getSession(); - RulesProfile rulesProfile = session.getSingleResult(RulesProfile.class, "id", profile.id()); - if (rulesProfile == null) { - throw new NotFoundException("This profile does not exist"); - } - ProfileExporter exporter = getProfileExporter(pluginKey); - Writer writer = new StringWriter(); - exporter.exportProfile(rulesProfile, writer); - return writer.toString(); - } - - public String getProfileExporterMimeType(String pluginKey) { - return getProfileExporter(pluginKey).getMimeType(); - } - private void importProfile(int profileId, RulesProfile rulesProfile, SqlSession sqlSession) { List activeRuleDtos = newArrayList(); Multimap paramsByActiveRule = ArrayListMultimap.create(); @@ -153,25 +126,6 @@ public class QProfileRepositoryExporter implements ServerComponent { throw new BadRequestException("No such importer : " + importerKey); } - private ProfileExporter getProfileExporter(String exporterKey) { - for (ProfileExporter exporter : exporters) { - if (StringUtils.equals(exporterKey, exporter.getKey())) { - return exporter; - } - } - throw new BadRequestException("No such exporter : " + exporterKey); - } - - public List getProfileExportersForLanguage(String language) { - List result = new ArrayList(); - for (ProfileExporter exporter : exporters) { - if (exporter.getSupportedLanguages() == null || exporter.getSupportedLanguages().length == 0 || ArrayUtils.contains(exporter.getSupportedLanguages(), language)) { - result.add(exporter); - } - } - return result; - } - public List getProfileImportersForLanguage(String language) { List result = new ArrayList(); for (ProfileImporter importer : importers) { diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java index 9ab2e196ba8..45d196b3f1b 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java @@ -19,16 +19,12 @@ */ package org.sonar.server.qualityprofile; -import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.FilterBuilders; import org.elasticsearch.index.query.OrFilterBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.sonar.api.ServerComponent; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.RuleStatus; import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.persistence.DbSession; import org.sonar.core.qualityprofile.db.ActiveRuleKey; @@ -37,10 +33,7 @@ import org.sonar.core.rule.RuleDto; import org.sonar.core.user.UserDto; import org.sonar.server.activity.index.ActivityIndex; import org.sonar.server.db.DbClient; -import org.sonar.server.qualityprofile.index.ActiveRuleIndex; -import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.rule.index.RuleQuery; -import org.sonar.server.search.FacetValue; import org.sonar.server.search.IndexClient; import org.sonar.server.search.QueryOptions; import org.sonar.server.search.Result; @@ -54,9 +47,7 @@ import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class QProfileService implements ServerComponent { @@ -68,8 +59,8 @@ public class QProfileService implements ServerComponent { private final QProfileCopier copier; private final QProfileReset reset; - public QProfileService(DbClient db, IndexClient index, RuleActivator ruleActivator, QProfileFactory factory, QProfileBackuper backuper, - QProfileCopier copier, QProfileReset reset) { + public QProfileService(DbClient db, IndexClient index, RuleActivator ruleActivator, QProfileFactory factory, + QProfileBackuper backuper, QProfileCopier copier, QProfileReset reset) { this.db = db; this.index = index; this.ruleActivator = ruleActivator; @@ -91,42 +82,6 @@ public class QProfileService implements ServerComponent { } } - /** - * Returns all Quality profiles as DTOs. This is a temporary solution as long as - * profiles are not indexed and declared as a business object - */ - public List findAll() { - DbSession dbSession = db.openSession(false); - try { - return db.qualityProfileDao().findAll(dbSession); - } finally { - dbSession.close(); - } - } - - @CheckForNull - public QualityProfileDto getByKey(String key) { - DbSession dbSession = db.openSession(false); - try { - return db.qualityProfileDao().getByKey(dbSession, key); - } finally { - dbSession.close(); - } - } - - @CheckForNull - public ActiveRule getActiveRule(ActiveRuleKey key) { - return index.get(ActiveRuleIndex.class).getByKey(key); - } - - public List findActiveRulesByRule(RuleKey key) { - return index.get(ActiveRuleIndex.class).findByRule(key); - } - - public List findActiveRulesByProfile(String key) { - return index.get(ActiveRuleIndex.class).findByProfile(key); - } - /** * Activate a rule on a Quality profile. Update configuration (severity/parameters) if the rule is already * activated. @@ -247,39 +202,6 @@ public class QProfileService implements ServerComponent { UserSession.get().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN); } - public long countActiveRulesByProfile(String key) { - return index.get(ActiveRuleIndex.class).countByQualityProfileKey(key); - } - - public Map countAllActiveRules() { - Map counts = new HashMap(); - for (Map.Entry entry : index.get(ActiveRuleIndex.class).countAllByQualityProfileKey().entrySet()) { - counts.put(entry.getKey(), entry.getValue()); - } - return counts; - } - - public Multimap getStatsByProfile(String key) { - return index.get(ActiveRuleIndex.class).getStatsByProfileKey(key); - } - - public Map> getAllProfileStats() { - List keys = Lists.newArrayList(); - for (QualityProfileDto profile : this.findAll()) { - keys.add(profile.getKey()); - } - return index.get(ActiveRuleIndex.class).getStatsByProfileKeys(keys); - } - - public long countDeprecatedActiveRulesByProfile(String key) { - return index.get(RuleIndex.class).search( - new RuleQuery() - .setQProfileKey(key) - .setActivation(true) - .setStatuses(Lists.newArrayList(RuleStatus.DEPRECATED)), - new QueryOptions().setLimit(0)).getTotal(); - } - public Result searchActivities(QProfileActivityQuery query, QueryOptions options) { DbSession session = db.openSession(false); try { diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java index 56ddaf26cac..e36b55dae05 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java @@ -28,8 +28,8 @@ import org.sonar.server.user.UserSession; import org.sonar.server.util.Validation; import javax.annotation.CheckForNull; + import java.util.List; -import java.util.Map; public class QProfiles implements ServerComponent { @@ -40,7 +40,7 @@ public class QProfiles implements ServerComponent { private final QProfileLookup profileLookup; public QProfiles(QProfileProjectOperations projectOperations, QProfileProjectLookup projectLookup, - QProfileLookup profileLookup) { + QProfileLookup profileLookup) { this.projectOperations = projectOperations; this.projectLookup = projectLookup; this.profileLookup = profileLookup; @@ -79,7 +79,6 @@ public class QProfiles implements ServerComponent { return profileLookup.ancestors(profile); } - // PROJECTS public List projects(int profileId) { @@ -114,7 +113,6 @@ public class QProfiles implements ServerComponent { projectOperations.removeAllProjects(profileId, UserSession.get()); } - private void checkProfileNameParam(String name) { if (Strings.isNullOrEmpty(name)) { throw new BadRequestException("quality_profiles.please_type_profile_name"); diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java index b486a19c32c..e89c21d1e32 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java @@ -65,13 +65,6 @@ public class RuleActivation { return this; } - /** - * For internal use - */ - boolean useDefaults() { - return severity == null && parameters.isEmpty(); - } - public RuleActivation setSeverity(@Nullable String s) { if (s != null && !Severity.ALL.contains(s)) { throw new IllegalArgumentException("Unknown severity: " + s); diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/ActiveRuleCompleter.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/ActiveRuleCompleter.java index 4920d7501a9..5f90f91c963 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ws/ActiveRuleCompleter.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/ActiveRuleCompleter.java @@ -24,7 +24,7 @@ import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.text.JsonWriter; import org.sonar.core.qualityprofile.db.ActiveRuleKey; import org.sonar.server.qualityprofile.ActiveRule; -import org.sonar.server.qualityprofile.QProfileService; +import org.sonar.server.qualityprofile.QProfileLoader; import org.sonar.server.rule.Rule; import org.sonar.server.rule.index.RuleQuery; @@ -37,10 +37,10 @@ import java.util.Map; * web services. */ public class ActiveRuleCompleter implements ServerComponent { - private final QProfileService service; + private final QProfileLoader loader; - public ActiveRuleCompleter(QProfileService service) { - this.service = service; + public ActiveRuleCompleter(QProfileLoader loader) { + this.loader = loader; } void completeSearch(RuleQuery query, Collection rules, JsonWriter json) { @@ -49,7 +49,7 @@ public class ActiveRuleCompleter implements ServerComponent { if (query.getQProfileKey() != null) { // Load details of active rules on the selected profile for (Rule rule : rules) { - ActiveRule activeRule = service.getActiveRule(ActiveRuleKey.of(query.getQProfileKey(), rule.key())); + ActiveRule activeRule = loader.getActiveRule(ActiveRuleKey.of(query.getQProfileKey(), rule.key())); if (activeRule != null) { writeActiveRules(rule.key(), Arrays.asList(activeRule), json); } @@ -57,7 +57,7 @@ public class ActiveRuleCompleter implements ServerComponent { } else { // Load details of all active rules for (Rule rule : rules) { - writeActiveRules(rule.key(), service.findActiveRulesByRule(rule.key()), json); + writeActiveRules(rule.key(), loader.findActiveRulesByRule(rule.key()), json); } } json.endObject(); @@ -65,7 +65,7 @@ public class ActiveRuleCompleter implements ServerComponent { void completeShow(Rule rule, JsonWriter json) { json.name("actives").beginArray(); - for (ActiveRule activeRule : service.findActiveRulesByRule(rule.key())) { + for (ActiveRule activeRule : loader.findActiveRulesByRule(rule.key())) { writeActiveRule(activeRule, json); } json.endArray(); diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/AppAction.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/AppAction.java index 2169b669c31..5a85557efce 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ws/AppAction.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/AppAction.java @@ -34,7 +34,7 @@ import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.text.JsonWriter; import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.qualityprofile.db.QualityProfileDto; -import org.sonar.server.qualityprofile.QProfileService; +import org.sonar.server.qualityprofile.QProfileLoader; import org.sonar.server.rule.RuleRepositories; import org.sonar.server.rule.RuleRepositories.Repository; import org.sonar.server.user.UserSession; @@ -51,15 +51,15 @@ public class AppAction implements RequestHandler { private final RuleRepositories ruleRepositories; private final I18n i18n; private final DebtModel debtModel; - private final QProfileService qualityProfileService; + private final QProfileLoader profileLoader; public AppAction(Languages languages, RuleRepositories ruleRepositories, I18n i18n, - DebtModel debtModel, QProfileService qualityProfileService) { + DebtModel debtModel, QProfileLoader profileLoader) { this.languages = languages; this.ruleRepositories = ruleRepositories; this.i18n = i18n; this.debtModel = debtModel; - this.qualityProfileService = qualityProfileService; + this.profileLoader = profileLoader; } @Override @@ -81,7 +81,7 @@ public class AppAction implements RequestHandler { private void addProfiles(JsonWriter json) { json.name("qualityprofiles").beginArray(); - for (QualityProfileDto profile : qualityProfileService.findAll()) { + for (QualityProfileDto profile : profileLoader.findAll()) { if (languageIsSupported(profile)) { json .beginObject() diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb index 9c9d485beb8..008f76db170 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb @@ -30,7 +30,7 @@ class ProfilesController < ApplicationController add_breadcrumbs ProfilesController::root_breadcrumb call_backend do @profiles = Internal.quality_profiles.allProfiles().to_a - @active_rule_counts = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).countAllActiveRules() + @active_rule_counts = Internal.qprofile_loader.countAllActiveRules() end Api::Utils.insensitive_sort!(@profiles) { |profile| profile.name() } end @@ -39,10 +39,10 @@ class ProfilesController < ApplicationController def show require_parameters 'key' call_backend do - @profile = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).getByKey(params[:key]) + @profile = Internal.qprofile_loader.getByKey(params[:key]) not_found('Profile not found') unless @profile - @deprecated_active_rules = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).countDeprecatedActiveRulesByProfile(@profile.getKey()) - @stats = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).getStatsByProfile(@profile.getKey()) + @deprecated_active_rules = Internal.qprofile_loader.countDeprecatedActiveRulesByProfile(@profile.getKey()) + @stats = Internal.qprofile_loader.getStatsByProfile(@profile.getKey()) end set_profile_breadcrumbs end @@ -66,7 +66,7 @@ class ProfilesController < ApplicationController end end profile_name = Java::OrgSonarServerQualityprofile::QProfileName.new(params[:language], params[:name]) - Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).create(profile_name) + Internal.qprofile_service.create(profile_name) # TODO use files_by_key #flash[:notice] = message('quality_profiles.profile_x_created', :params => result.profile.name) #flash_result(result) @@ -81,7 +81,7 @@ class ProfilesController < ApplicationController require_parameters 'language' @language = java_facade.getLanguages().find { |l| l.getKey()==params[:language].to_s } call_backend do - @builtin_profile_names = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).builtInProfileNamesForLanguage(params[:language].to_s) + @builtin_profile_names = Internal.qprofile_service.builtInProfileNamesForLanguage(params[:language].to_s) end render :partial => 'profiles/restore_built_in_form' end @@ -91,7 +91,7 @@ class ProfilesController < ApplicationController verify_post_request require_parameters 'language' call_backend do - Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).restoreBuiltInProfilesForLanguage(params[:language].to_s) + Internal.qprofile_service.restoreBuiltInProfilesForLanguage(params[:language].to_s) end redirect_to :action => 'index' end @@ -103,7 +103,7 @@ class ProfilesController < ApplicationController profile_key = profile_id_to_key(params[:id].to_i) call_backend do - Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).delete(profile_key) + Internal.qprofile_service.delete(profile_key) end redirect_to(:controller => 'profiles', :action => 'index') @@ -117,7 +117,7 @@ class ProfilesController < ApplicationController profile_key = profile_id_to_key(params[:id].to_i) call_backend do - Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).setDefault(profile_key) + Internal.qprofile_service.setDefault(profile_key) end redirect_to :action => 'index' end @@ -146,7 +146,7 @@ class ProfilesController < ApplicationController target_name = params['name'] call_backend do - Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).copyToName(source_key, target_name) + Internal.qprofile_service.copyToName(source_key, target_name) flash[:notice]= message('quality_profiles.profile_x_not_activated', :params => target_name) render :text => 'ok', :status => 200 end @@ -159,7 +159,7 @@ class ProfilesController < ApplicationController profile_key=params[:key] call_backend do - xml = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).backup(profile_key) + xml = Internal.qprofile_service.backup(profile_key) send_data(xml, :type => 'text/xml', :disposition => "attachment; filename=#{profile_key}.xml") end end @@ -179,7 +179,7 @@ class ProfilesController < ApplicationController else call_backend do xml=Api::Utils.read_post_request_param(params[:backup]) - Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).restore(xml) + Internal.qprofile_service.restore(xml) end end redirect_to :action => 'index' @@ -189,21 +189,21 @@ class ProfilesController < ApplicationController # GET /profiles/export?name=&language=&format def export language = params[:language] - if (params[:name].blank?) - profile = Internal.quality_profiles.defaultProfile(language) + if params[:name].blank? + profile = Internal.qprofile_service.getDefault(language) else - profile = Internal.quality_profiles.profile(CGI::unescape(params[:name]), language) + profile = Internal.qprofile_loader.getByLangAndName(language, CGI::unescape(params[:name])) end not_found('Profile not found') unless profile - if (params[:format].blank?) + if params[:format].blank? # standard sonar format - result = Internal.profile_backup.backupProfile(profile) + result = Internal.qprofile_service.backup(profile.getKee()) send_data(result, :type => 'text/xml', :disposition => 'inline') else exporter_key = params[:format] - result = Internal.profile_exporter.exportToXml(profile, exporter_key) - send_data(result, :type => Internal.profile_exporter.getProfileExporterMimeType(exporter_key), :disposition => 'inline') + result = Internal.qprofile_exporters.export(profile.getKee(), exporter_key) + send_data(result, :type => Internal.qprofile_exporters.mimeType(exporter_key), :disposition => 'inline') end end @@ -221,7 +221,7 @@ class ProfilesController < ApplicationController profiles = Api::Utils.insensitive_sort(profiles) { |p| p.name() } @select_parent = [[message('none'), nil]] + profiles.collect { |profile| [profile.name(), profile.id()] } - @all_profile_stats = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).getAllProfileStats() + @all_profile_stats = Internal.qprofile_loader.getAllProfileStats() end set_profile_breadcrumbs @@ -236,7 +236,7 @@ class ProfilesController < ApplicationController profile_key = profile_id_to_key(params[:id].to_i) parent_key = profile_id_to_key(params[:parent_id].to_i) unless params[:parent_id].empty? call_backend do - Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).setParent(profile_key, parent_key) + Internal.qprofile_service.setParent(profile_key, parent_key) end redirect_to :action => 'inheritance', :id => params[:id] end @@ -245,7 +245,7 @@ class ProfilesController < ApplicationController def changelog require_parameters 'key' - @profile = Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).getByKey(params[:key]) + @profile = Internal.qprofile_loader.getByKey(params[:key]) search = {'profileKeys' => @profile.key().to_s, 'since' => params[:since], 'to' => params[:to], 'p' => params[:p]} result = Internal.component(Java::OrgSonarServerActivity::RubyQProfileActivityService.java_class).search(search) @changes = result.activities @@ -341,7 +341,7 @@ class ProfilesController < ApplicationController call_backend do profile_key = profile_id_to_key(params[:id].to_i) - Internal.component(Java::OrgSonarServerQualityprofile::QProfileService.java_class).rename(profile_key, params[:new_name]) + Internal.qprofile_service.rename(profile_key, params[:new_name]) end render :text => 'ok', :status => 200 end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/profiles_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/profiles_helper.rb index 6c0f82c432f..edc76af0fa9 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/helpers/profiles_helper.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/profiles_helper.rb @@ -25,7 +25,7 @@ module ProfilesHelper def label_for_rules_count(qProfile, all_profile_stats) profile_stat = all_profile_stats[qProfile.key()] if all_profile_stats - profile_rules_count = profile_rules_count(qProfile, profile_stat) + profile_rules_count = profile_rules_count(profile_stat) label = "#{profile_rules_count} #{message('rules').downcase}" count_overriding = overriding_rules_count(profile_stat) @@ -52,7 +52,7 @@ module ProfilesHelper Internal.quality_profiles.countProjects(qProfile).to_i end - def profile_rules_count(qProfile, profile_stat) + def profile_rules_count(profile_stat) count = 0 count = profile_stat.get('countActiveRules').get(0).getValue() if profile_stat && profile_stat.get('countActiveRules') count diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb index bab4d8a47dc..d2bd4ed0bf0 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb @@ -66,12 +66,20 @@ class Internal component(Java::OrgSonarServerQualityprofile::QProfiles.java_class) end - def self.quality_gates - component(Java::OrgSonarServerQualitygate::QualityGates.java_class) + def self.qprofile_service + component(Java::OrgSonarServerQualityprofile::QProfileService.java_class) + end + + def self.qprofile_loader + component(Java::OrgSonarServerQualityprofile::QProfileLoader.java_class) end - def self.profile_exporter - component(Java::OrgSonarServerQualityprofile::QProfileRepositoryExporter.java_class) + def self.qprofile_exporters + component(Java::OrgSonarServerQualityprofile::QProfileExporters.java_class) + end + + def self.quality_gates + component(Java::OrgSonarServerQualitygate::QualityGates.java_class) end def self.rules diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_create_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_create_form.html.erb index 04101669b78..328e2af6add 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_create_form.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_create_form.html.erb @@ -1,6 +1,6 @@ <% language = controller.java_facade.getLanguages().find { |l| l.getKey()==language_key } - importers = Internal.profile_exporter.getProfileImportersForLanguage(language_key) + importers = Internal.component(Java::OrgSonarServerQualityprofile::QProfileRepositoryExporter.java_class).getProfileImportersForLanguage(language_key) %>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb index 5770af503fe..ab14ed861dd 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb @@ -50,7 +50,7 @@ - <% @profiles.select { |p| p.language == language.getKey() }.each do |profile| + <% @profiles.select { |p| p.language == language.getKey() }.each do |profile| projects_count = projects_count(profile) is_default_profile = default_profile && default_profile==profile.key() %> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/permalinks.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/permalinks.html.erb index 76e4a6e449d..71bb6fdfb07 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/permalinks.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/permalinks.html.erb @@ -2,7 +2,7 @@ <%= render :partial => 'profiles/tabs', :locals => {:selected_tab=>'Permalinks'} %>
- <% exporters = Internal.profile_exporter.getProfileExportersForLanguage(@profile.language()) %> + <% exporters = Internal.qprofile_exporters.exportersForLanguage(@profile.language()) %>
diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperMediumTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperMediumTest.java index 2b450686269..e27bc2cf9f6 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperMediumTest.java @@ -116,7 +116,7 @@ public class QProfileBackuperMediumTest { QualityProfileDto profile = db.qualityProfileDao().getByNameAndLanguage("P1", "xoo"); assertThat(profile).isNotNull(); - List activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(profile.getKey()); + List activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(profile.getKey()); assertThat(activeRules).hasSize(1); assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER"); assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE); @@ -143,7 +143,7 @@ public class QProfileBackuperMediumTest { tester.get(QProfileBackuper.class).restore(new StringReader( Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore.xml"), Charsets.UTF_8)), null); - List activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY); + List activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY); assertThat(activeRules).hasSize(1); assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER"); assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE); @@ -171,14 +171,14 @@ public class QProfileBackuperMediumTest { Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore-child.xml"), Charsets.UTF_8)), null); // parent profile is unchanged - List activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY); + List activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY); assertThat(activeRules).hasSize(1); assertThat(activeRules.get(0).severity()).isEqualTo("INFO"); assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE); assertThat(activeRules.get(0).params().get("max")).isEqualTo("10"); // child profile overrides parent - activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY); + activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY); assertThat(activeRules).hasSize(1); assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER"); assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.OVERRIDES); @@ -206,14 +206,14 @@ public class QProfileBackuperMediumTest { Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore-parent.xml"), Charsets.UTF_8)), null); // parent profile is updated - List activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY); + List activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY); assertThat(activeRules).hasSize(1); assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER"); assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.NONE); assertThat(activeRules.get(0).params().get("max")).isEqualTo("7"); // child profile is inherited - activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY); + activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY); assertThat(activeRules).hasSize(1); assertThat(activeRules.get(0).severity()).isEqualTo("BLOCKER"); assertThat(activeRules.get(0).inheritance()).isEqualTo(ActiveRule.Inheritance.INHERITED); @@ -241,7 +241,7 @@ public class QProfileBackuperMediumTest { Resources.toString(getClass().getResource("QProfileBackuperMediumTest/keep_other_inherited_rules.xml"), Charsets.UTF_8)), QProfileTesting.XOO_P2_NAME); // x1 and x2 - List activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY); + List activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P2_KEY); assertThat(activeRules).hasSize(2); } @@ -274,12 +274,12 @@ public class QProfileBackuperMediumTest { Resources.toString(getClass().getResource("QProfileBackuperMediumTest/restore.xml"), Charsets.UTF_8)), QProfileTesting.XOO_P3_NAME); - List activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY); + List activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(QProfileTesting.XOO_P1_KEY); assertThat(activeRules).hasSize(0); QualityProfileDto target = db.qualityProfileDao().getByNameAndLanguage("P3", "xoo"); assertThat(target).isNotNull(); - activeRules = tester.get(QProfileService.class).findActiveRulesByProfile(target.getKey()); + activeRules = tester.get(QProfileLoader.class).findActiveRulesByProfile(target.getKey()); assertThat(activeRules).hasSize(1); } diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java new file mode 100644 index 00000000000..72c4ea98088 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java @@ -0,0 +1,160 @@ +/* + * 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; + +import org.junit.ClassRule; +import org.junit.Test; +import org.sonar.api.profiles.ProfileDefinition; +import org.sonar.api.profiles.ProfileExporter; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rule.Severity; +import org.sonar.api.rules.*; +import org.sonar.api.rules.ActiveRule; +import org.sonar.api.server.rule.RuleParamType; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.api.utils.ValidationMessages; +import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.tester.ServerTester; + +import java.io.IOException; +import java.io.Writer; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; + +public class QProfileExportersTest { + + @ClassRule + public static ServerTester tester = new ServerTester().addComponents( + XooRulesDefinition.class, XooProfileDefinition.class, + XooExporter.class, StandardExporter.class); + + QProfileExporters exporters = tester.get(QProfileExporters.class); + + @Test + public void exportersForLanguage() throws Exception { + assertThat(exporters.exportersForLanguage("xoo")).hasSize(2); + assertThat(exporters.exportersForLanguage("java")).hasSize(1); + assertThat(exporters.exportersForLanguage("java").get(0)).isInstanceOf(StandardExporter.class); + } + + @Test + public void mimeType() throws Exception { + assertThat(exporters.mimeType("xootool")).isEqualTo("plain/custom"); + + // default mime type + assertThat(exporters.mimeType("standard")).isEqualTo("plain/text"); + } + + @Test + public void export() { + QualityProfileDto profile = tester.get(QProfileLoader.class).getByLangAndName("xoo", "P1"); + assertThat(exporters.export(profile.getKey(), "xootool")).isEqualTo("xoo -> P1 -> 1"); + assertThat(exporters.export(profile.getKey(), "standard")).isEqualTo("standard -> P1 -> 1"); + } + + @Test + public void fail_if_missing_exporter() { + QualityProfileDto profile = tester.get(QProfileLoader.class).getByLangAndName("xoo", "P1"); + try { + exporters.export(profile.getKey(), "unknown"); + fail(); + } catch (NotFoundException e) { + assertThat(e).hasMessage("Unknown quality profile exporter: unknown"); + } + } + + @Test + public void fail_if_missing_profile() { + try { + exporters.export("unknown", "xootool"); + fail(); + } catch (NotFoundException e) { + assertThat(e).hasMessage("Unknown Quality profile: unknown"); + } + } + + public static class XooExporter extends ProfileExporter { + public XooExporter() { + super("xootool", "Xoo Tool"); + } + + @Override + public String[] getSupportedLanguages() { + return new String[] {"xoo"}; + } + + @Override + public String getMimeType() { + return "plain/custom"; + } + + @Override + public void exportProfile(RulesProfile profile, Writer writer) { + try { + writer.write("xoo -> " + profile.getName() + " -> " + profile.getActiveRules().size()); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + } + + public static class StandardExporter extends ProfileExporter { + public StandardExporter() { + super("standard", "Standard"); + } + + @Override + public void exportProfile(RulesProfile profile, Writer writer) { + try { + writer.write("standard -> " + profile.getName() + " -> " + profile.getActiveRules().size()); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + } + + public static class XooRulesDefinition implements RulesDefinition { + @Override + public void define(Context context) { + NewRepository repository = context.createRepository("xoo", "xoo").setName("Xoo Repo"); + NewRule x1 = repository.createRule("R1") + .setName("R1 name") + .setHtmlDescription("R1 desc") + .setSeverity(Severity.MINOR); + x1.createParam("acceptWhitespace") + .setDefaultValue("false") + .setType(RuleParamType.BOOLEAN) + .setDescription("Accept whitespaces on the line"); + repository.done(); + } + } + + public static class XooProfileDefinition extends ProfileDefinition { + @Override + public RulesProfile createProfile(ValidationMessages validation) { + RulesProfile profile = RulesProfile.create("P1", "xoo"); + profile.activateRule(new Rule("xoo", "R1"), RulePriority.BLOCKER).setParameter("acceptWhitespace", "true"); + return profile; + } + } + +} diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java index 50584694df2..d4bf7a3ecb8 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java @@ -30,7 +30,6 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.sonar.api.database.DatabaseSession; -import org.sonar.api.profiles.ProfileExporter; import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.rule.Severity; @@ -41,12 +40,9 @@ import org.sonar.api.utils.ValidationMessages; import org.sonar.core.qualityprofile.db.ActiveRuleDao; import org.sonar.core.qualityprofile.db.ActiveRuleDto; import org.sonar.core.qualityprofile.db.ActiveRuleParamDto; -import org.sonar.jpa.session.DatabaseSessionFactory; import org.sonar.server.exceptions.BadRequestException; -import org.sonar.server.exceptions.NotFoundException; import java.io.Reader; -import java.io.Writer; import java.util.List; import static com.google.common.collect.Lists.newArrayList; @@ -54,11 +50,7 @@ import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; 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.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class QProfileRepositoryExporterTest { @@ -66,9 +58,6 @@ public class QProfileRepositoryExporterTest { @Mock SqlSession session; - @Mock - DatabaseSessionFactory sessionFactory; - @Mock DatabaseSession hibernateSession; @@ -76,7 +65,6 @@ public class QProfileRepositoryExporterTest { ActiveRuleDao activeRuleDao; List importers = newArrayList(); - List exporters = newArrayList(); Integer currentId = 1; @@ -84,8 +72,6 @@ public class QProfileRepositoryExporterTest { @Before public void setUp() throws Exception { - when(sessionFactory.getSession()).thenReturn(hibernateSession); - // Associate an id when inserting an object to simulate the db id generator doAnswer(new Answer() { public Object answer(InvocationOnMock invocation) { @@ -96,7 +82,7 @@ public class QProfileRepositoryExporterTest { } }).when(activeRuleDao).insert(any(ActiveRuleDto.class), any(SqlSession.class)); - operations = new QProfileRepositoryExporter(sessionFactory, activeRuleDao, importers, exporters); + operations = new QProfileRepositoryExporter(activeRuleDao, importers); } @Test @@ -150,7 +136,8 @@ public class QProfileRepositoryExporterTest { }).when(importer).importProfile(any(Reader.class), any(ValidationMessages.class)); importers.add(importer); - QProfileResult result = operations.importXml(new QProfile().setId(1), "pmd", "", session);; + QProfileResult result = operations.importXml(new QProfile().setId(1), "pmd", "", session); + ; assertThat(result.infos()).hasSize(1); assertThat(result.warnings()).hasSize(1); } @@ -209,108 +196,22 @@ public class QProfileRepositoryExporterTest { verify(importer, never()).importProfile(any(Reader.class), any(ValidationMessages.class)); } - @Test - public void export_to_plugin_xml() throws Exception { - RulesProfile profile = mock(RulesProfile.class); - when(profile.getId()).thenReturn(1); - when(hibernateSession.getSingleResult(any(Class.class), eq("id"), eq(1))).thenReturn(profile); - - ProfileExporter exporter = mock(ProfileExporter.class); - when(exporter.getKey()).thenReturn("pmd"); - exporters.add(exporter); - - operations.exportToXml(new QProfile().setId(1), "pmd"); - - verify(exporter).exportProfile(eq(profile), any(Writer.class)); - } - - @Test - public void fail_to_export_profile_when_missing_exporter() throws Exception { - RulesProfile profile = mock(RulesProfile.class); - when(profile.getId()).thenReturn(1); - when(hibernateSession.getSingleResult(any(Class.class), eq("id"), eq(1))).thenReturn(profile); - - ProfileExporter exporter = mock(ProfileExporter.class); - when(exporter.getKey()).thenReturn("pmd"); - exporters.add(exporter); - - try { - operations.exportToXml(new QProfile().setId(1), "unknown"); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("No such exporter : unknown"); - } - - verify(exporter, never()).exportProfile(any(RulesProfile.class), any(Writer.class)); - } - - @Test - public void fail_to_export_profile_when_profile_is_missing() throws Exception { - RulesProfile profile = mock(RulesProfile.class); - when(profile.getId()).thenReturn(1); - when(hibernateSession.getSingleResult(any(Class.class), eq("id"), eq(1))).thenReturn(null); - - ProfileExporter exporter = mock(ProfileExporter.class); - when(exporter.getKey()).thenReturn("pmd"); - exporters.add(exporter); - - try { - operations.exportToXml(new QProfile().setId(1), "pmd"); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("This profile does not exist"); - } - - verify(exporter, never()).exportProfile(any(RulesProfile.class), any(Writer.class)); - } - - @Test - public void get_profile_exporter_mime_type() throws Exception { - ProfileExporter exporter = mock(ProfileExporter.class); - when(exporter.getKey()).thenReturn("pmd"); - when(exporter.getMimeType()).thenReturn("mime"); - exporters.add(exporter); - - assertThat(operations.getProfileExporterMimeType("pmd")).isEqualTo("mime"); - } - - @Test - public void get_profile_exporters_for_language() throws Exception { - // 2 exporters not declaring supported languages -> match all languages -> to be include in result - ProfileExporter exporterWithEmptySupportedLanguagesList = mock(ProfileExporter.class); - when(exporterWithEmptySupportedLanguagesList.getSupportedLanguages()).thenReturn(new String[]{}); - exporters.add(exporterWithEmptySupportedLanguagesList); - exporters.add(mock(ProfileExporter.class)); - - // 1 exporter supporting the java language -> to be include in result - ProfileExporter exporterSupportingJava = mock(ProfileExporter.class); - when(exporterSupportingJava.getSupportedLanguages()).thenReturn(new String[]{"java"}); - exporters.add(exporterSupportingJava); - - // 1 exporter supporting another language -> not to be include in result - ProfileExporter exporterSupportingAnotherLanguage = mock(ProfileExporter.class); - when(exporterSupportingAnotherLanguage.getSupportedLanguages()).thenReturn(new String[]{"js"}); - exporters.add(exporterSupportingAnotherLanguage); - - assertThat(operations.getProfileExportersForLanguage("java")).hasSize(3); - } - @Test public void get_profile_importers_for_language() throws Exception { // 2 importers not declaring supported languages -> match all languages -> to be include in result ProfileImporter importersWithEmptySupportedLanguagesList = mock(ProfileImporter.class); - when(importersWithEmptySupportedLanguagesList.getSupportedLanguages()).thenReturn(new String[]{}); + when(importersWithEmptySupportedLanguagesList.getSupportedLanguages()).thenReturn(new String[] {}); importers.add(importersWithEmptySupportedLanguagesList); importers.add(mock(ProfileImporter.class)); // 1 importers supporting the java language -> to be include in result ProfileImporter importerSupportingJava = mock(ProfileImporter.class); - when(importerSupportingJava.getSupportedLanguages()).thenReturn(new String[]{"java"}); + when(importerSupportingJava.getSupportedLanguages()).thenReturn(new String[] {"java"}); importers.add(importerSupportingJava); // 1 importers supporting another language -> not to be include in result ProfileImporter importerSupportingAnotherLanguage = mock(ProfileImporter.class); - when(importerSupportingAnotherLanguage.getSupportedLanguages()).thenReturn(new String[]{"js"}); + when(importerSupportingAnotherLanguage.getSupportedLanguages()).thenReturn(new String[] {"js"}); importers.add(importerSupportingAnotherLanguage); assertThat(operations.getProfileImportersForLanguage("java")).hasSize(3); diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java index 184c4ca0232..49b7d947092 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java @@ -60,6 +60,7 @@ public class QProfileServiceMediumTest { DbClient db; DbSession dbSession; QProfileService service; + QProfileLoader loader; RuleActivator activator; @Before @@ -68,6 +69,7 @@ public class QProfileServiceMediumTest { db = tester.get(DbClient.class); dbSession = db.openSession(false); service = tester.get(QProfileService.class); + loader = tester.get(QProfileLoader.class); activator = tester.get(RuleActivator.class); // create pre-defined rules @@ -94,7 +96,7 @@ public class QProfileServiceMediumTest { dbSession.clearCache(); - Map counts = service.countAllActiveRules(); + Map counts = loader.countAllActiveRules(); assertThat(counts).hasSize(2); assertThat(counts.keySet()).containsOnly(XOO_P1_KEY, XOO_P2_KEY); assertThat(counts.values()).containsOnly(1L, 1L); @@ -108,7 +110,7 @@ public class QProfileServiceMediumTest { service.activate(XOO_P2_KEY, new RuleActivation(RuleTesting.XOO_X1).setSeverity("BLOCKER")); dbSession.clearCache(); - Map> stats = service.getAllProfileStats(); + Map> stats = loader.getAllProfileStats(); assertThat(stats.size()).isEqualTo(2); assertThat(stats.get(XOO_P1_KEY).size()).isEqualTo(3); @@ -132,7 +134,7 @@ public class QProfileServiceMediumTest { service.activate(XOO_P1_KEY, new RuleActivation(RuleTesting.XOO_X1).setSeverity("BLOCKER")); dbSession.commit(); - assertThat(service.countDeprecatedActiveRulesByProfile(XOO_P1_KEY)).isEqualTo(1); + assertThat(loader.countDeprecatedActiveRulesByProfile(XOO_P1_KEY)).isEqualTo(1); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java index 8deaf65a854..fa7103646a9 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java @@ -34,6 +34,7 @@ import org.sonar.api.server.debt.DebtModel; import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic; import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.server.qualityprofile.QProfileLoader; import org.sonar.server.qualityprofile.QProfileService; import org.sonar.server.qualityprofile.QProfileTesting; import org.sonar.server.rule.RuleRepositories; @@ -63,11 +64,11 @@ public class AppActionTest { DebtModel debtModel; @Mock - QProfileService qualityProfileService; + QProfileLoader profileLoader; @Test public void should_generate_app_init_info() throws Exception { - AppAction app = new AppAction(languages, ruleRepositories, i18n, debtModel, qualityProfileService); + AppAction app = new AppAction(languages, ruleRepositories, i18n, debtModel, profileLoader); WsTester tester = new WsTester(new RulesWebService( mock(SearchAction.class), mock(ShowAction.class), mock(TagsAction.class), mock(CreateAction.class), app, mock(UpdateAction.class), mock(DeleteAction.class))); @@ -76,7 +77,7 @@ public class AppActionTest { QualityProfileDto profile1 = QProfileTesting.newXooP1(); QualityProfileDto profile2 = QProfileTesting.newXooP2().setParentKee(QProfileTesting.XOO_P1_KEY); - when(qualityProfileService.findAll()).thenReturn(ImmutableList.of(profile1, profile2)); + when(profileLoader.findAll()).thenReturn(ImmutableList.of(profile1, profile2)); Language xoo = mock(Language.class); when(xoo.getKey()).thenReturn("xoo"); -- 2.39.5