package org.sonar.server.startup;
+import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.sonar.jpa.session.DatabaseSessionFactory;
import org.sonar.server.configuration.ProfilesManager;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
List<Rule> registeredRules = registerRules(existingRules, profiler, session);
disableDeprecatedRules(existingRules, registeredRules, session);
disableDeprecatedRepositories(existingRules, session);
- disableDeprecatedUserRules(profiler, existingRules, session);
session.commit();
private List<Rule> findAllRules(DatabaseSession session) {
// the hardcoded repository "manual" is used for manual violations
- return session.createQuery("from " + Rule.class.getSimpleName() + " r WHERE r.parent IS NULL AND r.pluginName<>:repository")
- .setParameter("repository", "manual")
- .getResultList();
+ return session.createQuery("from " + Rule.class.getSimpleName() + " r WHERE r.pluginName<>:repository")
+ .setParameter("repository", "manual")
+ .getResultList();
}
private List<Rule> registerRules(RulesByRepository existingRules, TimeProfiler profiler, DatabaseSession session) {
List<Rule> registeredRules = newArrayList();
for (RuleRepository repository : repositories) {
profiler.start("Register rules [" + repository.getKey() + "/" + StringUtils.defaultString(repository.getLanguage(), "-") + "]");
-
- registeredRules.addAll(registerRepository(repository, existingRules, session));
+ registeredRules.addAll(registerRepositoryRules(repository, existingRules, session));
+ registeredRules.addAll(registerTemplateRules(repository, existingRules, registeredRules, session));
profiler.stop();
}
return registeredRules;
}
- private List<Rule> registerRepository(RuleRepository repository, RulesByRepository existingRules, DatabaseSession session) {
+ private List<Rule> registerRepositoryRules(RuleRepository repository, RulesByRepository existingRules, DatabaseSession session) {
List<Rule> registeredRules = newArrayList();
Map<String, Rule> ruleByKey = newHashMap();
for (Rule rule : repository.createRules()) {
- rule.setRepositoryKey(repository.getKey());
- rule.setLanguage(repository.getLanguage());
- rule.setStatus(!Strings.isNullOrEmpty(rule.getStatus()) ? rule.getStatus() : Rule.STATUS_READY);
+ updateRuleFromRepositoryInfo(rule, repository);
validateRule(rule, repository.getKey());
ruleByKey.put(rule.getKey(), rule);
registeredRules.add(rule);
for (Rule persistedRule : existingRules.get(repository.getKey())) {
Rule rule = ruleByKey.get(persistedRule.getKey());
if (rule != null) {
- updateRule(persistedRule, rule, session);
+ updateExistingRule(persistedRule, rule, session);
session.saveWithoutFlush(persistedRule);
ruleByKey.remove(rule.getKey());
}
return registeredRules;
}
+ /**
+ * Template rules do not exists in the rule repository, only in database, but have to be updated.
+ */
+ private List<Rule> registerTemplateRules(RuleRepository repository, RulesByRepository existingRules, List<Rule> registeredRules, DatabaseSession session) {
+ List<Rule> templateRules = newArrayList();
+ for (Rule persistedRule : existingRules.get(repository.getKey())) {
+ Rule parent = persistedRule.getParent();
+ if (parent != null && registeredRules.contains(parent)) {
+ persistedRule.setRepositoryKey(parent.getRepositoryKey());
+ persistedRule.setLanguage(parent.getLanguage());
+ persistedRule.setStatus(parent.getStatus());
+ persistedRule.setUpdatedAt(new Date());
+
+ session.saveWithoutFlush(persistedRule);
+ templateRules.add(persistedRule);
+ }
+ }
+ return templateRules;
+ }
+
+ private void updateRuleFromRepositoryInfo(Rule rule, RuleRepository repository) {
+ rule.setRepositoryKey(repository.getKey());
+ rule.setLanguage(repository.getLanguage());
+ rule.setStatus(Objects.firstNonNull(rule.getStatus(), Rule.STATUS_READY));
+ }
+
private void validateRule(Rule rule, String repositoryKey) {
validateRuleRepositoryName(rule, repositoryKey);
validateRuleDescription(rule, repositoryKey);
if (!Strings.isNullOrEmpty(rule.getName()) && Strings.isNullOrEmpty(ruleI18nManager.getName(repositoryKey, rule.getKey(), Locale.ENGLISH))) {
// specific case
throw new SonarException("No description found for the rule '" + rule.getName() + "' (repository: " + repositoryKey + ") because the entry 'rule."
- + repositoryKey + "." + rule.getKey() + ".name' is missing from the bundle.");
+ + repositoryKey + "." + rule.getKey() + ".name' is missing from the bundle.");
} else {
throw new SonarException("The following rule (repository: " + repositoryKey + ") must have a description: " + rule);
}
}
}
- private void updateRule(Rule persistedRule, Rule rule, DatabaseSession session) {
- LOG.debug("Update rule " + rule);
+ private void updateExistingRule(Rule persistedRule, Rule rule, DatabaseSession session) {
+ LOG.debug("Update existing rule " + rule);
persistedRule.setName(rule.getName());
persistedRule.setConfigKey(rule.getConfigKey());
if (rule.getParam(persistedParam.getKey()) == null) {
it.remove();
session
- .createQuery("delete from " + ActiveRuleParam.class.getSimpleName() + " where ruleParam=:param")
- .setParameter("param", persistedParam)
- .executeUpdate();
+ .createQuery("delete from " + ActiveRuleParam.class.getSimpleName() + " where ruleParam=:param")
+ .setParameter("param", persistedParam)
+ .executeUpdate();
}
}
}
}
}
- private void disableDeprecatedUserRules(TimeProfiler profiler, RulesByRepository existingRules, DatabaseSession session) {
- profiler.start("Disable deprecated user rules");
- List<Integer> deprecatedUserRuleIds = Lists.newLinkedList();
- deprecatedUserRuleIds.addAll(session.createQuery(
- "SELECT r.id FROM " + Rule.class.getSimpleName() +
- " r WHERE r.parent IS NOT NULL AND NOT EXISTS(FROM " + Rule.class.getSimpleName() + " p WHERE r.parent=p)").getResultList());
-
- deprecatedUserRuleIds.addAll(session.createQuery(
- "SELECT r.id FROM " + Rule.class.getSimpleName() +
- " r WHERE r.parent IS NOT NULL AND EXISTS(FROM " + Rule.class.getSimpleName() + " p WHERE r.parent=p and p.status=:status)")
- .setParameter("status", Rule.STATUS_REMOVED)
- .getResultList());
-
- for (Integer deprecatedUserRuleId : deprecatedUserRuleIds) {
- Rule rule = session.getSingleResult(Rule.class, "id", deprecatedUserRuleId);
- disable(rule, existingRules, session);
- }
- profiler.stop();
- }
-
private void disable(Rule rule, RulesByRepository existingRules, DatabaseSession session) {
if (!rule.getStatus().equals(Rule.STATUS_REMOVED)) {
LOG.debug("Disable rule " + rule);
import org.junit.Before;
import org.junit.Test;
-import org.sonar.api.rules.ActiveRule;
-import org.sonar.api.rules.ActiveRuleParam;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleParam;
-import org.sonar.api.rules.RulePriority;
-import org.sonar.api.rules.RuleRepository;
+import org.sonar.api.rules.*;
import org.sonar.api.utils.SonarException;
import org.sonar.core.i18n.RuleI18nManager;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
import java.util.List;
import java.util.Locale;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.hamcrest.Matchers.nullValue;
+import static org.hamcrest.Matchers.*;
import static org.hamcrest.number.OrderingComparisons.greaterThan;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
public class RegisterRulesTest extends AbstractDbUnitTestCase {
assertThat(first.getParams().size(), is(2));
}
+ @Test
+ public void should_update_template_rule() {
+ setupData("should_update_template_rule_language");
+ task.start();
+
+ Rule rule = getSession().getSingleResult(Rule.class, "id", 2);
+ assertThat(rule.getRepositoryKey(), is("fake"));
+ assertThat(rule.getLanguage(), is("java"));
+ assertThat(rule.getStatus(), is(Rule.STATUS_READY));
+
+ rule = getSession().getSingleResult(Rule.class, "id", 4);
+ assertThat(rule.getRepositoryKey(), is("fake"));
+ assertThat(rule.getLanguage(), is("java"));
+ // Status was READY in db, but parent status is now DEPRECATED
+ assertThat(rule.getStatus(), is(Rule.STATUS_DEPRECATED));
+ }
+
@Test
public void should_disable_deprecated_repositories() {
setupData("shared");
assertThat(rule.getUpdatedAt(), notNullValue());
}
+ @Test
+ public void should_reactivate_disabled_template_rules() {
+ setupData("should_reactivate_disabled_template_rules");
+ task.start();
+
+ Rule rule = getSession().getSingleResult(Rule.class, "id", 2);
+ assertThat(rule.getStatus(), is(Rule.STATUS_READY));
+ assertThat(rule.getUpdatedAt(), notNullValue());
+ }
+
@Test
public void should_not_update_already_disabled_rules() {
setupData("notUpdateAlreadyDisabledRule");
}
@Test
- public void should_not_disable_user_rules_if_parent_is_enabled() {
+ public void should_not_disable_template_rules_if_parent_is_enabled() {
setupData("doNotDisableUserRulesIfParentIsEnabled");
task.start();
}
@Test
- public void should_disable_user_rules_if_parent_is_disabled() {
+ public void should_disable_template_rules_if_parent_is_disabled() {
setupData("disableUserRulesIfParentIsDisabled");
task.start();
Rule rule = getSession().getSingleResult(Rule.class, "id", 2);
assertThat(rule.isEnabled(), is(false));
assertThat(rule.getUpdatedAt(), notNullValue());
+
+ assertThat(getSession().getSingleResult(Rule.class, "id", 4).isEnabled(), is(false));
}
@Test