From: Simon Brandhof Date: Tue, 25 Nov 2014 09:25:06 +0000 (+0100) Subject: SONAR-5874 Support deprecated org.sonar.api.rules.RuleRepository when extending rules... X-Git-Tag: 5.0-RC1~230^2 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=344aa4461ce308745c63f6299145a3d8117d6dea;p=sonarqube.git SONAR-5874 Support deprecated org.sonar.api.rules.RuleRepository when extending rules of org.sonar.api.server.rule.RulesDefinition --- 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 0041a742d92..c30bf37d6bf 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 @@ -344,7 +344,7 @@ class ServerComponents { pico.addSingleton(RuleOperations.class); pico.addSingleton(RubyRuleService.class); pico.addSingleton(RuleRepositories.class); - pico.addSingleton(DeprecatedRulesDefinition.class); + pico.addSingleton(DeprecatedRulesDefinitionLoader.class); pico.addSingleton(RuleDefinitionsLoader.class); pico.addSingleton(RulesDefinitionXmlLoader.class); pico.addSingleton(RuleService.class); diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRulesDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRulesDefinition.java deleted file mode 100644 index 8f185baf378..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRulesDefinition.java +++ /dev/null @@ -1,200 +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.rule; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.RuleStatus; -import org.sonar.api.rules.RuleParam; -import org.sonar.api.rules.RuleRepository; -import org.sonar.api.server.debt.DebtRemediationFunction; -import org.sonar.api.server.rule.RuleParamType; -import org.sonar.api.server.rule.RulesDefinition; -import org.sonar.api.utils.ValidationMessages; -import org.sonar.core.i18n.RuleI18nManager; -import org.sonar.server.debt.DebtModelPluginRepository; -import org.sonar.server.debt.DebtModelXMLExporter; -import org.sonar.server.debt.DebtRulesXMLImporter; - -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import java.io.Reader; -import java.util.Collection; -import java.util.List; - -import static com.google.common.collect.Lists.newArrayList; -import static org.sonar.server.debt.DebtModelXMLExporter.RuleDebt; - -/** - * Inject deprecated RuleRepository into {@link org.sonar.api.server.rule.RulesDefinition} for backward-compatibility. - */ -public class DeprecatedRulesDefinition implements RulesDefinition { - - private static final Logger LOG = LoggerFactory.getLogger(DeprecatedRulesDefinition.class); - - private final RuleI18nManager i18n; - private final RuleRepository[] repositories; - - private final DebtModelPluginRepository languageModelFinder; - private final DebtRulesXMLImporter importer; - - public DeprecatedRulesDefinition(RuleI18nManager i18n, RuleRepository[] repositories, DebtModelPluginRepository languageModelFinder, DebtRulesXMLImporter importer) { - this.i18n = i18n; - this.repositories = repositories; - this.languageModelFinder = languageModelFinder; - this.importer = importer; - } - - public DeprecatedRulesDefinition(RuleI18nManager i18n, DebtModelPluginRepository languageModelFinder, DebtRulesXMLImporter importer) { - this(i18n, new RuleRepository[0], languageModelFinder, importer); - } - - @Override - public void define(Context context) { - // Load rule debt definitions from xml files provided by plugin - List ruleDebts = loadRuleDebtList(); - - for (RuleRepository repository : repositories) { - // RuleRepository API does not handle difference between new and extended repositories, - NewRepository newRepository; - if (context.repository(repository.getKey()) == null) { - newRepository = context.createRepository(repository.getKey(), repository.getLanguage()); - newRepository.setName(repository.getName()); - } else { - newRepository = (NewRepository) context.extendRepository(repository.getKey(), repository.getLanguage()); - } - for (org.sonar.api.rules.Rule rule : repository.createRules()) { - NewRule newRule = newRepository.createRule(rule.getKey()); - newRule.setName(ruleName(repository.getKey(), rule)); - newRule.setHtmlDescription(ruleDescription(repository.getKey(), rule)); - newRule.setInternalKey(rule.getConfigKey()); - newRule.setTemplate(rule.isTemplate()); - newRule.setSeverity(rule.getSeverity().toString()); - newRule.setStatus(rule.getStatus() == null ? RuleStatus.defaultStatus() : RuleStatus.valueOf(rule.getStatus())); - newRule.setTags(rule.getTags()); - for (RuleParam param : rule.getParams()) { - NewParam newParam = newRule.createParam(param.getKey()); - newParam.setDefaultValue(param.getDefaultValue()); - newParam.setDescription(paramDescription(repository.getKey(), rule.getKey(), param)); - newParam.setType(RuleParamType.parse(param.getType())); - } - updateRuleDebtDefinitions(newRule, repository.getKey(), rule.getKey(), ruleDebts); - } - newRepository.done(); - } - } - - private void updateRuleDebtDefinitions(NewRule newRule, String repoKey, String ruleKey, List ruleDebts) { - RuleDebt ruleDebt = findRequirement(ruleDebts, repoKey, ruleKey); - if (ruleDebt != null) { - newRule.setDebtSubCharacteristic(ruleDebt.subCharacteristicKey()); - newRule.setDebtRemediationFunction(remediationFunction(DebtRemediationFunction.Type.valueOf(ruleDebt.function()), - ruleDebt.coefficient(), - ruleDebt.offset(), - newRule.debtRemediationFunctions(), - repoKey, ruleKey - )); - } - } - - private DebtRemediationFunction remediationFunction(DebtRemediationFunction.Type function, @Nullable String coefficient, @Nullable String offset, - DebtRemediationFunctions functions, String repoKey, String ruleKey) { - if (DebtRemediationFunction.Type.LINEAR.equals(function) && coefficient != null) { - return functions.linear(coefficient); - } else if (DebtRemediationFunction.Type.CONSTANT_ISSUE.equals(function) && offset != null) { - return functions.constantPerIssue(offset); - } else if (DebtRemediationFunction.Type.LINEAR_OFFSET.equals(function) && coefficient != null && offset != null) { - return functions.linearWithOffset(coefficient, offset); - } else { - throw new IllegalArgumentException(String.format("Debt definition on rule '%s:%s' is invalid", repoKey, ruleKey)); - } - } - - @CheckForNull - private String ruleName(String repositoryKey, org.sonar.api.rules.Rule rule) { - String name = i18n.getName(repositoryKey, rule.getKey()); - if (StringUtils.isNotBlank(name)) { - return name; - } - return StringUtils.defaultIfBlank(rule.getName(), null); - } - - @CheckForNull - private String ruleDescription(String repositoryKey, org.sonar.api.rules.Rule rule) { - String description = i18n.getDescription(repositoryKey, rule.getKey()); - if (StringUtils.isNotBlank(description)) { - return description; - } - return StringUtils.defaultIfBlank(rule.getDescription(), null); - } - - @CheckForNull - private String paramDescription(String repositoryKey, String ruleKey, RuleParam param) { - String desc = StringUtils.defaultIfEmpty( - i18n.getParamDescription(repositoryKey, ruleKey, param.getKey()), - param.getDescription() - ); - return StringUtils.defaultIfBlank(desc, null); - } - - public List loadRuleDebtList() { - List ruleDebtList = newArrayList(); - for (String pluginKey : getContributingPluginListWithoutSqale()) { - ruleDebtList.addAll(loadRuleDebtsFromXml(pluginKey)); - } - return ruleDebtList; - } - - public List loadRuleDebtsFromXml(String pluginKey) { - Reader xmlFileReader = null; - try { - xmlFileReader = languageModelFinder.createReaderForXMLFile(pluginKey); - ValidationMessages validationMessages = ValidationMessages.create(); - List rules = importer.importXML(xmlFileReader, validationMessages); - validationMessages.log(LOG); - return rules; - } finally { - IOUtils.closeQuietly(xmlFileReader); - } - } - - private Collection getContributingPluginListWithoutSqale() { - Collection pluginList = newArrayList(languageModelFinder.getContributingPluginList()); - pluginList.remove(DebtModelPluginRepository.DEFAULT_MODEL); - return pluginList; - } - - @CheckForNull - private RuleDebt findRequirement(List requirements, final String repoKey, final String ruleKey) { - return Iterables.find(requirements, new Predicate() { - @Override - public boolean apply(RuleDebt input) { - return input.ruleKey().equals(RuleKey.of(repoKey, ruleKey)); - } - }, null); - } - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoader.java b/server/sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoader.java new file mode 100644 index 00000000000..e54002f4bc9 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoader.java @@ -0,0 +1,203 @@ +/* + * 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.rule; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.ServerComponent; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rules.RuleParam; +import org.sonar.api.rules.RuleRepository; +import org.sonar.api.server.debt.DebtRemediationFunction; +import org.sonar.api.server.rule.RuleParamType; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.api.utils.ValidationMessages; +import org.sonar.core.i18n.RuleI18nManager; +import org.sonar.server.debt.DebtModelPluginRepository; +import org.sonar.server.debt.DebtModelXMLExporter; +import org.sonar.server.debt.DebtRulesXMLImporter; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +import java.io.Reader; +import java.util.Collection; +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; +import static org.sonar.server.debt.DebtModelXMLExporter.RuleDebt; + +/** + * Inject deprecated RuleRepository into {@link org.sonar.api.server.rule.RulesDefinition} for backward-compatibility. + */ +public class DeprecatedRulesDefinitionLoader implements ServerComponent { + + private static final Logger LOG = LoggerFactory.getLogger(DeprecatedRulesDefinitionLoader.class); + + private final RuleI18nManager i18n; + private final RuleRepository[] repositories; + + private final DebtModelPluginRepository languageModelFinder; + private final DebtRulesXMLImporter importer; + + public DeprecatedRulesDefinitionLoader(RuleI18nManager i18n, DebtModelPluginRepository languageModelFinder, DebtRulesXMLImporter importer, RuleRepository[] repositories) { + this.i18n = i18n; + this.repositories = repositories; + this.languageModelFinder = languageModelFinder; + this.importer = importer; + } + + /** + * Used when no deprecated repositories + */ + public DeprecatedRulesDefinitionLoader(RuleI18nManager i18n, DebtModelPluginRepository languageModelFinder, DebtRulesXMLImporter importer) { + this(i18n, languageModelFinder, importer, new RuleRepository[0]); + } + + void complete(RulesDefinition.Context context) { + // Load rule debt definitions from xml files provided by plugin + List ruleDebts = loadRuleDebtList(); + + for (RuleRepository repository : repositories) { + // RuleRepository API does not handle difference between new and extended repositories, + RulesDefinition.NewRepository newRepository; + if (context.repository(repository.getKey()) == null) { + newRepository = context.createRepository(repository.getKey(), repository.getLanguage()); + newRepository.setName(repository.getName()); + } else { + newRepository = (RulesDefinition.NewRepository) context.extendRepository(repository.getKey(), repository.getLanguage()); + } + for (org.sonar.api.rules.Rule rule : repository.createRules()) { + RulesDefinition.NewRule newRule = newRepository.createRule(rule.getKey()); + newRule.setName(ruleName(repository.getKey(), rule)); + newRule.setHtmlDescription(ruleDescription(repository.getKey(), rule)); + newRule.setInternalKey(rule.getConfigKey()); + newRule.setTemplate(rule.isTemplate()); + newRule.setSeverity(rule.getSeverity().toString()); + newRule.setStatus(rule.getStatus() == null ? RuleStatus.defaultStatus() : RuleStatus.valueOf(rule.getStatus())); + newRule.setTags(rule.getTags()); + for (RuleParam param : rule.getParams()) { + RulesDefinition.NewParam newParam = newRule.createParam(param.getKey()); + newParam.setDefaultValue(param.getDefaultValue()); + newParam.setDescription(paramDescription(repository.getKey(), rule.getKey(), param)); + newParam.setType(RuleParamType.parse(param.getType())); + } + updateRuleDebtDefinitions(newRule, repository.getKey(), rule.getKey(), ruleDebts); + } + newRepository.done(); + } + } + + private void updateRuleDebtDefinitions(RulesDefinition.NewRule newRule, String repoKey, String ruleKey, List ruleDebts) { + RuleDebt ruleDebt = findRequirement(ruleDebts, repoKey, ruleKey); + if (ruleDebt != null) { + newRule.setDebtSubCharacteristic(ruleDebt.subCharacteristicKey()); + newRule.setDebtRemediationFunction(remediationFunction(DebtRemediationFunction.Type.valueOf(ruleDebt.function()), + ruleDebt.coefficient(), + ruleDebt.offset(), + newRule.debtRemediationFunctions(), + repoKey, ruleKey + )); + } + } + + private DebtRemediationFunction remediationFunction(DebtRemediationFunction.Type function, @Nullable String coefficient, @Nullable String offset, + RulesDefinition.DebtRemediationFunctions functions, String repoKey, String ruleKey) { + if (DebtRemediationFunction.Type.LINEAR.equals(function) && coefficient != null) { + return functions.linear(coefficient); + } else if (DebtRemediationFunction.Type.CONSTANT_ISSUE.equals(function) && offset != null) { + return functions.constantPerIssue(offset); + } else if (DebtRemediationFunction.Type.LINEAR_OFFSET.equals(function) && coefficient != null && offset != null) { + return functions.linearWithOffset(coefficient, offset); + } else { + throw new IllegalArgumentException(String.format("Debt definition on rule '%s:%s' is invalid", repoKey, ruleKey)); + } + } + + @CheckForNull + private String ruleName(String repositoryKey, org.sonar.api.rules.Rule rule) { + String name = i18n.getName(repositoryKey, rule.getKey()); + if (StringUtils.isNotBlank(name)) { + return name; + } + return StringUtils.defaultIfBlank(rule.getName(), null); + } + + @CheckForNull + private String ruleDescription(String repositoryKey, org.sonar.api.rules.Rule rule) { + String description = i18n.getDescription(repositoryKey, rule.getKey()); + if (StringUtils.isNotBlank(description)) { + return description; + } + return StringUtils.defaultIfBlank(rule.getDescription(), null); + } + + @CheckForNull + private String paramDescription(String repositoryKey, String ruleKey, RuleParam param) { + String desc = StringUtils.defaultIfEmpty( + i18n.getParamDescription(repositoryKey, ruleKey, param.getKey()), + param.getDescription() + ); + return StringUtils.defaultIfBlank(desc, null); + } + + public List loadRuleDebtList() { + List ruleDebtList = newArrayList(); + for (String pluginKey : getContributingPluginListWithoutSqale()) { + ruleDebtList.addAll(loadRuleDebtsFromXml(pluginKey)); + } + return ruleDebtList; + } + + public List loadRuleDebtsFromXml(String pluginKey) { + Reader xmlFileReader = null; + try { + xmlFileReader = languageModelFinder.createReaderForXMLFile(pluginKey); + ValidationMessages validationMessages = ValidationMessages.create(); + List rules = importer.importXML(xmlFileReader, validationMessages); + validationMessages.log(LOG); + return rules; + } finally { + IOUtils.closeQuietly(xmlFileReader); + } + } + + private Collection getContributingPluginListWithoutSqale() { + Collection pluginList = newArrayList(languageModelFinder.getContributingPluginList()); + pluginList.remove(DebtModelPluginRepository.DEFAULT_MODEL); + return pluginList; + } + + @CheckForNull + private RuleDebt findRequirement(List requirements, final String repoKey, final String ruleKey) { + return Iterables.find(requirements, new Predicate() { + @Override + public boolean apply(RuleDebt input) { + return input.ruleKey().equals(RuleKey.of(repoKey, ruleKey)); + } + }, null); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java index 1cf8dc29103..46609a8b6bd 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java @@ -36,7 +36,6 @@ import org.sonar.api.rule.RuleStatus; import org.sonar.api.server.debt.DebtRemediationFunction; import org.sonar.api.server.rule.RulesDefinition; import org.sonar.api.utils.MessageException; -import org.sonar.api.utils.System2; import org.sonar.api.utils.TimeProfiler; import org.sonar.core.persistence.DbSession; import org.sonar.core.qualityprofile.db.ActiveRuleDto; @@ -53,7 +52,12 @@ import org.sonar.server.startup.RegisterDebtModel; import javax.annotation.CheckForNull; import javax.annotation.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import static com.google.common.collect.Lists.newArrayList; @@ -74,12 +78,12 @@ public class RegisterRules implements Startable { * @param registerDebtModel used only to be started after init of the technical debt model */ public RegisterRules(RuleDefinitionsLoader defLoader, RuleActivator ruleActivator, DbClient dbClient, Languages languages, RegisterDebtModel registerDebtModel) { - this(defLoader, ruleActivator, dbClient, languages, System2.INSTANCE); + this(defLoader, ruleActivator, dbClient, languages); } @VisibleForTesting RegisterRules(RuleDefinitionsLoader defLoader, RuleActivator ruleActivator, - DbClient dbClient, Languages languages, System2 system) { + DbClient dbClient, Languages languages) { this.defLoader = defLoader; this.ruleActivator = ruleActivator; this.dbClient = dbClient; diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionsLoader.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionsLoader.java index ac4491e18ae..f64ba522009 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionsLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionsLoader.java @@ -27,16 +27,22 @@ import org.sonar.api.server.rule.RulesDefinition; * and initializes {@link org.sonar.server.rule.RuleRepositories}. Used at server startup. */ public class RuleDefinitionsLoader implements ServerComponent { + + private final DeprecatedRulesDefinitionLoader deprecatedDefinitionConverter; private final RulesDefinition[] definitions; private final RuleRepositories repositories; - public RuleDefinitionsLoader(RuleRepositories repositories, RulesDefinition[] definitions) { + public RuleDefinitionsLoader(DeprecatedRulesDefinitionLoader deprecatedDefinitionConverter, RuleRepositories repositories, RulesDefinition[] definitions) { + this.deprecatedDefinitionConverter = deprecatedDefinitionConverter; this.repositories = repositories; this.definitions = definitions; } - public RuleDefinitionsLoader(RuleRepositories repositories) { - this(repositories, new RulesDefinition[0]); + /** + * Used when no definitions at all. + */ + public RuleDefinitionsLoader(DeprecatedRulesDefinitionLoader converter, RuleRepositories repositories) { + this(converter, repositories, new RulesDefinition[0]); } public RulesDefinition.Context load() { @@ -44,6 +50,7 @@ public class RuleDefinitionsLoader implements ServerComponent { for (RulesDefinition definition : definitions) { definition.define(context); } + deprecatedDefinitionConverter.complete(context); repositories.register(context); return context; } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoaderTest.java new file mode 100644 index 00000000000..aca4a6157a1 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoaderTest.java @@ -0,0 +1,217 @@ +/* + * 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.rule; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +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.rules.RuleRepository; +import org.sonar.api.server.debt.DebtRemediationFunction; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.api.utils.ValidationMessages; +import org.sonar.core.i18n.RuleI18nManager; +import org.sonar.server.debt.DebtModelPluginRepository; +import org.sonar.server.debt.DebtModelXMLExporter; +import org.sonar.server.debt.DebtRulesXMLImporter; + +import java.io.Reader; +import java.util.Arrays; +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.mock; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class DeprecatedRulesDefinitionLoaderTest { + + @Mock + RuleI18nManager i18n; + + @Mock + DebtModelPluginRepository debtModelRepository; + + @Mock + DebtRulesXMLImporter importer; + + static class CheckstyleRules extends RuleRepository { + public CheckstyleRules() { + super("checkstyle", "java"); + setName("Checkstyle"); + } + + @Override + public List createRules() { + Rule rule = Rule.create("checkstyle", "ConstantName", "Constant Name"); + rule.setDescription("Checks that constant names conform to the specified format"); + rule.setConfigKey("Checker/TreeWalker/ConstantName"); + rule.setSeverity(RulePriority.BLOCKER); + rule.setStatus(Rule.STATUS_BETA); + rule.setTags(new String[] {"style", "security"}); + rule.createParameter("format").setDescription("Regular expression").setDefaultValue("A-Z").setType("REGULAR_EXPRESSION"); + return Arrays.asList(rule); + } + } + + static class UseBundles extends RuleRepository { + public UseBundles() { + super("checkstyle", "java"); + setName("Checkstyle"); + } + + @Override + public List createRules() { + Rule rule = Rule.create("checkstyle", "ConstantName"); + rule.createParameter("format"); + return Arrays.asList(rule); + } + } + + @Test + public void wrap_deprecated_rule_repositories() throws Exception { + RulesDefinition.Context context = new RulesDefinition.Context(); + new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, new RuleRepository[] {new CheckstyleRules()}).complete(context); + + assertThat(context.repositories()).hasSize(1); + RulesDefinition.Repository checkstyle = context.repository("checkstyle"); + assertThat(checkstyle).isNotNull(); + assertThat(checkstyle.key()).isEqualTo("checkstyle"); + assertThat(checkstyle.name()).isEqualTo("Checkstyle"); + assertThat(checkstyle.language()).isEqualTo("java"); + assertThat(checkstyle.rules()).hasSize(1); + RulesDefinition.Rule rule = checkstyle.rule("ConstantName"); + assertThat(rule).isNotNull(); + assertThat(rule.key()).isEqualTo("ConstantName"); + assertThat(rule.name()).isEqualTo("Constant Name"); + assertThat(rule.htmlDescription()).isEqualTo("Checks that constant names conform to the specified format"); + assertThat(rule.severity()).isEqualTo(Severity.BLOCKER); + assertThat(rule.internalKey()).isEqualTo("Checker/TreeWalker/ConstantName"); + assertThat(rule.status()).isEqualTo(RuleStatus.BETA); + assertThat(rule.tags()).containsOnly("style", "security"); + assertThat(rule.params()).hasSize(1); + RulesDefinition.Param param = rule.param("format"); + assertThat(param).isNotNull(); + assertThat(param.key()).isEqualTo("format"); + assertThat(param.name()).isEqualTo("format"); + assertThat(param.description()).isEqualTo("Regular expression"); + assertThat(param.defaultValue()).isEqualTo("A-Z"); + } + + @Test + public void emulate_the_day_deprecated_api_can_be_dropped() throws Exception { + RulesDefinition.Context context = new RulesDefinition.Context(); + + // no more RuleRepository ! + new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer); + + assertThat(context.repositories()).isEmpty(); + } + + @Test + public void use_l10n_bundles() throws Exception { + RulesDefinition.Context context = new RulesDefinition.Context(); + when(i18n.getName("checkstyle", "ConstantName")).thenReturn("Constant Name"); + when(i18n.getDescription("checkstyle", "ConstantName")).thenReturn("Checks that constant names conform to the specified format"); + when(i18n.getParamDescription("checkstyle", "ConstantName", "format")).thenReturn("Regular expression"); + + new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, new RuleRepository[] {new UseBundles()}).complete(context); + + RulesDefinition.Repository checkstyle = context.repository("checkstyle"); + RulesDefinition.Rule rule = checkstyle.rule("ConstantName"); + assertThat(rule.key()).isEqualTo("ConstantName"); + assertThat(rule.name()).isEqualTo("Constant Name"); + assertThat(rule.htmlDescription()).isEqualTo("Checks that constant names conform to the specified format"); + RulesDefinition.Param param = rule.param("format"); + assertThat(param.key()).isEqualTo("format"); + assertThat(param.name()).isEqualTo("format"); + assertThat(param.description()).isEqualTo("Regular expression"); + } + + @Test + public void define_rule_debt() throws Exception { + RulesDefinition.Context context = new RulesDefinition.Context(); + + List ruleDebts = newArrayList( + new DebtModelXMLExporter.RuleDebt() + .setSubCharacteristicKey("MEMORY_EFFICIENCY") + .setRuleKey(RuleKey.of("checkstyle", "ConstantName")) + .setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setCoefficient("1d") + .setOffset("10min") + ); + + Reader javaModelReader = mock(Reader.class); + when(debtModelRepository.createReaderForXMLFile("java")).thenReturn(javaModelReader); + when(debtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java")); + when(importer.importXML(eq(javaModelReader), any(ValidationMessages.class))).thenReturn(ruleDebts); + + new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, new RuleRepository[] {new CheckstyleRules()}).complete(context); + + assertThat(context.repositories()).hasSize(1); + RulesDefinition.Repository checkstyle = context.repository("checkstyle"); + assertThat(checkstyle.rules()).hasSize(1); + + RulesDefinition.Rule rule = checkstyle.rule("ConstantName"); + assertThat(rule).isNotNull(); + assertThat(rule.key()).isEqualTo("ConstantName"); + assertThat(rule.debtSubCharacteristic()).isEqualTo("MEMORY_EFFICIENCY"); + assertThat(rule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET); + assertThat(rule.debtRemediationFunction().coefficient()).isEqualTo("1d"); + assertThat(rule.debtRemediationFunction().offset()).isEqualTo("10min"); + } + + @Test + public void fail_on_invalid_rule_debt() throws Exception { + RulesDefinition.Context context = new RulesDefinition.Context(); + + List ruleDebts = newArrayList( + new DebtModelXMLExporter.RuleDebt() + .setSubCharacteristicKey("MEMORY_EFFICIENCY") + .setRuleKey(RuleKey.of("checkstyle", "ConstantName")) + .setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setCoefficient("1d") + ); + + Reader javaModelReader = mock(Reader.class); + when(debtModelRepository.createReaderForXMLFile("java")).thenReturn(javaModelReader); + when(debtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java")); + when(importer.importXML(eq(javaModelReader), any(ValidationMessages.class))).thenReturn(ruleDebts); + + try { + new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, new RuleRepository[] {new CheckstyleRules()}).complete(context); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + assertThat(context.repositories()).isEmpty(); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionTest.java deleted file mode 100644 index 59bfb301f1e..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionTest.java +++ /dev/null @@ -1,217 +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.rule; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; -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.rules.RuleRepository; -import org.sonar.api.server.debt.DebtRemediationFunction; -import org.sonar.api.server.rule.RulesDefinition; -import org.sonar.api.utils.ValidationMessages; -import org.sonar.core.i18n.RuleI18nManager; -import org.sonar.server.debt.DebtModelPluginRepository; -import org.sonar.server.debt.DebtModelXMLExporter; -import org.sonar.server.debt.DebtRulesXMLImporter; - -import java.io.Reader; -import java.util.Arrays; -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.mock; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class DeprecatedRulesDefinitionTest { - - @Mock - RuleI18nManager i18n; - - @Mock - DebtModelPluginRepository debtModelRepository; - - @Mock - DebtRulesXMLImporter importer; - - static class CheckstyleRules extends RuleRepository { - public CheckstyleRules() { - super("checkstyle", "java"); - setName("Checkstyle"); - } - - @Override - public List createRules() { - Rule rule = Rule.create("checkstyle", "ConstantName", "Constant Name"); - rule.setDescription("Checks that constant names conform to the specified format"); - rule.setConfigKey("Checker/TreeWalker/ConstantName"); - rule.setSeverity(RulePriority.BLOCKER); - rule.setStatus(Rule.STATUS_BETA); - rule.setTags(new String[]{"style", "security"}); - rule.createParameter("format").setDescription("Regular expression").setDefaultValue("A-Z").setType("REGULAR_EXPRESSION"); - return Arrays.asList(rule); - } - } - - static class UseBundles extends RuleRepository { - public UseBundles() { - super("checkstyle", "java"); - setName("Checkstyle"); - } - - @Override - public List createRules() { - Rule rule = Rule.create("checkstyle", "ConstantName"); - rule.createParameter("format"); - return Arrays.asList(rule); - } - } - - @Test - public void wrap_deprecated_rule_repositories() throws Exception { - RulesDefinition.Context context = new RulesDefinition.Context(); - new DeprecatedRulesDefinition(i18n, new RuleRepository[]{new CheckstyleRules()}, debtModelRepository, importer).define(context); - - assertThat(context.repositories()).hasSize(1); - RulesDefinition.Repository checkstyle = context.repository("checkstyle"); - assertThat(checkstyle).isNotNull(); - assertThat(checkstyle.key()).isEqualTo("checkstyle"); - assertThat(checkstyle.name()).isEqualTo("Checkstyle"); - assertThat(checkstyle.language()).isEqualTo("java"); - assertThat(checkstyle.rules()).hasSize(1); - RulesDefinition.Rule rule = checkstyle.rule("ConstantName"); - assertThat(rule).isNotNull(); - assertThat(rule.key()).isEqualTo("ConstantName"); - assertThat(rule.name()).isEqualTo("Constant Name"); - assertThat(rule.htmlDescription()).isEqualTo("Checks that constant names conform to the specified format"); - assertThat(rule.severity()).isEqualTo(Severity.BLOCKER); - assertThat(rule.internalKey()).isEqualTo("Checker/TreeWalker/ConstantName"); - assertThat(rule.status()).isEqualTo(RuleStatus.BETA); - assertThat(rule.tags()).containsOnly("style", "security"); - assertThat(rule.params()).hasSize(1); - RulesDefinition.Param param = rule.param("format"); - assertThat(param).isNotNull(); - assertThat(param.key()).isEqualTo("format"); - assertThat(param.name()).isEqualTo("format"); - assertThat(param.description()).isEqualTo("Regular expression"); - assertThat(param.defaultValue()).isEqualTo("A-Z"); - } - - @Test - public void emulate_the_day_deprecated_api_can_be_dropped() throws Exception { - RulesDefinition.Context context = new RulesDefinition.Context(); - - // no more RuleRepository ! - new DeprecatedRulesDefinition(i18n, debtModelRepository, importer); - - assertThat(context.repositories()).isEmpty(); - } - - @Test - public void use_l10n_bundles() throws Exception { - RulesDefinition.Context context = new RulesDefinition.Context(); - when(i18n.getName("checkstyle", "ConstantName")).thenReturn("Constant Name"); - when(i18n.getDescription("checkstyle", "ConstantName")).thenReturn("Checks that constant names conform to the specified format"); - when(i18n.getParamDescription("checkstyle", "ConstantName", "format")).thenReturn("Regular expression"); - - new DeprecatedRulesDefinition(i18n, new RuleRepository[]{new UseBundles()}, debtModelRepository, importer).define(context); - - RulesDefinition.Repository checkstyle = context.repository("checkstyle"); - RulesDefinition.Rule rule = checkstyle.rule("ConstantName"); - assertThat(rule.key()).isEqualTo("ConstantName"); - assertThat(rule.name()).isEqualTo("Constant Name"); - assertThat(rule.htmlDescription()).isEqualTo("Checks that constant names conform to the specified format"); - RulesDefinition.Param param = rule.param("format"); - assertThat(param.key()).isEqualTo("format"); - assertThat(param.name()).isEqualTo("format"); - assertThat(param.description()).isEqualTo("Regular expression"); - } - - @Test - public void define_rule_debt() throws Exception { - RulesDefinition.Context context = new RulesDefinition.Context(); - - List ruleDebts = newArrayList( - new DebtModelXMLExporter.RuleDebt() - .setSubCharacteristicKey("MEMORY_EFFICIENCY") - .setRuleKey(RuleKey.of("checkstyle", "ConstantName")) - .setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setCoefficient("1d") - .setOffset("10min") - ); - - Reader javaModelReader = mock(Reader.class); - when(debtModelRepository.createReaderForXMLFile("java")).thenReturn(javaModelReader); - when(debtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java")); - when(importer.importXML(eq(javaModelReader), any(ValidationMessages.class))).thenReturn(ruleDebts); - - new DeprecatedRulesDefinition(i18n, new RuleRepository[]{new CheckstyleRules()}, debtModelRepository, importer).define(context); - - assertThat(context.repositories()).hasSize(1); - RulesDefinition.Repository checkstyle = context.repository("checkstyle"); - assertThat(checkstyle.rules()).hasSize(1); - - RulesDefinition.Rule rule = checkstyle.rule("ConstantName"); - assertThat(rule).isNotNull(); - assertThat(rule.key()).isEqualTo("ConstantName"); - assertThat(rule.debtSubCharacteristic()).isEqualTo("MEMORY_EFFICIENCY"); - assertThat(rule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET); - assertThat(rule.debtRemediationFunction().coefficient()).isEqualTo("1d"); - assertThat(rule.debtRemediationFunction().offset()).isEqualTo("10min"); - } - - @Test - public void fail_on_invalid_rule_debt() throws Exception { - RulesDefinition.Context context = new RulesDefinition.Context(); - - List ruleDebts = newArrayList( - new DebtModelXMLExporter.RuleDebt() - .setSubCharacteristicKey("MEMORY_EFFICIENCY") - .setRuleKey(RuleKey.of("checkstyle", "ConstantName")) - .setFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setCoefficient("1d") - ); - - Reader javaModelReader = mock(Reader.class); - when(debtModelRepository.createReaderForXMLFile("java")).thenReturn(javaModelReader); - when(debtModelRepository.getContributingPluginList()).thenReturn(newArrayList("java")); - when(importer.importXML(eq(javaModelReader), any(ValidationMessages.class))).thenReturn(ruleDebts); - - try { - new DeprecatedRulesDefinition(i18n, new RuleRepository[]{new CheckstyleRules()}, debtModelRepository, importer).define(context); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalArgumentException.class); - } - - assertThat(context.repositories()).isEmpty(); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java index ac63a246aad..50921c05bad 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java @@ -200,11 +200,11 @@ public class RegisterRulesTest extends AbstractDaoTestCase { } private void execute(RulesDefinition... defs) { - RuleDefinitionsLoader loader = new RuleDefinitionsLoader(mock(RuleRepositories.class), defs); + RuleDefinitionsLoader loader = new RuleDefinitionsLoader(mock(DeprecatedRulesDefinitionLoader.class), new RuleRepositories(),defs); Languages languages = mock(Languages.class); when(languages.get("java")).thenReturn(mock(Language.class)); - RegisterRules task = new RegisterRules(loader, ruleActivator, dbClient, languages, system); + RegisterRules task = new RegisterRules(loader, ruleActivator, dbClient, languages); task.start(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RulesDefinitionLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RulesDefinitionLoaderTest.java index a5e6a23e0b9..74fb2b09d35 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RulesDefinitionLoaderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RulesDefinitionLoaderTest.java @@ -23,13 +23,14 @@ import org.junit.Test; import org.sonar.api.server.rule.RulesDefinition; import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; public class RulesDefinitionLoaderTest { @Test public void no_definitions() { RuleRepositories repositories = new RuleRepositories(); - RulesDefinition.Context context = new RuleDefinitionsLoader(repositories).load(); + RulesDefinition.Context context = new RuleDefinitionsLoader(mock(DeprecatedRulesDefinitionLoader.class), repositories).load(); assertThat(context.repositories()).isEmpty(); assertThat(repositories.repositories()).isEmpty(); @@ -39,7 +40,7 @@ public class RulesDefinitionLoaderTest { public void load_definitions() { RuleRepositories repositories = new RuleRepositories(); - RulesDefinition.Context context = new RuleDefinitionsLoader(repositories, new RulesDefinition[]{ + RulesDefinition.Context context = new RuleDefinitionsLoader(mock(DeprecatedRulesDefinitionLoader.class), repositories, new RulesDefinition[]{ new FindbugsDefinitions(), new SquidDefinitions() }).load();