}
}
- public List<RuleDto> selectNonManual() {
- SqlSession session = mybatis.openSession();
- try {
- return getMapper(session).selectNonManual();
- } finally {
- MyBatis.closeQuietly(session);
- }
+ public List<RuleDto> selectNonManual(SqlSession session) {
+ return getMapper(session).selectNonManual();
}
public RuleDto selectById(Integer id, SqlSession session) {
@Test
public void testSelectNonManual() throws Exception {
setupData("selectNonManual");
- List<RuleDto> ruleDtos = dao.selectNonManual();
+ List<RuleDto> ruleDtos = dao.selectNonManual(getMyBatis().openSession());
assertThat(ruleDtos.size()).isEqualTo(1);
RuleDto ruleDto = ruleDtos.get(0);
private final ListMultimap<String, ExtendedRepository> extendedRepositoriesByKey = ArrayListMultimap.create();
public NewRepository newRepository(String key, String language) {
- return new NewRepositoryImpl(this, key, language);
+ return new NewRepositoryImpl(this, key, language, false);
}
- public NewExtendedRepository extendRepository(String key) {
- return new NewRepositoryImpl(this, key);
+ public NewExtendedRepository extendRepository(String key, String language) {
+ return new NewRepositoryImpl(this, key, language, true);
}
@CheckForNull
private String name;
private final Map<String, NewRule> newRules = Maps.newHashMap();
- private NewRepositoryImpl(Context context, String key, String language) {
- this.extended = false;
+ private NewRepositoryImpl(Context context, String key, String language, boolean extended) {
+ this.extended = extended;
this.context = context;
this.key = this.name = key;
this.language = language;
}
- private NewRepositoryImpl(Context context, String key) {
- this.extended = true;
- this.context = context;
- this.key = this.name = key;
- }
-
@Override
public NewRepositoryImpl setName(String s) {
this.name = s;
static interface ExtendedRepository {
String key();
+ String language();
+
@CheckForNull
Rule rule(String ruleKey);
}
static interface Repository extends ExtendedRepository {
- String language();
-
String name();
}
ImmutableMap.Builder<String, Rule> ruleBuilder = ImmutableMap.builder();
for (NewRule newRule : newRepository.newRules.values()) {
newRule.validate();
- ruleBuilder.put(newRule.key, new Rule(newRule));
+ ruleBuilder.put(newRule.key, new Rule(this, newRule));
}
this.rulesByKey = ruleBuilder.build();
}
private final String repoKey, key;
private String name, htmlDescription, metadata, defaultSeverity = Severity.MAJOR;
private boolean template;
- private final Set<String> tags = Sets.newHashSet();
+ private Status status = Status.READY;
+ private final Set<String> tags = Sets.newTreeSet();
private final Map<String, NewParam> paramsByKey = Maps.newHashMap();
private NewRule(String repoKey, String key) {
return this;
}
+ public NewRule setStatus(Status status) {
+ this.status = status;
+ return this;
+ }
+
public NewParam newParam(String paramKey) {
if (paramsByKey.containsKey(paramKey)) {
throw new IllegalArgumentException(String.format("The parameter '%s' is declared several times on the rule %s", paramKey, this));
}
}
+ static enum Status {
+ BETA, DEPRECATED, READY
+ }
+
static class Rule {
+ private final Repository repository;
private final String repoKey, key, name, htmlDescription, metadata, defaultSeverity;
private final boolean template;
private final Set<String> tags;
private final Map<String, Param> params;
+ private final Status status;
- private Rule(NewRule newRule) {
+ private Rule(Repository repository, NewRule newRule) {
+ this.repository = repository;
this.repoKey = newRule.repoKey;
this.key = newRule.key;
this.name = newRule.name;
this.metadata = newRule.metadata;
this.defaultSeverity = newRule.defaultSeverity;
this.template = newRule.template;
- this.tags = ImmutableSet.copyOf(newRule.tags);
+ this.status = newRule.status;
+ this.tags = ImmutableSortedSet.copyOf(newRule.tags);
ImmutableMap.Builder<String, Param> paramsBuilder = ImmutableMap.builder();
for (NewParam newParam : newRule.paramsByKey.values()) {
paramsBuilder.put(newParam.key, new Param(newParam));
this.params = paramsBuilder.build();
}
+ public Repository repository() {
+ return repository;
+ }
+
public String key() {
return key;
}
return template;
}
+ public Status status() {
+ return status;
+ }
+
@CheckForNull
public Param param(String key) {
return params.get(key);
.setHtmlDescription("Detect <code>java.lang.NullPointerException</code>")
.setDefaultSeverity(Severity.BLOCKER)
.setMetadata("/something")
+ .setStatus(RuleDefinitions.Status.BETA)
.setTags("one", "two")
.addTags("two", "three", "four");
newFindbugs.newRule("ABC").setName("ABC").setHtmlDescription("ABC");
assertThat(npeRule.params()).isEmpty();
assertThat(npeRule.metadata()).isEqualTo("/something");
assertThat(npeRule.template()).isFalse();
+ assertThat(npeRule.status()).isEqualTo(RuleDefinitions.Status.BETA);
assertThat(npeRule.toString()).isEqualTo("[repository=findbugs, key=NPE]");
+ assertThat(npeRule.repository()).isSameAs(findbugs);
// test equals() and hashCode()
RuleDefinitions.Rule otherRule = findbugs.rule("ABC");
assertThat(rule.defaultSeverity()).isEqualTo(Severity.MAJOR);
assertThat(rule.params()).isEmpty();
assertThat(rule.metadata()).isNull();
+ assertThat(rule.status()).isEqualTo(RuleDefinitions.Status.READY);
assertThat(rule.tags()).isEmpty();
}
assertThat(context.extendedRepositories()).isEmpty();
// for example fb-contrib
- RuleDefinitions.NewExtendedRepository newFindbugs = context.extendRepository("findbugs");
+ RuleDefinitions.NewExtendedRepository newFindbugs = context.extendRepository("findbugs", "java");
newFindbugs.newRule("NPE").setName("NPE").setHtmlDescription("NPE");
newFindbugs.done();
assertThat(context.extendedRepositories("findbugs")).hasSize(1);
RuleDefinitions.ExtendedRepository findbugs = context.extendedRepositories("findbugs").get(0);
+ assertThat(findbugs.language()).isEqualTo("java");
assertThat(findbugs.rule("NPE")).isNotNull();
}
newRepository = context.newRepository(repository.getKey(), repository.getLanguage());
newRepository.setName(repository.getName());
} else {
- newRepository = (NewRepository) context.extendRepository(repository.getKey());
+ newRepository = (NewRepository) context.extendRepository(repository.getKey(), repository.getLanguage());
}
for (org.sonar.api.rules.Rule rule : repository.createRules()) {
// TODO remove org.sonar.api.rules.Rule#tags
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.sonar.api.rule.RuleDefinitions;
+
+/**
+ * Loads all instances of RuleDefinitions and initializes RuleRepositories.
+ */
+public class RuleDefinitionsLoader {
+ private final RuleDefinitions[] definitions;
+ private final RuleRepositories repositories;
+
+ public RuleDefinitionsLoader(RuleRepositories repositories, RuleDefinitions[] definitions) {
+ this.repositories = repositories;
+ this.definitions = definitions;
+ }
+
+ public RuleDefinitionsLoader(RuleRepositories repositories) {
+ this(repositories, new RuleDefinitions[0]);
+ }
+
+ public RuleDefinitions.Context load() {
+ RuleDefinitions.Context context = new RuleDefinitions.Context();
+ for (RuleDefinitions definition : definitions) {
+ definition.define(context);
+ }
+ repositories.register(context);
+ return context;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.collect.*;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.ibatis.session.SqlSession;
+import org.picocontainer.Startable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.rule.RuleDefinitions;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.utils.System2;
+import org.sonar.check.Cardinality;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.qualityprofile.db.ActiveRuleDao;
+import org.sonar.core.rule.*;
+import org.sonar.server.configuration.ProfilesManager;
+
+import javax.annotation.CheckForNull;
+import java.util.*;
+
+public class RuleRegistration implements Startable {
+ private static final Logger LOG = LoggerFactory.getLogger(RuleRegistration.class);
+
+ private final RuleDefinitionsLoader defLoader;
+ private final ProfilesManager profilesManager;
+ private final RuleRegistry ruleRegistry;
+ private final MyBatis myBatis;
+ private final RuleDao ruleDao;
+ private final ActiveRuleDao activeRuleDao;
+ private final System2 system = System2.INSTANCE;
+
+ public RuleRegistration(RuleDefinitionsLoader defLoader, ProfilesManager profilesManager,
+ RuleRegistry ruleRegistry,
+ MyBatis myBatis, RuleDao ruleDao, ActiveRuleDao activeRuleDao) {
+ this.defLoader = defLoader;
+ this.profilesManager = profilesManager;
+ this.ruleRegistry = ruleRegistry;
+ this.myBatis = myBatis;
+ this.ruleDao = ruleDao;
+ this.activeRuleDao = activeRuleDao;
+ }
+
+ @Override
+ public void start() {
+ SqlSession sqlSession = myBatis.openSession();
+ try {
+ Buffer buffer = new Buffer(system.now());
+ selectRulesFromDb(buffer, sqlSession);
+ enableRuleDefinitions(buffer, sqlSession);
+ processRemainingDbRules(buffer, sqlSession);
+ index(buffer);
+
+ } finally {
+ sqlSession.close();
+ }
+ }
+
+ @Override
+ public void stop() {
+ // nothing
+ }
+
+ private void selectRulesFromDb(Buffer buffer, SqlSession sqlSession) {
+ for (RuleDto ruleDto : ruleDao.selectNonManual(sqlSession)) {
+ buffer.add(ruleDto);
+ buffer.markUnprocessed(ruleDto);
+ }
+ for (RuleParamDto paramDto : ruleDao.selectParameters(sqlSession)) {
+ buffer.add(paramDto);
+ }
+ for (RuleTagDto tagDto : ruleDao.selectTags(sqlSession)) {
+ buffer.add(tagDto);
+ }
+ }
+
+ private void enableRuleDefinitions(Buffer buffer, SqlSession sqlSession) {
+ RuleDefinitions.Context context = defLoader.load();
+ for (RuleDefinitions.Repository repoDef : context.repositories()) {
+ enableRepository(buffer, sqlSession, repoDef);
+ }
+ for (RuleDefinitions.ExtendedRepository extendedRepoDef : context.extendedRepositories()) {
+ if (context.repository(extendedRepoDef.key())==null) {
+ LOG.warn(String.format("Extension is ignored, repository %s does not exist", extendedRepoDef.key()));
+ } else {
+ enableRepository(buffer, sqlSession, extendedRepoDef);
+ }
+ }
+ }
+
+ private void enableRepository(Buffer buffer, SqlSession sqlSession, RuleDefinitions.ExtendedRepository repoDef) {
+ int count = 0;
+ for (RuleDefinitions.Rule ruleDef : repoDef.rules()) {
+ RuleDto dto = buffer.rule(RuleKey.of(ruleDef.repository().key(), ruleDef.key()));
+ if (dto == null) {
+ dto = enableAndInsert(buffer, sqlSession, ruleDef);
+ } else {
+ enableAndUpdate(buffer, sqlSession, ruleDef, dto);
+ }
+ buffer.markProcessed(dto);
+ count++;
+ if (count % 100 == 0) {
+ sqlSession.commit();
+ }
+ }
+ sqlSession.commit();
+ }
+
+ private RuleDto enableAndInsert(Buffer buffer, SqlSession sqlSession, RuleDefinitions.Rule ruleDef) {
+ RuleDto ruleDto = new RuleDto()
+ .setCardinality(ruleDef.template() ? Cardinality.MULTIPLE : Cardinality.SINGLE)
+ .setConfigKey(ruleDef.metadata())
+ .setDescription(ruleDef.htmlDescription())
+ .setLanguage(ruleDef.repository().language())
+ .setName(ruleDef.name())
+ .setRepositoryKey(ruleDef.repository().key())
+ .setRuleKey(ruleDef.key())
+ .setSeverity(RulePriority.valueOf(ruleDef.defaultSeverity()).ordinal())
+ .setCreatedAt(buffer.now())
+ .setUpdatedAt(buffer.now())
+ .setStatus(ruleDef.status().name());
+ ruleDao.insert(ruleDto, sqlSession);
+ buffer.add(ruleDto);
+
+ for (RuleDefinitions.Param param : ruleDef.params()) {
+ RuleParamDto paramDto = new RuleParamDto()
+ .setRuleId(ruleDto.getId())
+ .setDefaultValue(param.defaultValue())
+ .setDescription(param.description())
+ .setName(param.name())
+ .setType(param.type().toString());
+ ruleDao.insert(paramDto, sqlSession);
+ buffer.add(paramDto);
+ }
+ for (String tag : ruleDef.tags()) {
+ RuleTagDto tagDto = new RuleTagDto().setRuleId(ruleDto.getId()).setTag(tag).setType(RuleTagType.SYSTEM);
+ ruleDao.insert(tagDto, sqlSession);
+ buffer.add(tagDto);
+ }
+ return ruleDto;
+ }
+
+ private void enableAndUpdate(Buffer buffer, SqlSession sqlSession, RuleDefinitions.Rule ruleDef, RuleDto dto) {
+ if (mergeRule(buffer, ruleDef, dto)) {
+ ruleDao.update(dto);
+ }
+ mergeParams(buffer, sqlSession, ruleDef, dto);
+ mergeTags(buffer, sqlSession, ruleDef, dto);
+ buffer.markProcessed(dto);
+ }
+
+ private boolean mergeRule(Buffer buffer, RuleDefinitions.Rule def, RuleDto dto) {
+ boolean changed = false;
+ if (!StringUtils.equals(dto.getName(), def.name())) {
+ dto.setName(def.name());
+ changed = true;
+ }
+ if (!StringUtils.equals(dto.getDescription(), def.htmlDescription())) {
+ dto.setDescription(def.htmlDescription());
+ changed = true;
+ }
+ if (!StringUtils.equals(dto.getConfigKey(), def.metadata())) {
+ dto.setConfigKey(def.metadata());
+ changed = true;
+ }
+ int severity = RulePriority.valueOf(def.defaultSeverity()).ordinal();
+ if (!ObjectUtils.equals(dto.getSeverity(), severity)) {
+ dto.setSeverity(severity);
+ changed = true;
+ }
+ Cardinality cardinality = def.template() ? Cardinality.MULTIPLE : Cardinality.SINGLE;
+ if (!cardinality.equals(dto.getCardinality())) {
+ dto.setCardinality(cardinality);
+ changed = true;
+ }
+ String status = def.status().name();
+ if (!StringUtils.equals(dto.getStatus(), status)) {
+ dto.setStatus(status);
+ changed = true;
+ }
+ if (!StringUtils.equals(dto.getLanguage(), def.repository().language())) {
+ dto.setLanguage(def.repository().language());
+ changed = true;
+ }
+ if (changed) {
+ dto.setUpdatedAt(buffer.now());
+ }
+ return changed;
+ }
+
+ private void mergeParams(Buffer buffer, SqlSession sqlSession, RuleDefinitions.Rule ruleDef, RuleDto dto) {
+ Collection<RuleParamDto> paramDtos = buffer.paramsForRuleId(dto.getId());
+ Set<String> persistedParamKeys = Sets.newHashSet();
+ for (RuleParamDto paramDto : paramDtos) {
+ RuleDefinitions.Param paramDef = ruleDef.param(paramDto.getName());
+ if (paramDef == null) {
+ activeRuleDao.deleteParametersWithParamId(paramDto.getId(), sqlSession);
+ ruleDao.deleteParam(paramDto, sqlSession);
+ } else {
+ // TODO validate that existing active rules still match constraints
+ // TODO store param name
+ if (mergeParam(paramDto, paramDef)) {
+ ruleDao.update(paramDto, sqlSession);
+ }
+ persistedParamKeys.add(paramDto.getName());
+ }
+ }
+ for (RuleDefinitions.Param param : ruleDef.params()) {
+ if (!persistedParamKeys.contains(param.key())) {
+ RuleParamDto paramDto = new RuleParamDto()
+ .setRuleId(dto.getId())
+ .setName(param.key())
+ .setDescription(param.description())
+ .setDefaultValue(param.defaultValue())
+ .setType(param.type().toString());
+ ruleDao.insert(paramDto, sqlSession);
+ buffer.add(paramDto);
+ }
+ }
+ }
+
+ private boolean mergeParam(RuleParamDto paramDto, RuleDefinitions.Param paramDef) {
+ boolean changed = false;
+ if (!StringUtils.equals(paramDto.getType(), paramDef.type().toString())) {
+ paramDto.setType(paramDef.type().toString());
+ changed = true;
+ }
+ if (!StringUtils.equals(paramDto.getDefaultValue(), paramDef.defaultValue())) {
+ paramDto.setDefaultValue(paramDef.defaultValue());
+ changed = true;
+ }
+ if (!StringUtils.equals(paramDto.getDescription(), paramDef.description())) {
+ paramDto.setDescription(paramDef.description());
+ changed = true;
+ }
+ return changed;
+ }
+
+ private void mergeTags(Buffer buffer, SqlSession sqlSession, RuleDefinitions.Rule ruleDef, RuleDto dto) {
+ Set<String> existingSystemTags = Sets.newHashSet();
+
+ Collection<RuleTagDto> tagDtos = ImmutableList.copyOf(buffer.tagsForRuleId(dto.getId()));
+ for (RuleTagDto tagDto : tagDtos) {
+ String tag = tagDto.getTag();
+
+ if (tagDto.getType() == RuleTagType.SYSTEM) {
+ // tag previously declared by plugin
+ if (!ruleDef.tags().contains(tag)) {
+ // not declared anymore
+ ruleDao.deleteTag(tagDto, sqlSession);
+ buffer.remove(tagDto);
+ } else {
+ existingSystemTags.add(tagDto.getTag());
+ }
+ } else {
+ // tags created by end-users
+ if (ruleDef.tags().contains(tag)) {
+ // End-user tag is converted to system tag
+ ruleDao.deleteTag(tagDto, sqlSession);
+ buffer.remove(tagDto);
+ RuleTagDto newTag = new RuleTagDto().setRuleId(dto.getId()).setTag(tag).setType(RuleTagType.SYSTEM);
+ ruleDao.insert(newTag, sqlSession);
+ existingSystemTags.add(tag);
+ buffer.add(newTag);
+ }
+ }
+ }
+
+ for (String tag : ruleDef.tags()) {
+ if (!existingSystemTags.contains(tag)) {
+ RuleTagDto newTagDto = new RuleTagDto().setRuleId(dto.getId()).setTag(tag).setType(RuleTagType.SYSTEM);
+ ruleDao.insert(newTagDto, sqlSession);
+ buffer.add(newTagDto);
+ }
+ }
+ }
+
+ private void processRemainingDbRules(Buffer buffer, SqlSession sqlSession) {
+ List<Integer> removedIds = Lists.newArrayList();
+ for (Integer unprocessedRuleId : buffer.unprocessedRuleIds) {
+ RuleDto ruleDto = buffer.rulesById.get(unprocessedRuleId);
+ boolean toBeRemoved = true;
+ if (ruleDto.getParentId() != null && !ruleDto.getStatus().equals(Rule.STATUS_REMOVED)) {
+ RuleDto parent = buffer.rulesById.get(ruleDto.getParentId());
+ if (parent != null) {
+ // TODO merge params and tags ?
+ ruleDto.setLanguage(parent.getLanguage());
+ ruleDto.setStatus(parent.getStatus());
+ ruleDto.setUpdatedAt(buffer.now());
+ ruleDao.update(ruleDto, sqlSession);
+ toBeRemoved = false;
+ }
+ }
+ if (toBeRemoved) {
+ // TODO log repository key
+ LOG.info("Disable rule " + ruleDto.getRuleKey());
+ ruleDto.setStatus(Rule.STATUS_REMOVED);
+ ruleDto.setUpdatedAt(buffer.now());
+ ruleDao.update(ruleDto, sqlSession);
+ removedIds.add(ruleDto.getId());
+ if (removedIds.size() % 100 == 0) {
+ sqlSession.commit();
+ }
+ }
+ }
+ sqlSession.commit();
+
+ // call to ProfileManager requires session to be committed
+ for (Integer removedId : removedIds) {
+ profilesManager.removeActivatedRules(removedId);
+ }
+ }
+
+ private void index(Buffer buffer) {
+ ruleRegistry.bulkRegisterRules(buffer.rulesById.values(), buffer.paramsByRuleId, buffer.tagsByRuleId);
+ }
+
+ static class Buffer {
+ private Date now;
+ private List<Integer> unprocessedRuleIds = Lists.newArrayList();
+ private Map<RuleKey, RuleDto> rulesByKey = Maps.newHashMap();
+ private Map<Integer, RuleDto> rulesById = Maps.newHashMap();
+ private Multimap<Integer, RuleParamDto> paramsByRuleId = ArrayListMultimap.create();
+ private Multimap<Integer, RuleTagDto> tagsByRuleId = ArrayListMultimap.create();
+
+ Buffer(long now) {
+ this.now = new Date(now);
+ }
+
+ Date now() {
+ return now;
+ }
+
+ void add(RuleDto rule) {
+ rulesById.put(rule.getId(), rule);
+ rulesByKey.put(RuleKey.of(rule.getRepositoryKey(), rule.getRuleKey()), rule);
+ }
+
+ void add(RuleParamDto param) {
+ paramsByRuleId.put(param.getRuleId(), param);
+ }
+
+ void add(RuleTagDto tag) {
+ tagsByRuleId.put(tag.getRuleId(), tag);
+ }
+
+ void remove(RuleTagDto tag) {
+ tagsByRuleId.remove(tag.getRuleId(), tag);
+ }
+
+ @CheckForNull
+ RuleDto rule(RuleKey key) {
+ return rulesByKey.get(key);
+ }
+
+ Collection<RuleParamDto> paramsForRuleId(Integer ruleId) {
+ return paramsByRuleId.get(ruleId);
+ }
+
+ Collection<RuleTagDto> tagsForRuleId(Integer ruleId) {
+ return tagsByRuleId.get(ruleId);
+ }
+
+ void markUnprocessed(RuleDto ruleDto) {
+ unprocessedRuleIds.add(ruleDto.getId());
+ }
+
+ void markProcessed(RuleDto ruleDto) {
+ unprocessedRuleIds.remove(ruleDto.getId());
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.SetMultimap;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.rule.RuleDefinitions;
+
+import javax.annotation.CheckForNull;
+import java.util.Collection;
+import java.util.Map;
+import java.util.SortedSet;
+
+/**
+ * This component keeps metadata of rule repositories.
+ * <p/>
+ * Rule repositories are not persisted into datastores, so their metadata (name)
+ * is kept by this component.
+ *
+ * @since 4.2
+ */
+public class RuleRepositories implements ServerComponent {
+
+ public static class Repository implements Comparable<Repository> {
+ private final String key, name, language;
+
+ private Repository(RuleDefinitions.Repository repoDef) {
+ this.key = repoDef.key();
+ this.name = repoDef.name();
+ this.language = repoDef.language();
+ }
+
+ public String key() {
+ return key;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public String language() {
+ return language;
+ }
+
+ /**
+ * Kept for backward-compatibility in Ruby code
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Kept for backward-compatibility in Ruby code
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Kept for backward-compatibility in Ruby code
+ */
+ public String getLanguage() {
+ return language;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Repository that = (Repository) o;
+ return key.equals(that.key);
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode();
+ }
+
+ @Override
+ public int compareTo(Repository o) {
+ return name.toLowerCase().compareTo(o.name.toLowerCase());
+ }
+ }
+
+ private SortedSet<Repository> repositories;
+ private Map<String, Repository> repositoriesByKey;
+ private SetMultimap<String, Repository> repositoriesByLang;
+
+ void register(RuleDefinitions.Context context) {
+ ImmutableSortedSet.Builder<Repository> listBuilder = ImmutableSortedSet.naturalOrder();
+ ImmutableSetMultimap.Builder<String, Repository> langBuilder = ImmutableSetMultimap.builder();
+ ImmutableMap.Builder<String, Repository> keyBuilder = ImmutableMap.builder();
+ for (RuleDefinitions.Repository repoDef : context.repositories()) {
+ Repository repository = new Repository(repoDef);
+ listBuilder.add(repository);
+ langBuilder.put(repository.language(), repository);
+ keyBuilder.put(repository.key(), repository);
+ }
+ repositories = listBuilder.build();
+ repositoriesByLang = langBuilder.build();
+ repositoriesByKey = keyBuilder.build();
+ }
+
+ @CheckForNull
+ public Repository repository(String key) {
+ return repositoriesByKey.get(key);
+ }
+
+ /**
+ * Repositories for a given language, sorted by name.
+ */
+ public Collection<Repository> repositoriesForLang(String lang) {
+ return repositoriesByLang.get(lang);
+ }
+
+ /**
+ * Repositories, sorted by name.
+ */
+ public Collection<Repository> repositories() {
+ return repositories;
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.rules;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.SetMultimap;
-import org.sonar.api.ServerComponent;
-import org.sonar.api.rules.RuleRepository;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-public final class RulesConsole implements ServerComponent {
-
- private List<RuleRepository> repositories = Lists.newArrayList();
- private Map<String, RuleRepository> repositoryByKey = Maps.newHashMap();
- private SetMultimap<String, RuleRepository> repositoriesByLanguage = HashMultimap.create();
-
-
- public RulesConsole(RuleRepository[] repositories) {
- initRepositories(repositories);
- }
-
- private void initRepositories(RuleRepository[] repositories) {
- this.repositories.addAll(Arrays.asList(repositories));
- for (RuleRepository repository : this.repositories) {
- if (!repositoryByKey.containsKey(repository.getKey())) {
- repositoriesByLanguage.put(repository.getLanguage(), repository);
- repositoryByKey.put(repository.getKey(), repository);
- }
- }
- }
-
- public Set<RuleRepository> getRepositoriesByLanguage(String language) {
- return repositoriesByLanguage.get(language);
- }
-
- public List<RuleRepository> getRepositories() {
- return repositories;
- }
-
- public RuleRepository getRepository(String key) {
- return repositoryByKey.get(key);
- }
-}
import org.sonar.core.template.LoadedTemplateDto;
import org.sonar.jpa.session.DatabaseSessionFactory;
import org.sonar.server.platform.PersistentSettings;
+import org.sonar.server.rule.RuleRegistration;
import org.sonar.server.rule.RuleRegistry;
import java.util.*;
RuleRegistry ruleRegistry,
LoadedTemplateDao loadedTemplateDao,
DatabaseSessionFactory sessionFactory,
- RegisterRules registerRulesBefore) {
+ RuleRegistration registerRulesBefore) {
this.settings = settings;
this.ruleFinder = ruleFinder;
this.ruleRegistry = ruleRegistry;
RuleRegistry ruleRegistry,
LoadedTemplateDao loadedTemplateDao,
DatabaseSessionFactory sessionFactory,
- RegisterRules registerRulesBefore) {
+ RuleRegistration registerRulesBefore) {
this(Collections.<ProfileDefinition>emptyList(), settings, ruleFinder, ruleRegistry, loadedTemplateDao, sessionFactory, registerRulesBefore);
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.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.Maps;
-import com.google.common.collect.Multimap;
-import org.apache.commons.lang.StringUtils;
-import org.apache.ibatis.session.SqlSession;
-import org.elasticsearch.common.collect.Lists;
-import org.elasticsearch.common.collect.Sets;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleParam;
-import org.sonar.api.rules.RuleRepository;
-import org.sonar.api.utils.SonarException;
-import org.sonar.api.utils.TimeProfiler;
-import org.sonar.core.i18n.RuleI18nManager;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.qualityprofile.db.ActiveRuleDao;
-import org.sonar.core.rule.*;
-import org.sonar.server.configuration.ProfilesManager;
-import org.sonar.server.rule.RuleRegistry;
-
-import java.util.*;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
-import static com.google.common.collect.Sets.newHashSet;
-
-public final class RegisterRules {
-
- private static final Logger LOG = LoggerFactory.getLogger(RegisterRules.class);
- private final ProfilesManager profilesManager;
- private final List<RuleRepository> repositories;
- private final RuleI18nManager ruleI18nManager;
- private final RuleRegistry ruleRegistry;
- private final MyBatis myBatis;
- private final RuleDao ruleDao;
- private final ActiveRuleDao activeRuleDao;
- private SqlSession sqlSession;
-
- public RegisterRules(RuleRepository[] repos, RuleI18nManager ruleI18nManager, ProfilesManager profilesManager, RuleRegistry ruleRegistry,
- MyBatis myBatis, RuleDao ruleDao, ActiveRuleDao activeRuleDao) {
- this.profilesManager = profilesManager;
- this.repositories = newArrayList(repos);
- this.ruleI18nManager = ruleI18nManager;
- this.ruleRegistry = ruleRegistry;
- this.myBatis = myBatis;
- this.ruleDao = ruleDao;
- this.activeRuleDao = activeRuleDao;
- }
-
- public RegisterRules(RuleI18nManager ruleI18nManager, ProfilesManager profilesManager, RuleRegistry ruleRegistry, MyBatis myBatis,
- RuleDao ruleDao, ActiveRuleDao activeRuleDao) {
- this(new RuleRepository[0], ruleI18nManager, profilesManager, ruleRegistry, myBatis, ruleDao, activeRuleDao);
- }
-
- public void start() {
- sqlSession = myBatis.openSession();
-
- RulesByRepository existingRules = new RulesByRepository(
- findAllRules(), ruleDao.selectParameters(sqlSession), ruleDao.selectTags(sqlSession));
-
- try {
- List<RuleDto> registeredRules = registerRules(existingRules);
-
- LOG.info("Removing deprecated rules");
- Set<RuleDto> disabledRules = newHashSet();
- disabledRules.addAll(disableDeprecatedRules(existingRules, registeredRules));
- disabledRules.addAll(disableDeprecatedRepositories(existingRules));
- sqlSession.commit();
- removeActiveRulesOnDisabledRules(disabledRules);
-
- Set<RuleDto> allRules = Sets.newHashSet();
- allRules.addAll(existingRules.rules());
- allRules.addAll(registeredRules);
-
- ruleRegistry.bulkRegisterRules(allRules, existingRules.params, existingRules.tags);
- } finally {
- sqlSession.close();
- }
- }
-
- private List<RuleDto> findAllRules() {
- return ruleDao.selectNonManual();
- }
-
- private List<RuleDto> registerRules(RulesByRepository existingRules) {
- TimeProfiler profiler = new TimeProfiler();
- List<RuleDto> registeredRules = newArrayList();
- for (RuleRepository repository : repositories) {
- profiler.start("Register rules [" + repository.getKey() + "/" + StringUtils.defaultString(repository.getLanguage(), "-") + "]");
- registeredRules.addAll(registerRepositoryRules(repository, existingRules));
- profiler.stop();
- }
- // Template rules have to be registered after all rules in order for their parent to be updated.
- registeredRules.addAll(registerTemplateRules(registeredRules, existingRules));
- return registeredRules;
- }
-
- private List<RuleDto> registerRepositoryRules(RuleRepository repository, RulesByRepository existingRules) {
- List<RuleDto> registeredRules = newArrayList();
- Map<String, Rule> ruleByKey = newHashMap();
-
- for (Rule rule : repository.createRules()) {
- updateRuleFromRepositoryInfo(rule, repository);
- validateRule(rule, repository.getKey());
- ruleByKey.put(rule.getKey(), rule);
- }
- LOG.debug(ruleByKey.size() + " rules");
-
- for (RuleDto persistedRule : existingRules.get(repository.getKey())) {
- Rule rule = ruleByKey.get(persistedRule.getRuleKey());
- if (rule != null) {
- updateExistingRule(persistedRule, existingRules, rule);
- ruleDao.update(persistedRule, sqlSession);
- registeredRules.add(persistedRule);
- ruleByKey.remove(rule.getKey());
- }
- }
- registeredRules.addAll(saveNewRules(ruleByKey.values(), existingRules));
- return registeredRules;
- }
-
- /**
- * Template rules do not exists in rule repositories, only in database, they have to be updated from their parent.
- */
- private List<RuleDto> registerTemplateRules(List<RuleDto> registeredRules, RulesByRepository existingRules) {
- List<RuleDto> templateRules = newArrayList();
- for (RuleDto persistedRule : existingRules.rules()) {
- RuleDto parent = existingRules.ruleById(persistedRule.getParentId());
- if (parent != null && registeredRules.contains(parent)) {
- persistedRule.setRepositoryKey(parent.getRepositoryKey());
- persistedRule.setLanguage(parent.getLanguage());
- persistedRule.setStatus(Objects.firstNonNull(persistedRule.getStatus(), Rule.STATUS_READY));
- persistedRule.setCreatedAt(Objects.firstNonNull(persistedRule.getCreatedAt(), new Date()));
- persistedRule.setUpdatedAt(new Date());
-
- ruleDao.update(persistedRule, sqlSession);
- 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);
- }
-
- private void validateRuleRepositoryName(Rule rule, String repositoryKey) {
- String nameFromBundle = ruleI18nManager.getName(repositoryKey, rule.getKey());
- if (!Strings.isNullOrEmpty(nameFromBundle)) {
- rule.setName(nameFromBundle);
- }
- if (Strings.isNullOrEmpty(rule.getName())) {
- throw new SonarException("The following rule (repository: " + repositoryKey + ") must have a name: " + rule);
- }
- }
-
- private void validateRuleDescription(Rule rule, String repositoryKey) {
- String descriptionFromBundle = ruleI18nManager.getDescription(repositoryKey, rule.getKey());
- if (!Strings.isNullOrEmpty(descriptionFromBundle)) {
- rule.setDescription(descriptionFromBundle);
- }
- if (Strings.isNullOrEmpty(rule.getDescription())) {
- if (!Strings.isNullOrEmpty(rule.getName()) && Strings.isNullOrEmpty(ruleI18nManager.getName(repositoryKey, rule.getKey()))) {
- // 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.");
- } else {
- throw new SonarException("The following rule (repository: " + repositoryKey + ") must have a description: " + rule);
- }
- }
- }
-
- private void updateExistingRule(RuleDto persistedRule, RulesByRepository existingRules, Rule rule) {
- LOG.debug("Update existing rule " + rule);
-
- persistedRule.setName(rule.getName());
- persistedRule.setConfigKey(rule.getConfigKey());
- persistedRule.setDescription(rule.getDescription());
- persistedRule.setSeverity(rule.getSeverity().ordinal());
- persistedRule.setCardinality(rule.getCardinality());
- persistedRule.setStatus(rule.getStatus());
- persistedRule.setLanguage(rule.getLanguage());
- persistedRule.setUpdatedAt(new Date());
-
- Collection<RuleParamDto> ruleParams = existingRules.params(persistedRule.getId());
-
- // delete deprecated params
- deleteDeprecatedParameters(ruleParams, rule);
-
- // add new params and update existing params
- updateParameters(persistedRule, ruleParams, rule);
-
- synchronizeTags(persistedRule, existingRules, rule);
- }
-
- private void updateParameters(RuleDto persistedRule, Collection<RuleParamDto> ruleParams, Rule rule) {
- Map<String, RuleParamDto> paramsByKey = Maps.newHashMap();
- for (RuleParamDto param: ruleParams) {
- paramsByKey.put(param.getName(), param);
- }
-
- if (rule.getParams() != null) {
- for (RuleParam param : rule.getParams()) {
- RuleParamDto persistedParam = paramsByKey.get(param.getKey());
- if (persistedParam == null) {
- persistedParam = new RuleParamDto()
- .setRuleId(persistedRule.getId())
- .setName(param.getKey())
- .setType(param.getType());
- ruleDao.insert(persistedParam, sqlSession);
- ruleParams.add(persistedParam);
- }
- String desc = StringUtils.defaultIfEmpty(
- ruleI18nManager.getParamDescription(rule.getRepositoryKey(), rule.getKey(), param.getKey()),
- param.getDescription()
- );
- persistedParam.setDescription(desc);
- persistedParam.setType(param.getType());
- persistedParam.setDefaultValue(param.getDefaultValue());
-
- ruleDao.update(persistedParam, sqlSession);
- }
- }
- }
-
- private void deleteDeprecatedParameters(Collection<RuleParamDto> ruleParams, Rule rule) {
- if (ruleParams != null && !ruleParams.isEmpty()) {
- for (Iterator<RuleParamDto> it = ruleParams.iterator(); it.hasNext(); ) {
- RuleParamDto persistedParam = it.next();
- if (rule.getParam(persistedParam.getName()) == null) {
- it.remove();
- activeRuleDao.deleteParametersWithParamId(persistedParam.getId(), sqlSession);
- ruleDao.deleteParam(persistedParam, sqlSession);
- }
- }
- }
- }
-
- void synchronizeTags(RuleDto persistedRule, RulesByRepository existingRules, Rule rule) {
- Set<String> existingSystemTags = Sets.newHashSet();
- List<RuleTagDto> newTags = Lists.newArrayList();
-
- Iterator<RuleTagDto> tagsIterator = existingRules.tags(persistedRule.getId()).iterator();
- while (tagsIterator.hasNext()) {
- RuleTagDto existingTag = tagsIterator.next();
-
- String existingTagValue = existingTag.getTag();
-
- if (existingTag.getType() == RuleTagType.SYSTEM) {
- existingSystemTags.add(existingTagValue);
- if (! rule.getTags().contains(existingTagValue)) {
- ruleDao.deleteTag(existingTag, sqlSession);
- tagsIterator.remove();
- }
- } else {
- if (rule.getTags().contains(existingTagValue)) {
- // Existing admin tag with same value as system tag must be converted
- ruleDao.deleteTag(existingTag, sqlSession);
- tagsIterator.remove();
- existingSystemTags.add(existingTagValue);
- RuleTagDto newTag = dtoFrom(existingTagValue, persistedRule.getId());
- ruleDao.insert(newTag, sqlSession);
- newTags.add(newTag);
- }
- }
- }
-
- for (String newTag: rule.getTags()) {
- if (! existingSystemTags.contains(newTag)) {
- RuleTagDto newTagDto = dtoFrom(newTag, persistedRule.getId());
- ruleDao.insert(newTagDto, sqlSession);
- newTags.add(newTagDto);
- }
- }
-
- existingRules.tags.putAll(persistedRule.getId(), newTags);
- }
-
-
- private List<RuleDto> saveNewRules(Collection<Rule> rules, RulesByRepository existingRules) {
- List<RuleDto> registeredRules = newArrayList();
- for (Rule rule : rules) {
- LOG.debug("Save new rule " + rule);
- RuleDto newRule = dtoFrom(rule);
- newRule.setCreatedAt(new Date());
- ruleDao.insert(newRule, sqlSession);
- registeredRules.add(newRule);
-
- for(RuleParam param : rule.getParams()) {
- RuleParamDto newParam = dtoFrom(param, newRule.getId());
- ruleDao.insert(newParam, sqlSession);
- existingRules.params.put(newRule.getId(), newParam);
- }
-
- for(String tag : rule.getTags()) {
- RuleTagDto newTag = dtoFrom(tag, newRule.getId());
- ruleDao.insert(newTag, sqlSession);
- existingRules.tags.put(newRule.getId(), newTag);
- }
- }
- return registeredRules;
- }
-
- private Collection<RuleDto> disableDeprecatedRules(RulesByRepository existingRules, List<RuleDto> registeredRules) {
- List<RuleDto> disabledRules = newArrayList();
- for (RuleDto rule : existingRules.rules()) {
- if (!registeredRules.contains(rule)) {
- disableRule(rule);
- disabledRules.add(rule);
- }
- }
- return disabledRules;
- }
-
- private Collection<RuleDto> disableDeprecatedRepositories(RulesByRepository existingRules) {
- List<RuleDto> disabledRules = newArrayList();
- for (final String repositoryKey : existingRules.repositories()) {
- if (!Iterables.any(repositories, new Predicate<RuleRepository>() {
- public boolean apply(RuleRepository input) {
- return input.getKey().equals(repositoryKey);
- }
- })) {
- for (RuleDto rule : existingRules.get(repositoryKey)) {
- disableRule(rule);
- disabledRules.add(rule);
- }
- }
- }
- return disabledRules;
- }
-
- private void disableRule(RuleDto rule) {
- if (!rule.getStatus().equals(Rule.STATUS_REMOVED)) {
- LOG.info("Removing rule " + rule.getRuleKey());
- rule.setStatus(Rule.STATUS_REMOVED);
- rule.setUpdatedAt(new Date());
- ruleDao.update(rule, sqlSession);
- }
- }
-
- private void removeActiveRulesOnDisabledRules(Set<RuleDto> disabledRules) {
- for (RuleDto rule : disabledRules) {
- profilesManager.removeActivatedRules(rule.getId());
- }
- }
-
- static RuleDto dtoFrom(Rule rule) {
- return new RuleDto()
- .setCardinality(rule.getCardinality())
- .setConfigKey(rule.getConfigKey())
- .setDescription(rule.getDescription())
- .setLanguage(rule.getLanguage())
- .setName(rule.getName())
- .setRepositoryKey(rule.getRepositoryKey())
- .setRuleKey(rule.getKey())
- .setSeverity(rule.getSeverity().ordinal())
- .setStatus(rule.getStatus());
- }
-
- static RuleParamDto dtoFrom(RuleParam param, Integer ruleId) {
- return new RuleParamDto()
- .setRuleId(ruleId)
- .setDefaultValue(param.getDefaultValue())
- .setDescription(param.getDescription())
- .setName(param.getKey())
- .setType(param.getType());
- }
-
- static RuleTagDto dtoFrom(String tag, Integer ruleId) {
- return new RuleTagDto()
- .setRuleId(ruleId)
- .setTag(tag)
- .setType(RuleTagType.SYSTEM);
- }
-
- static class RulesByRepository {
- Multimap<String, RuleDto> ruleRepositoryList;
- Map<Integer, RuleDto> rulesById;
- Multimap<Integer, RuleParamDto> params;
- Multimap<Integer, RuleTagDto> tags;
-
- RulesByRepository(List<RuleDto> rules, List<RuleParamDto> params, List<RuleTagDto> tags) {
- ruleRepositoryList = ArrayListMultimap.create();
- rulesById = Maps.newHashMap();
- for (RuleDto rule : rules) {
- ruleRepositoryList.put(rule.getRepositoryKey(), rule);
- rulesById.put(rule.getId(), rule);
- }
- this.params = ArrayListMultimap.create();
- for (RuleParamDto param: params) {
- this.params.put(param.getRuleId(), param);
- }
- this.tags = ArrayListMultimap.create();
- for (RuleTagDto tag: tags) {
- this.tags.put(tag.getRuleId(), tag);
- }
- }
-
- Collection<RuleDto> get(String repositoryKey) {
- return ruleRepositoryList.get(repositoryKey);
- }
-
- Collection<String> repositories() {
- return ruleRepositoryList.keySet();
- }
-
- Collection<RuleDto> rules() {
- return ruleRepositoryList.values();
- }
-
- RuleDto ruleById(Integer id) {
- return rulesById.get(id);
- }
-
- Collection<RuleParamDto> params(Integer ruleId) {
- return params.get(ruleId);
- }
-
- Collection<RuleTagDto> tags(Integer ruleId) {
- return tags.get(ruleId);
- }
- }
-}
import org.sonar.api.utils.ValidationMessages;
import org.sonar.core.technicaldebt.TechnicalDebtModelSynchronizer;
import org.sonar.core.technicaldebt.TechnicalDebtRuleCache;
+import org.sonar.server.rule.RuleRegistration;
public final class RegisterTechnicalDebtModel {
/**
* @param registerRulesBeforeModels used only to be started after the creation of check templates
*/
- public RegisterTechnicalDebtModel(TechnicalDebtModelSynchronizer manager, RuleFinder ruleFinder, RegisterRules registerRulesBeforeModels) {
+ public RegisterTechnicalDebtModel(TechnicalDebtModelSynchronizer manager, RuleFinder ruleFinder, RuleRegistration registerRulesBeforeModels) {
this.manager = manager;
this.ruleFinder = ruleFinder;
}
import org.sonar.api.resources.ResourceType;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.rules.RulePriority;
-import org.sonar.api.rules.RuleRepository;
import org.sonar.api.test.MutableTestPlan;
import org.sonar.api.test.MutableTestable;
import org.sonar.api.test.TestPlan;
import org.sonar.server.platform.ServerSettings;
import org.sonar.server.platform.SettingsChangeNotifier;
import org.sonar.server.plugins.*;
+import org.sonar.server.rule.RuleRepositories;
import org.sonar.server.rules.ProfilesConsole;
-import org.sonar.server.rules.RulesConsole;
import org.sonar.server.user.NewUserNotifier;
import org.sonar.updatecenter.common.PluginReferential;
import org.sonar.updatecenter.common.UpdateCenter;
import org.sonar.updatecenter.common.Version;
import javax.annotation.Nullable;
-
import java.net.InetAddress;
import java.sql.Connection;
-import java.util.*;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
import static com.google.common.collect.Lists.newArrayList;
}
/* PROFILES CONSOLE : RULES AND METRIC THRESHOLDS */
- public List<RuleRepository> getRuleRepositories() {
- return get(RulesConsole.class).getRepositories();
+ public Collection<RuleRepositories.Repository> getRuleRepositories() {
+ return get(RuleRepositories.class).repositories();
}
- public RuleRepository getRuleRepository(String repositoryKey) {
- return get(RulesConsole.class).getRepository(repositoryKey);
+ public RuleRepositories.Repository getRuleRepository(String repositoryKey) {
+ return get(RuleRepositories.class).repository(repositoryKey);
}
- public Set<RuleRepository> getRuleRepositoriesByLanguage(String languageKey) {
- return get(RulesConsole.class).getRepositoriesByLanguage(languageKey);
+ public Collection<RuleRepositories.Repository> getRuleRepositoriesByLanguage(String languageKey) {
+ return get(RuleRepositories.class).repositoriesForLang(languageKey);
}
// TODO move this to QProfiles
public void ruleSeverityChanged(int parentProfileId, int activeRuleId, int oldSeverityId, int newSeverityId, String userName) {
getProfilesManager().ruleSeverityChanged(parentProfileId, activeRuleId, RulePriority.values()[oldSeverityId],
- RulePriority.values()[newSeverityId], userName);
+ RulePriority.values()[newSeverityId], userName);
}
public void ruleDeactivated(int parentProfileId, int deactivatedRuleId, String userName) {
// notifier is null when creating the administrator in the migration script 011.
if (notifier != null) {
notifier.onNewUser(NewUserHandler.Context.builder()
- .setLogin(fields.get("login"))
- .setName(fields.get("name"))
- .setEmail(fields.get("email"))
- .build());
+ .setLogin(fields.get("login"))
+ .setName(fields.get("name"))
+ .setEmail(fields.get("email"))
+ .build());
}
}
init_params()
- @select_repositories = ANY_SELECTION + java_facade.getRuleRepositoriesByLanguage(@profile.language).collect { |repo| [repo.getName(true), repo.getKey()] }.sort
+ @select_repositories = ANY_SELECTION + java_facade.getRuleRepositoriesByLanguage(@profile.language).collect { |repo| [repo.name(), repo.key()] }.sort
@select_priority = ANY_SELECTION + RULE_PRIORITIES
@select_activation = [[message('any'), 'any'], [message('active'), STATUS_ACTIVE], [message('inactive'), STATUS_INACTIVE]]
@select_inheritance = [[message('any'), 'any'], [message('rules_configuration.not_inherited'), 'NOT'], [message('rules_configuration.inherited'), 'INHERITED'],
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.sonar.api.rule.RuleDefinitions;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class RuleDefinitionsLoaderTest {
+ @Test
+ public void no_definitions() {
+ RuleRepositories repositories = new RuleRepositories();
+
+ RuleDefinitions.Context context = new RuleDefinitionsLoader(repositories).load();
+
+ assertThat(context.repositories()).isEmpty();
+ assertThat(repositories.repositories()).isEmpty();
+ }
+
+ @Test
+ public void load_definitions() {
+ RuleRepositories repositories = new RuleRepositories();
+
+ RuleDefinitions.Context context = new RuleDefinitionsLoader(repositories, new RuleDefinitions[]{
+ new FindbugsDefinitions(), new SquidDefinitions()
+ }).load();
+
+ assertThat(context.repositories()).hasSize(2);
+ assertThat(context.repository("findbugs")).isNotNull();
+ assertThat(context.repository("squid")).isNotNull();
+ assertThat(repositories.repositories()).hasSize(2);
+ assertThat(repositories.repository("findbugs")).isNotNull();
+ assertThat(repositories.repository("squid")).isNotNull();
+ }
+
+ static class FindbugsDefinitions implements RuleDefinitions {
+ @Override
+ public void define(Context context) {
+ NewRepository repo = context.newRepository("findbugs", "java");
+ repo.setName("Findbugs");
+ repo.newRule("ABC")
+ .setName("ABC")
+ .setHtmlDescription("Description of ABC");
+ repo.done();
+ }
+ }
+
+ static class SquidDefinitions implements RuleDefinitions {
+ @Override
+ public void define(Context context) {
+ NewRepository repo = context.newRepository("squid", "java");
+ repo.setName("Squid");
+ repo.newRule("DEF")
+ .setName("DEF")
+ .setHtmlDescription("Description of DEF");
+ repo.done();
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.Before;
+import org.junit.Test;
+import org.sonar.api.rule.RuleDefinitions;
+import org.sonar.api.rule.Severity;
+import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.qualityprofile.db.ActiveRuleDao;
+import org.sonar.core.rule.RuleDao;
+import org.sonar.server.configuration.ProfilesManager;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class RuleRegistrationTest extends AbstractDaoTestCase {
+
+ private static final String[] EXCLUDED_COLUMN_NAMES = {
+ "created_at", "updated_at", "note_data", "note_user_login", "note_created_at", "note_updated_at"};
+
+ RuleRegistration task;
+ ProfilesManager profilesManager;
+ RuleRegistry ruleRegistry;
+ MyBatis myBatis;
+ RuleDao ruleDao;
+ ActiveRuleDao activeRuleDao;
+
+ @Before
+ public void before() {
+ profilesManager = mock(ProfilesManager.class);
+ ruleRegistry = mock(RuleRegistry.class);
+ myBatis = getMyBatis();
+ ruleDao = new RuleDao(myBatis);
+ activeRuleDao = new ActiveRuleDao(myBatis);
+ task = new RuleRegistration(new RuleDefinitionsLoader(mock(RuleRepositories.class), new RuleDefinitions[]{new FakeRepository()}),
+ profilesManager, ruleRegistry, myBatis, ruleDao, activeRuleDao);
+ }
+
+ @Test
+ public void should_insert_new_rules() {
+ setupData("shared");
+ task.start();
+
+ checkTables("should_insert_new_rules", EXCLUDED_COLUMN_NAMES, "rules", "rules_parameters", "rule_tags");
+ }
+
+ @Test
+ public void should_update_template_rule_language() {
+ setupData("should_update_template_rule_language");
+ task.start();
+
+ checkTables("should_update_template_rule_language", EXCLUDED_COLUMN_NAMES, "rules");
+ }
+
+ @Test
+ public void should_notify_for_removed_rules() {
+ setupData("shared");
+ task.start();
+
+ verify(profilesManager).removeActivatedRules(1);
+ }
+
+ @Test
+ public void should_reactivate_disabled_rules() {
+ setupData("should_reactivate_disabled_rules");
+ task.start();
+
+ checkTables("should_reactivate_disabled_rules", EXCLUDED_COLUMN_NAMES, "rules");
+
+ assertThat(ruleDao.selectById(1).getUpdatedAt()).isNotNull();
+ }
+
+ @Test
+ public void should_not_reactivate_disabled_template_rules() {
+ setupData("should_not_reactivate_disabled_template_rules");
+ task.start();
+
+ checkTables("should_not_reactivate_disabled_template_rules", EXCLUDED_COLUMN_NAMES, "rules");
+ }
+
+ @Test
+ public void should_disable_deprecated_active_rules() {
+ setupData("should_disable_deprecated_active_rules");
+ task.start();
+
+ checkTables("should_disable_deprecated_active_rules", EXCLUDED_COLUMN_NAMES, "rules");
+ }
+
+ @Test
+ public void should_disable_deprecated_active_rule_params() {
+ setupData("should_disable_deprecated_active_rule_params");
+ task.start();
+
+ checkTables("should_disable_deprecated_active_rule_params", EXCLUDED_COLUMN_NAMES, "rules", "rules_parameters", "active_rules", "active_rule_parameters");
+ }
+
+ @Test
+ public void should_disable_deprecated_rules() {
+ setupData("should_disable_deprecated_rules");
+ task.start();
+
+ checkTables("should_disable_deprecated_rules", EXCLUDED_COLUMN_NAMES, "rules", "rules_parameters");
+ }
+
+ @Test
+ public void should_update_rule_fields() {
+ setupData("updadeRuleFields");
+ task.start();
+
+ checkTables("updadeRuleFields", EXCLUDED_COLUMN_NAMES, "rules", "rules_parameters", "rule_tags");
+ }
+
+ @Test
+ public void should_update_rule_parameters() {
+ setupData("should_update_rule_parameters");
+ task.start();
+
+ checkTables("should_update_rule_parameters", EXCLUDED_COLUMN_NAMES, "rules", "rules_parameters");
+ }
+
+ @Test
+ public void should_not_disable_template_rules_if_parent_is_enabled() {
+ setupData("doNotDisableUserRulesIfParentIsEnabled");
+ task.start();
+
+ checkTables("doNotDisableUserRulesIfParentIsEnabled", EXCLUDED_COLUMN_NAMES, "rules");
+ }
+
+ @Test
+ public void should_disable_template_rules_if_parent_is_disabled() {
+ setupData("disableUserRulesIfParentIsDisabled");
+ task.start();
+
+ checkTables("disableUserRulesIfParentIsDisabled", EXCLUDED_COLUMN_NAMES, "rules");
+ }
+
+ @Test
+ public void should_not_disable_manual_rules() {
+ // the hardcoded repository "manual" is used for manual violations
+ setupData("shouldNotDisableManualRules");
+ task.start();
+
+ checkTables("shouldNotDisableManualRules", EXCLUDED_COLUMN_NAMES, "rules");
+ }
+
+ @Test
+ public void test_high_number_of_rules() {
+ task = new RuleRegistration(new RuleDefinitionsLoader(mock(RuleRepositories.class), new RuleDefinitions[]{new BigRepository()}),
+ profilesManager, ruleRegistry, myBatis, ruleDao, activeRuleDao);
+
+ setupData("shared");
+ task.start();
+
+ // There is already one rule in DB
+ assertThat(ruleDao.selectAll()).hasSize(BigRepository.SIZE + 1);
+ assertThat(ruleDao.selectParameters()).hasSize(BigRepository.SIZE * 20);
+ assertThat(ruleDao.selectTags(getMyBatis().openSession())).hasSize(BigRepository.SIZE * 3);
+ }
+
+ @Test
+ public void should_insert_extended_repositories() {
+ task = new RuleRegistration(new RuleDefinitionsLoader(mock(RuleRepositories.class), new RuleDefinitions[]{
+ new FindbugsRepository(), new FbContribRepository()}),
+ profilesManager, ruleRegistry, myBatis, ruleDao, activeRuleDao);
+
+ setupData("empty");
+ task.start();
+
+ checkTables("should_insert_extended_repositories", EXCLUDED_COLUMN_NAMES, "rules");
+ }
+
+ static class FakeRepository implements RuleDefinitions {
+ @Override
+ public void define(Context context) {
+ NewRepository repo = context.newRepository("fake", "java");
+
+ NewRule rule1 = repo.newRule("rule1")
+ .setName("One")
+ .setHtmlDescription("Description of One")
+ .setDefaultSeverity(Severity.BLOCKER)
+ .setMetadata("config1")
+ .setTags("tag1", "tag3", "tag5");
+ rule1.newParam("param1").setDescription("parameter one").setDefaultValue("default value one");
+ rule1.newParam("param2").setDescription("parameter two").setDefaultValue("default value two");
+
+ repo.newRule("rule2")
+ .setName("Two")
+ .setHtmlDescription("Description of Two")
+ .setDefaultSeverity(Severity.INFO)
+ .setStatus(Status.DEPRECATED);
+ repo.done();
+ }
+ }
+
+ static class BigRepository implements RuleDefinitions {
+ static final int SIZE = 500;
+
+ @Override
+ public void define(Context context) {
+ NewRepository repo = context.newRepository("big", "java");
+ for (int i = 0; i < SIZE; i++) {
+ NewRule rule = repo.newRule("rule" + i)
+ .setName("name of " + i)
+ .setHtmlDescription("description of " + i)
+ .setDefaultSeverity(Severity.BLOCKER)
+ .setMetadata("config1")
+ .setTags("tag1", "tag3", "tag5");
+ for (int j = 0; j < 20; j++) {
+ rule.newParam("param" + j);
+ }
+
+ }
+ repo.done();
+ }
+ }
+
+ static class FindbugsRepository implements RuleDefinitions {
+ @Override
+ public void define(Context context) {
+ NewRepository repo = context.newRepository("findbugs", "java");
+ repo.newRule("rule1")
+ .setName("Rule One")
+ .setHtmlDescription("Description of Rule One");
+ repo.done();
+ }
+ }
+
+ static class FbContribRepository implements RuleDefinitions {
+ @Override
+ public void define(Context context) {
+ NewExtendedRepository repo = context.extendRepository("findbugs", "java");
+ repo.newRule("rule2")
+ .setName("Rule Two")
+ .setHtmlDescription("Description of Rule Two");
+ repo.done();
+ }
+ }
+}
+
+
+
+
import static org.elasticsearch.index.query.FilterBuilders.hasParentFilter;
import static org.elasticsearch.index.query.FilterBuilders.termFilter;
import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
List<RuleDto> rules = ImmutableList.of(rule1, rule2);
assertThat(esSetup.exists("rules", "rule", "3")).isTrue();
- when(ruleDao.selectNonManual()).thenReturn(rules);
+ when(ruleDao.selectNonManual(any(SqlSession.class))).thenReturn(rules);
final Multimap<Integer, RuleParamDto> params = ArrayListMultimap.create();
final Multimap<Integer, RuleTagDto> tags = ArrayListMultimap.create();
registry.bulkRegisterRules(rules, params, tags);
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.sonar.api.rule.RuleDefinitions;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class RuleRepositoriesTest {
+ @Test
+ public void should_register_repositories() {
+ RuleDefinitions.Context context = new RuleDefinitions.Context();
+ new SquidDefinitions().define(context);
+ new FindbugsDefinitions().define(context);
+
+ RuleRepositories repositories = new RuleRepositories();
+ repositories.register(context);
+
+ RuleRepositories.Repository findbugs = repositories.repository("findbugs");
+ assertThat(findbugs).isNotNull();
+ assertThat(findbugs.key()).isEqualTo("findbugs");
+ assertThat(findbugs.name()).isEqualTo("Findbugs");
+ assertThat(findbugs.language()).isEqualTo("java");
+ assertThat(findbugs.getKey()).isEqualTo("findbugs");
+ assertThat(findbugs.getName()).isEqualTo("Findbugs");
+ assertThat(findbugs.getLanguage()).isEqualTo("java");
+
+ RuleRepositories.Repository squid = repositories.repository("squid");
+ assertThat(squid).isNotNull();
+ assertThat(squid.key()).isEqualTo("squid");
+ assertThat(squid.name()).isEqualTo("Squid");
+ assertThat(squid.language()).isEqualTo("java");
+
+ assertThat(repositories.repositories()).containsOnly(findbugs, squid);
+ assertThat(repositories.repositoriesForLang("java")).containsOnly(findbugs, squid);
+
+ // test equals() and hashCode()
+ assertThat(findbugs).isEqualTo(findbugs).isNotEqualTo(squid).isNotEqualTo("findbugs").isNotEqualTo(null);
+ }
+
+ static class FindbugsDefinitions implements RuleDefinitions {
+ @Override
+ public void define(Context context) {
+ NewRepository repo = context.newRepository("findbugs", "java");
+ repo.setName("Findbugs");
+ repo.newRule("ABC")
+ .setName("ABC")
+ .setHtmlDescription("Description of ABC");
+ repo.done();
+ }
+ }
+
+ static class SquidDefinitions implements RuleDefinitions {
+ @Override
+ public void define(Context context) {
+ NewRepository repo = context.newRepository("squid", "java");
+ repo.setName("Squid");
+ repo.newRule("DEF")
+ .setName("DEF")
+ .setHtmlDescription("Description of DEF");
+ repo.done();
+ }
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.rules;
-
-import org.hamcrest.Matchers;
-import org.junit.Test;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleRepository;
-
-import java.util.Collections;
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-
-public class RulesConsoleTest {
- @Test
- public void shouldIgnoreRepositoryExtensions() throws Exception {
- RuleRepository[] repositories = new RuleRepository[]{
- new FakeRepository("findbugs", "java"),
- new FakeRepository("findbugs", "java"), // for example fb-contrib
- };
- RulesConsole console = new RulesConsole(repositories);
-
- assertThat(console.getRepository("findbugs"), not(Matchers.nullValue()));
- assertThat(console.getRepositoriesByLanguage("java").size(), is(1));
- }
-
- private static class FakeRepository extends RuleRepository {
-
- private FakeRepository(String key, String language) {
- super(key, language);
- }
-
- @Override
- public List<Rule> createRules() {
- return Collections.emptyList();
- }
- }
-}
-
-
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.startup;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RulePriority;
-import org.sonar.api.rules.RuleRepository;
-import org.sonar.api.utils.SonarException;
-import org.sonar.core.i18n.RuleI18nManager;
-import org.sonar.core.persistence.AbstractDaoTestCase;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.qualityprofile.db.ActiveRuleDao;
-import org.sonar.core.rule.RuleDao;
-import org.sonar.server.configuration.ProfilesManager;
-import org.sonar.server.rule.RuleRegistry;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.*;
-
-public class RegisterRulesTest extends AbstractDaoTestCase {
-
- private static final String[] EXCLUDED_COLUMN_NAMES = {
- "created_at", "updated_at", "note_data", "note_user_login", "note_created_at", "note_updated_at"};
-
- RegisterRules task;
- ProfilesManager profilesManager;
- RuleRegistry ruleRegistry;
- RuleI18nManager ruleI18nManager;
- MyBatis myBatis;
- RuleDao ruleDao;
- ActiveRuleDao activeRuleDao;
-
- @Before
- public void init() {
- profilesManager = mock(ProfilesManager.class);
- ruleRegistry = mock(RuleRegistry.class);
- ruleI18nManager = mock(RuleI18nManager.class);
- myBatis = getMyBatis();
- ruleDao = new RuleDao(myBatis);
- activeRuleDao = new ActiveRuleDao(myBatis);
- task = new RegisterRules(new RuleRepository[]{new FakeRepository()}, ruleI18nManager, profilesManager, ruleRegistry, myBatis, ruleDao, activeRuleDao);
- }
-
- @Test
- public void should_save_new_repositories() {
- setupData("shared");
- task.start();
-
- checkTables("should_save_new_repositories", EXCLUDED_COLUMN_NAMES, "rules", "rules_parameters", "rule_tags");
- }
-
- @Test
- public void should_update_template_rule() {
- setupData("should_update_template_rule_language");
- task.start();
-
- checkTables("should_update_template_rule_language", EXCLUDED_COLUMN_NAMES, "rules");
- }
-
- @Test
- public void should_notify_for_removed_rules() {
- setupData("shared");
- task.start();
-
- verify(profilesManager).removeActivatedRules(anyInt());
- }
-
- @Test
- public void should_reactivate_disabled_rules() {
- setupData("reactivateDisabledRules");
- task.start();
-
- checkTables("reactivateDisabledRules", EXCLUDED_COLUMN_NAMES, "rules");
-
- assertThat(ruleDao.selectById(1).getUpdatedAt()).isNotNull();
- }
-
- @Test
- public void should_not_reactivate_disabled_template_rules() {
- setupData("should_reactivate_disabled_template_rules");
- task.start();
-
- checkTables("should_reactivate_disabled_template_rules", EXCLUDED_COLUMN_NAMES, "rules");
- }
-
- @Test
- public void should_not_update_already_disabled_rules() {
- setupData("notUpdateAlreadyDisabledRule");
- task.start();
-
- checkTables("should_save_new_repositories", EXCLUDED_COLUMN_NAMES, "rules");
-
- assertThat(ruleDao.selectById(1).getUpdatedAt()).isNull();
- }
-
- @Test
- public void should_disable_deprecated_active_rules() {
- setupData("disableDeprecatedActiveRules");
- task.start();
-
- checkTables("disableDeprecatedActiveRules", EXCLUDED_COLUMN_NAMES, "rules");
- }
-
- @Test
- public void should_disable_deprecated_active_rule_parameters() {
- setupData("disableDeprecatedActiveRuleParameters");
- task.start();
-
- checkTables("disableDeprecatedActiveRuleParameters", EXCLUDED_COLUMN_NAMES, "rules", "rules_parameters", "active_rules", "active_rule_parameters");
- }
-
- @Test
- public void should_disable_deprecated_rules() {
- setupData("disableDeprecatedRules");
- task.start();
-
- checkTables("disableDeprecatedRules", EXCLUDED_COLUMN_NAMES, "rules", "rules_parameters");
- }
-
- @Test
- public void should_update_rule_fields() {
- setupData("updadeRuleFields");
- task.start();
-
- checkTables("updadeRuleFields", EXCLUDED_COLUMN_NAMES, "rules", "rules_parameters", "rule_tags");
- }
-
- @Test
- public void should_store_bundle_name_and_description_in_database() {
- setupData("updadeRuleFields");
- String i18nName = "The One";
- String i18nDescription = "The Description of One";
- when(ruleI18nManager.getName("fake", "rule1")).thenReturn(i18nName);
- when(ruleI18nManager.getDescription("fake", "rule1")).thenReturn(i18nDescription);
- task.start();
-
- checkTables("should_store_bundle_name_and_description_in_database", EXCLUDED_COLUMN_NAMES, "rules");
- }
-
- @Test
- public void should_update_rule_parameters() {
- setupData("updateRuleParameters");
- task.start();
-
- checkTables("updateRuleParameters", EXCLUDED_COLUMN_NAMES, "rules", "rules_parameters");
- }
-
- @Test
- public void should_not_disable_template_rules_if_parent_is_enabled() {
- setupData("doNotDisableUserRulesIfParentIsEnabled");
- task.start();
-
- checkTables("doNotDisableUserRulesIfParentIsEnabled", EXCLUDED_COLUMN_NAMES, "rules");
- }
-
- @Test
- public void should_disable_template_rules_if_parent_is_disabled() {
- setupData("disableUserRulesIfParentIsDisabled");
- task.start();
-
- checkTables("disableUserRulesIfParentIsDisabled", EXCLUDED_COLUMN_NAMES, "rules");
- }
-
- @Test
- public void should_not_disable_manual_rules() {
- // the hardcoded repository "manual" is used for manual violations
- setupData("shouldNotDisableManualRules");
- task.start();
-
- checkTables("shouldNotDisableManualRules", EXCLUDED_COLUMN_NAMES, "rules");
- }
-
- @Test
- public void volume_testing() {
- task = new RegisterRules(new RuleRepository[]{new VolumeRepository()}, ruleI18nManager, profilesManager, ruleRegistry, myBatis, ruleDao, activeRuleDao);
- setupData("shared");
- task.start();
-
- // There is already one rule in DB
- assertThat(ruleDao.selectAll()).hasSize(VolumeRepository.SIZE + 1);
- }
-
- // SONAR-3305
- @Test
- public void should_fail_with_rule_without_name() throws Exception {
- task = new RegisterRules(new RuleRepository[]{new RuleWithoutNameRepository()}, ruleI18nManager, profilesManager, ruleRegistry, myBatis, ruleDao, activeRuleDao);
- setupData("shared");
-
- // the rule has no name, it should fail
- try {
- task.start();
- fail("Rule must have a name");
- } catch (SonarException e) {
- assertThat(e.getMessage()).contains("must have a name");
- }
-
- // now it is ok, the rule has a name in the English bundle
- when(ruleI18nManager.getName(anyString(), anyString())).thenReturn("Name");
- when(ruleI18nManager.getDescription(anyString(), anyString())).thenReturn("Description");
- task.start();
- }
-
- // SONAR-3769
- @Test
- public void should_fail_with_rule_with_blank_name() throws Exception {
- task = new RegisterRules(new RuleRepository[]{new RuleWithoutNameRepository()}, ruleI18nManager, profilesManager, ruleRegistry, myBatis, ruleDao, activeRuleDao);
- setupData("shared");
-
- // the rule has no name, it should fail
- try {
- task.start();
- fail("Rule must have a name");
- } catch (SonarException e) {
- assertThat(e.getMessage()).contains("must have a name");
- }
- }
-
- // SONAR-3305
- @Test
- public void should_fail_with_rule_without_description() throws Exception {
- when(ruleI18nManager.getName(anyString(), anyString())).thenReturn("Name");
- task = new RegisterRules(new RuleRepository[]{new RuleWithoutDescriptionRepository()}, ruleI18nManager, profilesManager, ruleRegistry, myBatis, ruleDao, activeRuleDao);
- setupData("shared");
-
- // the rule has no name, it should fail
- try {
- task.start();
- fail("Rule must have a description");
- } catch (SonarException e) {
- assertThat(e.getMessage()).contains("must have a description");
- }
-
- // now it is ok, the rule has a name & a description in the English bundle
- when(ruleI18nManager.getName(anyString(), anyString())).thenReturn("Name");
- when(ruleI18nManager.getDescription(anyString(), anyString())).thenReturn("Description");
- task.start();
- }
-
- // http://jira.codehaus.org/browse/SONAR-3722
- @Test
- public void should_fail_with_rule_without_name_in_bundle() throws Exception {
- task = new RegisterRules(new RuleRepository[]{new RuleWithoutDescriptionRepository()}, ruleI18nManager, profilesManager, ruleRegistry, myBatis, ruleDao, activeRuleDao);
- setupData("shared");
-
- // the rule has no name, it should fail
- try {
- task.start();
- fail("Rule must have a description");
- } catch (SonarException e) {
- assertThat(e.getMessage()).contains("No description found for the rule 'Rule 1' (repository: rule-without-description-repo) " +
- "because the entry 'rule.rule-without-description-repo.rule1.name' is missing from the bundle.");
- }
- }
-
-}
-
-class FakeRepository extends RuleRepository {
- public FakeRepository() {
- super("fake", "java");
- }
-
- @Override
- public List<Rule> createRules() {
- Rule rule1 = Rule.create("fake", "rule1", "One");
- rule1.setDescription("Description of One");
- rule1.setSeverity(RulePriority.BLOCKER);
- rule1.setConfigKey("config1");
- rule1.createParameter("param1").setDescription("parameter one").setDefaultValue("default value one");
- rule1.createParameter("param2").setDescription("parameter two").setDefaultValue("default value two");
- rule1.setTags("tag1", "tag3", "tag5");
-
- Rule rule2 = Rule.create("fake", "rule2", "Two");
- rule2.setDescription("Description of Two");
- rule2.setSeverity(RulePriority.INFO);
- rule2.setStatus(Rule.STATUS_DEPRECATED);
-
- return Arrays.asList(rule1, rule2);
- }
-}
-
-class RuleWithoutNameRepository extends RuleRepository {
- public RuleWithoutNameRepository() {
- super("rule-without-name-repo", "java");
- }
-
- @Override
- public List<Rule> createRules() {
- // Rules must not have empty name
- Rule rule1 = Rule.create("fake", "rule1", null);
- return Arrays.asList(rule1);
- }
-}
-
-class RuleWithoutDescriptionRepository extends RuleRepository {
- public RuleWithoutDescriptionRepository() {
- super("rule-without-description-repo", "java");
- }
-
- @Override
- public List<Rule> createRules() {
- // Rules must not have empty description
- Rule rule1 = Rule.create("fake", "rule1", "Rule 1");
- return Arrays.asList(rule1);
- }
-}
-
-class VolumeRepository extends RuleRepository {
- static final int SIZE = 500;
-
- public VolumeRepository() {
- super("volume", "java");
- }
-
- @Override
- public List<Rule> createRules() {
- List<Rule> rules = new ArrayList<Rule>();
- for (int i = 0; i < SIZE; i++) {
- Rule rule = Rule.create("volume", "rule" + i, "name of " + i);
- rule.setDescription("description of " + i);
- rule.setSeverity(RulePriority.BLOCKER);
- for (int j = 0; j < 20; j++) {
- rule.createParameter("param" + j);
- }
- rules.add(rule);
- }
- return rules;
- }
-}
-
-class RuleWithUnkownStatusRepository extends RuleRepository {
- public RuleWithUnkownStatusRepository() {
- super("rule-with-unknwon-status-repo", "java");
- }
-
- @Override
- public List<Rule> createRules() {
- Rule rule1 = Rule.create("fake", "rule1", "rule1").setDescription("Description").setStatus("UNKNOWN");
- return Arrays.asList(rule1);
- }
-}
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="disabled_rule" plugin_name="fake" plugin_config_key="[null]" name="Disabled rule" description="[null]"
+ status="REMOVED" priority="4" cardinality="MULTIPLE" parent_id="[null]" language="[null]"/>
+
+ <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="1" language="[null]"/>
+
+ <rules id="3" plugin_rule_key="disabled_rule2" plugin_name="fake" plugin_config_key="old_config_key2" name="old name2" description="old description2"
+ status="REMOVED" priority="1" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
+
+ <rules id="4" plugin_rule_key="template_rule2" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="3" language="[null]"/>
+
+ <rules id="5" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="6" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <!-- Rule as been removed -->
+ <rules id="1" plugin_rule_key="disabled_rule" plugin_name="fake" plugin_config_key="[null]" name="Disabled rule" description="[null]"
+ status="REMOVED" priority="4" cardinality="MULTIPLE" parent_id="[null]"/>
+
+ <!-- user rule duplicated from rule 1. It is currently enabled. -->
+ <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="1"/>
+
+ <!-- This rule will be removed... -->
+ <rules id="3" plugin_rule_key="disabled_rule2" plugin_name="fake" plugin_config_key="old_config_key2" name="old name2" description="old description2"
+ status="READY" priority="1" cardinality="SINGLE" parent_id="[null]" />
+
+ <!-- ...so this template will be removed too -->
+ <rules id="4" plugin_rule_key="template_rule2" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="3"/>
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="1" language="java"/>
+
+ <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="[null]" name="Rule one" description="[null]"
+ status="READY" priority="4" cardinality="MULTIPLE" parent_id="[null]"/>
+
+ <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="1"/>
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset></dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="PerformanceIssue" plugin_name="manual" plugin_config_key="[null]" name="Performance Issue" description="[null]"
+ status="READY" priority="[null]" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
+
+ <rules id="2" plugin_rule_key="IllegalExceptionCheck" plugin_name="checkstyle" plugin_config_key="[null]" name="Illegal Exception" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
+
+ <rules id="3" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="4" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="PerformanceIssue" plugin_name="manual" plugin_config_key="[null]" name="Performance Issue" description="[null]"
+ status="READY" priority="[null]" cardinality="SINGLE" parent_id="[null]"/>
+
+ <rules id="2" plugin_rule_key="IllegalExceptionCheck" plugin_name="checkstyle" plugin_config_key="[null]" name="Illegal Exception" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules_parameters id="1" rule_id="1" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
+ <rules_parameters id="2" rule_id="1" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
+
+ <rules_profiles id="1" version="1" used_profile="true" name="profile name" language="java" />
+ <active_rules id="1" rule_id="1" profile_id="1" failure_level="4" inheritance="[null]" />
+ <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="one" rules_parameter_key="[null]"/>
+ <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" value="two" rules_parameter_key="[null]"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="old_config_key" name="old name" description="old description"
+ status="READY" priority="2" cardinality="SINGLE" parent_id="[null]" />
+
+ <rules_parameters id="1" rule_id="1" name="param1" description="[null]" param_type="STRING"/>
+ <rules_parameters id="2" rule_id="1" name="param2" description="[null]" param_type="STRING"/>
+
+ <!-- to be removed -->
+ <rules_parameters id="3" rule_id="1" name="param3" description="[null]" param_type="STRING"/>
+
+
+ <rules_profiles id="1" version="1" used_profile="true" name="profile name" language="java" />
+ <active_rules id="1" rule_id="1" profile_id="1" failure_level="4" />
+ <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="one" />
+ <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" value="two" />
+
+ <!-- to be removed -->
+ <active_rule_parameters id="3" active_rule_id="1" rules_parameter_id="3" value="three" />
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
+
+ <rules id="2" plugin_rule_key="deprecated" plugin_name="fake" plugin_config_key="[null]" name="Deprecated fake" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
+
+ <rules id="3" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="4" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
+
+ <rules id="2" plugin_rule_key="deprecated" plugin_name="fake" plugin_config_key="[null]" name="Deprecated fake" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
+
+ <rules_parameters id="1" rule_id="1" name="deprecated-prop" description="[null]" param_type="STRING"/>
+
+ <rules_profiles id="1" version="1" used_profile="true" name="sonar way" language="java" />
+ <active_rules id="1" rule_id="1" profile_id="1" failure_level="4" />
+ <active_rules id="2" rule_id="2" profile_id="1" failure_level="0" />
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
+
+ <rules id="2" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+ <rules_parameters id="1" rule_id="2" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
+ <rules_parameters id="2" rule_id="2" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
+ <rule_tags id="1" rule_id="2" tag="tag1" tag_type="SYSTEM"/>
+ <rule_tags id="2" rule_id="2" tag="tag3" tag_type="SYSTEM"/>
+ <rule_tags id="3" rule_id="2" tag="tag5" tag_type="SYSTEM"/>
+
+ <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
+
+ <rules id="2" plugin_rule_key="deprecated" plugin_name="fake" plugin_config_key="[null]" name="Deprecated fake" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
+
+ <rules_parameters id="1" rule_id="1" name="deprecated-prop" description="[null]" param_type="STRING" default_value="[null]"/>
+
+ <rules id="3" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules_parameters id="2" rule_id="3" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
+ <rules_parameters id="3" rule_id="3" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
+
+ <rules id="4" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
+
+ <rules id="2" plugin_rule_key="deprecated" plugin_name="fake" plugin_config_key="[null]" name="Deprecated fake" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
+
+ <rules_parameters id="1" rule_id="1" name="deprecated-prop" description="[null]" param_type="STRING"/>
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="findbugs" plugin_config_key="[null]" name="Rule One" description="Description of Rule One"
+ status="READY" priority="2" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="2" plugin_rule_key="rule2" plugin_name="findbugs" plugin_config_key="[null]" name="Rule Two" description="Description of Rule Two"
+ status="READY" priority="2" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
+
+ <rules id="2" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+ <rules_parameters id="1" rule_id="2" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
+ <rules_parameters id="2" rule_id="2" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
+ <rule_tags id="1" rule_id="2" tag="tag1" tag_type="SYSTEM"/>
+ <rule_tags id="2" rule_id="2" tag="tag3" tag_type="SYSTEM"/>
+ <rule_tags id="3" rule_id="2" tag="tag5" tag_type="SYSTEM"/>
+
+ <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="1" language="java"/>
+
+ <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="1" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="[null]" name="Old name" description="Old description"
+ status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="The One" description="The Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+ <rules_parameters id="1" rule_id="1" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
+ <rules_parameters id="3" rule_id="1" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
+
+ <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="old_config_key" name="old name" description="old description"
+ status="READY" priority="2" cardinality="SINGLE" parent_id="[null]"/>
+
+ <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="old_config_key2" name="old name2" description="old description2"
+ status="READY" priority="1" cardinality="SINGLE" parent_id="[null]"/>
+
+ <rules_parameters id="1" rule_id="1" name="param1" description="old description" param_type="STRING"/>
+ <rules_parameters id="2" rule_id="1" name="deprecated_param" description="deprecated param to be removed" param_type="STRING"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <!-- Instance of old rule 1 :/ -->
+ <rules id="2" plugin_rule_key="template_rule1" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="1" language="java"/>
+
+ <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <!-- Template of old rule 3 :/ -->
+ <rules id="4" plugin_rule_key="template_rule2" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="DEPRECATED" priority="4" cardinality="SINGLE" parent_id="3" language="java"/>
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="[null]" name="Rule one" description="[null]"
+ status="READY" priority="4" cardinality="MULTIPLE" parent_id="[null]" language="[null]"/>
+
+ <!-- Instance of rule 1 -->
+ <rules id="2" plugin_rule_key="template_rule1" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="1" language="[null]"/>
+
+ <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="old_config_key2" name="old name2" description="old description2"
+ status="DEPRECATED" priority="1" cardinality="MULTIPLE" parent_id="[null]" />
+
+ <!-- Instance of rule 3 -->
+ <rules id="4" plugin_rule_key="template_rule2" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="3"/>
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
+ status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+ <rules_parameters id="1" rule_id="1" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
+ <rules_parameters id="2" rule_id="1" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
+
+ <rule_tags id="1" rule_id="1" tag="tag1" tag_type="SYSTEM"/>
+ <rule_tags id="4" rule_id="1" tag="tag4" tag_type="ADMIN"/>
+ <rule_tags id="5" rule_id="1" tag="tag3" tag_type="SYSTEM"/>
+ <rule_tags id="6" rule_id="1" tag="tag5" tag_type="SYSTEM"/>
+
+ <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="[null]" name="Two" description="Description of Two"
+ status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="old_config_key" name="old name" description="old description"
+ status="READY" priority="2" cardinality="SINGLE" parent_id="[null]" />
+
+ <rules_parameters id="1" rule_id="1" name="param1" description="[null]" param_type="STRING"/>
+
+ <rule_tags id="1" rule_id="1" tag="tag1" tag_type="SYSTEM"/>
+ <rule_tags id="2" rule_id="1" tag="tag2" tag_type="SYSTEM"/>
+ <rule_tags id="3" rule_id="1" tag="tag3" tag_type="ADMIN"/>
+ <rule_tags id="4" rule_id="1" tag="tag4" tag_type="ADMIN"/>
+
+ <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="old_config_key2" name="old name2" description="old description2"
+ status="READY" priority="1" cardinality="SINGLE" parent_id="[null]" />
+
+
+</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules_parameters id="1" rule_id="1" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
- <rules_parameters id="2" rule_id="1" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
-
- <rules_profiles id="1" version="1" used_profile="true" name="profile name" language="java" />
- <active_rules id="1" rule_id="1" profile_id="1" failure_level="4" inheritance="[null]" />
- <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="one" rules_parameter_key="[null]"/>
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" value="two" rules_parameter_key="[null]"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="old_config_key" name="old name" description="old description"
- status="READY" priority="2" cardinality="SINGLE" parent_id="[null]" />
-
- <rules_parameters id="1" rule_id="1" name="param1" description="[null]" param_type="STRING"/>
- <rules_parameters id="2" rule_id="1" name="param2" description="[null]" param_type="STRING"/>
-
- <!-- to be removed -->
- <rules_parameters id="3" rule_id="1" name="param3" description="[null]" param_type="STRING"/>
-
-
- <rules_profiles id="1" version="1" used_profile="true" name="profile name" language="java" />
- <active_rules id="1" rule_id="1" profile_id="1" failure_level="4" />
- <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" value="one" />
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" value="two" />
-
- <!-- to be removed -->
- <active_rule_parameters id="3" active_rule_id="1" rules_parameter_id="3" value="three" />
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
-
- <rules id="2" plugin_rule_key="deprecated" plugin_name="fake" plugin_config_key="[null]" name="Deprecated fake" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
-
- <rules id="3" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules id="4" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="2" plugin_rule_key="deprecated" plugin_name="fake" plugin_config_key="[null]" name="Deprecated fake" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
-
- <rules_parameters id="1" rule_id="1" name="deprecated-prop" description="[null]" param_type="STRING"/>
-
- <rules_profiles id="1" version="1" used_profile="true" name="sonar way" language="java" />
- <active_rules id="1" rule_id="1" profile_id="1" failure_level="4" />
- <active_rules id="2" rule_id="2" profile_id="1" failure_level="0" />
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
-
- <rules id="2" plugin_rule_key="deprecated" plugin_name="fake" plugin_config_key="[null]" name="Deprecated fake" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
-
- <rules_parameters id="1" rule_id="1" name="deprecated-prop" description="[null]" param_type="STRING" default_value="[null]"/>
-
- <rules id="3" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules_parameters id="2" rule_id="3" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
- <rules_parameters id="3" rule_id="3" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
-
- <rules id="4" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="2" plugin_rule_key="deprecated" plugin_name="fake" plugin_config_key="[null]" name="Deprecated fake" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
-
- <rules_parameters id="1" rule_id="1" name="deprecated-prop" description="[null]" param_type="STRING"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="disabled_rule" plugin_name="fake" plugin_config_key="[null]" name="Disabled rule" description="[null]"
- status="REMOVED" priority="4" cardinality="MULTIPLE" parent_id="[null]" language="[null]"/>
-
- <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="1" language="[null]"/>
-
- <rules id="3" plugin_rule_key="disabled_rule2" plugin_name="fake" plugin_config_key="old_config_key2" name="old name2" description="old description2"
- status="REMOVED" priority="1" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
-
- <rules id="4" plugin_rule_key="template_rule2" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="3" language="[null]"/>
-
- <rules id="5" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules id="6" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <!-- Rule as been removed -->
- <rules id="1" plugin_rule_key="disabled_rule" plugin_name="fake" plugin_config_key="[null]" name="Disabled rule" description="[null]"
- status="REMOVED" priority="4" cardinality="MULTIPLE" parent_id="[null]"/>
-
- <!-- user rule duplicated from rule 1. It is currently enabled. -->
- <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="1"/>
-
- <!-- This rule will be removed... -->
- <rules id="3" plugin_rule_key="disabled_rule2" plugin_name="fake" plugin_config_key="old_config_key2" name="old name2" description="old description2"
- status="READY" priority="1" cardinality="SINGLE" parent_id="[null]" />
-
- <!-- ...so this template will be removed too -->
- <rules id="4" plugin_rule_key="template_rule2" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="3"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="1" language="java"/>
-
- <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="[null]" name="Rule one" description="[null]"
- status="READY" priority="4" cardinality="MULTIPLE" parent_id="[null]"/>
-
- <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="1"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="PerformanceIssue" plugin_name="manual" plugin_config_key="[null]" name="Performance Issue" description="[null]"
- status="READY" priority="[null]" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
-
- <rules id="2" plugin_rule_key="IllegalExceptionCheck" plugin_name="checkstyle" plugin_config_key="[null]" name="Illegal Exception" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
-
- <rules id="3" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules id="4" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="PerformanceIssue" plugin_name="manual" plugin_config_key="[null]" name="Performance Issue" description="[null]"
- status="READY" priority="[null]" cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="2" plugin_rule_key="IllegalExceptionCheck" plugin_name="checkstyle" plugin_config_key="[null]" name="Illegal Exception" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
-
- <rules id="2" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
- <rules_parameters id="1" rule_id="2" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
- <rules_parameters id="2" rule_id="2" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
- <rule_tags id="1" rule_id="2" tag="tag1" tag_type="SYSTEM"/>
- <rule_tags id="2" rule_id="2" tag="tag3" tag_type="SYSTEM"/>
- <rule_tags id="3" rule_id="2" tag="tag5" tag_type="SYSTEM"/>
-
- <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="1" language="java"/>
-
- <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="2" plugin_rule_key="user_rule" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="1"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="deprecated-key" plugin_name="deprecated-repo" plugin_config_key="[null]" name="Deprecated" description="[null]"
- status="REMOVED" priority="4" cardinality="SINGLE" parent_id="[null]" language="[null]"/>
-
- <rules id="2" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
- <rules_parameters id="1" rule_id="2" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
- <rules_parameters id="2" rule_id="2" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
- <rule_tags id="1" rule_id="2" tag="tag1" tag_type="SYSTEM"/>
- <rule_tags id="2" rule_id="2" tag="tag3" tag_type="SYSTEM"/>
- <rule_tags id="3" rule_id="2" tag="tag5" tag_type="SYSTEM"/>
-
- <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="The One" description="The Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <!-- Instance of old rule 1 :/ -->
- <rules id="2" plugin_rule_key="template_rule1" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="1" language="java"/>
-
- <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <!-- Template of old rule 3 :/ -->
- <rules id="4" plugin_rule_key="template_rule2" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="3" language="java"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="[null]" name="Rule one" description="[null]"
- status="READY" priority="4" cardinality="MULTIPLE" parent_id="[null]" language="[null]"/>
-
- <!-- Instance of rule 1 -->
- <rules id="2" plugin_rule_key="template_rule1" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="1"/>
-
- <rules id="3" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="old_config_key2" name="old name2" description="old description2"
- status="DEPRECATED" priority="1" cardinality="MULTIPLE" parent_id="[null]" />
-
- <!-- Instance of rule 3 -->
- <rules id="4" plugin_rule_key="template_rule2" plugin_name="fake" plugin_config_key="[null]" name="User rule" description="[null]"
- status="READY" priority="4" cardinality="SINGLE" parent_id="3"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
- <rules_parameters id="1" rule_id="1" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
- <rules_parameters id="2" rule_id="1" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
-
- <rule_tags id="1" rule_id="1" tag="tag1" tag_type="SYSTEM"/>
- <rule_tags id="4" rule_id="1" tag="tag4" tag_type="ADMIN"/>
- <rule_tags id="5" rule_id="1" tag="tag3" tag_type="SYSTEM"/>
- <rule_tags id="6" rule_id="1" tag="tag5" tag_type="SYSTEM"/>
-
- <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="old_config_key" name="old name" description="old description"
- status="READY" priority="2" cardinality="SINGLE" parent_id="[null]" />
-
- <rules_parameters id="1" rule_id="1" name="param1" description="[null]" param_type="STRING"/>
-
- <rule_tags id="1" rule_id="1" tag="tag1" tag_type="SYSTEM"/>
- <rule_tags id="2" rule_id="1" tag="tag2" tag_type="SYSTEM"/>
- <rule_tags id="3" rule_id="1" tag="tag3" tag_type="ADMIN"/>
- <rule_tags id="4" rule_id="1" tag="tag4" tag_type="ADMIN"/>
-
- <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="old_config_key2" name="old name2" description="old description2"
- status="READY" priority="1" cardinality="SINGLE" parent_id="[null]" />
-
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
- status="READY" priority="4" cardinality="SINGLE" parent_id="[null]" language="java"/>
- <rules_parameters id="1" rule_id="1" default_value="default value one" description="parameter one" name="param1" param_type="STRING"/>
- <rules_parameters id="3" rule_id="1" default_value="default value two" description="parameter two" name="param2" param_type="STRING"/>
-
- <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="rule2" name="Two" description="Description of Two"
- status="DEPRECATED" priority="0" cardinality="SINGLE" parent_id="[null]" language="java"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="old_config_key" name="old name" description="old description"
- status="READY" priority="2" cardinality="SINGLE" parent_id="[null]"/>
-
- <rules id="2" plugin_rule_key="rule2" plugin_name="fake" plugin_config_key="old_config_key2" name="old name2" description="old description2"
- status="READY" priority="1" cardinality="SINGLE" parent_id="[null]"/>
-
- <rules_parameters id="1" rule_id="1" name="param1" description="old description" param_type="STRING"/>
- <rules_parameters id="2" rule_id="1" name="deprecated_param" description="deprecated param to be removed" param_type="STRING"/>
-
-</dataset>