Browse Source

SONAR-4908 enable extension point RuleDefinitions

tags/4.2
Simon Brandhof 10 years ago
parent
commit
487c103cd2
50 changed files with 1103 additions and 1014 deletions
  1. 2
    7
      sonar-core/src/main/java/org/sonar/core/rule/RuleDao.java
  2. 1
    1
      sonar-core/src/test/java/org/sonar/core/rule/RuleDaoTest.java
  3. 33
    17
      sonar-plugin-api/src/main/java/org/sonar/api/rule/RuleDefinitions.java
  4. 6
    1
      sonar-plugin-api/src/test/java/org/sonar/api/rule/RuleDefinitionsTest.java
  5. 1
    1
      sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRuleDefinitions.java
  6. 48
    0
      sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionsLoader.java
  7. 393
    0
      sonar-server/src/main/java/org/sonar/server/rule/RuleRegistration.java
  8. 146
    0
      sonar-server/src/main/java/org/sonar/server/rule/RuleRepositories.java
  9. 0
    66
      sonar-server/src/main/java/org/sonar/server/rules/RulesConsole.java
  10. 3
    2
      sonar-server/src/main/java/org/sonar/server/startup/RegisterNewProfiles.java
  11. 0
    457
      sonar-server/src/main/java/org/sonar/server/startup/RegisterRules.java
  12. 2
    1
      sonar-server/src/main/java/org/sonar/server/startup/RegisterTechnicalDebtModel.java
  13. 16
    15
      sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
  14. 1
    1
      sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb
  15. 77
    0
      sonar-server/src/test/java/org/sonar/server/rule/RuleDefinitionsLoaderTest.java
  16. 263
    0
      sonar-server/src/test/java/org/sonar/server/rule/RuleRegistrationTest.java
  17. 2
    1
      sonar-server/src/test/java/org/sonar/server/rule/RuleRegistryTest.java
  18. 82
    0
      sonar-server/src/test/java/org/sonar/server/rule/RuleRepositoriesTest.java
  19. 0
    60
      sonar-server/src/test/java/org/sonar/server/rules/RulesConsoleTest.java
  20. 0
    367
      sonar-server/src/test/java/org/sonar/server/startup/RegisterRulesTest.java
  21. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/disableUserRulesIfParentIsDisabled-result.xml
  22. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/disableUserRulesIfParentIsDisabled.xml
  23. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/doNotDisableUserRulesIfParentIsEnabled-result.xml
  24. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/doNotDisableUserRulesIfParentIsEnabled.xml
  25. 1
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/empty.xml
  26. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/shared.xml
  27. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/shouldNotDisableManualRules-result.xml
  28. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/shouldNotDisableManualRules.xml
  29. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_active_rule_params-result.xml
  30. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_active_rule_params.xml
  31. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_active_rules-result.xml
  32. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_active_rules.xml
  33. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_repositories-result.xml
  34. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_rules-result.xml
  35. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_rules.xml
  36. 9
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_insert_extended_repositories-result.xml
  37. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_insert_new_rules-result.xml
  38. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_not_reactivate_disabled_template_rules-result.xml
  39. 2
    2
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_not_reactivate_disabled_template_rules.xml
  40. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_not_update_already_disabled_rules-result.xml
  41. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_not_update_already_disabled_rules.xml
  42. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_reactivate_disabled_rules-result.xml
  43. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_reactivate_disabled_rules.xml
  44. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_store_bundle_name_and_description_in_database-result.xml
  45. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_update_rule_parameters-result.xml
  46. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_update_rule_parameters.xml
  47. 2
    2
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_update_template_rule_language-result.xml
  48. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_update_template_rule_language.xml
  49. 1
    1
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/updadeRuleFields-result.xml
  50. 0
    0
      sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/updadeRuleFields.xml

+ 2
- 7
sonar-core/src/main/java/org/sonar/core/rule/RuleDao.java View File

@@ -46,13 +46,8 @@ public class RuleDao implements BatchComponent, ServerComponent {
}
}

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) {

+ 1
- 1
sonar-core/src/test/java/org/sonar/core/rule/RuleDaoTest.java View File

@@ -83,7 +83,7 @@ public class RuleDaoTest extends AbstractDaoTestCase {
@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);

+ 33
- 17
sonar-plugin-api/src/main/java/org/sonar/api/rule/RuleDefinitions.java View File

@@ -47,11 +47,11 @@ public interface RuleDefinitions extends ServerExtension {
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
@@ -101,19 +101,13 @@ public interface RuleDefinitions extends ServerExtension {
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;
@@ -146,6 +140,8 @@ public interface RuleDefinitions extends ServerExtension {
static interface ExtendedRepository {
String key();

String language();

@CheckForNull
Rule rule(String ruleKey);

@@ -153,8 +149,6 @@ public interface RuleDefinitions extends ServerExtension {
}

static interface Repository extends ExtendedRepository {
String language();

String name();
}

@@ -169,7 +163,7 @@ public interface RuleDefinitions extends ServerExtension {
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();
}
@@ -223,7 +217,8 @@ public interface RuleDefinitions extends ServerExtension {
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) {
@@ -254,6 +249,11 @@ public interface RuleDefinitions extends ServerExtension {
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));
@@ -308,13 +308,20 @@ public interface RuleDefinitions extends ServerExtension {
}
}

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;
@@ -322,7 +329,8 @@ public interface RuleDefinitions extends ServerExtension {
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));
@@ -330,6 +338,10 @@ public interface RuleDefinitions extends ServerExtension {
this.params = paramsBuilder.build();
}

public Repository repository() {
return repository;
}

public String key() {
return key;
}
@@ -351,6 +363,10 @@ public interface RuleDefinitions extends ServerExtension {
return template;
}

public Status status() {
return status;
}

@CheckForNull
public Param param(String key) {
return params.get(key);

+ 6
- 1
sonar-plugin-api/src/test/java/org/sonar/api/rule/RuleDefinitionsTest.java View File

@@ -66,6 +66,7 @@ public class RuleDefinitionsTest {
.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");
@@ -83,7 +84,9 @@ public class RuleDefinitionsTest {
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");
@@ -102,6 +105,7 @@ public class RuleDefinitionsTest {
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();
}

@@ -139,7 +143,7 @@ public class RuleDefinitionsTest {
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();

@@ -149,6 +153,7 @@ public class RuleDefinitionsTest {
assertThat(context.extendedRepositories("findbugs")).hasSize(1);

RuleDefinitions.ExtendedRepository findbugs = context.extendedRepositories("findbugs").get(0);
assertThat(findbugs.language()).isEqualTo("java");
assertThat(findbugs.rule("NPE")).isNotNull();
}


+ 1
- 1
sonar-server/src/main/java/org/sonar/server/rule/DeprecatedRuleDefinitions.java View File

@@ -54,7 +54,7 @@ public class DeprecatedRuleDefinitions implements RuleDefinitions {
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

+ 48
- 0
sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionsLoader.java View File

@@ -0,0 +1,48 @@
/*
* 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;
}
}

+ 393
- 0
sonar-server/src/main/java/org/sonar/server/rule/RuleRegistration.java View File

@@ -0,0 +1,393 @@
/*
* 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());
}
}
}

+ 146
- 0
sonar-server/src/main/java/org/sonar/server/rule/RuleRepositories.java View File

@@ -0,0 +1,146 @@
/*
* 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;
}
}

+ 0
- 66
sonar-server/src/main/java/org/sonar/server/rules/RulesConsole.java View File

@@ -1,66 +0,0 @@
/*
* 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);
}
}

+ 3
- 2
sonar-server/src/main/java/org/sonar/server/startup/RegisterNewProfiles.java View File

@@ -38,6 +38,7 @@ import org.sonar.core.template.LoadedTemplateDao;
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.*;
@@ -61,7 +62,7 @@ public class RegisterNewProfiles {
RuleRegistry ruleRegistry,
LoadedTemplateDao loadedTemplateDao,
DatabaseSessionFactory sessionFactory,
RegisterRules registerRulesBefore) {
RuleRegistration registerRulesBefore) {
this.settings = settings;
this.ruleFinder = ruleFinder;
this.ruleRegistry = ruleRegistry;
@@ -75,7 +76,7 @@ public class RegisterNewProfiles {
RuleRegistry ruleRegistry,
LoadedTemplateDao loadedTemplateDao,
DatabaseSessionFactory sessionFactory,
RegisterRules registerRulesBefore) {
RuleRegistration registerRulesBefore) {
this(Collections.<ProfileDefinition>emptyList(), settings, ruleFinder, ruleRegistry, loadedTemplateDao, sessionFactory, registerRulesBefore);
}


+ 0
- 457
sonar-server/src/main/java/org/sonar/server/startup/RegisterRules.java View File

@@ -1,457 +0,0 @@
/*
* 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);
}
}
}

+ 2
- 1
sonar-server/src/main/java/org/sonar/server/startup/RegisterTechnicalDebtModel.java View File

@@ -26,6 +26,7 @@ import org.sonar.api.utils.TimeProfiler;
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 {

@@ -37,7 +38,7 @@ 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;
}

+ 16
- 15
sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java View File

@@ -34,7 +34,6 @@ import org.sonar.api.resources.Language;
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;
@@ -58,18 +57,20 @@ import org.sonar.server.platform.ServerIdGenerator;
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;

@@ -245,16 +246,16 @@ public final class JRubyFacade {
}

/* 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
@@ -303,7 +304,7 @@ public final class JRubyFacade {

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) {
@@ -457,10 +458,10 @@ public final class JRubyFacade {
// 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());
}
}


+ 1
- 1
sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb View File

@@ -38,7 +38,7 @@ class RulesConfigurationController < ApplicationController

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'],

+ 77
- 0
sonar-server/src/test/java/org/sonar/server/rule/RuleDefinitionsLoaderTest.java View File

@@ -0,0 +1,77 @@
/*
* 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();
}
}
}

+ 263
- 0
sonar-server/src/test/java/org/sonar/server/rule/RuleRegistrationTest.java View File

@@ -0,0 +1,263 @@
/*
* 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();
}
}
}





+ 2
- 1
sonar-server/src/test/java/org/sonar/server/rule/RuleRegistryTest.java View File

@@ -58,6 +58,7 @@ import static org.elasticsearch.index.query.FilterBuilders.hasChildFilter;
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;

@@ -261,7 +262,7 @@ public class RuleRegistryTest {
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);

+ 82
- 0
sonar-server/src/test/java/org/sonar/server/rule/RuleRepositoriesTest.java View File

@@ -0,0 +1,82 @@
/*
* 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();
}
}
}

+ 0
- 60
sonar-server/src/test/java/org/sonar/server/rules/RulesConsoleTest.java View File

@@ -1,60 +0,0 @@
/*
* 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();
}
}
}



+ 0
- 367
sonar-server/src/test/java/org/sonar/server/startup/RegisterRulesTest.java View File

@@ -1,367 +0,0 @@
/*
* 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);
}
}

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableUserRulesIfParentIsDisabled-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/disableUserRulesIfParentIsDisabled-result.xml View File

@@ -15,7 +15,7 @@
<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"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableUserRulesIfParentIsDisabled.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/disableUserRulesIfParentIsDisabled.xml View File


sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/doNotDisableUserRulesIfParentIsEnabled-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/doNotDisableUserRulesIfParentIsEnabled-result.xml View File

@@ -6,7 +6,7 @@
<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"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/doNotDisableUserRulesIfParentIsEnabled.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/doNotDisableUserRulesIfParentIsEnabled.xml View File


+ 1
- 0
sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/empty.xml View File

@@ -0,0 +1 @@
<dataset></dataset>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/shared.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/shared.xml View File


sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/shouldNotDisableManualRules-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/shouldNotDisableManualRules-result.xml View File

@@ -9,7 +9,7 @@
<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"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/shouldNotDisableManualRules.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/shouldNotDisableManualRules.xml View File


sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRuleParameters-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_active_rule_params-result.xml View File

@@ -3,7 +3,7 @@
<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"
<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"/>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRuleParameters.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_active_rule_params.xml View File


sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRules-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_active_rules-result.xml View File

@@ -9,7 +9,7 @@
<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"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedActiveRules.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_active_rules.xml View File


sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/should_disable_deprecated_repositories-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_repositories-result.xml View File


sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedRules-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_rules-result.xml View File

@@ -14,7 +14,7 @@
<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"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/disableDeprecatedRules.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_disable_deprecated_rules.xml View File


+ 9
- 0
sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_insert_extended_repositories-result.xml View File

@@ -0,0 +1,9 @@
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/should_save_new_repositories-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_insert_new_rules-result.xml View File

@@ -11,7 +11,7 @@
<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"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/should_reactivate_disabled_template_rules-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_not_reactivate_disabled_template_rules-result.xml View File

@@ -6,7 +6,7 @@
<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"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/should_reactivate_disabled_template_rules.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_not_reactivate_disabled_template_rules.xml View File

@@ -1,9 +1,9 @@
<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]"/>
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"/>
status="REMOVED" priority="4" cardinality="SINGLE" parent_id="1" language="java"/>

</dataset>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/notUpdateAlreadyDisabledRule-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_not_update_already_disabled_rules-result.xml View File


sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/notUpdateAlreadyDisabledRule.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_not_update_already_disabled_rules.xml View File


sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/reactivateDisabledRules-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_reactivate_disabled_rules-result.xml View File

@@ -3,7 +3,7 @@
<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"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/reactivateDisabledRules.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_reactivate_disabled_rules.xml View File

@@ -1,6 +1,6 @@
<dataset>

<rules id="1" plugin_rule_key="rule1" plugin_name="fake" plugin_config_key="config1" name="One" description="Description of One"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/should_store_bundle_name_and_description_in_database-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_store_bundle_name_and_description_in_database-result.xml View File


sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/updateRuleParameters-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_update_rule_parameters-result.xml View File

@@ -5,7 +5,7 @@
<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"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/updateRuleParameters.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_update_rule_parameters.xml View File


sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/should_update_template_rule_language-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_update_template_rule_language-result.xml View File

@@ -7,11 +7,11 @@
<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"
<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="READY" priority="4" cardinality="SINGLE" parent_id="3" language="java"/>
status="DEPRECATED" priority="4" cardinality="SINGLE" parent_id="3" language="java"/>

</dataset>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/should_update_template_rule_language.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/should_update_template_rule_language.xml View File

@@ -5,7 +5,7 @@

<!-- 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"/>
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]" />

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/updadeRuleFields-result.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/updadeRuleFields-result.xml View File

@@ -11,7 +11,7 @@
<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"
<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>

sonar-server/src/test/resources/org/sonar/server/startup/RegisterRulesTest/updadeRuleFields.xml → sonar-server/src/test/resources/org/sonar/server/rule/RuleRegistrationTest/updadeRuleFields.xml View File


Loading…
Cancel
Save