@@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableList; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import javax.annotation.concurrent.Immutable; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; | |||
/** | |||
@@ -32,7 +33,7 @@ import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; | |||
public final class BuiltInQProfile { | |||
private final QProfileName qProfileName; | |||
private final boolean isDefault; | |||
private final List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> activeRules; | |||
private final List<ActiveRule> activeRules; | |||
private BuiltInQProfile(Builder builder) { | |||
this.qProfileName = new QProfileName(builder.language, builder.name); | |||
@@ -56,16 +57,38 @@ public final class BuiltInQProfile { | |||
return isDefault; | |||
} | |||
public List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> getActiveRules() { | |||
public List<ActiveRule> getActiveRules() { | |||
return activeRules; | |||
} | |||
static final class ActiveRule { | |||
private final int ruleId; | |||
private final BuiltInQualityProfilesDefinition.BuiltInActiveRule builtIn; | |||
ActiveRule(int ruleId, BuiltInQualityProfilesDefinition.BuiltInActiveRule builtIn) { | |||
this.ruleId = ruleId; | |||
this.builtIn = builtIn; | |||
} | |||
public int getRuleId() { | |||
return ruleId; | |||
} | |||
public RuleKey getRuleKey() { | |||
return RuleKey.of(builtIn.repoKey(), builtIn.ruleKey()); | |||
} | |||
public BuiltInQualityProfilesDefinition.BuiltInActiveRule getBuiltIn() { | |||
return builtIn; | |||
} | |||
} | |||
static final class Builder { | |||
private String language; | |||
private String name; | |||
private boolean declaredDefault; | |||
private boolean computedDefault; | |||
private final List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> activeRules = new ArrayList<>(); | |||
private final List<ActiveRule> activeRules = new ArrayList<>(); | |||
public Builder setLanguage(String language) { | |||
this.language = language; | |||
@@ -95,8 +118,13 @@ public final class BuiltInQProfile { | |||
return this; | |||
} | |||
Builder addRules(List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> rules) { | |||
this.activeRules.addAll(rules); | |||
Builder addRule(BuiltInQualityProfilesDefinition.BuiltInActiveRule rule, int ruleId) { | |||
this.activeRules.add(new ActiveRule(ruleId, rule)); | |||
return this; | |||
} | |||
Builder addRule(ActiveRule activeRule) { | |||
this.activeRules.add(activeRule); | |||
return this; | |||
} | |||
@@ -139,8 +139,8 @@ public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert { | |||
return dto; | |||
} | |||
private ActiveRuleChange insertActiveRule(DbSession dbSession, RulesProfileDto rulesProfileDto, BuiltInQualityProfilesDefinition.BuiltInActiveRule activeRule, long now) { | |||
RuleKey ruleKey = RuleKey.of(activeRule.repoKey(), activeRule.ruleKey()); | |||
private ActiveRuleChange insertActiveRule(DbSession dbSession, RulesProfileDto rulesProfileDto, BuiltInQProfile.ActiveRule activeRule, long now) { | |||
RuleKey ruleKey = activeRule.getRuleKey(); | |||
RuleDefinitionDto ruleDefinitionDto = ruleRepository.getDefinition(ruleKey) | |||
.orElseThrow(() -> new IllegalStateException("RuleDefinition not found for key " + ruleKey)); | |||
@@ -148,12 +148,12 @@ public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert { | |||
dto.setProfileId(rulesProfileDto.getId()); | |||
dto.setRuleId(ruleDefinitionDto.getId()); | |||
dto.setKey(ActiveRuleKey.of(rulesProfileDto, ruleDefinitionDto.getKey())); | |||
dto.setSeverity(firstNonNull(activeRule.overriddenSeverity(), ruleDefinitionDto.getSeverityString())); | |||
dto.setSeverity(firstNonNull(activeRule.getBuiltIn().overriddenSeverity(), ruleDefinitionDto.getSeverityString())); | |||
dto.setUpdatedAt(now); | |||
dto.setCreatedAt(now); | |||
dbClient.activeRuleDao().insert(dbSession, dto); | |||
List<ActiveRuleParamDto> paramDtos = insertActiveRuleParams(dbSession, activeRule, ruleKey, dto); | |||
List<ActiveRuleParamDto> paramDtos = insertActiveRuleParams(dbSession, activeRule, dto); | |||
ActiveRuleChange change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, dto, ruleDefinitionDto); | |||
change.setSeverity(dto.getSeverityString()); | |||
@@ -161,12 +161,12 @@ public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert { | |||
return change; | |||
} | |||
private List<ActiveRuleParamDto> insertActiveRuleParams(DbSession session, BuiltInQualityProfilesDefinition.BuiltInActiveRule activeRule, RuleKey ruleKey, | |||
private List<ActiveRuleParamDto> insertActiveRuleParams(DbSession session, BuiltInQProfile.ActiveRule activeRule, | |||
ActiveRuleDto activeRuleDto) { | |||
Map<String, String> valuesByParamKey = activeRule.overriddenParams() | |||
Map<String, String> valuesByParamKey = activeRule.getBuiltIn().overriddenParams() | |||
.stream() | |||
.collect(MoreCollectors.uniqueIndex(BuiltInQualityProfilesDefinition.OverriddenParam::key, BuiltInQualityProfilesDefinition.OverriddenParam::overriddenValue)); | |||
return ruleRepository.getRuleParams(ruleKey) | |||
return ruleRepository.getRuleParams(activeRule.getRuleKey()) | |||
.stream() | |||
.map(param -> { | |||
String activeRuleValue = valuesByParamKey.get(param.getName()); |
@@ -21,6 +21,7 @@ package org.sonar.server.qualityprofile; | |||
import com.google.common.collect.ImmutableList; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.LinkedHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
@@ -29,12 +30,16 @@ import java.util.Set; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Languages; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInQualityProfile; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.api.utils.log.Profiler; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import static com.google.common.base.Preconditions.checkState; | |||
@@ -42,6 +47,7 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository | |||
private static final Logger LOGGER = Loggers.get(BuiltInQProfileRepositoryImpl.class); | |||
private static final String DEFAULT_PROFILE_NAME = "Sonar way"; | |||
private final DbClient dbClient; | |||
private final Languages languages; | |||
private final List<BuiltInQualityProfilesDefinition> definitions; | |||
private List<BuiltInQProfile> qProfiles; | |||
@@ -49,11 +55,12 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository | |||
/** | |||
* Requires for pico container when no {@link BuiltInQualityProfilesDefinition} is defined at all | |||
*/ | |||
public BuiltInQProfileRepositoryImpl(Languages languages) { | |||
this(languages, new BuiltInQualityProfilesDefinition[0]); | |||
public BuiltInQProfileRepositoryImpl(DbClient dbClient, Languages languages) { | |||
this(dbClient, languages, new BuiltInQualityProfilesDefinition[0]); | |||
} | |||
public BuiltInQProfileRepositoryImpl(Languages languages, BuiltInQualityProfilesDefinition... definitions) { | |||
public BuiltInQProfileRepositoryImpl(DbClient dbClient, Languages languages, BuiltInQualityProfilesDefinition... definitions) { | |||
this.dbClient = dbClient; | |||
this.languages = languages; | |||
this.definitions = ImmutableList.copyOf(definitions); | |||
} | |||
@@ -98,18 +105,29 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository | |||
return profilesByLanguageAndName; | |||
} | |||
private static List<BuiltInQProfile> toFlatList(Map<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguage) { | |||
Map<String, List<BuiltInQProfile.Builder>> buildersByLanguage = rulesProfilesByLanguage | |||
.entrySet() | |||
.stream() | |||
.collect(MoreCollectors.uniqueIndex(Map.Entry::getKey, BuiltInQProfileRepositoryImpl::toQualityProfileBuilders)); | |||
return buildersByLanguage | |||
.entrySet() | |||
.stream() | |||
.filter(BuiltInQProfileRepositoryImpl::ensureAtMostOneDeclaredDefault) | |||
.map(entry -> toQualityProfiles(entry.getValue())) | |||
.flatMap(Collection::stream) | |||
.collect(MoreCollectors.toList()); | |||
private List<BuiltInQProfile> toFlatList(Map<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguage) { | |||
if (rulesProfilesByLanguage.isEmpty()) { | |||
return Collections.emptyList(); | |||
} | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
Map<RuleKey, RuleDefinitionDto> rulesByRuleKey = dbClient.ruleDao().selectAllDefinitions(dbSession) | |||
.stream() | |||
.collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getKey)); | |||
Map<String, List<BuiltInQProfile.Builder>> buildersByLanguage = rulesProfilesByLanguage | |||
.entrySet() | |||
.stream() | |||
.collect(MoreCollectors.uniqueIndex( | |||
Map.Entry::getKey, | |||
rulesProfilesByLanguageAndName -> toQualityProfileBuilders(rulesProfilesByLanguageAndName, rulesByRuleKey))); | |||
return buildersByLanguage | |||
.entrySet() | |||
.stream() | |||
.filter(BuiltInQProfileRepositoryImpl::ensureAtMostOneDeclaredDefault) | |||
.map(entry -> toQualityProfiles(entry.getValue())) | |||
.flatMap(Collection::stream) | |||
.collect(MoreCollectors.toList()); | |||
} | |||
} | |||
/** | |||
@@ -124,14 +142,15 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository | |||
* RulesProfile with a given name</li> | |||
* </ul> | |||
*/ | |||
private static List<BuiltInQProfile.Builder> toQualityProfileBuilders(Map.Entry<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguageAndName) { | |||
private static List<BuiltInQProfile.Builder> toQualityProfileBuilders(Map.Entry<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguageAndName, | |||
Map<RuleKey, RuleDefinitionDto> rulesByRuleKey) { | |||
String language = rulesProfilesByLanguageAndName.getKey(); | |||
// use a LinkedHashMap to keep order of insertion of RulesProfiles | |||
Map<String, BuiltInQProfile.Builder> qualityProfileBuildersByName = new LinkedHashMap<>(); | |||
for (BuiltInQualityProfile builtInProfile : rulesProfilesByLanguageAndName.getValue().values()) { | |||
qualityProfileBuildersByName.compute( | |||
builtInProfile.name(), | |||
(name, existingBuilder) -> updateOrCreateBuilder(language, existingBuilder, builtInProfile)); | |||
(name, existingBuilder) -> updateOrCreateBuilder(language, existingBuilder, builtInProfile, rulesByRuleKey)); | |||
} | |||
return ImmutableList.copyOf(qualityProfileBuildersByName.values()); | |||
} | |||
@@ -148,16 +167,26 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository | |||
return true; | |||
} | |||
private static BuiltInQProfile.Builder updateOrCreateBuilder(String language, @Nullable BuiltInQProfile.Builder existingBuilder, BuiltInQualityProfile builtInProfile) { | |||
BuiltInQProfile.Builder builder = existingBuilder; | |||
if (builder == null) { | |||
builder = new BuiltInQProfile.Builder() | |||
private static BuiltInQProfile.Builder updateOrCreateBuilder(String language, @Nullable BuiltInQProfile.Builder existingBuilder, BuiltInQualityProfile builtInProfile, | |||
Map<RuleKey, RuleDefinitionDto> rulesByRuleKey) { | |||
BuiltInQProfile.Builder builder = createOrReuseBuilder(existingBuilder, language, builtInProfile); | |||
builder.setDeclaredDefault(builtInProfile.isDefault()); | |||
builtInProfile.rules().forEach(builtInActiveRule -> { | |||
RuleKey ruleKey = RuleKey.of(builtInActiveRule.repoKey(), builtInActiveRule.ruleKey()); | |||
RuleDefinitionDto ruleDefinition = rulesByRuleKey.get(ruleKey); | |||
checkState(ruleDefinition != null, "Rule with key '%s' not found", ruleKey); | |||
builder.addRule(builtInActiveRule, ruleDefinition.getId()); | |||
}); | |||
return builder; | |||
} | |||
private static BuiltInQProfile.Builder createOrReuseBuilder(@Nullable BuiltInQProfile.Builder existingBuilder, String language, BuiltInQualityProfile builtInProfile) { | |||
if (existingBuilder == null) { | |||
return new BuiltInQProfile.Builder() | |||
.setLanguage(language) | |||
.setName(builtInProfile.name()); | |||
} | |||
return builder | |||
.setDeclaredDefault(builtInProfile.isDefault()) | |||
.addRules(builtInProfile.rules()); | |||
return existingBuilder; | |||
} | |||
private static List<BuiltInQProfile> toQualityProfiles(List<BuiltInQProfile.Builder> builders) { |
@@ -27,13 +27,11 @@ import java.util.Set; | |||
import java.util.stream.Stream; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInActiveRule; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.RulesProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import static org.sonar.core.util.stream.MoreCollectors.toSet; | |||
@@ -59,13 +57,13 @@ public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate { | |||
Set<RuleKey> ruleKeys = Stream.concat( | |||
deactivatedKeys.stream(), | |||
builtIn.getActiveRules().stream().map(ar -> RuleKey.of(ar.repoKey(), ar.ruleKey()))) | |||
builtIn.getActiveRules().stream().map(BuiltInQProfile.ActiveRule::getRuleKey)) | |||
.collect(toSet()); | |||
RuleActivationContext context = ruleActivator.createContextForBuiltInProfile(dbSession, rulesProfile, ruleKeys); | |||
Collection<RuleActivation> activations = new ArrayList<>(); | |||
for (BuiltInActiveRule ar : builtIn.getActiveRules()) { | |||
RuleActivation activation = convert(ar, context); | |||
for (BuiltInQProfile.ActiveRule ar : builtIn.getActiveRules()) { | |||
RuleActivation activation = convert(ar); | |||
activations.add(activation); | |||
deactivatedKeys.remove(activation.getRuleKey()); | |||
} | |||
@@ -82,13 +80,10 @@ public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate { | |||
return changes; | |||
} | |||
private static RuleActivation convert(BuiltInActiveRule ar, RuleActivationContext context) { | |||
RuleKey ruleKey = RuleKey.of(ar.repoKey(), ar.ruleKey()); | |||
context.reset(ruleKey); | |||
RuleDefinitionDto ruleDefinition = context.getRule().get(); | |||
Map<String, String> params = ar.overriddenParams().stream() | |||
private static RuleActivation convert(BuiltInQProfile.ActiveRule ar) { | |||
Map<String, String> params = ar.getBuiltIn().overriddenParams().stream() | |||
.collect(MoreCollectors.uniqueIndex(BuiltInQualityProfilesDefinition.OverriddenParam::key, BuiltInQualityProfilesDefinition.OverriddenParam::overriddenValue)); | |||
return RuleActivation.create(ruleDefinition.getId(), ruleKey, ar.overriddenSeverity(), params); | |||
return RuleActivation.create(ar.getRuleId(), ar.getRuleKey(), ar.getBuiltIn().overriddenSeverity(), params); | |||
} | |||
} |
@@ -108,7 +108,7 @@ public class BuiltInQProfileInsertImplTest { | |||
newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR); | |||
newQp.done(); | |||
BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name")); | |||
BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"), rule1, rule2); | |||
call(builtIn); | |||
verifyTableSize("rules_profiles", 1); |
@@ -28,11 +28,15 @@ import org.junit.rules.ExpectedException; | |||
import org.sonar.api.resources.Language; | |||
import org.sonar.api.resources.Languages; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.server.language.LanguageTesting; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.groups.Tuple.tuple; | |||
import static org.mockito.Mockito.mock; | |||
public class BuiltInQProfileRepositoryImplTest { | |||
private static final Language FOO_LANGUAGE = LanguageTesting.newLanguage("foo", "foo", "foo"); | |||
@@ -40,10 +44,14 @@ public class BuiltInQProfileRepositoryImplTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public DbTester dbTester = DbTester.create(System2.INSTANCE); | |||
private DbClient dbClient = dbTester.getDbClient(); | |||
@Test | |||
public void get_throws_ISE_if_called_before_initialize() { | |||
BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(new Languages()); | |||
BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages()); | |||
expectedException.expect(IllegalStateException.class); | |||
expectedException.expectMessage("initialize must be called first"); | |||
@@ -53,7 +61,7 @@ public class BuiltInQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_throws_ISE_if_called_twice() { | |||
BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(new Languages()); | |||
BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages()); | |||
underTest.initialize(); | |||
expectedException.expect(IllegalStateException.class); | |||
@@ -64,7 +72,7 @@ public class BuiltInQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_creates_no_BuiltInQProfile_when_there_is_no_definition() { | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE)); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages(FOO_LANGUAGE)); | |||
underTest.initialize(); | |||
@@ -73,7 +81,7 @@ public class BuiltInQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_creates_no_BuiltInQProfile_when_all_definitions_apply_to_non_defined_languages() { | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(), new DummyProfileDefinition("foo", "P1", false)); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages(), new DummyProfileDefinition("foo", "P1", false)); | |||
underTest.initialize(); | |||
@@ -82,7 +90,7 @@ public class BuiltInQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_makes_single_profile_of_a_language_default_even_if_not_flagged_as_so() { | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", false)); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", false)); | |||
underTest.initialize(); | |||
@@ -93,7 +101,7 @@ public class BuiltInQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_makes_single_profile_of_a_language_default_even_if_flagged_as_so() { | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", true)); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", true)); | |||
underTest.initialize(); | |||
@@ -109,7 +117,7 @@ public class BuiltInQProfileRepositoryImplTest { | |||
Collections.shuffle(definitions); | |||
String firstName = definitions.get(0).getName(); | |||
String secondName = definitions.get(1).getName(); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), definitions.toArray(new BuiltInQualityProfilesDefinition[0])); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), definitions.toArray(new BuiltInQualityProfilesDefinition[0])); | |||
underTest.initialize(); | |||
@@ -120,7 +128,7 @@ public class BuiltInQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_fails_with_ISE_when_two_profiles_with_different_name_are_default_for_the_same_language() { | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), | |||
new DummyProfileDefinition("foo", "foo1", true), new DummyProfileDefinition("foo", "foo2", true)); | |||
expectedException.expect(IllegalStateException.class); | |||
@@ -132,7 +140,7 @@ public class BuiltInQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_creates_profile_Sonar_Way_as_default_if_none_other_is_defined_default_for_a_given_language() { | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl( | |||
new Languages(FOO_LANGUAGE), | |||
dbClient, new Languages(FOO_LANGUAGE), | |||
new DummyProfileDefinition("foo", "doh", false), new DummyProfileDefinition("foo", "boo", false), | |||
new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", false)); | |||
@@ -148,7 +156,7 @@ public class BuiltInQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_does_not_create_Sonar_Way_as_default_if_other_profile_is_defined_as_default() { | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl( | |||
new Languages(FOO_LANGUAGE), | |||
dbClient, new Languages(FOO_LANGUAGE), | |||
new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", true)); | |||
underTest.initialize(); | |||
@@ -164,7 +172,7 @@ public class BuiltInQProfileRepositoryImplTest { | |||
public void initialize_matches_Sonar_Way_default_with_case_sensitivity() { | |||
String sonarWayInOtherCase = SONAR_WAY_QP_NAME.toUpperCase(); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl( | |||
new Languages(FOO_LANGUAGE), | |||
dbClient, new Languages(FOO_LANGUAGE), | |||
new DummyProfileDefinition("foo", "goo", false), new DummyProfileDefinition("foo", sonarWayInOtherCase, false)); | |||
underTest.initialize(); |
@@ -19,13 +19,18 @@ | |||
*/ | |||
package org.sonar.server.qualityprofile; | |||
import com.google.common.base.Preconditions; | |||
import com.google.common.collect.ImmutableList; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.junit.rules.ExternalResource; | |||
import org.sonar.api.resources.Language; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import static com.google.common.base.Preconditions.checkState; | |||
@@ -60,27 +65,39 @@ public class BuiltInQProfileRepositoryRule extends ExternalResource implements B | |||
return add(language, profileName, false); | |||
} | |||
public BuiltInQProfile add(Language language, String profileName, boolean isDefault, BuiltInQualityProfilesDefinition.BuiltInActiveRule... rules) { | |||
public BuiltInQProfile add(Language language, String profileName, boolean isDefault) { | |||
return add(language, profileName, isDefault, new BuiltInQProfile.ActiveRule[0]); | |||
} | |||
public BuiltInQProfile add(Language language, String profileName, boolean isDefault, BuiltInQProfile.ActiveRule... rules) { | |||
BuiltInQProfile builtIn = create(language, profileName, isDefault, rules); | |||
profiles.add(builtIn); | |||
return builtIn; | |||
} | |||
public BuiltInQProfile create(Language language, String profileName, boolean isDefault, BuiltInQualityProfilesDefinition.BuiltInActiveRule... rules) { | |||
return new BuiltInQProfile.Builder() | |||
public BuiltInQProfile create(Language language, String profileName, boolean isDefault, BuiltInQProfile.ActiveRule... rules) { | |||
BuiltInQProfile.Builder builder = new BuiltInQProfile.Builder() | |||
.setLanguage(language.getKey()) | |||
.setName(profileName) | |||
.setDeclaredDefault(isDefault) | |||
.addRules(Arrays.asList(rules)) | |||
.build(); | |||
.setDeclaredDefault(isDefault); | |||
Arrays.stream(rules).forEach(builder::addRule); | |||
return builder.build(); | |||
} | |||
public BuiltInQProfile create(BuiltInQualityProfilesDefinition.BuiltInQualityProfile api) { | |||
return new BuiltInQProfile.Builder() | |||
public BuiltInQProfile create(BuiltInQualityProfilesDefinition.BuiltInQualityProfile api, RuleDefinitionDto... rules) { | |||
BuiltInQProfile.Builder builder = new BuiltInQProfile.Builder() | |||
.setLanguage(api.language()) | |||
.setName(api.name()) | |||
.setDeclaredDefault(api.isDefault()) | |||
.addRules(new ArrayList<>(api.rules())) | |||
.setDeclaredDefault(api.isDefault()); | |||
Map<RuleKey, RuleDefinitionDto> rulesByRuleKey = Arrays.stream(rules) | |||
.collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getKey)); | |||
api.rules().forEach(rule -> { | |||
RuleKey ruleKey = RuleKey.of(rule.repoKey(), rule.ruleKey()); | |||
RuleDefinitionDto ruleDefinition = rulesByRuleKey.get(ruleKey); | |||
Preconditions.checkState(ruleDefinition != null, "Rule '%s' not found", ruleKey); | |||
builder.addRule(rule, ruleDefinition.getId()); | |||
}); | |||
return builder | |||
.build(); | |||
} | |||
} |
@@ -87,7 +87,7 @@ public class BuiltInQProfileUpdateImplTest { | |||
newQp.activateRule(rule1.getRepositoryKey(), rule1.getRuleKey()).overrideSeverity(Severity.CRITICAL); | |||
newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR); | |||
newQp.done(); | |||
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way")); | |||
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule1, rule2); | |||
underTest.update(db.getSession(), builtIn, persistedProfile); | |||
@@ -105,7 +105,7 @@ public class BuiltInQProfileUpdateImplTest { | |||
NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo"); | |||
newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()).overrideSeverity(Severity.CRITICAL); | |||
newQp.done(); | |||
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way")); | |||
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule); | |||
activateRuleInDb(persistedProfile, rule, BLOCKER); | |||
@@ -124,7 +124,7 @@ public class BuiltInQProfileUpdateImplTest { | |||
NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo"); | |||
newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()).overrideSeverity(Severity.CRITICAL); | |||
newQp.done(); | |||
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way")); | |||
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule); | |||
activateRuleInDb(persistedProfile, rule, CRITICAL); | |||
@@ -144,7 +144,7 @@ public class BuiltInQProfileUpdateImplTest { | |||
NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo"); | |||
newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR); | |||
newQp.done(); | |||
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way")); | |||
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule1, rule2); | |||
// built-in definition contains only rule2 | |||
// so rule1 must be deactivated | |||
@@ -169,7 +169,7 @@ public class BuiltInQProfileUpdateImplTest { | |||
newQp.activateRule(rule1.getRepositoryKey(), rule1.getRuleKey()).overrideSeverity(Severity.CRITICAL); | |||
newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR); | |||
newQp.done(); | |||
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way")); | |||
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule1, rule2); | |||
// rule1 must be updated (blocker to critical) | |||
// rule2 must be activated |
@@ -22,12 +22,15 @@ package org.sonar.server.qualityprofile; | |||
import com.google.common.collect.Multimap; | |||
import java.security.SecureRandom; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Random; | |||
import java.util.function.Consumer; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.mockito.ArgumentCaptor; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; | |||
@@ -36,6 +39,7 @@ import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQ | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.log.LogTester; | |||
import org.sonar.core.util.UuidFactoryFast; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.organization.OrganizationDto; | |||
@@ -48,6 +52,7 @@ import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.util.TypeValidations; | |||
import static com.google.common.base.Preconditions.checkState; | |||
import static java.util.Collections.singleton; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.apache.commons.lang.math.RandomUtils.nextLong; | |||
@@ -303,8 +308,21 @@ public class RegisterQualityProfilesNotificationTest { | |||
Arrays.stream(dbRules).forEach(dbRule -> newQp.activateRule(dbRule.getRepositoryKey(), dbRule.getRuleKey()).overrideSeverity(Severity.MAJOR)); | |||
newQp.done(); | |||
builtInQProfileRepositoryRule.add(newLanguage(dbProfile.getLanguage()), dbProfile.getName(), false, | |||
context.profile(dbProfile.getLanguage(), dbProfile.getName()).rules().toArray(new BuiltInActiveRule[0])); | |||
List<BuiltInActiveRule> rules = context.profile(dbProfile.getLanguage(), dbProfile.getName()).rules(); | |||
BuiltInQProfile.ActiveRule[] activeRules = toActiveRules(rules, dbRules); | |||
builtInQProfileRepositoryRule.add(newLanguage(dbProfile.getLanguage()), dbProfile.getName(), false, activeRules); | |||
} | |||
private static BuiltInQProfile.ActiveRule[] toActiveRules(List<BuiltInActiveRule> rules, RuleDefinitionDto[] dbRules) { | |||
Map<RuleKey, RuleDefinitionDto> dbRulesByRuleKey = Arrays.stream(dbRules) | |||
.collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getKey)); | |||
return rules.stream() | |||
.map(r -> { | |||
RuleKey ruleKey = RuleKey.of(r.repoKey(), r.ruleKey()); | |||
RuleDefinitionDto ruleDefinitionDto = dbRulesByRuleKey.get(ruleKey); | |||
checkState(ruleDefinitionDto != null, "Rule '%s' not found", ruleKey); | |||
return new BuiltInQProfile.ActiveRule(ruleDefinitionDto.getId(), r); | |||
}).toArray(BuiltInQProfile.ActiveRule[]::new); | |||
} | |||
private void addPluginProfile(QProfileDto profile, RuleDefinitionDto... dbRules) { | |||
@@ -313,8 +331,8 @@ public class RegisterQualityProfilesNotificationTest { | |||
Arrays.stream(dbRules).forEach(dbRule -> newQp.activateRule(dbRule.getRepositoryKey(), dbRule.getRuleKey()).overrideSeverity(Severity.MAJOR)); | |||
newQp.done(); | |||
builtInQProfileRepositoryRule.add(newLanguage(profile.getLanguage()), profile.getName(), false, | |||
context.profile(profile.getLanguage(), profile.getName()).rules().toArray(new BuiltInActiveRule[0])); | |||
BuiltInQProfile.ActiveRule[] activeRules = toActiveRules(context.profile(profile.getLanguage(), profile.getName()).rules(), dbRules); | |||
builtInQProfileRepositoryRule.add(newLanguage(profile.getLanguage()), profile.getName(), false, activeRules); | |||
} | |||
private RulesProfileDto insertBuiltInProfile(String language) { |