From 3ac8de59552f3d38f9b952079cbffa8572840731 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Mon, 13 Oct 2014 12:40:37 +0200 Subject: [PATCH] SONAR-5673 Creating a new profile from a configuration file is not working --- .../main/java/org/sonar/xoo/XooPlugin.java | 16 +- .../org/sonar/xoo/rule/XooFakeExporter.java | 55 +++++ .../org/sonar/xoo/rule/XooFakeImporter.java | 50 ++++ .../xoo/rule/XooFakeImporterWithMessages.java | 47 ++++ .../java/org/sonar/xoo/XooPluginTest.java | 2 +- .../server/platform/ServerComponents.java | 1 - .../qualityprofile/QProfileExporters.java | 73 +++++- .../server/qualityprofile/QProfileName.java | 4 + .../QProfileRepositoryExporter.java | 139 ----------- .../server/qualityprofile/QProfileResult.java | 8 +- .../qualityprofile/QProfileService.java | 16 +- .../server/qualityprofile/RuleActivator.java | 6 +- .../RuleActivatorContextFactory.java | 14 +- .../qualityprofile/QProfileExportersTest.java | 130 +++++++++- .../QProfileRepositoryExporterTest.java | 224 ------------------ .../QProfileServiceMediumTest.java | 89 ++++++- .../RuleActivatorMediumTest.java | 28 ++- .../app/controllers/profiles_controller.rb | 9 +- .../app/views/profiles/_create_form.html.erb | 2 +- 19 files changed, 512 insertions(+), 401 deletions(-) create mode 100644 plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeExporter.java create mode 100644 plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporter.java create mode 100644 plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporterWithMessages.java delete mode 100644 server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java delete mode 100644 server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java index 3477fab825c..8715210be75 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java @@ -20,16 +20,8 @@ package org.sonar.xoo; import org.sonar.api.SonarPlugin; -import org.sonar.xoo.lang.MeasureSensor; -import org.sonar.xoo.lang.ScmActivitySensor; -import org.sonar.xoo.lang.SymbolReferencesSensor; -import org.sonar.xoo.lang.SyntaxHighlightingSensor; -import org.sonar.xoo.lang.XooTokenizerSensor; -import org.sonar.xoo.rule.CreateIssueByInternalKeySensor; -import org.sonar.xoo.rule.OneIssueOnDirPerFileSensor; -import org.sonar.xoo.rule.OneIssuePerLineSensor; -import org.sonar.xoo.rule.XooQualityProfile; -import org.sonar.xoo.rule.XooRulesDefinition; +import org.sonar.xoo.lang.*; +import org.sonar.xoo.rule.*; import java.util.Arrays; import java.util.List; @@ -49,6 +41,10 @@ public class XooPlugin extends SonarPlugin { XooRulesDefinition.class, XooQualityProfile.class, + XooFakeExporter.class, + XooFakeImporter.class, + XooFakeImporterWithMessages.class, + // sensors MeasureSensor.class, ScmActivitySensor.class, diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeExporter.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeExporter.java new file mode 100644 index 00000000000..b8375db463f --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeExporter.java @@ -0,0 +1,55 @@ +/* + * 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.xoo.rule; + +import org.sonar.api.profiles.ProfileExporter; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.xoo.Xoo; + +import java.io.IOException; +import java.io.Writer; + +/** + * Fake exporter just for test + */ +public class XooFakeExporter extends ProfileExporter { + public XooFakeExporter() { + super("XooFakeExporter", "Xoo Fake Exporter"); + } + + @Override + public String[] getSupportedLanguages() { + return new String[]{Xoo.KEY}; + } + + @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); + } + } +} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporter.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporter.java new file mode 100644 index 00000000000..867c11100dc --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporter.java @@ -0,0 +1,50 @@ +/* + * 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.xoo.rule; + +import org.sonar.api.profiles.ProfileImporter; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RulePriority; +import org.sonar.api.utils.ValidationMessages; +import org.sonar.xoo.Xoo; + +import java.io.Reader; + +/** + * Fake importer just for test, it will NOT take into account the given file but will create some hard-coded rules + */ +public class XooFakeImporter extends ProfileImporter { + public XooFakeImporter() { + super("XooProfileImporter", "Xoo Profile Importer"); + } + + @Override + public String[] getSupportedLanguages() { + return new String[] {Xoo.KEY}; + } + + @Override + public RulesProfile importProfile(Reader reader, ValidationMessages messages) { + RulesProfile rulesProfile = RulesProfile.create(); + rulesProfile.activateRule(Rule.create(XooRulesDefinition.XOO_REPOSITORY, "x1"), RulePriority.CRITICAL); + return rulesProfile; + } +} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporterWithMessages.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporterWithMessages.java new file mode 100644 index 00000000000..a11e3a2cca0 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooFakeImporterWithMessages.java @@ -0,0 +1,47 @@ +/* + * 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.xoo.rule; + +import org.sonar.api.profiles.ProfileImporter; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.utils.ValidationMessages; + +import java.io.Reader; + +/** + * Fake importer just for test, it will NOT take into account the given file but will display some info and warning messages + */ +public class XooFakeImporterWithMessages extends ProfileImporter { + public XooFakeImporterWithMessages() { + super("XooFakeImporterWithMessages", "Xoo Profile Importer With Messages"); + } + + @Override + public String[] getSupportedLanguages() { + return new String[] {}; + } + + @Override + public RulesProfile importProfile(Reader reader, ValidationMessages messages) { + messages.addWarningText("a warning"); + messages.addInfoText("an info"); + return RulesProfile.create(); + } +} diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java index bfe1fd99afa..e8100740345 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java @@ -27,6 +27,6 @@ public class XooPluginTest { @Test public void provide_extensions() { - assertThat(new XooPlugin().getExtensions()).hasSize(11); + assertThat(new XooPlugin().getExtensions()).hasSize(14); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index 148f27a2b36..0041a742d92 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -320,7 +320,6 @@ class ServerComponents { pico.addSingleton(QProfileLookup.class); pico.addSingleton(QProfileProjectOperations.class); pico.addSingleton(QProfileProjectLookup.class); - pico.addSingleton(QProfileRepositoryExporter.class); pico.addSingleton(BuiltInProfiles.class); pico.addSingleton(QProfileRestoreBuiltInAction.class); pico.addSingleton(QProfilesWs.class); diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java index d8a224f8957..0651346fcd4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileExporters.java @@ -20,15 +20,22 @@ package org.sonar.server.qualityprofile; import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; import org.sonar.api.ServerComponent; import org.sonar.api.profiles.ProfileExporter; +import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rules.ActiveRuleParam; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RulePriority; +import org.sonar.api.utils.ValidationMessages; +import org.sonar.core.persistence.DbSession; import org.sonar.core.qualityprofile.db.QualityProfileDto; +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; @@ -39,16 +46,20 @@ public class QProfileExporters implements ServerComponent { private final QProfileLoader loader; private final RuleFinder ruleFinder; + private final RuleActivator ruleActivator; private final ProfileExporter[] exporters; + private final ProfileImporter[] importers; - public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder, ProfileExporter[] exporters) { + public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder, RuleActivator ruleActivator, ProfileExporter[] exporters, ProfileImporter[] importers) { this.loader = loader; this.ruleFinder = ruleFinder; + this.ruleActivator = ruleActivator; this.exporters = exporters; + this.importers = importers; } - public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder) { - this(loader, ruleFinder, new ProfileExporter[0]); + public QProfileExporters(QProfileLoader loader, RuleFinder ruleFinder, RuleActivator ruleActivator) { + this(loader, ruleFinder, ruleActivator, new ProfileExporter[0], new ProfileImporter[0]); } public List exportersForLanguage(String language) { @@ -104,4 +115,60 @@ public class QProfileExporters implements ServerComponent { } throw new NotFoundException("Unknown quality profile exporter: " + exporterKey); } + + /** + * Used by rails + */ + public List findProfileImportersForLanguage(String language) { + List result = new ArrayList(); + for (ProfileImporter importer : importers) { + if (importer.getSupportedLanguages() == null || importer.getSupportedLanguages().length == 0 || ArrayUtils.contains(importer.getSupportedLanguages(), language)) { + result.add(importer); + } + } + return result; + } + + public QProfileResult importXml(QualityProfileDto profileDto, String importerKey, String xml, DbSession dbSession) { + QProfileResult result = new QProfileResult(); + ValidationMessages messages = ValidationMessages.create(); + ProfileImporter importer = getProfileImporter(importerKey); + RulesProfile rulesProfile = importer.importProfile(new StringReader(xml), messages); + importProfile(profileDto, rulesProfile, dbSession); + processValidationMessages(messages, result); + return result; + } + + private void importProfile(QualityProfileDto profileDto, RulesProfile rulesProfile, DbSession dbSession) { + for (org.sonar.api.rules.ActiveRule activeRule : rulesProfile.getActiveRules()) { + ruleActivator.activate(dbSession, toRuleActivation(activeRule), profileDto); + } + } + + private ProfileImporter getProfileImporter(String importerKey) { + for (ProfileImporter importer : importers) { + if (StringUtils.equals(importerKey, importer.getKey())) { + return importer; + } + } + throw new BadRequestException("No such importer : " + importerKey); + } + + private void processValidationMessages(ValidationMessages messages, QProfileResult result) { + if (!messages.getErrors().isEmpty()) { + throw new BadRequestException(messages); + } + result.addWarnings(messages.getWarnings()); + result.addInfos(messages.getInfos()); + } + + private RuleActivation toRuleActivation(org.sonar.api.rules.ActiveRule activeRule) { + RuleActivation ruleActivation = new RuleActivation(activeRule.getRule().ruleKey()); + ruleActivation.setSeverity(activeRule.getSeverity().name()); + for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) { + ruleActivation.setParameter(activeRuleParam.getKey(), activeRuleParam.getValue()); + } + return ruleActivation; + } + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileName.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileName.java index ae09c899cd5..d794058ea97 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileName.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileName.java @@ -37,6 +37,10 @@ public class QProfileName { return name; } + public static QProfileName createFor(String lang, String name){ + return new QProfileName(lang, name); + } + @Override public boolean equals(@Nullable Object o) { if (this == o) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java deleted file mode 100644 index 883d05675c7..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRepositoryExporter.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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.ArrayListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; -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.profiles.ProfileImporter; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.rules.ActiveRule; -import org.sonar.api.rules.ActiveRuleParam; -import org.sonar.api.rules.RulePriority; -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.server.exceptions.BadRequestException; - -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; - -import static com.google.common.collect.Lists.newArrayList; - -/** - * Used through ruby code
Internal.profile_exporter
- */ -public class QProfileRepositoryExporter implements ServerComponent { - - private final ActiveRuleDao activeRuleDao; - private final List importers; - - /** - * Used by pico when no plugin provide profile exporter / importer - */ - public QProfileRepositoryExporter(ActiveRuleDao activeRuleDao) { - this(activeRuleDao, Lists.newArrayList()); - } - - public QProfileRepositoryExporter(ActiveRuleDao activeRuleDao, List importers) { - this.activeRuleDao = activeRuleDao; - this.importers = importers; - } - - public QProfileResult importXml(QProfile profile, String pluginKey, String xml, SqlSession session) { - QProfileResult result = new QProfileResult(); - ValidationMessages messages = ValidationMessages.create(); - ProfileImporter importer = getProfileImporter(pluginKey); - RulesProfile rulesProfile = importer.importProfile(new StringReader(xml), messages); - importProfile(profile.id(), rulesProfile, session); - processValidationMessages(messages, result); - return result; - } - - private void importProfile(int profileId, RulesProfile rulesProfile, SqlSession sqlSession) { - List activeRuleDtos = newArrayList(); - Multimap paramsByActiveRule = ArrayListMultimap.create(); - for (ActiveRule activeRule : rulesProfile.getActiveRules()) { - ActiveRuleDto activeRuleDto = toActiveRuleDto(activeRule, profileId); - activeRuleDao.insert(activeRuleDto, sqlSession); - activeRuleDtos.add(activeRuleDto); - for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) { - ActiveRuleParamDto activeRuleParamDto = toActiveRuleParamDto(activeRuleParam, activeRuleDto); - activeRuleDao.insert(activeRuleParamDto, sqlSession); - paramsByActiveRule.put(activeRuleDto.getId(), activeRuleParamDto); - } - } - // TODO use RuleActivator to benefit from changelog and preview cache cleanup - } - - private void processValidationMessages(ValidationMessages messages, QProfileResult result) { - if (!messages.getErrors().isEmpty()) { - throw new BadRequestException(messages); - } - result.addWarnings(messages.getWarnings()); - result.addInfos(messages.getInfos()); - } - - private ActiveRuleDto toActiveRuleDto(ActiveRule activeRule, int profileId) { - return new ActiveRuleDto() - .setProfileId(profileId) - .setRuleId(activeRule.getRule().getId()) - .setSeverity(toSeverityLevel(activeRule.getSeverity())); - } - - private String toSeverityLevel(RulePriority rulePriority) { - return rulePriority.name(); - } - - private ActiveRuleParamDto toActiveRuleParamDto(ActiveRuleParam activeRuleParam, ActiveRuleDto activeRuleDto) { - return new ActiveRuleParamDto() - .setActiveRuleId(activeRuleDto.getId()) - .setRulesParameterId(activeRuleParam.getRuleParam().getId()) - .setKey(activeRuleParam.getKey()) - .setValue(activeRuleParam.getValue()); - } - - private ProfileImporter getProfileImporter(String importerKey) { - for (ProfileImporter importer : importers) { - if (StringUtils.equals(importerKey, importer.getKey())) { - return importer; - } - } - throw new BadRequestException("No such importer : " + importerKey); - } - - public List getProfileImportersForLanguage(String language) { - List result = new ArrayList(); - for (ProfileImporter importer : importers) { - if (importer.getSupportedLanguages() == null || importer.getSupportedLanguages().length == 0 || ArrayUtils.contains(importer.getSupportedLanguages(), language)) { - result.add(importer); - } - } - return result; - } - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileResult.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileResult.java index 81fbb63faa3..5873862f58d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileResult.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileResult.java @@ -20,6 +20,8 @@ package org.sonar.server.qualityprofile; +import org.sonar.core.qualityprofile.db.QualityProfileDto; + import java.util.List; import static com.google.common.collect.Lists.newArrayList; @@ -29,7 +31,7 @@ public class QProfileResult { private List warnings; private List infos; - private QProfile profile; + private QualityProfileDto profile; public QProfileResult() { warnings = newArrayList(); @@ -54,11 +56,11 @@ public class QProfileResult { return this; } - public QProfile profile() { + public QualityProfileDto profile() { return profile; } - public QProfileResult setProfile(QProfile profile) { + public QProfileResult setProfile(QualityProfileDto profile) { this.profile = profile; return this; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java index fde5a90ed2f..d67cb2db9d2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java @@ -48,6 +48,7 @@ import java.io.StringWriter; import java.io.Writer; import java.util.Collection; import java.util.List; +import java.util.Map; public class QProfileService implements ServerComponent { @@ -58,9 +59,10 @@ public class QProfileService implements ServerComponent { private final QProfileBackuper backuper; private final QProfileCopier copier; private final QProfileReset reset; + private final QProfileExporters exporters; public QProfileService(DbClient db, IndexClient index, RuleActivator ruleActivator, QProfileFactory factory, - QProfileBackuper backuper, QProfileCopier copier, QProfileReset reset) { + QProfileBackuper backuper, QProfileCopier copier, QProfileReset reset, QProfileExporters exporters) { this.db = db; this.index = index; this.ruleActivator = ruleActivator; @@ -68,15 +70,23 @@ public class QProfileService implements ServerComponent { this.backuper = backuper; this.copier = copier; this.reset = reset; + this.exporters = exporters; } - public QualityProfileDto create(QProfileName name) { + public QProfileResult create(QProfileName name, @Nullable Map xmlQProfilesByPlugin) { verifyAdminPermission(); DbSession dbSession = db.openSession(false); try { + QProfileResult result = new QProfileResult(); QualityProfileDto profile = factory.create(dbSession, name); + result.setProfile(profile); + if (xmlQProfilesByPlugin != null) { + for (Map.Entry entry : xmlQProfilesByPlugin.entrySet()) { + result.add(exporters.importXml(profile, entry.getKey(), entry.getValue(), dbSession)); + } + } dbSession.commit(); - return profile; + return result; } finally { dbSession.close(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java index 2fb2b565d6d..a456b77eea9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java @@ -21,7 +21,6 @@ package org.sonar.server.qualityprofile; import com.google.common.base.Splitter; import com.google.common.collect.Lists; -import org.apache.commons.lang.StringUtils; import org.sonar.api.ServerComponent; import org.sonar.api.server.rule.RuleParamType; import org.sonar.core.activity.Activity; @@ -89,6 +88,11 @@ public class RuleActivator implements ServerComponent { return doActivate(dbSession, activation, context); } + List activate(DbSession dbSession, RuleActivation activation, QualityProfileDto profileDto) { + RuleActivatorContext context = contextFactory.create(profileDto, activation.getRuleKey(), dbSession); + return doActivate(dbSession, activation, context); + } + private List doActivate(DbSession dbSession, RuleActivation activation, RuleActivatorContext context) { context.verifyForActivation(); List changes = Lists.newArrayList(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivatorContextFactory.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivatorContextFactory.java index 1854942476b..184d3fdf187 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivatorContextFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivatorContextFactory.java @@ -47,7 +47,7 @@ public class RuleActivatorContextFactory implements ServerComponent { throw new BadRequestException("Quality profile not found: " + profileKey); } context.setProfile(profile); - return create(profile, ruleKey, session, context); + return create(ruleKey, session, context); } RuleActivatorContext create(QProfileName profileName, RuleKey ruleKey, DbSession session) { @@ -57,13 +57,17 @@ public class RuleActivatorContextFactory implements ServerComponent { throw new BadRequestException("Quality profile not found: " + profileName); } context.setProfile(profile); - return create(profile, ruleKey, session, context); + return create(ruleKey, session, context); } - private RuleActivatorContext create(QualityProfileDto profile, RuleKey ruleKey, DbSession session, RuleActivatorContext context) { + RuleActivatorContext create(QualityProfileDto profile, RuleKey ruleKey, DbSession session) { + return create(ruleKey, session, new RuleActivatorContext().setProfile(profile)); + } + + private RuleActivatorContext create(RuleKey ruleKey, DbSession session, RuleActivatorContext context) { initRule(ruleKey, context, session); - initActiveRules(profile.getKey(), ruleKey, context, session, false); - String parentKee = profile.getParentKee(); + initActiveRules(context.profile().getKey(), ruleKey, context, session, false); + String parentKee = context.profile().getParentKee(); if (parentKee != null) { initActiveRules(parentKee, ruleKey, context, session, true); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java index fd8a87a9dd2..8c0f19312c8 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java @@ -19,23 +19,32 @@ */ package org.sonar.server.qualityprofile; +import org.junit.After; +import org.junit.Before; 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.ProfileImporter; import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RulePriority; import org.sonar.api.server.rule.RuleParamType; import org.sonar.api.server.rule.RulesDefinition; import org.sonar.api.utils.ValidationMessages; +import org.sonar.core.persistence.DbSession; import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.server.db.DbClient; +import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.tester.ServerTester; import java.io.IOException; +import java.io.Reader; import java.io.Writer; +import java.util.List; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; @@ -45,9 +54,26 @@ public class QProfileExportersTest { @ClassRule public static ServerTester tester = new ServerTester().addXoo().addComponents( XooRulesDefinition.class, XooProfileDefinition.class, - XooExporter.class, StandardExporter.class); + XooExporter.class, StandardExporter.class, + XooProfileImporter.class, XooProfileImporterWithMessages.class, XooProfileImporterWithError.class); - QProfileExporters exporters = tester.get(QProfileExporters.class); + DbClient db; + DbSession dbSession; + QProfileExporters exporters; + QProfileLoader loader; + + @Before + public void before() { + db = tester.get(DbClient.class); + dbSession = db.openSession(false); + exporters = tester.get(QProfileExporters.class); + loader = tester.get(QProfileLoader.class); + } + + @After + public void after() throws Exception { + dbSession.close(); + } @Test public void exportersForLanguage() throws Exception { @@ -92,6 +118,58 @@ public class QProfileExportersTest { } } + @Test + public void profile_importers_for_language() throws Exception { + assertThat(exporters.findProfileImportersForLanguage("xoo")).hasSize(3); + } + + @Test + public void import_xml() throws Exception { + QualityProfileDto profileDto = QProfileTesting.newDto(QProfileName.createFor("xoo", "import_xml"), "import_xml"); + db.qualityProfileDao().insert(dbSession, profileDto); + dbSession.commit(); + + assertThat(loader.findActiveRulesByProfile(profileDto.getKey())).isEmpty(); + + exporters.importXml(profileDto, "XooProfileImporter", "", dbSession); + dbSession.commit(); + + List activeRules = loader.findActiveRulesByProfile(profileDto.getKey()); + assertThat(activeRules).hasSize(1); + ActiveRule activeRule = activeRules.get(0); + assertThat(activeRule.key().ruleKey()).isEqualTo(RuleKey.of("xoo", "R1")); + assertThat(activeRule.severity()).isEqualTo(Severity.CRITICAL); + } + + @Test + public void import_xml_return_messages() throws Exception { + QProfileResult result = exporters.importXml(QProfileTesting.newXooP1(), "XooProfileImporterWithMessages", "", dbSession); + dbSession.commit(); + + assertThat(result.infos()).containsOnly("an info"); + assertThat(result.warnings()).containsOnly("a warning"); + } + + @Test + public void fail_to_import_xml_when_error_in_importer() throws Exception { + try { + exporters.importXml(QProfileTesting.newXooP1(), "XooProfileImporterWithError", "", dbSession); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("error!"); + } + } + + @Test + public void fail_to_import_xml_on_unknown_importer() throws Exception { + try { + exporters.importXml(QProfileTesting.newXooP1(), "Unknown", "", dbSession); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("No such importer : Unknown"); + } + } + public static class XooExporter extends ProfileExporter { public XooExporter() { super("xootool", "Xoo Tool"); @@ -157,4 +235,52 @@ public class QProfileExportersTest { } } + public static class XooProfileImporter extends ProfileImporter { + public XooProfileImporter() { + super("XooProfileImporter", "Xoo Profile Importer"); + } + + @Override + public String[] getSupportedLanguages() { + return new String[] {"xoo"}; + } + + @Override + public RulesProfile importProfile(Reader reader, ValidationMessages messages) { + RulesProfile rulesProfile = RulesProfile.create(); + rulesProfile.activateRule(Rule.create("xoo", "R1"), RulePriority.CRITICAL); + return rulesProfile; + } + } + + public static class XooProfileImporterWithMessages extends ProfileImporter { + public XooProfileImporterWithMessages() { + super("XooProfileImporterWithMessages", "Xoo Profile Importer With Message"); + } + + @Override + public String[] getSupportedLanguages() { + return new String[] {}; + } + + @Override + public RulesProfile importProfile(Reader reader, ValidationMessages messages) { + messages.addWarningText("a warning"); + messages.addInfoText("an info"); + return RulesProfile.create(); + } + } + + public static class XooProfileImporterWithError extends ProfileImporter { + public XooProfileImporterWithError() { + super("XooProfileImporterWithError", "Xoo Profile Importer With Error"); + } + + @Override + public RulesProfile importProfile(Reader reader, ValidationMessages messages) { + messages.addErrorText("error!"); + return RulesProfile.create(); + } + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java deleted file mode 100644 index cdbc9cad7aa..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRepositoryExporterTest.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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.ibatis.session.SqlSession; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -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.ProfileImporter; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.rule.Severity; -import org.sonar.api.rules.ActiveRule; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RulePriority; -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.server.exceptions.BadRequestException; - -import java.io.Reader; -import java.util.List; - -import static com.google.common.collect.Lists.newArrayList; -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; - -@RunWith(MockitoJUnitRunner.class) -public class QProfileRepositoryExporterTest { - - @Mock - SqlSession session; - - @Mock - DatabaseSession hibernateSession; - - @Mock - ActiveRuleDao activeRuleDao; - - List importers = newArrayList(); - - Integer currentId = 1; - - QProfileRepositoryExporter operations; - - @Before - public void setUp() throws Exception { - // Associate an id when inserting an object to simulate the db id generator - doAnswer(new Answer() { - public Object answer(InvocationOnMock invocation) { - Object[] args = invocation.getArguments(); - ActiveRuleDto dto = (ActiveRuleDto) args[0]; - dto.setId(currentId++); - return null; - } - }).when(activeRuleDao).insert(any(ActiveRuleDto.class), any(SqlSession.class)); - - operations = new QProfileRepositoryExporter(activeRuleDao, importers); - } - - @Test - public void import_from_xml_plugin() throws Exception { - RulesProfile profile = RulesProfile.create("Default", "java"); - Rule rule = Rule.create("pmd", "rule1"); - rule.createParameter("max"); - rule.setId(10); - ActiveRule activeRule = profile.activateRule(rule, RulePriority.BLOCKER); - activeRule.setParameter("max", "10"); - - ProfileImporter importer = mock(ProfileImporter.class); - when(importer.getKey()).thenReturn("pmd"); - when(importer.importProfile(any(Reader.class), any(ValidationMessages.class))).thenReturn(profile); - importers.add(importer); - - operations.importXml(new QProfile().setId(1), "pmd", "", session); - - verify(importer).importProfile(any(Reader.class), any(ValidationMessages.class)); - - ArgumentCaptor activeRuleArgument = ArgumentCaptor.forClass(ActiveRuleDto.class); - verify(activeRuleDao).insert(activeRuleArgument.capture(), eq(session)); - assertThat(activeRuleArgument.getValue().getRuleId()).isEqualTo(10); - assertThat(activeRuleArgument.getValue().getSeverityString()).isEqualTo(Severity.BLOCKER); - - ArgumentCaptor activeRuleParamArgument = ArgumentCaptor.forClass(ActiveRuleParamDto.class); - verify(activeRuleDao).insert(activeRuleParamArgument.capture(), eq(session)); - assertThat(activeRuleParamArgument.getValue().getKey()).isEqualTo("max"); - assertThat(activeRuleParamArgument.getValue().getValue()).isEqualTo("10"); - } - - @Test - public void import_from_xml_plugin_add_infos_and_warnings() throws Exception { - final RulesProfile profile = RulesProfile.create("Default", "java"); - Rule rule = Rule.create("pmd", "rule1"); - rule.createParameter("max"); - rule.setId(10); - ActiveRule activeRule = profile.activateRule(rule, RulePriority.BLOCKER); - activeRule.setParameter("max", "10"); - - ProfileImporter importer = mock(ProfileImporter.class); - when(importer.getKey()).thenReturn("pmd"); - doAnswer(new Answer() { - public Object answer(InvocationOnMock invocation) { - Object[] args = invocation.getArguments(); - ValidationMessages validationMessages = (ValidationMessages) args[1]; - validationMessages.addInfoText("an info message"); - validationMessages.addWarningText("a warning message"); - return profile; - } - }).when(importer).importProfile(any(Reader.class), any(ValidationMessages.class)); - importers.add(importer); - - QProfileResult result = operations.importXml(new QProfile().setId(1), "pmd", "", session); - ; - assertThat(result.infos()).hasSize(1); - assertThat(result.warnings()).hasSize(1); - } - - @Test - public void fail_to_import_profile_from_xml_plugin_if_error() throws Exception { - final RulesProfile profile = RulesProfile.create("Default", "java"); - Rule rule = Rule.create("pmd", "rule1"); - rule.createParameter("max"); - rule.setId(10); - ActiveRule activeRule = profile.activateRule(rule, RulePriority.BLOCKER); - activeRule.setParameter("max", "10"); - - ProfileImporter importer = mock(ProfileImporter.class); - when(importer.getKey()).thenReturn("pmd"); - importers.add(importer); - - doAnswer(new Answer() { - public Object answer(InvocationOnMock invocation) { - Object[] args = invocation.getArguments(); - ValidationMessages validationMessages = (ValidationMessages) args[1]; - validationMessages.addErrorText("error!"); - return profile; - } - }).when(importer).importProfile(any(Reader.class), any(ValidationMessages.class)); - - try { - operations.importXml(new QProfile().setId(1), "pmd", "", session); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(BadRequestException.class); - } - } - - @Test - public void fail_to_import_profile_when_missing_importer() throws Exception { - final RulesProfile profile = RulesProfile.create("Default", "java"); - Rule rule = Rule.create("pmd", "rule1"); - rule.createParameter("max"); - rule.setId(10); - ActiveRule activeRule = profile.activateRule(rule, RulePriority.BLOCKER); - activeRule.setParameter("max", "10"); - - ProfileImporter importer = mock(ProfileImporter.class); - when(importer.getKey()).thenReturn("pmd"); - importers.add(importer); - - when(importer.importProfile(any(Reader.class), any(ValidationMessages.class))).thenReturn(profile); - - try { - operations.importXml(new QProfile().setId(1), "unknown", "", session); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("No such importer : unknown"); - } - verify(importer, never()).importProfile(any(Reader.class), any(ValidationMessages.class)); - } - - @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[] {}); - 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"}); - 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"}); - importers.add(importerSupportingAnotherLanguage); - - assertThat(operations.getProfileImportersForLanguage("java")).hasSize(3); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java index 6985b4815df..6f7d04c2328 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java @@ -19,19 +19,27 @@ */ package org.sonar.server.qualityprofile; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; +import org.sonar.api.profiles.ProfileExporter; +import org.sonar.api.profiles.ProfileImporter; +import org.sonar.api.profiles.RulesProfile; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; import org.sonar.api.rule.Severity; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RulePriority; +import org.sonar.api.utils.ValidationMessages; import org.sonar.core.activity.Activity; import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.persistence.DbSession; import org.sonar.core.qualityprofile.db.ActiveRuleKey; +import org.sonar.core.qualityprofile.db.QualityProfileDto; import org.sonar.core.rule.RuleDto; import org.sonar.core.user.UserDto; import org.sonar.server.activity.ActivityService; @@ -44,6 +52,9 @@ import org.sonar.server.search.Result; import org.sonar.server.tester.ServerTester; import org.sonar.server.user.MockUserSession; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; import java.util.Date; import java.util.List; import java.util.Map; @@ -55,7 +66,7 @@ import static org.sonar.server.qualityprofile.QProfileTesting.XOO_P2_KEY; public class QProfileServiceMediumTest { @ClassRule - public static ServerTester tester = new ServerTester(); + public static ServerTester tester = new ServerTester().addComponents(XooProfileImporter.class, XooExporter.class); DbClient db; DbSession dbSession; @@ -87,6 +98,35 @@ public class QProfileServiceMediumTest { dbSession.close(); } + @Test + public void create_profile() throws Exception { + MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("me"); + + QualityProfileDto profile = service.create(QProfileName.createFor("xoo", "New Profile"), null).profile(); + + assertThat(loader.getByKey(profile.getKey())).isNotNull(); + assertThat(loader.getByKey(profile.getKey()).getLanguage()).isEqualTo("xoo"); + assertThat(loader.getByKey(profile.getKey()).getName()).isEqualTo("New Profile"); + } + + @Test + public void create_profile_with_xml() throws Exception { + MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("me"); + + db.ruleDao().insert(dbSession, RuleTesting.newDto(RuleKey.of("xoo", "R1")).setLanguage("xoo").setSeverity("MINOR")); + dbSession.commit(); + + QProfileResult result = service.create(QProfileName.createFor("xoo", "New Profile"), ImmutableMap.of("XooProfileImporter", "")); + QualityProfileDto profile = result.profile(); + + assertThat(loader.getByKey(profile.getKey())).isNotNull(); + assertThat(loader.getByKey(profile.getKey()).getLanguage()).isEqualTo("xoo"); + assertThat(loader.getByKey(profile.getKey()).getName()).isEqualTo("New Profile"); + + List activeRules = loader.findActiveRulesByProfile(profile.getKey()); + assertThat(activeRules).hasSize(1); + } + @Test public void count_by_all_profiles() throws Exception { MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("me"); @@ -294,4 +334,51 @@ public class QProfileServiceMediumTest { assertThat(service.getDefault("xoo").getKey()).isEqualTo(XOO_P1_KEY); } + + 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 XooProfileImporter extends ProfileImporter { + public XooProfileImporter() { + super("XooProfileImporter", "Xoo Profile Importer"); + } + + @Override + public String[] getSupportedLanguages() { + return new String[]{"xoo"}; + } + + @Override + public RulesProfile importProfile(Reader reader, ValidationMessages messages) { + RulesProfile rulesProfile = RulesProfile.create(); + Rule rule = Rule.create("xoo", "R1"); + rule.createParameter("acceptWhitespace"); + org.sonar.api.rules.ActiveRule activeRule = rulesProfile.activateRule(rule, RulePriority.CRITICAL); + activeRule.setParameter("acceptWhitespace", "true"); + return rulesProfile; + } + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RuleActivatorMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RuleActivatorMediumTest.java index cf4cd585bff..c93870cf723 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RuleActivatorMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RuleActivatorMediumTest.java @@ -20,7 +20,10 @@ package org.sonar.server.qualityprofile; import com.google.common.collect.ImmutableMap; -import org.junit.*; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; import org.sonar.api.rule.Severity; @@ -29,6 +32,7 @@ import org.sonar.core.persistence.DbSession; import org.sonar.core.qualityprofile.db.ActiveRuleDto; import org.sonar.core.qualityprofile.db.ActiveRuleKey; import org.sonar.core.qualityprofile.db.ActiveRuleParamDto; +import org.sonar.core.qualityprofile.db.QualityProfileDto; import org.sonar.core.rule.RuleDto; import org.sonar.core.rule.RuleParamDto; import org.sonar.server.db.DbClient; @@ -66,6 +70,8 @@ public class RuleActivatorMediumTest { RuleActivator ruleActivator; ActiveRuleIndex index; + QualityProfileDto profileDto; + @Before public void before() { tester.clearDbAndIndexes(); @@ -97,7 +103,8 @@ public class RuleActivatorMediumTest { .setName("format").setDefaultValue("txt").setType(RuleParamType.STRING.type())); // create pre-defined profile P1 - db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1()); + profileDto = QProfileTesting.newXooP1(); + db.qualityProfileDao().insert(dbSession, profileDto); dbSession.commit(); dbSession.clearCache(); } @@ -124,6 +131,23 @@ public class RuleActivatorMediumTest { assertThat(changes.get(0).getType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED); } + @Test + public void activate_with_profile_dto() throws Exception { + RuleActivation activation = new RuleActivation(RuleTesting.XOO_X1); + activation.setSeverity(Severity.BLOCKER); + activation.setParameter("max", "7"); + activation.setParameter("min", "3"); + List changes = ruleActivator.activate(dbSession, activation, profileDto); + dbSession.commit(); + dbSession.clearCache(); + + assertThat(countActiveRules(XOO_P1_KEY)).isEqualTo(1); + verifyHasActiveRule(ActiveRuleKey.of(XOO_P1_KEY, RuleTesting.XOO_X1), Severity.BLOCKER, null, + ImmutableMap.of("max", "7", "min", "3")); + assertThat(changes).hasSize(1); + assertThat(changes.get(0).getType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED); + } + @Test public void activate_with_default_severity_and_parameter() throws Exception { activate(new RuleActivation(RuleTesting.XOO_X1), XOO_P1_KEY); diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb index b6a5ba9f4e2..6956a1287eb 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb @@ -71,10 +71,9 @@ class ProfilesController < ApplicationController end end profile_name = Java::OrgSonarServerQualityprofile::QProfileName.new(params[:language], params[: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) + result = Internal.qprofile_service.create(profile_name, files_by_key) + flash[:notice] = message('quality_profiles.profile_x_created', :params => result.profile().getName()) + flash_result(result) end redirect_to :action => 'index' end @@ -530,7 +529,7 @@ class ProfilesController < ApplicationController def flash_result(result) # only 4 messages are kept each time to avoid cookie overflow. unless result.infos.empty? - flash[:notice] += result.infos.to_a[0...4].join('
') + flash[:notice] += '
' + result.infos.to_a[0...4].join('
') end unless result.warnings.empty? flash[:warning] = result.warnings.to_a[0...4].join('
') diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/profiles/_create_form.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/profiles/_create_form.html.erb index 328e2af6add..a003c054478 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/profiles/_create_form.html.erb +++ b/server/sonar-web/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.component(Java::OrgSonarServerQualityprofile::QProfileRepositoryExporter.java_class).getProfileImportersForLanguage(language_key) + importers = Internal.component(Java::OrgSonarServerQualityprofile::QProfileExporters.java_class).findProfileImportersForLanguage(language_key) %>
-- 2.39.5