@@ -25,12 +25,17 @@ import java.util.List; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
import java.util.function.Consumer; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.Dao; | |||
import org.sonar.db.DatabaseUtils; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static java.util.Collections.emptyList; | |||
import static org.sonar.db.DatabaseUtils.PARTITION_SIZE_FOR_ORACLE; | |||
import static org.sonar.db.DatabaseUtils.executeLargeInputs; | |||
import static org.sonar.db.DatabaseUtils.executeLargeInputsWithoutOutput; | |||
import static org.sonar.db.KeyLongValue.toMap; | |||
@@ -76,18 +81,28 @@ public class ActiveRuleDao implements Dao { | |||
return mapper(dbSession).selectByRuleProfileUuid(ruleProfileDto.getKee()); | |||
} | |||
public Collection<ActiveRuleDto> selectByRulesAndRuleProfileUuids(DbSession dbSession, Collection<RuleDefinitionDto> rules, Collection<String> ruleProfileUuids) { | |||
if (rules.isEmpty()) { | |||
return emptyList(); | |||
} | |||
checkArgument(rules.size() < PARTITION_SIZE_FOR_ORACLE, | |||
"too many rules (got %s, max is %s)", rules.size(), PARTITION_SIZE_FOR_ORACLE); | |||
List<Integer> ruleIds = rules.stream().map(RuleDefinitionDto::getId).collect(MoreCollectors.toArrayList(rules.size())); | |||
return executeLargeInputs(ruleProfileUuids, chunk -> mapper(dbSession).selectByRuleIdsAndRuleProfileUuids(ruleIds, chunk)); | |||
} | |||
public ActiveRuleDto insert(DbSession dbSession, ActiveRuleDto item) { | |||
Preconditions.checkArgument(item.getProfileId() != null, QUALITY_PROFILE_IS_NOT_PERSISTED); | |||
Preconditions.checkArgument(item.getRuleId() != null, RULE_IS_NOT_PERSISTED); | |||
Preconditions.checkArgument(item.getId() == null, ACTIVE_RULE_IS_ALREADY_PERSISTED); | |||
checkArgument(item.getProfileId() != null, QUALITY_PROFILE_IS_NOT_PERSISTED); | |||
checkArgument(item.getRuleId() != null, RULE_IS_NOT_PERSISTED); | |||
checkArgument(item.getId() == null, ACTIVE_RULE_IS_ALREADY_PERSISTED); | |||
mapper(dbSession).insert(item); | |||
return item; | |||
} | |||
public ActiveRuleDto update(DbSession dbSession, ActiveRuleDto item) { | |||
Preconditions.checkArgument(item.getProfileId() != null, QUALITY_PROFILE_IS_NOT_PERSISTED); | |||
Preconditions.checkArgument(item.getRuleId() != null, ActiveRuleDao.RULE_IS_NOT_PERSISTED); | |||
Preconditions.checkArgument(item.getId() != null, ACTIVE_RULE_IS_NOT_PERSISTED); | |||
checkArgument(item.getProfileId() != null, QUALITY_PROFILE_IS_NOT_PERSISTED); | |||
checkArgument(item.getRuleId() != null, ActiveRuleDao.RULE_IS_NOT_PERSISTED); | |||
checkArgument(item.getId() != null, ACTIVE_RULE_IS_NOT_PERSISTED); | |||
mapper(dbSession).update(item); | |||
return item; | |||
} | |||
@@ -128,8 +143,8 @@ public class ActiveRuleDao implements Dao { | |||
} | |||
public ActiveRuleParamDto insertParam(DbSession dbSession, ActiveRuleDto activeRule, ActiveRuleParamDto activeRuleParam) { | |||
Preconditions.checkArgument(activeRule.getId() != null, ACTIVE_RULE_IS_NOT_PERSISTED); | |||
Preconditions.checkArgument(activeRuleParam.getId() == null, ACTIVE_RULE_PARAM_IS_ALREADY_PERSISTED); | |||
checkArgument(activeRule.getId() != null, ACTIVE_RULE_IS_NOT_PERSISTED); | |||
checkArgument(activeRuleParam.getId() == null, ACTIVE_RULE_PARAM_IS_ALREADY_PERSISTED); | |||
Preconditions.checkNotNull(activeRuleParam.getRulesParameterId(), RULE_PARAM_IS_NOT_PERSISTED); | |||
activeRuleParam.setActiveRuleId(activeRule.getId()); | |||
@@ -199,4 +214,5 @@ public class ActiveRuleDao implements Dao { | |||
private static ActiveRuleMapper mapper(DbSession dbSession) { | |||
return dbSession.getMapper(ActiveRuleMapper.class); | |||
} | |||
} |
@@ -55,6 +55,10 @@ public interface ActiveRuleMapper { | |||
List<ActiveRuleDto> selectByRuleProfileUuid(@Param("ruleProfileUuid") String uuid); | |||
List<ActiveRuleDto> selectByRuleIdsAndRuleProfileUuids( | |||
@Param("ruleIds") Collection<Integer> ruleIds, | |||
@Param("ruleProfileUuids") Collection<String> ruleProfileUuids); | |||
void insertParameter(ActiveRuleParamDto dto); | |||
void updateParameter(ActiveRuleParamDto dto); |
@@ -233,8 +233,8 @@ public class QualityProfileDao implements Dao { | |||
DatabaseUtils.executeLargeUpdates(rulesProfileUuids, mapper::deleteRuleProfilesByUuids); | |||
} | |||
public List<QProfileDto> selectChildrenOfBuiltInRulesProfile(DbSession dbSession, RulesProfileDto rulesProfile) { | |||
return mapper(dbSession).selectChildrenOfBuiltInRulesProfile(rulesProfile.getKee()); | |||
public List<QProfileDto> selectQProfilesByRuleProfile(DbSession dbSession, RulesProfileDto rulesProfile) { | |||
return mapper(dbSession).selectQProfilesByRuleProfileUuid(rulesProfile.getKee()); | |||
} | |||
private static String sqlQueryString(@Nullable String query) { |
@@ -125,5 +125,5 @@ public interface QualityProfileMapper { | |||
void renameRuleProfiles(@Param("newName") String newName, @Param("updatedAt") Date updatedAt, @Param("uuids") Collection<String> uuids); | |||
List<QProfileDto> selectChildrenOfBuiltInRulesProfile(@Param("rulesProfileUuid") String rulesProfileUuid); | |||
List<QProfileDto> selectQProfilesByRuleProfileUuid(@Param("rulesProfileUuid") String rulesProfileUuid); | |||
} |
@@ -132,6 +132,16 @@ | |||
rp.kee = #{ruleProfileUuid, jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectByRuleIdsAndRuleProfileUuids" parameterType="map" resultType="org.sonar.db.qualityprofile.ActiveRuleDto"> | |||
select | |||
<include refid="activeRuleColumns"/> | |||
from active_rules a | |||
<include refid="activeRuleKeyJoin"/> | |||
where | |||
r.id in <foreach collection="ruleIds" item="ruleId" separator="," open="(" close=")">#{ruleId, jdbcType=BIGINT}</foreach> | |||
and rp.kee in <foreach collection="ruleProfileUuids" item="ruleProfileUuid" separator="," open="(" close=")">#{ruleProfileUuid, jdbcType=VARCHAR}</foreach> | |||
</select> | |||
<select id="selectByRuleId" parameterType="map" resultType="org.sonar.db.qualityprofile.OrgActiveRuleDto"> | |||
select | |||
<include refid="orgActiveRuleColumns"/> |
@@ -346,17 +346,13 @@ | |||
kee in <foreach collection="uuids" open="(" close=")" item="uuid" separator=",">#{uuid, jdbcType=VARCHAR}</foreach> | |||
</update> | |||
<select id="selectChildrenOfBuiltInRulesProfile" parameterType="string" resultType="org.sonar.db.qualityprofile.QProfileDto"> | |||
<select id="selectQProfilesByRuleProfileUuid" parameterType="string" resultType="org.sonar.db.qualityprofile.QProfileDto"> | |||
select | |||
<include refid="qProfileColumns"/> | |||
from org_qprofiles oqp | |||
inner join rules_profiles rp on oqp.rules_profile_uuid = rp.kee | |||
inner join org_qprofiles parentoqp on parentoqp.uuid = oqp.parent_uuid | |||
inner join rules_profiles parentrp on parentoqp.rules_profile_uuid = parentrp.kee | |||
where | |||
parentrp.kee = #{rulesProfileUuid, jdbcType=VARCHAR} | |||
and parentrp.is_built_in = ${_true} | |||
and oqp.parent_uuid is not null | |||
rp.kee= #{rulesProfileUuid, jdbcType=VARCHAR} | |||
</select> | |||
</mapper> | |||
@@ -20,6 +20,7 @@ | |||
package org.sonar.db.qualityprofile; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Objects; | |||
import java.util.function.Consumer; | |||
@@ -40,7 +41,6 @@ import org.sonar.db.rule.RuleParamDto; | |||
import static com.google.common.collect.Lists.newArrayList; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.emptyList; | |||
import static java.util.Collections.singletonList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.entry; | |||
import static org.assertj.core.api.Assertions.tuple; | |||
@@ -108,7 +108,7 @@ public class ActiveRuleDaoTest { | |||
} | |||
@Test | |||
public void select_by_rule() { | |||
public void selectByRuleId() { | |||
ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
ActiveRuleDto activeRule2 = createFor(profile2, rule1).setSeverity(BLOCKER); | |||
underTest.insert(dbSession, activeRule1); | |||
@@ -120,7 +120,7 @@ public class ActiveRuleDaoTest { | |||
} | |||
@Test | |||
public void select_by_rule_ids() { | |||
public void selectByRuleIds() { | |||
ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
ActiveRuleDto activeRule2 = createFor(profile1, rule2).setSeverity(BLOCKER); | |||
ActiveRuleDto activeRule3 = createFor(profile2, rule1).setSeverity(BLOCKER); | |||
@@ -129,7 +129,7 @@ public class ActiveRuleDaoTest { | |||
underTest.insert(dbSession, activeRule3); | |||
dbSession.commit(); | |||
assertThat(underTest.selectByRuleIds(dbSession, organization, singletonList(rule1.getId()))) | |||
assertThat(underTest.selectByRuleIds(dbSession, organization, asList(rule1.getId()))) | |||
.extracting("key").containsOnly(activeRule1.getKey(), activeRule3.getKey()); | |||
assertThat(underTest.selectByRuleIds(dbSession, organization, newArrayList(rule1.getId(), rule2.getId()))) | |||
.extracting("key").containsOnly(activeRule1.getKey(), activeRule2.getKey(), activeRule3.getKey()); | |||
@@ -160,7 +160,7 @@ public class ActiveRuleDaoTest { | |||
} | |||
@Test | |||
public void selectByRuleProfileUuid() { | |||
public void selectByRuleProfile() { | |||
ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER); | |||
ActiveRuleDto activeRule2 = createFor(profile1, rule2).setSeverity(MAJOR); | |||
underTest.insert(dbSession, activeRule1); | |||
@@ -175,6 +175,42 @@ public class ActiveRuleDaoTest { | |||
assertThat(underTest.selectByProfile(dbSession, profile2)).isEmpty(); | |||
} | |||
@Test | |||
public void selectByRulesAndRuleProfileUuids() { | |||
ActiveRuleDto rule1P1 = createFor(profile1, rule1).setSeverity(MAJOR); | |||
ActiveRuleDto rule2P1 = createFor(profile1, rule2).setSeverity(MAJOR); | |||
ActiveRuleDto rule1P2 = createFor(profile2, rule1).setSeverity(MAJOR); | |||
underTest.insert(dbSession, rule1P1); | |||
underTest.insert(dbSession, rule2P1); | |||
underTest.insert(dbSession, rule1P2); | |||
// empty rules | |||
Collection<ActiveRuleDto> result = underTest.selectByRulesAndRuleProfileUuids(dbSession, emptyList(), asList(profile1.getRulesProfileUuid())); | |||
assertThat(result).isEmpty(); | |||
// empty profiles | |||
result = underTest.selectByRulesAndRuleProfileUuids(dbSession, asList(rule1), emptyList()); | |||
assertThat(result).isEmpty(); | |||
// match | |||
result = underTest.selectByRulesAndRuleProfileUuids(dbSession, asList(rule1), asList(profile1.getRulesProfileUuid(), profile2.getRulesProfileUuid())); | |||
assertThat(result) | |||
.extracting(ActiveRuleDto::getId) | |||
.containsExactlyInAnyOrder(rule1P1.getId(), rule1P2.getId()); | |||
result = underTest.selectByRulesAndRuleProfileUuids(dbSession, asList(rule1, rule2), asList(profile1.getRulesProfileUuid(), profile2.getRulesProfileUuid())); | |||
assertThat(result) | |||
.extracting(ActiveRuleDto::getId) | |||
.containsExactlyInAnyOrder(rule1P1.getId(), rule1P2.getId(), rule2P1.getId()); | |||
// do not match | |||
result = underTest.selectByRulesAndRuleProfileUuids(dbSession, asList(rule3), asList(profile1.getRulesProfileUuid(), profile2.getRulesProfileUuid())); | |||
assertThat(result).isEmpty(); | |||
result = underTest.selectByRulesAndRuleProfileUuids(dbSession, asList(rule1), asList("unknown")); | |||
assertThat(result).isEmpty(); | |||
} | |||
@Test | |||
public void insert() { | |||
ActiveRuleDto activeRule = createFor(profile1, rule1) | |||
@@ -527,7 +563,7 @@ public class ActiveRuleDaoTest { | |||
ActiveRuleCountQuery.Builder builder = ActiveRuleCountQuery.builder().setOrganization(organization); | |||
assertThat(underTest.countActiveRulesByQuery(dbSession, builder.setProfiles(asList(profile1, profile2)).build())) | |||
.containsOnly(entry(profile1.getKee(), 2L), entry(profile2.getKee(), 1L)); | |||
assertThat(underTest.countActiveRulesByQuery(dbSession, builder.setProfiles(singletonList(profileWithoutActiveRule)).build())).isEmpty(); | |||
assertThat(underTest.countActiveRulesByQuery(dbSession, builder.setProfiles(asList(profileWithoutActiveRule)).build())).isEmpty(); | |||
assertThat(underTest.countActiveRulesByQuery(dbSession, builder.setProfiles(asList(profile1, profile2, profileWithoutActiveRule)).build())).containsOnly( | |||
entry(profile1.getKee(), 2L), | |||
entry(profile2.getKee(), 1L)); | |||
@@ -547,9 +583,9 @@ public class ActiveRuleDaoTest { | |||
ActiveRuleCountQuery.Builder builder = ActiveRuleCountQuery.builder().setOrganization(organization); | |||
assertThat(underTest.countActiveRulesByQuery(dbSession, builder.setProfiles(asList(profile1, profile2)).setRuleStatus(BETA).build())) | |||
.containsOnly(entry(profile1.getKee(), 1L), entry(profile2.getKee(), 1L)); | |||
assertThat(underTest.countActiveRulesByQuery(dbSession, builder.setProfiles(singletonList(profile1)).setRuleStatus(READY).build())) | |||
assertThat(underTest.countActiveRulesByQuery(dbSession, builder.setProfiles(asList(profile1)).setRuleStatus(READY).build())) | |||
.containsOnly(entry(profile1.getKee(), 2L)); | |||
assertThat(underTest.countActiveRulesByQuery(dbSession, builder.setProfiles(singletonList(profile1)).setRuleStatus(REMOVED).build())) | |||
assertThat(underTest.countActiveRulesByQuery(dbSession, builder.setProfiles(asList(profile1)).setRuleStatus(REMOVED).build())) | |||
.containsOnly(entry(profile1.getKee(), 1L)); | |||
} | |||
@@ -577,7 +613,7 @@ public class ActiveRuleDaoTest { | |||
assertThat(underTest.countActiveRulesByQuery(dbSession, | |||
ActiveRuleCountQuery.builder().setOrganization(organization).setProfiles(asList(profile1, profileOnAnotherOrganization)).build())) | |||
.containsOnly(entry(profile1.getKee(), 1L)); | |||
.containsOnly(entry(profile1.getKee(), 1L)); | |||
} | |||
@Test | |||
@@ -599,9 +635,9 @@ public class ActiveRuleDaoTest { | |||
.extracting(IndexedActiveRuleDto::getId, IndexedActiveRuleDto::getRepository, IndexedActiveRuleDto::getKey, IndexedActiveRuleDto::getRuleProfileUuid, | |||
IndexedActiveRuleDto::getSeverity, IndexedActiveRuleDto::getInheritance) | |||
.containsExactlyInAnyOrder( | |||
tuple((long)ar1.getId(), ar1.getRuleKey().repository(), ar1.getRuleKey().rule(), profile1.getRulesProfileUuid(), ar1.getSeverity(), ar1.getInheritance()), | |||
tuple((long)ar2.getId(), ar2.getRuleKey().repository(), ar2.getRuleKey().rule(), profile2.getRulesProfileUuid(), ar2.getSeverity(), ar2.getInheritance()), | |||
tuple((long)ar3.getId(), ar3.getRuleKey().repository(), ar3.getRuleKey().rule(), profile2.getRulesProfileUuid(), ar3.getSeverity(), ar3.getInheritance())); | |||
tuple((long) ar1.getId(), ar1.getRuleKey().repository(), ar1.getRuleKey().rule(), profile1.getRulesProfileUuid(), ar1.getSeverity(), ar1.getInheritance()), | |||
tuple((long) ar2.getId(), ar2.getRuleKey().repository(), ar2.getRuleKey().rule(), profile2.getRulesProfileUuid(), ar2.getSeverity(), ar2.getInheritance()), | |||
tuple((long) ar3.getId(), ar3.getRuleKey().repository(), ar3.getRuleKey().rule(), profile2.getRulesProfileUuid(), ar3.getSeverity(), ar3.getInheritance())); | |||
} | |||
@Test | |||
@@ -611,13 +647,13 @@ public class ActiveRuleDaoTest { | |||
ActiveRuleDto ar3 = db.qualityProfiles().activateRule(profile2, rule2); | |||
Accumulator accumulator = new Accumulator(); | |||
underTest.scrollByIdsForIndexing(dbSession, asList((long)ar1.getId(), (long)ar2.getId()), accumulator); | |||
underTest.scrollByIdsForIndexing(dbSession, asList((long) ar1.getId(), (long) ar2.getId()), accumulator); | |||
assertThat(accumulator.list) | |||
.extracting(IndexedActiveRuleDto::getId, IndexedActiveRuleDto::getRepository, IndexedActiveRuleDto::getKey, IndexedActiveRuleDto::getRuleProfileUuid, | |||
IndexedActiveRuleDto::getSeverity) | |||
.containsExactlyInAnyOrder( | |||
tuple((long)ar1.getId(), ar1.getRuleKey().repository(), ar1.getRuleKey().rule(), profile1.getRulesProfileUuid(), ar1.getSeverity()), | |||
tuple((long)ar2.getId(), ar2.getRuleKey().repository(), ar2.getRuleKey().rule(), profile2.getRulesProfileUuid(), ar2.getSeverity())); | |||
tuple((long) ar1.getId(), ar1.getRuleKey().repository(), ar1.getRuleKey().rule(), profile1.getRulesProfileUuid(), ar1.getSeverity()), | |||
tuple((long) ar2.getId(), ar2.getRuleKey().repository(), ar2.getRuleKey().rule(), profile2.getRulesProfileUuid(), ar2.getSeverity())); | |||
} | |||
@Test | |||
@@ -632,8 +668,8 @@ public class ActiveRuleDaoTest { | |||
.extracting(IndexedActiveRuleDto::getId, IndexedActiveRuleDto::getRepository, IndexedActiveRuleDto::getKey, IndexedActiveRuleDto::getRuleProfileUuid, | |||
IndexedActiveRuleDto::getSeverity) | |||
.containsExactlyInAnyOrder( | |||
tuple((long)ar2.getId(), ar2.getRuleKey().repository(), ar2.getRuleKey().rule(), profile2.getRulesProfileUuid(), ar2.getSeverity()), | |||
tuple((long)ar3.getId(), ar3.getRuleKey().repository(), ar3.getRuleKey().rule(), profile2.getRulesProfileUuid(), ar3.getSeverity())); | |||
tuple((long) ar2.getId(), ar2.getRuleKey().repository(), ar2.getRuleKey().rule(), profile2.getRulesProfileUuid(), ar2.getSeverity()), | |||
tuple((long) ar3.getId(), ar3.getRuleKey().repository(), ar3.getRuleKey().rule(), profile2.getRulesProfileUuid(), ar3.getSeverity())); | |||
} | |||
private static class Accumulator implements Consumer<IndexedActiveRuleDto> { |
@@ -49,9 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.tuple; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.core.util.stream.MoreCollectors.toList; | |||
import static org.sonar.db.qualityprofile.QualityProfileTesting.newQualityProfileDto; | |||
import static org.sonar.db.qualityprofile.RulesProfileDto.from; | |||
public class QualityProfileDaoTest { | |||
@@ -706,6 +704,36 @@ public class QualityProfileDaoTest { | |||
assertThat(underTest.selectOrFailByUuid(dbSession, profile.getKee()).getName()).isEqualTo("foo"); | |||
} | |||
@Test | |||
public void selectQProfilesByRuleProfileUuid() { | |||
OrganizationDto org1 = db.organizations().insert(); | |||
OrganizationDto org2 = db.organizations().insert(); | |||
RulesProfileDto ruleProfile1 = QualityProfileTesting.newRuleProfileDto(); | |||
OrgQProfileDto profile1InOrg1 = new OrgQProfileDto().setOrganizationUuid(org1.getUuid()).setRulesProfileUuid(ruleProfile1.getKee()).setUuid(Uuids.create()); | |||
OrgQProfileDto profile1InOrg2 = new OrgQProfileDto().setOrganizationUuid(org2.getUuid()).setRulesProfileUuid(ruleProfile1.getKee()).setUuid(Uuids.create()); | |||
RulesProfileDto ruleProfile2 = QualityProfileTesting.newRuleProfileDto(); | |||
OrgQProfileDto profile2InOrg1 = new OrgQProfileDto().setOrganizationUuid(org1.getUuid()).setRulesProfileUuid(ruleProfile2.getKee()).setUuid(Uuids.create()); | |||
db.getDbClient().qualityProfileDao().insert(db.getSession(), ruleProfile1); | |||
db.getDbClient().qualityProfileDao().insert(db.getSession(), profile1InOrg1); | |||
db.getDbClient().qualityProfileDao().insert(db.getSession(), profile1InOrg2); | |||
db.getDbClient().qualityProfileDao().insert(db.getSession(), ruleProfile2); | |||
db.getDbClient().qualityProfileDao().insert(db.getSession(), profile2InOrg1); | |||
List<QProfileDto> result = db.getDbClient().qualityProfileDao().selectQProfilesByRuleProfile(db.getSession(), ruleProfile1); | |||
assertThat(result).extracting(QProfileDto::getKee).containsExactlyInAnyOrder(profile1InOrg1.getUuid(), profile1InOrg2.getUuid()); | |||
result = db.getDbClient().qualityProfileDao().selectQProfilesByRuleProfile(db.getSession(), ruleProfile2); | |||
assertThat(result).extracting(QProfileDto::getKee).containsExactlyInAnyOrder(profile2InOrg1.getUuid()); | |||
} | |||
@Test | |||
public void selectQProfilesByRuleProfileUuid_returns_empty_list_if_rule_profile_does_not_exist() { | |||
List<QProfileDto> result = db.getDbClient().qualityProfileDao().selectQProfilesByRuleProfile(db.getSession(), new RulesProfileDto().setKee("unknown")); | |||
assertThat(result).isEmpty(); | |||
} | |||
private List<QProfileDto> createSharedData() { | |||
QProfileDto dto1 = new QProfileDto() | |||
.setKee("java_sonar_way") | |||
@@ -739,36 +767,4 @@ public class QualityProfileDaoTest { | |||
return Arrays.asList(dto1, dto2); | |||
} | |||
@Test | |||
public void selectChildrenOfBuiltInRulesProfile_must_return_only_inherited_profiles() { | |||
OrganizationDto org1 = db.organizations().insert(); | |||
OrganizationDto org2 = db.organizations().insert(); | |||
OrganizationDto org3 = db.organizations().insert(); | |||
QProfileDto builtInProfile = db.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(true).setLanguage("java").setName("foo")); | |||
QProfileDto javaProfileOrg2 = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); | |||
QProfileDto inheritedJavaProfileOrg2 = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo").setParentKee(builtInProfile.getKee())); | |||
QProfileDto differentLanguage = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("cobol").setName("foo")); | |||
QProfileDto differentName = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("bar")); | |||
QProfileDto javaProfileOrg3 = db.qualityProfiles().insert(org3, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); | |||
QProfileDto inheritedJavaProfileOrg3 = db.qualityProfiles().insert(org3, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo").setParentKee(builtInProfile.getKee())); | |||
List<QProfileDto> children = db.getDbClient().qualityProfileDao().selectChildrenOfBuiltInRulesProfile(db.getSession(), from(builtInProfile)); | |||
assertThat(children.stream().map(qp -> qp.getId()).collect(toList())).containsExactlyInAnyOrder( | |||
inheritedJavaProfileOrg2.getId(), inheritedJavaProfileOrg3.getId()); | |||
} | |||
@Test | |||
public void selectChildrenOfBuiltInRulesProfile_must_return_empty_list_if_not_built_in() { | |||
OrganizationDto org = db.organizations().insert(); | |||
QProfileDto notBuiltInProfile = db.qualityProfiles().insert(org, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); | |||
QProfileDto inheritedProfile = db.qualityProfiles().insert(org, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo").setParentKee(notBuiltInProfile.getKee())); | |||
List<QProfileDto> children = db.getDbClient().qualityProfileDao().selectChildrenOfBuiltInRulesProfile(db.getSession(), from(notBuiltInProfile)); | |||
assertThat(children).isEmpty(); | |||
} | |||
} |
@@ -167,8 +167,9 @@ import org.sonar.server.qualityprofile.QProfileCopier; | |||
import org.sonar.server.qualityprofile.QProfileExporters; | |||
import org.sonar.server.qualityprofile.QProfileFactoryImpl; | |||
import org.sonar.server.qualityprofile.QProfileResetImpl; | |||
import org.sonar.server.qualityprofile.QProfileRulesImpl; | |||
import org.sonar.server.qualityprofile.QProfileTreeImpl; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.RuleActivatorContextFactory; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.qualityprofile.ws.ProfilesWs; | |||
import org.sonar.server.qualityprofile.ws.QProfilesWsModule; | |||
@@ -306,9 +307,10 @@ public class PlatformLevel4 extends PlatformLevel { | |||
AnnotationProfileParser.class, | |||
QProfileComparison.class, | |||
ProfilesWs.class, | |||
QProfileTreeImpl.class, | |||
QProfileRulesImpl.class, | |||
RuleActivator.class, | |||
QProfileExporters.class, | |||
RuleActivatorContextFactory.class, | |||
QProfileFactoryImpl.class, | |||
QProfileCopier.class, | |||
QProfileBackuperImpl.class, |
@@ -20,6 +20,8 @@ | |||
package org.sonar.server.qualityprofile; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
@@ -45,22 +47,31 @@ public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate { | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
} | |||
public List<ActiveRuleChange> update(DbSession dbSession, BuiltInQProfile builtIn, RulesProfileDto ruleProfile) { | |||
public List<ActiveRuleChange> update(DbSession dbSession, BuiltInQProfile builtIn, RulesProfileDto rulesProfile) { | |||
// Keep reference to all the activated rules before update | |||
Set<RuleKey> toBeDeactivated = dbClient.activeRuleDao().selectByRuleProfile(dbSession, ruleProfile) | |||
Set<RuleKey> deactivatedKeys = dbClient.activeRuleDao().selectByRuleProfile(dbSession, rulesProfile) | |||
.stream() | |||
.map(ActiveRuleDto::getRuleKey) | |||
.collect(MoreCollectors.toHashSet()); | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
builtIn.getActiveRules().forEach(ar -> { | |||
Collection<RuleActivation> activations = new ArrayList<>(); | |||
Collection<RuleKey> ruleKeys = new HashSet<>(deactivatedKeys); | |||
for (BuiltInActiveRule ar : builtIn.getActiveRules()) { | |||
RuleActivation activation = convert(ar); | |||
toBeDeactivated.remove(activation.getRuleKey()); | |||
changes.addAll(ruleActivator.activateOnBuiltInRulesProfile(dbSession, activation, ruleProfile)); | |||
}); | |||
activations.add(activation); | |||
ruleKeys.add(activation.getRuleKey()); | |||
deactivatedKeys.remove(activation.getRuleKey()); | |||
} | |||
RuleActivationContext context = ruleActivator.createContextForBuiltInProfile(dbSession, rulesProfile, ruleKeys); | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
for (RuleActivation activation : activations) { | |||
changes.addAll(ruleActivator.activate(dbSession, activation, context)); | |||
} | |||
// these rules are not part of the built-in profile anymore | |||
toBeDeactivated.forEach(ruleKey -> changes.addAll(ruleActivator.deactivateOnBuiltInRulesProfile(dbSession, ruleProfile, ruleKey, false))); | |||
deactivatedKeys.forEach(ruleKey -> changes.addAll(ruleActivator.deactivate(dbSession, context, ruleKey, false))); | |||
activeRuleIndexer.commitAndIndex(dbSession, changes); | |||
return changes; |
@@ -36,6 +36,7 @@ import org.sonar.api.profiles.ProfileExporter; | |||
import org.sonar.api.profiles.ProfileImporter; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.ActiveRuleParam; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
@@ -59,14 +60,14 @@ public class QProfileExporters { | |||
private final DbClient dbClient; | |||
private final RuleFinder ruleFinder; | |||
private final RuleActivator ruleActivator; | |||
private final QProfileRules qProfileRules; | |||
private final ProfileExporter[] exporters; | |||
private final ProfileImporter[] importers; | |||
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, RuleActivator ruleActivator, ProfileExporter[] exporters, ProfileImporter[] importers) { | |||
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, QProfileRules qProfileRules, ProfileExporter[] exporters, ProfileImporter[] importers) { | |||
this.dbClient = dbClient; | |||
this.ruleFinder = ruleFinder; | |||
this.ruleActivator = ruleActivator; | |||
this.qProfileRules = qProfileRules; | |||
this.exporters = exporters; | |||
this.importers = importers; | |||
} | |||
@@ -74,22 +75,22 @@ public class QProfileExporters { | |||
/** | |||
* Used by Pico if no {@link ProfileImporter} is found | |||
*/ | |||
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, RuleActivator ruleActivator, ProfileExporter[] exporters) { | |||
this(dbClient, ruleFinder, ruleActivator, exporters, new ProfileImporter[0]); | |||
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, QProfileRules qProfileRules, ProfileExporter[] exporters) { | |||
this(dbClient, ruleFinder, qProfileRules, exporters, new ProfileImporter[0]); | |||
} | |||
/** | |||
* Used by Pico if no {@link ProfileExporter} is found | |||
*/ | |||
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, RuleActivator ruleActivator, ProfileImporter[] importers) { | |||
this(dbClient, ruleFinder, ruleActivator, new ProfileExporter[0], importers); | |||
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, QProfileRules qProfileRules, ProfileImporter[] importers) { | |||
this(dbClient, ruleFinder, qProfileRules, new ProfileExporter[0], importers); | |||
} | |||
/** | |||
* Used by Pico if no {@link ProfileImporter} nor {@link ProfileExporter} is found | |||
*/ | |||
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, RuleActivator ruleActivator) { | |||
this(dbClient, ruleFinder, ruleActivator, new ProfileExporter[0], new ProfileImporter[0]); | |||
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, QProfileRules qProfileRules) { | |||
this(dbClient, ruleFinder, qProfileRules, new ProfileExporter[0], new ProfileImporter[0]); | |||
} | |||
public List<ProfileExporter> exportersForLanguage(String language) { | |||
@@ -139,27 +140,27 @@ public class QProfileExporters { | |||
throw new NotFoundException("Unknown quality profile exporter: " + exporterKey); | |||
} | |||
public QProfileResult importXml(QProfileDto profileDto, String importerKey, InputStream xml, DbSession dbSession) { | |||
return importXml(profileDto, importerKey, new InputStreamReader(xml, StandardCharsets.UTF_8), dbSession); | |||
public QProfileResult importXml(QProfileDto profile, String importerKey, InputStream xml, DbSession dbSession) { | |||
return importXml(profile, importerKey, new InputStreamReader(xml, StandardCharsets.UTF_8), dbSession); | |||
} | |||
private QProfileResult importXml(QProfileDto profileDto, String importerKey, Reader xml, DbSession dbSession) { | |||
private QProfileResult importXml(QProfileDto profile, String importerKey, Reader xml, DbSession dbSession) { | |||
QProfileResult result = new QProfileResult(); | |||
ValidationMessages messages = ValidationMessages.create(); | |||
ProfileImporter importer = getProfileImporter(importerKey); | |||
RulesProfile rulesProfile = importer.importProfile(xml, messages); | |||
List<ActiveRuleChange> changes = importProfile(profileDto, rulesProfile, dbSession); | |||
RulesProfile definition = importer.importProfile(xml, messages); | |||
List<ActiveRuleChange> changes = importProfile(profile, definition, dbSession); | |||
result.addChanges(changes); | |||
processValidationMessages(messages, result); | |||
return result; | |||
} | |||
private List<ActiveRuleChange> importProfile(QProfileDto profileDto, RulesProfile rulesProfile, DbSession dbSession) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
for (org.sonar.api.rules.ActiveRule activeRule : rulesProfile.getActiveRules()) { | |||
changes.addAll(ruleActivator.activate(dbSession, toRuleActivation(activeRule), profileDto)); | |||
} | |||
return changes; | |||
private List<ActiveRuleChange> importProfile(QProfileDto profile, RulesProfile definition, DbSession dbSession) { | |||
List<ActiveRule> activeRules = definition.getActiveRules(); | |||
List<RuleActivation> activations = activeRules.stream() | |||
.map(QProfileExporters::toRuleActivation) | |||
.collect(MoreCollectors.toArrayList(activeRules.size())); | |||
return qProfileRules.activateAndCommit(dbSession, profile, activations); | |||
} | |||
private ProfileImporter getProfileImporter(String importerKey) { | |||
@@ -177,7 +178,7 @@ public class QProfileExporters { | |||
result.addInfos(messages.getInfos()); | |||
} | |||
private static RuleActivation toRuleActivation(org.sonar.api.rules.ActiveRule activeRule) { | |||
private static RuleActivation toRuleActivation(ActiveRule activeRule) { | |||
RuleKey ruleKey = activeRule.getRule().ruleKey(); | |||
String severity = activeRule.getSeverity().name(); | |||
Map<String, String> params = activeRule.getActiveRuleParams().stream() |
@@ -53,20 +53,24 @@ public class QProfileResetImpl implements QProfileReset { | |||
public BulkChangeResult reset(DbSession dbSession, QProfileDto profile, Collection<RuleActivation> activations) { | |||
requireNonNull(profile.getId(), "Quality profile must be persisted"); | |||
checkArgument(!profile.isBuiltIn(), "Operation forbidden for built-in Quality Profile '%s'", profile.getKee()); | |||
BulkChangeResult result = new BulkChangeResult(); | |||
Set<RuleKey> ruleToBeDeactivated = new HashSet<>(); | |||
Set<RuleKey> rulesToBeDeactivated = new HashSet<>(); | |||
// Keep reference to all the activated rules before backup restore | |||
for (ActiveRuleDto activeRuleDto : db.activeRuleDao().selectByProfile(dbSession, profile)) { | |||
if (activeRuleDto.getInheritance() == null) { | |||
// inherited rules can't be deactivated | |||
ruleToBeDeactivated.add(activeRuleDto.getRuleKey()); | |||
rulesToBeDeactivated.add(activeRuleDto.getRuleKey()); | |||
} | |||
} | |||
Set<RuleKey> ruleKeys = new HashSet<>(rulesToBeDeactivated); | |||
activations.forEach(a -> ruleKeys.add(a.getRuleKey())); | |||
RuleActivationContext context = activator.createContextForUserProfile(dbSession, profile, ruleKeys); | |||
for (RuleActivation activation : activations) { | |||
try { | |||
List<ActiveRuleChange> changes = activator.activate(dbSession, activation, profile); | |||
ruleToBeDeactivated.remove(activation.getRuleKey()); | |||
List<ActiveRuleChange> changes = activator.activate(dbSession, activation, context); | |||
rulesToBeDeactivated.remove(activation.getRuleKey()); | |||
result.incrementSucceeded(); | |||
result.addChanges(changes); | |||
} catch (BadRequestException e) { | |||
@@ -75,11 +79,10 @@ public class QProfileResetImpl implements QProfileReset { | |||
} | |||
} | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
changes.addAll(result.getChanges()); | |||
for (RuleKey ruleKey : ruleToBeDeactivated) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(result.getChanges()); | |||
for (RuleKey ruleKey : rulesToBeDeactivated) { | |||
try { | |||
changes.addAll(activator.deactivate(dbSession, profile, ruleKey)); | |||
changes.addAll(activator.deactivate(dbSession, context, ruleKey, false)); | |||
} catch (BadRequestException e) { | |||
// ignore, probably a rule inherited from parent that can't be deactivated | |||
} |
@@ -0,0 +1,66 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program 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. | |||
* | |||
* This program 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.qualityprofile; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.server.rule.index.RuleQuery; | |||
/** | |||
* Operations related to activation and deactivation of rules on user profiles. | |||
* Use {@link BuiltInQProfileUpdate} for built-in profiles. | |||
*/ | |||
@ServerSide | |||
public interface QProfileRules { | |||
/** | |||
* Activate multiple rules at once on a Quality profile. | |||
* Db session is committed and Elasticsearch indices are updated. | |||
* If an activation fails to be executed, then all others are | |||
* canceled, db session is not committed and an exception is | |||
* thrown. | |||
*/ | |||
List<ActiveRuleChange> activateAndCommit(DbSession dbSession, QProfileDto profile, Collection<RuleActivation> activations); | |||
/** | |||
* Same as {@link #activateAndCommit(DbSession, QProfileDto, Collection)} except | |||
* that: | |||
* - rules are loaded from search engine | |||
* - rules are activated with default parameters | |||
* - an activation failure does not break others. No exception is thrown. | |||
*/ | |||
BulkChangeResult bulkActivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery, @Nullable String severity); | |||
List<ActiveRuleChange> deactivateAndCommit(DbSession dbSession, QProfileDto profile, Collection<RuleKey> ruleKeys); | |||
BulkChangeResult bulkDeactivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery); | |||
/** | |||
* Delete a rule from all Quality profiles. Db session is not committed. As a | |||
* consequence Elasticsearch indices are NOT updated. | |||
*/ | |||
List<ActiveRuleChange> deleteRule(DbSession dbSession, RuleDefinitionDto rule); | |||
} |
@@ -0,0 +1,139 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program 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. | |||
* | |||
* This program 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.qualityprofile; | |||
import com.google.common.collect.Sets; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.function.BiFunction; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleQuery; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
public class QProfileRulesImpl implements QProfileRules { | |||
private final DbClient db; | |||
private final RuleActivator ruleActivator; | |||
private final RuleIndex ruleIndex; | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
public QProfileRulesImpl(DbClient db, RuleActivator ruleActivator, RuleIndex ruleIndex, ActiveRuleIndexer activeRuleIndexer) { | |||
this.db = db; | |||
this.ruleActivator = ruleActivator; | |||
this.ruleIndex = ruleIndex; | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
} | |||
@Override | |||
public List<ActiveRuleChange> activateAndCommit(DbSession dbSession, QProfileDto profile, Collection<RuleActivation> activations) { | |||
verifyNotBuiltIn(profile); | |||
Set<RuleKey> ruleKeys = activations.stream().map(RuleActivation::getRuleKey).collect(MoreCollectors.toHashSet(activations.size())); | |||
RuleActivationContext context = ruleActivator.createContextForUserProfile(dbSession, profile, ruleKeys); | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
for (RuleActivation activation : activations) { | |||
changes.addAll(ruleActivator.activate(dbSession, activation, context)); | |||
} | |||
activeRuleIndexer.commitAndIndex(dbSession, changes); | |||
return changes; | |||
} | |||
@Override | |||
public BulkChangeResult bulkActivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery, @Nullable String severity) { | |||
verifyNotBuiltIn(profile); | |||
return doBulk(dbSession, profile, ruleQuery, (context, ruleKey) -> { | |||
RuleActivation activation = RuleActivation.create(ruleKey, severity, null); | |||
return ruleActivator.activate(dbSession, activation, context); | |||
}); | |||
} | |||
@Override | |||
public List<ActiveRuleChange> deactivateAndCommit(DbSession dbSession, QProfileDto profile, Collection<RuleKey> ruleKeys) { | |||
verifyNotBuiltIn(profile); | |||
RuleActivationContext context = ruleActivator.createContextForUserProfile(dbSession, profile, ruleKeys); | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
for (RuleKey ruleKey : ruleKeys) { | |||
changes.addAll(ruleActivator.deactivate(dbSession, context, ruleKey, false)); | |||
} | |||
activeRuleIndexer.commitAndIndex(dbSession, changes); | |||
return changes; | |||
} | |||
@Override | |||
public BulkChangeResult bulkDeactivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery) { | |||
verifyNotBuiltIn(profile); | |||
return doBulk(dbSession, profile, ruleQuery, (context, ruleKey) -> ruleActivator.deactivate(dbSession, context, ruleKey, false)); | |||
} | |||
@Override | |||
public List<ActiveRuleChange> deleteRule(DbSession dbSession, RuleDefinitionDto rule) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
List<Integer> activeRuleIds = new ArrayList<>(); | |||
db.activeRuleDao().selectByRuleIdOfAllOrganizations(dbSession, rule.getId()).forEach(ar -> { | |||
activeRuleIds.add(ar.getId()); | |||
changes.add(new ActiveRuleChange(ActiveRuleChange.Type.DEACTIVATED, ar)); | |||
}); | |||
db.activeRuleDao().deleteByIds(dbSession, activeRuleIds); | |||
db.activeRuleDao().deleteParamsByActiveRuleIds(dbSession, activeRuleIds); | |||
return changes; | |||
} | |||
private static void verifyNotBuiltIn(QProfileDto profile) { | |||
checkArgument(!profile.isBuiltIn(), "The built-in profile %s is read-only and can't be updated", profile.getName()); | |||
} | |||
private BulkChangeResult doBulk(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery, BiFunction<RuleActivationContext, RuleKey, List<ActiveRuleChange>> fn) { | |||
BulkChangeResult result = new BulkChangeResult(); | |||
Collection<RuleKey> ruleKeys = Sets.newHashSet(ruleIndex.searchAll(ruleQuery)); | |||
RuleActivationContext context = ruleActivator.createContextForUserProfile(dbSession, profile, ruleKeys); | |||
for (RuleKey ruleKey : ruleKeys) { | |||
try { | |||
List<ActiveRuleChange> changes = fn.apply(context, ruleKey); | |||
result.addChanges(changes); | |||
if (!changes.isEmpty()) { | |||
result.incrementSucceeded(); | |||
} | |||
} catch (BadRequestException e) { | |||
// other exceptions stop the bulk activation | |||
result.incrementFailed(); | |||
result.getErrors().addAll(e.errors()); | |||
} | |||
} | |||
activeRuleIndexer.commitAndIndex(dbSession, result.getChanges()); | |||
return result; | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program 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. | |||
* | |||
* This program 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.qualityprofile; | |||
import java.util.List; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
/** | |||
* Operations related to hierarchy of profiles | |||
*/ | |||
@ServerSide | |||
public interface QProfileTree { | |||
List<ActiveRuleChange> removeParentAndCommit(DbSession dbSession, QProfileDto profile); | |||
List<ActiveRuleChange> setParentAndCommit(DbSession dbSession, QProfileDto profile, QProfileDto parentProfile); | |||
} |
@@ -0,0 +1,141 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program 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. | |||
* | |||
* This program 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.qualityprofile; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.utils.System2; | |||
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.OrgActiveRuleDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import static org.sonar.server.ws.WsUtils.checkRequest; | |||
public class QProfileTreeImpl implements QProfileTree { | |||
private final DbClient db; | |||
private final RuleActivator ruleActivator; | |||
private final System2 system2; | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
public QProfileTreeImpl(DbClient db, RuleActivator ruleActivator, System2 system2, ActiveRuleIndexer activeRuleIndexer) { | |||
this.db = db; | |||
this.ruleActivator = ruleActivator; | |||
this.system2 = system2; | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
} | |||
@Override | |||
public List<ActiveRuleChange> removeParentAndCommit(DbSession dbSession, QProfileDto profile) { | |||
List<ActiveRuleChange> changes = removeParent(dbSession, profile); | |||
activeRuleIndexer.commitAndIndex(dbSession, changes); | |||
return changes; | |||
} | |||
@Override | |||
public List<ActiveRuleChange> setParentAndCommit(DbSession dbSession, QProfileDto profile, QProfileDto parentProfile) { | |||
List<ActiveRuleChange> changes = setParent(dbSession, profile, parentProfile); | |||
activeRuleIndexer.commitAndIndex(dbSession, changes); | |||
return changes; | |||
} | |||
private List<ActiveRuleChange> setParent(DbSession dbSession, QProfileDto profile, QProfileDto parent) { | |||
checkRequest(parent.getLanguage().equals(profile.getLanguage()), "Cannot set the profile '%s' as the parent of profile '%s' since their languages differ ('%s' != '%s')", | |||
parent.getKee(), profile.getKee(), parent.getLanguage(), profile.getLanguage()); | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
if (parent.getKee().equals(profile.getParentKee())) { | |||
return changes; | |||
} | |||
checkRequest(!isDescendant(dbSession, profile, parent), "Descendant profile '%s' can not be selected as parent of '%s'", parent.getKee(), profile.getKee()); | |||
changes.addAll(removeParent(dbSession, profile)); | |||
// set new parent | |||
profile.setParentKee(parent.getKee()); | |||
db.qualityProfileDao().update(dbSession, profile); | |||
List<OrgActiveRuleDto> parentActiveRules = db.activeRuleDao().selectByProfile(dbSession, parent); | |||
Collection<RuleKey> ruleKeys = parentActiveRules.stream().map(ActiveRuleDto::getRuleKey).collect(MoreCollectors.toArrayList()); | |||
RuleActivationContext context = ruleActivator.createContextForUserProfile(dbSession, profile, ruleKeys); | |||
for (ActiveRuleDto parentActiveRule : parentActiveRules) { | |||
try { | |||
RuleActivation activation = RuleActivation.create(parentActiveRule.getRuleKey(), null, null); | |||
changes.addAll(ruleActivator.activate(dbSession, activation, context)); | |||
} catch (BadRequestException e) { | |||
// for example because rule status is REMOVED | |||
// TODO return errors | |||
} | |||
} | |||
return changes; | |||
} | |||
private List<ActiveRuleChange> removeParent(DbSession dbSession, QProfileDto profile) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
if (profile.getParentKee() == null) { | |||
return changes; | |||
} | |||
profile.setParentKee(null); | |||
db.qualityProfileDao().update(dbSession, profile); | |||
List<OrgActiveRuleDto> activeRules = db.activeRuleDao().selectByProfile(dbSession, profile); | |||
Collection<RuleKey> ruleKeys = activeRules.stream().map(ActiveRuleDto::getRuleKey).collect(MoreCollectors.toArrayList()); | |||
RuleActivationContext context = ruleActivator.createContextForUserProfile(dbSession, profile, ruleKeys); | |||
for (OrgActiveRuleDto activeRule : activeRules) { | |||
if (ActiveRuleDto.INHERITED.equals(activeRule.getInheritance())) { | |||
changes.addAll(ruleActivator.deactivate(dbSession, context, activeRule.getRuleKey(), true)); | |||
} else if (ActiveRuleDto.OVERRIDES.equals(activeRule.getInheritance())) { | |||
activeRule.setInheritance(null); | |||
activeRule.setUpdatedAt(system2.now()); | |||
db.activeRuleDao().update(dbSession, activeRule); | |||
changes.add(new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRule).setInheritance(null)); | |||
} | |||
} | |||
return changes; | |||
} | |||
private boolean isDescendant(DbSession dbSession, QProfileDto childProfile, @Nullable QProfileDto parentProfile) { | |||
QProfileDto currentParent = parentProfile; | |||
while (currentParent != null) { | |||
if (childProfile.getName().equals(currentParent.getName())) { | |||
return true; | |||
} | |||
String parentKey = currentParent.getParentKee(); | |||
if (parentKey != null) { | |||
currentParent = db.qualityProfileDao().selectByUuid(dbSession, parentKey); | |||
} else { | |||
currentParent = null; | |||
} | |||
} | |||
return false; | |||
} | |||
} |
@@ -80,7 +80,7 @@ public class RegisterQualityProfiles { | |||
builtInQProfiles.forEach(builtIn -> { | |||
RulesProfileDto ruleProfile = persistedRuleProfiles.get(builtIn.getQProfileName()); | |||
if (ruleProfile == null) { | |||
register(dbSession, batchDbSession, builtIn); | |||
create(dbSession, batchDbSession, builtIn); | |||
} else { | |||
List<ActiveRuleChange> changes = update(dbSession, builtIn, ruleProfile); | |||
changedProfiles.putAll(builtIn.getQProfileName(), changes.stream() | |||
@@ -104,7 +104,7 @@ public class RegisterQualityProfiles { | |||
.collect(MoreCollectors.uniqueIndex(rp -> new QProfileName(rp.getLanguage(), rp.getName()))); | |||
} | |||
private void register(DbSession dbSession, DbSession batchDbSession, BuiltInQProfile builtIn) { | |||
private void create(DbSession dbSession, DbSession batchDbSession, BuiltInQProfile builtIn) { | |||
LOGGER.info("Register profile {}", builtIn.getQProfileName()); | |||
renameOutdatedProfiles(dbSession, builtIn); |
@@ -0,0 +1,335 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program 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. | |||
* | |||
* This program 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.qualityprofile; | |||
import com.google.common.collect.ArrayListMultimap; | |||
import com.google.common.collect.ListMultimap; | |||
import com.google.common.collect.Maps; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.qualityprofile.RulesProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static com.google.common.base.Preconditions.checkState; | |||
import static java.util.Objects.requireNonNull; | |||
import static org.sonar.core.util.stream.MoreCollectors.index; | |||
import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; | |||
import static org.sonar.server.ws.WsUtils.checkRequest; | |||
/** | |||
* Cache of the data required to activate/deactivate | |||
* multiple rules on a Quality profile, including | |||
* the rule definitions, the rule parameters, the tree | |||
* of profiles hierarchy and its related active rules. | |||
*/ | |||
class RuleActivationContext { | |||
private final long date; | |||
// the profiles | |||
private RulesProfileDto baseRulesProfile; | |||
@Nullable | |||
private QProfileDto baseProfile; | |||
private final Map<String, QProfileDto> profilesByUuid = new HashMap<>(); | |||
private final ListMultimap<String, QProfileDto> profilesByParentUuid = ArrayListMultimap.create(); | |||
private final List<QProfileDto> builtInAliases = new ArrayList<>(); | |||
// the rules | |||
private final Map<RuleKey, RuleWrapper> rulesByKey; | |||
private final Map<ActiveRuleKey, ActiveRuleWrapper> activeRulesByKey; | |||
// cursor, moved in the tree of profiles | |||
private boolean cascading = false; | |||
private RulesProfileDto currentRulesProfile; | |||
@Nullable | |||
private QProfileDto currentProfile; | |||
@Nullable | |||
private RuleWrapper currentRule; | |||
@Nullable | |||
private ActiveRuleWrapper currentActiveRule; | |||
@Nullable | |||
private ActiveRuleWrapper currentParentActiveRule; | |||
private RuleActivationContext(Builder builder) { | |||
this.date = builder.date; | |||
// rules | |||
this.rulesByKey = Maps.newHashMapWithExpectedSize(builder.rules.size()); | |||
ListMultimap<Integer, RuleParamDto> paramsByRuleId = builder.ruleParams.stream().collect(index(RuleParamDto::getRuleId)); | |||
for (RuleDefinitionDto rule : builder.rules) { | |||
RuleWrapper wrapper = new RuleWrapper(rule, paramsByRuleId.get(rule.getId())); | |||
rulesByKey.put(rule.getKey(), wrapper); | |||
} | |||
// profiles | |||
this.baseProfile = builder.baseProfile; | |||
this.baseRulesProfile = builder.baseRulesProfile; | |||
for (QProfileDto profile : builder.profiles) { | |||
profilesByUuid.put(profile.getKee(), profile); | |||
if (profile.isBuiltIn()) { | |||
builtInAliases.add(profile); | |||
} else if (profile.getParentKee() != null) { | |||
profilesByParentUuid.put(profile.getParentKee(), profile); | |||
} | |||
} | |||
// active rules | |||
this.activeRulesByKey = Maps.newHashMapWithExpectedSize(builder.activeRules.size()); | |||
ListMultimap<Integer, ActiveRuleParamDto> paramsByActiveRuleId = builder.activeRuleParams.stream().collect(index(ActiveRuleParamDto::getActiveRuleId)); | |||
for (ActiveRuleDto activeRule : builder.activeRules) { | |||
ActiveRuleWrapper wrapper = new ActiveRuleWrapper(activeRule, paramsByActiveRuleId.get(activeRule.getId())); | |||
this.activeRulesByKey.put(activeRule.getKey(), wrapper); | |||
} | |||
} | |||
long getDate() { | |||
return date; | |||
} | |||
RuleWrapper getRule() { | |||
return currentRule; | |||
} | |||
@CheckForNull | |||
String getRequestedParamValue(RuleActivation request, String key) { | |||
if (currentRule.rule.isCustomRule()) { | |||
return null; | |||
} | |||
return request.getParameter(key); | |||
} | |||
boolean hasRequestedParamValue(RuleActivation request, String key) { | |||
return request.hasParameter(key); | |||
} | |||
RulesProfileDto getRulesProfile() { | |||
return currentRulesProfile; | |||
} | |||
@CheckForNull | |||
ActiveRuleWrapper getActiveRule() { | |||
return currentActiveRule; | |||
} | |||
@CheckForNull | |||
ActiveRuleWrapper getParentActiveRule() { | |||
return currentParentActiveRule; | |||
} | |||
boolean isCascading() { | |||
return cascading; | |||
} | |||
@CheckForNull | |||
QProfileDto getProfile() { | |||
return currentProfile; | |||
} | |||
Collection<QProfileDto> getChildProfiles() { | |||
if (currentProfile != null) { | |||
return profilesByParentUuid.get(currentProfile.getKee()); | |||
} | |||
// on built-in profile | |||
checkState(currentRulesProfile.isBuiltIn()); | |||
return builtInAliases.stream() | |||
.flatMap(a -> profilesByParentUuid.get(a.getKee()).stream()) | |||
.collect(Collectors.toList()); | |||
} | |||
/** | |||
* Resets cursor to base profile and selects the rule with specified key. | |||
*/ | |||
void reset(RuleKey ruleKey) { | |||
this.cascading = false; | |||
doSwitch(this.baseProfile, this.baseRulesProfile, ruleKey); | |||
} | |||
/** | |||
* Moves cursor to a child profile | |||
*/ | |||
void switchToChild(QProfileDto to) { | |||
checkState(!to.isBuiltIn()); | |||
requireNonNull(this.currentRule, "can not switch profile if rule is not set"); | |||
RuleKey ruleKey = this.currentRule.get().getKey(); | |||
QProfileDto qp = requireNonNull(this.profilesByUuid.get(to.getKee()), () -> "No profile with uuid " + to.getKee()); | |||
RulesProfileDto rulesProfile = RulesProfileDto.from(qp); | |||
this.cascading = true; | |||
doSwitch(qp, rulesProfile, ruleKey); | |||
} | |||
private void doSwitch(@Nullable QProfileDto qp, RulesProfileDto rulesProfile, RuleKey ruleKey) { | |||
this.currentRule = rulesByKey.get(ruleKey); | |||
checkRequest(this.currentRule != null, "Rule not found: %s", ruleKey); | |||
checkRequest(rulesProfile.getLanguage().equals(currentRule.get().getLanguage()), | |||
"%s rule %s cannot be activated on %s profile %s", currentRule.get().getLanguage(), currentRule.get().getKey(), rulesProfile.getLanguage(), rulesProfile.getName()); | |||
this.currentRulesProfile = rulesProfile; | |||
this.currentProfile = qp; | |||
this.currentActiveRule = this.activeRulesByKey.get(ActiveRuleKey.of(rulesProfile, ruleKey)); | |||
this.currentParentActiveRule = null; | |||
if (this.currentProfile != null) { | |||
String parentUuid = this.currentProfile.getParentKee(); | |||
if (parentUuid != null) { | |||
QProfileDto parent = requireNonNull(this.profilesByUuid.get(parentUuid), () -> "No profile with uuid " + parentUuid); | |||
this.currentParentActiveRule = this.activeRulesByKey.get(ActiveRuleKey.of(parent, ruleKey)); | |||
} | |||
} | |||
} | |||
static final class Builder { | |||
private long date = System.currentTimeMillis(); | |||
private RulesProfileDto baseRulesProfile; | |||
private QProfileDto baseProfile; | |||
private Collection<RuleDefinitionDto> rules; | |||
private Collection<RuleParamDto> ruleParams; | |||
private Collection<QProfileDto> profiles; | |||
private Collection<ActiveRuleDto> activeRules; | |||
private Collection<ActiveRuleParamDto> activeRuleParams; | |||
Builder setDate(long l) { | |||
this.date = l; | |||
return this; | |||
} | |||
Builder setBaseProfile(RulesProfileDto p) { | |||
this.baseRulesProfile = p; | |||
this.baseProfile = null; | |||
return this; | |||
} | |||
Builder setBaseProfile(QProfileDto p) { | |||
this.baseRulesProfile = RulesProfileDto.from(p); | |||
this.baseProfile = p; | |||
return this; | |||
} | |||
Builder setRules(Collection<RuleDefinitionDto> rules) { | |||
this.rules = rules; | |||
return this; | |||
} | |||
Builder setRuleParams(Collection<RuleParamDto> ruleParams) { | |||
this.ruleParams = ruleParams; | |||
return this; | |||
} | |||
/** | |||
* All the profiles involved in the activation workflow, including the | |||
* parent profile, even if it's not updated. | |||
*/ | |||
Builder setProfiles(Collection<QProfileDto> profiles) { | |||
this.profiles = profiles; | |||
return this; | |||
} | |||
Builder setActiveRules(Collection<ActiveRuleDto> activeRules) { | |||
this.activeRules = activeRules; | |||
return this; | |||
} | |||
Builder setActiveRuleParams(Collection<ActiveRuleParamDto> activeRuleParams) { | |||
this.activeRuleParams = activeRuleParams; | |||
return this; | |||
} | |||
RuleActivationContext build() { | |||
checkArgument(date > 0, "date is not set"); | |||
requireNonNull(baseRulesProfile, "baseRulesProfile is null"); | |||
requireNonNull(rules, "rules is null"); | |||
requireNonNull(ruleParams, "ruleParams is null"); | |||
requireNonNull(profiles, "profiles is null"); | |||
requireNonNull(activeRules, "activeRules is null"); | |||
requireNonNull(activeRuleParams, "activeRuleParams is null"); | |||
return new RuleActivationContext(this); | |||
} | |||
} | |||
static final class RuleWrapper { | |||
private final RuleDefinitionDto rule; | |||
private final Map<String, RuleParamDto> paramsByKey; | |||
private RuleWrapper(RuleDefinitionDto rule, Collection<RuleParamDto> params) { | |||
this.rule = rule; | |||
this.paramsByKey = params.stream().collect(uniqueIndex(RuleParamDto::getName)); | |||
} | |||
RuleDefinitionDto get() { | |||
return rule; | |||
} | |||
Collection<RuleParamDto> getParams() { | |||
return paramsByKey.values(); | |||
} | |||
@CheckForNull | |||
RuleParamDto getParam(String key) { | |||
return paramsByKey.get(key); | |||
} | |||
@CheckForNull | |||
String getParamDefaultValue(String key) { | |||
RuleParamDto param = getParam(key); | |||
return param != null ? param.getDefaultValue() : null; | |||
} | |||
} | |||
static final class ActiveRuleWrapper { | |||
private final ActiveRuleDto activeRule; | |||
private final Map<String, ActiveRuleParamDto> paramsByKey; | |||
private ActiveRuleWrapper(ActiveRuleDto activeRule, Collection<ActiveRuleParamDto> params) { | |||
this.activeRule = activeRule; | |||
this.paramsByKey = params.stream().collect(uniqueIndex(ActiveRuleParamDto::getKey)); | |||
} | |||
ActiveRuleDto get() { | |||
return activeRule; | |||
} | |||
Collection<ActiveRuleParamDto> getParams() { | |||
return paramsByKey.values(); | |||
} | |||
@CheckForNull | |||
ActiveRuleParamDto getParam(String key) { | |||
return paramsByKey.get(key); | |||
} | |||
@CheckForNull | |||
String getParamValue(String key) { | |||
ActiveRuleParamDto param = paramsByKey.get(key); | |||
return param != null ? param.getValue() : null; | |||
} | |||
} | |||
} |
@@ -21,16 +21,20 @@ package org.sonar.server.qualityprofile; | |||
import com.google.common.base.Splitter; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.Iterator; | |||
import java.util.Collection; | |||
import java.util.Date; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Stream; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.api.server.rule.RuleParamType; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.ActiveRuleDao; | |||
@@ -41,10 +45,8 @@ import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.qualityprofile.RulesProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleQuery; | |||
import org.sonar.server.qualityprofile.RuleActivationContext.ActiveRuleWrapper; | |||
import org.sonar.server.qualityprofile.RuleActivationContext.RuleWrapper; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonar.server.util.TypeValidations; | |||
@@ -60,78 +62,65 @@ public class RuleActivator { | |||
private final System2 system2; | |||
private final DbClient db; | |||
private final TypeValidations typeValidations; | |||
private final RuleActivatorContextFactory contextFactory; | |||
private final RuleIndex ruleIndex; | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
private final UserSession userSession; | |||
public RuleActivator(System2 system2, DbClient db, RuleIndex ruleIndex, | |||
RuleActivatorContextFactory contextFactory, TypeValidations typeValidations, | |||
ActiveRuleIndexer activeRuleIndexer, UserSession userSession) { | |||
public RuleActivator(System2 system2, DbClient db, TypeValidations typeValidations, UserSession userSession) { | |||
this.system2 = system2; | |||
this.db = db; | |||
this.ruleIndex = ruleIndex; | |||
this.contextFactory = contextFactory; | |||
this.typeValidations = typeValidations; | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
this.userSession = userSession; | |||
} | |||
public List<ActiveRuleChange> activateOnBuiltInRulesProfile(DbSession dbSession, RuleActivation activation, RulesProfileDto rulesProfile) { | |||
checkArgument(rulesProfile.isBuiltIn(), "Rules profile must be a built-in profile: " + rulesProfile.getKee()); | |||
RuleActivatorContext context = contextFactory.createForBuiltIn(dbSession, activation.getRuleKey(), rulesProfile); | |||
public List<ActiveRuleChange> activate(DbSession dbSession, RuleActivation activation, RuleActivationContext context) { | |||
context.reset(activation.getRuleKey()); | |||
return doActivate(dbSession, activation, context); | |||
} | |||
public void activateAndCommit(DbSession dbSession, RuleActivation activation, QProfileDto profile) { | |||
List<ActiveRuleChange> changes = activate(dbSession, activation, profile); | |||
activeRuleIndexer.commitAndIndex(dbSession, changes); | |||
} | |||
public List<ActiveRuleChange> activate(DbSession dbSession, RuleActivation activation, QProfileDto profile) { | |||
RuleActivatorContext context = contextFactory.create(dbSession, activation.getRuleKey(), profile, false); | |||
return doActivate(dbSession, activation, context); | |||
} | |||
private List<ActiveRuleChange> doActivate(DbSession dbSession, RuleActivation activation, RuleActivationContext context) { | |||
RuleDefinitionDto rule = context.getRule().get(); | |||
checkRequest(RuleStatus.REMOVED != rule.getStatus(), "Rule was removed: %s", rule.getKey()); | |||
checkRequest(!rule.isTemplate(), "Rule template can't be activated on a Quality profile: %s", rule.getKey()); | |||
private List<ActiveRuleChange> doActivate(DbSession dbSession, RuleActivation activation, RuleActivatorContext context) { | |||
context.verifyForActivation(); | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
ActiveRuleChange change; | |||
boolean stopPropagation = false; | |||
boolean stopCascading = false; | |||
ActiveRuleDto activeRule = context.getActiveRule(); | |||
ActiveRuleWrapper activeRule = context.getActiveRule(); | |||
ActiveRuleKey activeRuleKey = ActiveRuleKey.of(context.getRulesProfile(), rule.getKey()); | |||
if (activeRule == null) { | |||
if (activation.isReset()) { | |||
// ignore reset when rule is not activated | |||
return changes; | |||
} | |||
// new activation | |||
change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, context.getActiveRuleKey()); | |||
change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, activeRuleKey); | |||
applySeverityAndParamToChange(activation, context, change); | |||
if (context.isCascade() || context.isSameAsParent(change)) { | |||
if (context.isCascading() || isSameAsParent(change, context)) { | |||
change.setInheritance(ActiveRule.Inheritance.INHERITED); | |||
} | |||
} else { | |||
// already activated | |||
if (context.isCascade() && activeRule.doesOverride()) { | |||
if (context.isCascading() && activeRule.get().doesOverride()) { | |||
// propagating to descendants, but child profile already overrides rule -> stop propagation | |||
return changes; | |||
} | |||
change = new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, context.getActiveRuleKey()); | |||
if (context.isCascade() && activeRule.getInheritance() == null) { | |||
change = new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRuleKey); | |||
if (context.isCascading() && activeRule.get().getInheritance() == null) { | |||
// activate on child, then on parent -> mark child as overriding parent | |||
change.setInheritance(ActiveRule.Inheritance.OVERRIDES); | |||
change.setSeverity(context.getActiveSeverityBeforeChange()); | |||
change.setParameters(context.activeRuleParamsAsStringMap()); | |||
stopPropagation = true; | |||
change.setSeverity(activeRule.get().getSeverityString()); | |||
for (ActiveRuleParamDto activeParam : activeRule.getParams()) { | |||
change.setParameter(activeParam.getKey(), activeParam.getValue()); | |||
} | |||
stopCascading = true; | |||
} else { | |||
applySeverityAndParamToChange(activation, context, change); | |||
if (!context.isCascade() && context.getParentActiveRule() != null) { | |||
if (!context.isCascading() && context.getParentActiveRule() != null) { | |||
// override rule which is already declared on parents | |||
change.setInheritance(context.isSameAsParent(change) ? ActiveRule.Inheritance.INHERITED : ActiveRule.Inheritance.OVERRIDES); | |||
change.setInheritance(isSameAsParent(change, context) ? ActiveRule.Inheritance.INHERITED : ActiveRule.Inheritance.OVERRIDES); | |||
} | |||
} | |||
if (context.isSame(change)) { | |||
if (isSame(change, activeRule)) { | |||
change = null; | |||
} | |||
} | |||
@@ -141,8 +130,8 @@ public class RuleActivator { | |||
persist(change, context, dbSession); | |||
} | |||
if (!stopPropagation) { | |||
changes.addAll(cascadeActivation(dbSession, activation, context)); | |||
if (!stopCascading) { | |||
changes.addAll(propagateActivationToDescendants(dbSession, activation, context)); | |||
} | |||
if (!changes.isEmpty()) { | |||
@@ -151,18 +140,19 @@ public class RuleActivator { | |||
return changes; | |||
} | |||
private void updateProfileDates(DbSession dbSession, RuleActivatorContext context) { | |||
QProfileDto profile = context.getOrganizationProfile(); | |||
private void updateProfileDates(DbSession dbSession, RuleActivationContext context) { | |||
QProfileDto profile = context.getProfile(); | |||
if (profile != null) { | |||
profile.setRulesUpdatedAtAsDate(context.getDate()); | |||
profile.setRulesUpdatedAtAsDate(new Date(context.getDate())); | |||
if (userSession.isLoggedIn()) { | |||
profile.setUserUpdatedAt(context.getDate().getTime()); | |||
profile.setUserUpdatedAt(context.getDate()); | |||
} | |||
db.qualityProfileDao().update(dbSession, profile); | |||
} else { | |||
// built-in profile, change rules_profiles.rules_updated_at | |||
RulesProfileDto rulesProfile = context.getRulesProfile(); | |||
rulesProfile.setRulesUpdatedAtAsDate(context.getDate()); | |||
rulesProfile.setRulesUpdatedAtAsDate(new Date(context.getDate())); | |||
db.qualityProfileDao().update(dbSession, rulesProfile); | |||
} | |||
} | |||
@@ -175,88 +165,78 @@ public class RuleActivator { | |||
* <p/> | |||
* On custom rules, it's always rule parameters that are used | |||
*/ | |||
private void applySeverityAndParamToChange(RuleActivation request, RuleActivatorContext context, ActiveRuleChange change) { | |||
private void applySeverityAndParamToChange(RuleActivation request, RuleActivationContext context, ActiveRuleChange change) { | |||
RuleWrapper rule = context.getRule(); | |||
ActiveRuleWrapper activeRule = context.getActiveRule(); | |||
ActiveRuleWrapper parentActiveRule = context.getParentActiveRule(); | |||
if (request.isReset()) { | |||
// load severity and params from parent profile, else from default values | |||
change.setSeverity(firstNonNull( | |||
context.getActiveParentSeverity(), context.getRule().getSeverityString())); | |||
for (RuleParamDto ruleParamDto : context.getRuleParams()) { | |||
parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null, | |||
rule.get().getSeverityString())); | |||
for (RuleParamDto ruleParamDto : rule.getParams()) { | |||
String paramKey = ruleParamDto.getName(); | |||
change.setParameter(paramKey, validateParam(ruleParamDto, firstNonNull( | |||
context.getActiveParentParamValue(paramKey), context.getDefaultParamValue(paramKey)))); | |||
parentActiveRule != null ? parentActiveRule.getParamValue(paramKey) : null, | |||
rule.getParamDefaultValue(paramKey)))); | |||
} | |||
} else if (context.getActiveRule() != null) { | |||
} else if (activeRule != null) { | |||
// already activated -> load severity and parameters from request, else keep existing ones, else from parent, | |||
// else from default | |||
change.setSeverity(firstNonNull( | |||
request.getSeverity(), | |||
context.getActiveSeverityBeforeChange(), | |||
context.getActiveParentSeverity(), | |||
context.getRule().getSeverityString())); | |||
for (RuleParamDto ruleParamDto : context.getRuleParams()) { | |||
activeRule.get().getSeverityString(), | |||
parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null, | |||
rule.get().getSeverityString())); | |||
for (RuleParamDto ruleParamDto : rule.getParams()) { | |||
String paramKey = ruleParamDto.getName(); | |||
String parentValue = parentActiveRule != null ? parentActiveRule.getParamValue(paramKey) : null; | |||
String paramValue = context.hasRequestedParamValue(request, paramKey) ? | |||
// If the request contains the parameter then we're using either value from request, or parent value, or default value | |||
firstNonNull( | |||
context.getRequestedParamValue(request, paramKey), | |||
context.getActiveParentParamValue(paramKey), | |||
context.getDefaultParamValue(paramKey)) | |||
parentValue, | |||
rule.getParamDefaultValue(paramKey)) | |||
// If the request doesn't contain the parameter, then we're using either value in DB, or parent value, or default value | |||
: firstNonNull( | |||
context.getActiveParamValue(paramKey), | |||
context.getActiveParentParamValue(paramKey), | |||
context.getDefaultParamValue(paramKey)); | |||
activeRule.getParamValue(paramKey), | |||
parentValue, | |||
rule.getParamDefaultValue(paramKey)); | |||
change.setParameter(paramKey, validateParam(ruleParamDto, paramValue)); | |||
} | |||
} else if (context.getActiveRule() == null) { | |||
} else { | |||
// not activated -> load severity and parameters from request, else from parent, else from defaults | |||
change.setSeverity(firstNonNull( | |||
request.getSeverity(), | |||
context.getActiveParentSeverity(), | |||
context.getRule().getSeverityString())); | |||
for (RuleParamDto ruleParamDto : context.getRuleParams()) { | |||
parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null, | |||
rule.get().getSeverityString())); | |||
for (RuleParamDto ruleParamDto : rule.getParams()) { | |||
String paramKey = ruleParamDto.getName(); | |||
change.setParameter(paramKey, validateParam(ruleParamDto, | |||
firstNonNull( | |||
context.getRequestedParamValue(request, paramKey), | |||
context.getActiveParentParamValue(paramKey), | |||
context.getDefaultParamValue(paramKey)))); | |||
} | |||
} | |||
} | |||
@CheckForNull | |||
private static String firstNonNull(String... strings) { | |||
for (String s : strings) { | |||
if (s != null) { | |||
return s; | |||
parentActiveRule != null ? parentActiveRule.getParamValue(paramKey) : null, | |||
rule.getParamDefaultValue(paramKey)))); | |||
} | |||
} | |||
return null; | |||
} | |||
private List<ActiveRuleChange> cascadeActivation(DbSession dbSession, RuleActivation activation, RuleActivatorContext context) { | |||
private List<ActiveRuleChange> propagateActivationToDescendants(DbSession dbSession, RuleActivation activation, RuleActivationContext context) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
// get all inherited profiles | |||
getChildren(dbSession, context).forEach(child -> { | |||
RuleActivatorContext childContext = contextFactory.create(dbSession, activation.getRuleKey(), child, true); | |||
changes.addAll(doActivate(dbSession, activation, childContext)); | |||
context.getChildProfiles().forEach(child -> { | |||
context.switchToChild(child); | |||
changes.addAll(doActivate(dbSession, activation, context)); | |||
}); | |||
return changes; | |||
} | |||
protected List<QProfileDto> getChildren(DbSession session, RuleActivatorContext context) { | |||
QProfileDto orgProfile = context.getOrganizationProfile(); | |||
if (orgProfile != null) { | |||
return db.qualityProfileDao().selectChildren(session, orgProfile); | |||
} | |||
return db.qualityProfileDao().selectChildrenOfBuiltInRulesProfile(session, context.getRulesProfile()); | |||
} | |||
private void persist(ActiveRuleChange change, RuleActivatorContext context, DbSession dbSession) { | |||
private void persist(ActiveRuleChange change, RuleActivationContext context, DbSession dbSession) { | |||
ActiveRuleDto activeRule = null; | |||
if (change.getType() == ActiveRuleChange.Type.ACTIVATED) { | |||
activeRule = doInsert(change, context, dbSession); | |||
@@ -271,12 +251,14 @@ public class RuleActivator { | |||
db.qProfileChangeDao().insert(dbSession, change.toDto(userSession.getLogin())); | |||
} | |||
private ActiveRuleDto doInsert(ActiveRuleChange change, RuleActivatorContext context, DbSession dbSession) { | |||
private ActiveRuleDto doInsert(ActiveRuleChange change, RuleActivationContext context, DbSession dbSession) { | |||
ActiveRuleDao dao = db.activeRuleDao(); | |||
RuleWrapper rule = context.getRule(); | |||
ActiveRuleDto activeRule = new ActiveRuleDto(); | |||
activeRule.setProfileId(context.getRulesProfile().getId()); | |||
activeRule.setRuleId(context.getRule().getId()); | |||
activeRule.setKey(ActiveRuleKey.of(context.getRulesProfile(), context.getRule().getKey())); | |||
activeRule.setRuleId(rule.get().getId()); | |||
activeRule.setKey(ActiveRuleKey.of(context.getRulesProfile(), rule.get().getKey())); | |||
String severity = change.getSeverity(); | |||
if (severity != null) { | |||
activeRule.setSeverity(severity); | |||
@@ -290,7 +272,7 @@ public class RuleActivator { | |||
dao.insert(dbSession, activeRule); | |||
for (Map.Entry<String, String> param : change.getParameters().entrySet()) { | |||
if (param.getValue() != null) { | |||
ActiveRuleParamDto paramDto = ActiveRuleParamDto.createFor(context.getRuleParam(param.getKey())); | |||
ActiveRuleParamDto paramDto = ActiveRuleParamDto.createFor(rule.getParam(param.getKey())); | |||
paramDto.setValue(param.getValue()); | |||
dao.insertParam(dbSession, activeRule, paramDto); | |||
} | |||
@@ -298,108 +280,66 @@ public class RuleActivator { | |||
return activeRule; | |||
} | |||
private ActiveRuleDto doUpdate(ActiveRuleChange change, RuleActivatorContext context, DbSession dbSession) { | |||
private ActiveRuleDto doUpdate(ActiveRuleChange change, RuleActivationContext context, DbSession dbSession) { | |||
ActiveRuleWrapper activeRule = context.getActiveRule(); | |||
if (activeRule == null) { | |||
return null; | |||
} | |||
ActiveRuleDao dao = db.activeRuleDao(); | |||
ActiveRuleDto activeRule = context.getActiveRule(); | |||
if (activeRule != null) { | |||
String severity = change.getSeverity(); | |||
if (severity != null) { | |||
activeRule.setSeverity(severity); | |||
} | |||
ActiveRule.Inheritance inheritance = change.getInheritance(); | |||
if (inheritance != null) { | |||
activeRule.setInheritance(inheritance.name()); | |||
} | |||
activeRule.setUpdatedAt(system2.now()); | |||
dao.update(dbSession, activeRule); | |||
for (Map.Entry<String, String> param : change.getParameters().entrySet()) { | |||
ActiveRuleParamDto activeRuleParamDto = context.getActiveParamBeforeChange(param.getKey()); | |||
if (activeRuleParamDto == null) { | |||
// did not exist | |||
if (param.getValue() != null) { | |||
activeRuleParamDto = ActiveRuleParamDto.createFor(context.getRuleParam(param.getKey())); | |||
activeRuleParamDto.setValue(param.getValue()); | |||
dao.insertParam(dbSession, activeRule, activeRuleParamDto); | |||
} | |||
String severity = change.getSeverity(); | |||
if (severity != null) { | |||
activeRule.get().setSeverity(severity); | |||
} | |||
ActiveRule.Inheritance inheritance = change.getInheritance(); | |||
if (inheritance != null) { | |||
activeRule.get().setInheritance(inheritance.name()); | |||
} | |||
activeRule.get().setUpdatedAt(system2.now()); | |||
dao.update(dbSession, activeRule.get()); | |||
for (Map.Entry<String, String> param : change.getParameters().entrySet()) { | |||
ActiveRuleParamDto activeRuleParamDto = activeRule.getParam(param.getKey()); | |||
if (activeRuleParamDto == null) { | |||
// did not exist | |||
if (param.getValue() != null) { | |||
activeRuleParamDto = ActiveRuleParamDto.createFor(context.getRule().getParam(param.getKey())); | |||
activeRuleParamDto.setValue(param.getValue()); | |||
dao.insertParam(dbSession, activeRule.get(), activeRuleParamDto); | |||
} | |||
} else { | |||
if (param.getValue() != null) { | |||
activeRuleParamDto.setValue(param.getValue()); | |||
dao.updateParam(dbSession, activeRuleParamDto); | |||
} else { | |||
if (param.getValue() != null) { | |||
activeRuleParamDto.setValue(param.getValue()); | |||
dao.updateParam(dbSession, activeRuleParamDto); | |||
} else { | |||
dao.deleteParam(dbSession, activeRuleParamDto); | |||
} | |||
dao.deleteParam(dbSession, activeRuleParamDto); | |||
} | |||
} | |||
} | |||
return activeRule; | |||
} | |||
/** | |||
* Deactivate a rule on a Quality profile. Does nothing if the rule is not activated, but | |||
* fails (fast) if the rule or the profile does not exist. | |||
*/ | |||
public void deactivateAndCommit(DbSession dbSession, QProfileDto profile, RuleKey ruleKey) { | |||
List<ActiveRuleChange> changes = deactivate(dbSession, profile, ruleKey); | |||
activeRuleIndexer.commitAndIndex(dbSession, changes); | |||
} | |||
/** | |||
* Deactivate a rule on a Quality profile WITHOUT committing db session and WITHOUT checking permissions | |||
*/ | |||
List<ActiveRuleChange> deactivate(DbSession dbSession, QProfileDto profile, RuleKey ruleKey) { | |||
return deactivate(dbSession, profile, ruleKey, false); | |||
} | |||
/** | |||
* Deletes a rule from all Quality profiles. | |||
*/ | |||
public List<ActiveRuleChange> delete(DbSession dbSession, RuleDefinitionDto rule) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
List<Integer> activeRuleIds = new ArrayList<>(); | |||
db.activeRuleDao().selectByRuleIdOfAllOrganizations(dbSession, rule.getId()).forEach(ar -> { | |||
activeRuleIds.add(ar.getId()); | |||
changes.add(new ActiveRuleChange(ActiveRuleChange.Type.DEACTIVATED, ar)); | |||
}); | |||
db.activeRuleDao().deleteByIds(dbSession, activeRuleIds); | |||
db.activeRuleDao().deleteParamsByActiveRuleIds(dbSession, activeRuleIds); | |||
return changes; | |||
return activeRule.get(); | |||
} | |||
/** | |||
* @param force if true then inherited rules are deactivated | |||
*/ | |||
public List<ActiveRuleChange> deactivate(DbSession dbSession, QProfileDto profile, RuleKey ruleKey, boolean force) { | |||
RuleActivatorContext context = contextFactory.create(dbSession, ruleKey, profile, false); | |||
return cascadeDeactivation(dbSession, context, ruleKey, force); | |||
public List<ActiveRuleChange> deactivate(DbSession dbSession, RuleActivationContext context, RuleKey ruleKey, boolean force) { | |||
context.reset(ruleKey); | |||
return doDeactivate(dbSession, context, force); | |||
} | |||
public List<ActiveRuleChange> deactivateOnBuiltInRulesProfile(DbSession dbSession, RulesProfileDto rulesProfile, RuleKey ruleKey, boolean force) { | |||
checkArgument(rulesProfile.isBuiltIn(), "Rules profile must be a built-in profile: " + rulesProfile.getKee()); | |||
RuleActivatorContext context = contextFactory.createForBuiltIn(dbSession, ruleKey, rulesProfile); | |||
return cascadeDeactivation(dbSession, context, ruleKey, force); | |||
} | |||
private List<ActiveRuleChange> cascadeDeactivation(DbSession dbSession, RuleActivatorContext context, RuleKey ruleKey, boolean force) { | |||
private List<ActiveRuleChange> doDeactivate(DbSession dbSession, RuleActivationContext context, boolean force) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
ActiveRuleChange change; | |||
ActiveRuleDto activeRuleDto = context.getActiveRule(); | |||
if (activeRuleDto == null) { | |||
ActiveRuleWrapper activeRule = context.getActiveRule(); | |||
if (activeRule == null) { | |||
return changes; | |||
} | |||
checkRequest(force || context.isCascade() || activeRuleDto.getInheritance() == null, "Cannot deactivate inherited rule '%s'", ruleKey); | |||
change = new ActiveRuleChange(ActiveRuleChange.Type.DEACTIVATED, activeRuleDto); | |||
ActiveRuleChange change; | |||
checkRequest(force || context.isCascading() || activeRule.get().getInheritance() == null, "Cannot deactivate inherited rule '%s'", context.getRule().get().getKey()); | |||
change = new ActiveRuleChange(ActiveRuleChange.Type.DEACTIVATED, activeRule.get()); | |||
changes.add(change); | |||
persist(change, context, dbSession); | |||
// get all inherited profiles (they are not built-in by design) | |||
getChildren(dbSession, context).forEach(child -> { | |||
RuleActivatorContext childContext = contextFactory.create(dbSession, ruleKey, child, true); | |||
changes.addAll(cascadeDeactivation(dbSession, childContext, ruleKey, force)); | |||
context.getChildProfiles().forEach(child -> { | |||
context.switchToChild(child); | |||
changes.addAll(doDeactivate(dbSession, context, force)); | |||
}); | |||
if (!changes.isEmpty()) { | |||
@@ -423,118 +363,119 @@ public class RuleActivator { | |||
return value; | |||
} | |||
public BulkChangeResult bulkActivateAndCommit(DbSession dbSession, RuleQuery ruleQuery, QProfileDto profile, @Nullable String severity) { | |||
BulkChangeResult result = new BulkChangeResult(); | |||
Iterator<RuleKey> rules = ruleIndex.searchAll(ruleQuery); | |||
while (rules.hasNext()) { | |||
RuleKey ruleKey = rules.next(); | |||
try { | |||
RuleActivation activation = RuleActivation.create(ruleKey, severity, null); | |||
List<ActiveRuleChange> changes = activate(dbSession, activation, profile); | |||
result.addChanges(changes); | |||
if (!changes.isEmpty()) { | |||
result.incrementSucceeded(); | |||
} | |||
public RuleActivationContext createContextForBuiltInProfile(DbSession dbSession, RulesProfileDto builtInProfile, Collection<RuleKey> ruleKeys) { | |||
checkArgument(builtInProfile.isBuiltIn(), "Rules profile with UUID %s is not built-in", builtInProfile.getKee()); | |||
} catch (BadRequestException e) { | |||
// other exceptions stop the bulk activation | |||
result.incrementFailed(); | |||
result.getErrors().addAll(e.errors()); | |||
} | |||
RuleActivationContext.Builder builder = new RuleActivationContext.Builder(); | |||
// load rules | |||
List<RuleDefinitionDto> rules = completeWithRules(dbSession, builder, ruleKeys); | |||
// load profiles | |||
List<QProfileDto> aliasedBuiltInProfiles = db.qualityProfileDao().selectQProfilesByRuleProfile(dbSession, builtInProfile); | |||
List<QProfileDto> profiles = new ArrayList<>(aliasedBuiltInProfiles); | |||
for (QProfileDto aliasProfile : aliasedBuiltInProfiles) { | |||
// FIXME N+1 syndrome. To be optimized by replacing db column parent_kee by ancestor_keys. | |||
profiles.addAll(db.qualityProfileDao().selectDescendants(dbSession, aliasProfile)); | |||
} | |||
activeRuleIndexer.commitAndIndex(dbSession, result.getChanges()); | |||
return result; | |||
builder.setProfiles(profiles); | |||
builder.setBaseProfile(builtInProfile); | |||
// load active rules | |||
Collection<String> ruleProfileUuids = Stream | |||
.concat(Stream.of(builtInProfile.getKee()), profiles.stream().map(QProfileDto::getRulesProfileUuid)) | |||
.collect(MoreCollectors.toHashSet(profiles.size() + 1)); | |||
completeWithActiveRules(dbSession, builder, rules, ruleProfileUuids); | |||
return builder.build(); | |||
} | |||
public BulkChangeResult bulkDeactivateAndCommit(DbSession dbSession, RuleQuery ruleQuery, QProfileDto profile) { | |||
BulkChangeResult result = new BulkChangeResult(); | |||
Iterator<RuleKey> rules = ruleIndex.searchAll(ruleQuery); | |||
while (rules.hasNext()) { | |||
try { | |||
RuleKey ruleKey = rules.next(); | |||
List<ActiveRuleChange> changes = deactivate(dbSession, profile, ruleKey); | |||
result.addChanges(changes); | |||
if (!changes.isEmpty()) { | |||
result.incrementSucceeded(); | |||
} | |||
} catch (BadRequestException e) { | |||
// other exceptions stop the bulk activation | |||
result.incrementFailed(); | |||
result.getErrors().addAll(e.errors()); | |||
} | |||
public RuleActivationContext createContextForUserProfile(DbSession dbSession, QProfileDto profile, Collection<RuleKey> ruleKeys) { | |||
checkArgument(!profile.isBuiltIn(), "Profile with UUID %s is built-in", profile.getKee()); | |||
RuleActivationContext.Builder builder = new RuleActivationContext.Builder(); | |||
// load rules | |||
List<RuleDefinitionDto> rules = completeWithRules(dbSession, builder, ruleKeys); | |||
// load descendant profiles | |||
List<QProfileDto> profiles = new ArrayList<>(db.qualityProfileDao().selectDescendants(dbSession, profile)); | |||
profiles.add(profile); | |||
if (profile.getParentKee() != null) { | |||
profiles.add(db.qualityProfileDao().selectByUuid(dbSession, profile.getParentKee())); | |||
} | |||
activeRuleIndexer.commitAndIndex(dbSession, result.getChanges()); | |||
return result; | |||
} | |||
builder.setProfiles(profiles); | |||
builder.setBaseProfile(profile); | |||
public List<ActiveRuleChange> setParentAndCommit(DbSession dbSession, QProfileDto profile, @Nullable QProfileDto parent) { | |||
checkRequest( | |||
parent == null || profile.getLanguage().equals(parent.getLanguage()), | |||
"Cannot set the profile '%s' as the parent of profile '%s' since their languages differ ('%s' != '%s')", | |||
parent != null ? parent.getKee() : "", profile.getKee(), parent != null ? parent.getLanguage() : "", profile.getLanguage()); | |||
// load active rules | |||
Collection<String> ruleProfileUuids = profiles.stream() | |||
.map(QProfileDto::getRulesProfileUuid) | |||
.collect(MoreCollectors.toHashSet(profiles.size())); | |||
completeWithActiveRules(dbSession, builder, rules, ruleProfileUuids); | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
if (parent == null) { | |||
// unset if parent is defined, else nothing to do | |||
changes.addAll(removeParent(dbSession, profile)); | |||
return builder.build(); | |||
} | |||
} else if (profile.getParentKee() == null || !parent.getKee().equals(profile.getParentKee())) { | |||
checkRequest(!isDescendant(dbSession, profile, parent), "Descendant profile '%s' can not be selected as parent of '%s'", parent.getKee(), profile.getKee()); | |||
changes.addAll(removeParent(dbSession, profile)); | |||
private List<RuleDefinitionDto> completeWithRules(DbSession dbSession, RuleActivationContext.Builder builder, Collection<RuleKey> ruleKeys) { | |||
List<RuleDefinitionDto> rules = db.ruleDao().selectDefinitionByKeys(dbSession, ruleKeys); | |||
builder.setRules(rules); | |||
builder.setRuleParams(db.ruleDao().selectRuleParamsByRuleKeys(dbSession, ruleKeys)); | |||
return rules; | |||
} | |||
// set new parent | |||
profile.setParentKee(parent.getKee()); | |||
db.qualityProfileDao().update(dbSession, profile); | |||
for (ActiveRuleDto parentActiveRule : db.activeRuleDao().selectByProfile(dbSession, parent)) { | |||
try { | |||
RuleActivation activation = RuleActivation.create(parentActiveRule.getRuleKey(), null, null); | |||
changes.addAll(activate(dbSession, activation, profile)); | |||
} catch (BadRequestException e) { | |||
// for example because rule status is REMOVED | |||
// TODO return errors | |||
} | |||
private void completeWithActiveRules(DbSession dbSession, RuleActivationContext.Builder builder, Collection<RuleDefinitionDto> rules, Collection<String> ruleProfileUuids) { | |||
Collection<ActiveRuleDto> activeRules = db.activeRuleDao().selectByRulesAndRuleProfileUuids(dbSession, rules, ruleProfileUuids); | |||
builder.setActiveRules(activeRules); | |||
List<Integer> activeRuleIds = activeRules.stream().map(ActiveRuleDto::getId).collect(MoreCollectors.toArrayList(activeRules.size())); | |||
builder.setActiveRuleParams(db.activeRuleDao().selectParamsByActiveRuleIds(dbSession, activeRuleIds)); | |||
} | |||
private static boolean isSame(ActiveRuleChange change, ActiveRuleWrapper activeRule) { | |||
ActiveRule.Inheritance inheritance = change.getInheritance(); | |||
if (inheritance != null && !inheritance.name().equals(activeRule.get().getInheritance())) { | |||
return false; | |||
} | |||
String severity = change.getSeverity(); | |||
if (severity != null && !severity.equals(activeRule.get().getSeverityString())) { | |||
return false; | |||
} | |||
for (Map.Entry<String, String> changeParam : change.getParameters().entrySet()) { | |||
String activeParamValue = activeRule.getParamValue(changeParam.getKey()); | |||
if (changeParam.getValue() == null && activeParamValue != null) { | |||
return false; | |||
} | |||
if (changeParam.getValue() != null && (activeParamValue == null || !StringUtils.equals(changeParam.getValue(), activeParamValue))) { | |||
return false; | |||
} | |||
} | |||
activeRuleIndexer.commitAndIndex(dbSession, changes); | |||
return changes; | |||
return true; | |||
} | |||
/** | |||
* Does not commit | |||
* True if trying to override an inherited rule but with exactly the same values | |||
*/ | |||
private List<ActiveRuleChange> removeParent(DbSession dbSession, QProfileDto profile) { | |||
if (profile.getParentKee() != null) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
profile.setParentKee(null); | |||
db.qualityProfileDao().update(dbSession, profile); | |||
for (ActiveRuleDto activeRule : db.activeRuleDao().selectByProfile(dbSession, profile)) { | |||
if (ActiveRuleDto.INHERITED.equals(activeRule.getInheritance())) { | |||
changes.addAll(deactivate(dbSession, profile, activeRule.getRuleKey(), true)); | |||
} else if (ActiveRuleDto.OVERRIDES.equals(activeRule.getInheritance())) { | |||
activeRule.setInheritance(null); | |||
activeRule.setUpdatedAt(system2.now()); | |||
db.activeRuleDao().update(dbSession, activeRule); | |||
changes.add(new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRule).setInheritance(null)); | |||
} | |||
private static boolean isSameAsParent(ActiveRuleChange change, RuleActivationContext context) { | |||
ActiveRuleWrapper parentActiveRule = context.getParentActiveRule(); | |||
if (parentActiveRule == null) { | |||
return false; | |||
} | |||
if (!StringUtils.equals(change.getSeverity(), parentActiveRule.get().getSeverityString())) { | |||
return false; | |||
} | |||
for (Map.Entry<String, String> entry : change.getParameters().entrySet()) { | |||
if (entry.getValue() != null && !entry.getValue().equals(parentActiveRule.getParamValue(entry.getKey()))) { | |||
return false; | |||
} | |||
return changes; | |||
} | |||
return Collections.emptyList(); | |||
return true; | |||
} | |||
private boolean isDescendant(DbSession dbSession, QProfileDto childProfile, @Nullable QProfileDto parentProfile) { | |||
QProfileDto currentParent = parentProfile; | |||
while (currentParent != null) { | |||
if (childProfile.getName().equals(currentParent.getName())) { | |||
return true; | |||
} | |||
String parentKey = currentParent.getParentKee(); | |||
if (parentKey != null) { | |||
currentParent = db.qualityProfileDao().selectByUuid(dbSession, parentKey); | |||
} else { | |||
currentParent = null; | |||
@CheckForNull | |||
private static String firstNonNull(String... strings) { | |||
for (String s : strings) { | |||
if (s != null) { | |||
return s; | |||
} | |||
} | |||
return false; | |||
return null; | |||
} | |||
} |
@@ -1,264 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program 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. | |||
* | |||
* This program 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.qualityprofile; | |||
import com.google.common.collect.Maps; | |||
import java.util.Collection; | |||
import java.util.Date; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.qualityprofile.RulesProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static org.sonar.server.ws.WsUtils.checkRequest; | |||
class RuleActivatorContext { | |||
private final QProfileDto profile; | |||
private final RulesProfileDto rulesProfile; | |||
private final Date now = new Date(); | |||
private RuleDefinitionDto rule; | |||
private final Map<String, RuleParamDto> ruleParamsByKey = new HashMap<>(); | |||
private ActiveRuleDto activeRule; | |||
private ActiveRuleDto parentActiveRule; | |||
private final Map<String, ActiveRuleParamDto> activeRuleParams = new HashMap<>(); | |||
private final Map<String, ActiveRuleParamDto> parentActiveRuleParams = new HashMap<>(); | |||
private final boolean isCascade; | |||
RuleActivatorContext(QProfileDto profile, boolean isCascade) { | |||
this.profile = profile; | |||
this.rulesProfile = RulesProfileDto.from(profile); | |||
this.isCascade = isCascade; | |||
} | |||
RuleActivatorContext(RulesProfileDto rulesProfile) { | |||
checkArgument(rulesProfile.isBuiltIn(), "Rules profile must be a built-in profile: " + rulesProfile.getKee()); | |||
this.profile = null; | |||
this.rulesProfile = rulesProfile; | |||
this.isCascade = false; | |||
} | |||
/** | |||
* The organization profile that is being updated. Null if updating built-in profile. | |||
*/ | |||
@CheckForNull | |||
QProfileDto getOrganizationProfile() { | |||
return profile; | |||
} | |||
RulesProfileDto getRulesProfile() { | |||
return rulesProfile; | |||
} | |||
/** | |||
* Whether activation is being applied on a descendant profile ({@code true}) or | |||
* on the target profile ({@code false}). | |||
*/ | |||
boolean isCascade() { | |||
return isCascade; | |||
} | |||
ActiveRuleKey getActiveRuleKey() { | |||
return ActiveRuleKey.of(rulesProfile, rule.getKey()); | |||
} | |||
RuleDefinitionDto getRule() { | |||
return rule; | |||
} | |||
RuleActivatorContext setRule(RuleDefinitionDto rule) { | |||
this.rule = rule; | |||
return this; | |||
} | |||
/** | |||
* Date of request for activation. | |||
*/ | |||
Date getDate() { | |||
return now; | |||
} | |||
@CheckForNull | |||
RuleParamDto getRuleParam(String key) { | |||
return ruleParamsByKey.get(key); | |||
} | |||
Collection<RuleParamDto> getRuleParams() { | |||
return ruleParamsByKey.values(); | |||
} | |||
void setRuleParams(Collection<RuleParamDto> ruleParams) { | |||
this.ruleParamsByKey.clear(); | |||
for (RuleParamDto ruleParam : ruleParams) { | |||
this.ruleParamsByKey.put(ruleParam.getName(), ruleParam); | |||
} | |||
} | |||
/** | |||
* The active rule as it was before applying the current activation. | |||
* Return null if the rule was not activated. | |||
*/ | |||
@CheckForNull | |||
ActiveRuleDto getActiveRule() { | |||
return activeRule; | |||
} | |||
RuleActivatorContext setActiveRule(@Nullable ActiveRuleDto a) { | |||
this.activeRule = a; | |||
return this; | |||
} | |||
@CheckForNull | |||
ActiveRuleDto getParentActiveRule() { | |||
return parentActiveRule; | |||
} | |||
void setParentActiveRule(@Nullable ActiveRuleDto a) { | |||
this.parentActiveRule = a; | |||
} | |||
@CheckForNull | |||
String getRequestedParamValue(RuleActivation request, String key) { | |||
if (rule.isCustomRule()) { | |||
return null; | |||
} | |||
return request.getParameter(key); | |||
} | |||
boolean hasRequestedParamValue(RuleActivation request, String key) { | |||
return request.hasParameter(key); | |||
} | |||
@CheckForNull | |||
String getActiveParamValue(String key) { | |||
ActiveRuleParamDto param = activeRuleParams.get(key); | |||
return param != null ? param.getValue() : null; | |||
} | |||
@CheckForNull | |||
ActiveRuleParamDto getActiveParamBeforeChange(String key) { | |||
return activeRuleParams.get(key); | |||
} | |||
@CheckForNull | |||
String getActiveParentParamValue(String key) { | |||
ActiveRuleParamDto param = parentActiveRuleParams.get(key); | |||
return param != null ? param.getValue() : null; | |||
} | |||
@CheckForNull | |||
String getDefaultParamValue(String key) { | |||
RuleParamDto param = ruleParamsByKey.get(key); | |||
return param != null ? param.getDefaultValue() : null; | |||
} | |||
@CheckForNull | |||
String getActiveSeverityBeforeChange() { | |||
return activeRule != null ? activeRule.getSeverityString() : null; | |||
} | |||
@CheckForNull | |||
String getActiveParentSeverity() { | |||
return parentActiveRule != null ? parentActiveRule.getSeverityString() : null; | |||
} | |||
Map<String, String> activeRuleParamsAsStringMap() { | |||
Map<String, String> params = Maps.newHashMap(); | |||
for (Map.Entry<String, ActiveRuleParamDto> param : activeRuleParams.entrySet()) { | |||
params.put(param.getKey(), param.getValue().getValue()); | |||
} | |||
return params; | |||
} | |||
void setActiveRuleParams(@Nullable Collection<ActiveRuleParamDto> a) { | |||
activeRuleParams.clear(); | |||
if (a != null) { | |||
for (ActiveRuleParamDto ar : a) { | |||
this.activeRuleParams.put(ar.getKey(), ar); | |||
} | |||
} | |||
} | |||
void setParentActiveRuleParams(@Nullable Collection<ActiveRuleParamDto> a) { | |||
parentActiveRuleParams.clear(); | |||
if (a != null) { | |||
for (ActiveRuleParamDto ar : a) { | |||
this.parentActiveRuleParams.put(ar.getKey(), ar); | |||
} | |||
} | |||
} | |||
/** | |||
* True if trying to override an inherited rule but with exactly the same values | |||
*/ | |||
boolean isSameAsParent(ActiveRuleChange change) { | |||
if (parentActiveRule == null) { | |||
return false; | |||
} | |||
if (!StringUtils.equals(change.getSeverity(), parentActiveRule.getSeverityString())) { | |||
return false; | |||
} | |||
for (Map.Entry<String, String> entry : change.getParameters().entrySet()) { | |||
if (entry.getValue() != null && !entry.getValue().equals(getActiveParentParamValue(entry.getKey()))) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
boolean isSame(ActiveRuleChange change) { | |||
ActiveRule.Inheritance inheritance = change.getInheritance(); | |||
if (inheritance != null && !inheritance.name().equals(activeRule.getInheritance())) { | |||
return false; | |||
} | |||
String severity = change.getSeverity(); | |||
if (severity != null && !severity.equals(activeRule.getSeverityString())) { | |||
return false; | |||
} | |||
for (Map.Entry<String, String> changeParam : change.getParameters().entrySet()) { | |||
ActiveRuleParamDto param = activeRuleParams.get(changeParam.getKey()); | |||
if (changeParam.getValue() == null && param != null && param.getValue() != null) { | |||
return false; | |||
} | |||
if (changeParam.getValue() != null && (param == null || !StringUtils.equals(changeParam.getValue(), param.getValue()))) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
void verifyForActivation() { | |||
checkRequest(RuleStatus.REMOVED != rule.getStatus(), "Rule was removed: %s", rule.getKey()); | |||
checkRequest(!rule.isTemplate(), "Rule template can't be activated on a Quality profile: %s", rule.getKey()); | |||
checkRequest(rulesProfile.getLanguage().equals(rule.getLanguage()), | |||
"Rule %s and profile %s have different languages", rule.getKey(), profile != null ? profile.getKee() : rulesProfile.getKee()); | |||
} | |||
} |
@@ -1,113 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program 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. | |||
* | |||
* This program 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.qualityprofile; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.qualityprofile.RulesProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import static org.sonar.server.ws.WsUtils.checkRequest; | |||
@ServerSide | |||
public class RuleActivatorContextFactory { | |||
private final DbClient db; | |||
public RuleActivatorContextFactory(DbClient db) { | |||
this.db = db; | |||
} | |||
RuleActivatorContext createForBuiltIn(DbSession dbSession, RuleKey ruleKey, RulesProfileDto rulesProfile) { | |||
RuleActivatorContext context = new RuleActivatorContext(rulesProfile); | |||
return init(dbSession, ruleKey, context); | |||
} | |||
RuleActivatorContext create(DbSession dbSession, RuleKey ruleKey, QProfileDto profile, boolean cascade) { | |||
RuleActivatorContext context = new RuleActivatorContext(profile, cascade); | |||
return init(dbSession, ruleKey, context); | |||
} | |||
private RuleActivatorContext init(DbSession dbSession, RuleKey ruleKey, RuleActivatorContext context) { | |||
initRule(ruleKey, context, dbSession); | |||
initActiveRules(context.getRulesProfile(), ruleKey, context, dbSession, false); | |||
QProfileDto orgProfile = context.getOrganizationProfile(); | |||
if (orgProfile != null && orgProfile.getParentKee() != null) { | |||
QProfileDto parent = db.qualityProfileDao().selectByUuid(dbSession, orgProfile.getParentKee()); | |||
if (parent != null) { | |||
initActiveRules(RulesProfileDto.from(parent), ruleKey, context, dbSession, true); | |||
} | |||
} | |||
return context; | |||
} | |||
private RuleDefinitionDto initRule(RuleKey ruleKey, RuleActivatorContext context, DbSession dbSession) { | |||
Optional<RuleDefinitionDto> rule = getRule(dbSession, ruleKey); | |||
checkRequest(rule.isPresent(), "Rule not found: %s", ruleKey); | |||
RuleDefinitionDto ruleDefinitionDto = rule.get(); | |||
context.setRule(ruleDefinitionDto); | |||
context.setRuleParams(getRuleParams(dbSession, ruleDefinitionDto)); | |||
return ruleDefinitionDto; | |||
} | |||
private void initActiveRules(RulesProfileDto rulesProfile, RuleKey ruleKey, RuleActivatorContext context, DbSession dbSession, boolean isParent) { | |||
ActiveRuleKey key = ActiveRuleKey.of(rulesProfile, ruleKey); | |||
Optional<ActiveRuleDto> activeRule = getActiveRule(dbSession, key); | |||
Collection<ActiveRuleParamDto> activeRuleParams = null; | |||
if (activeRule.isPresent()) { | |||
activeRuleParams = getActiveRuleParams(dbSession, activeRule.get()); | |||
} | |||
if (isParent) { | |||
context.setParentActiveRule(activeRule.orElse(null)); | |||
context.setParentActiveRuleParams(activeRuleParams); | |||
} else { | |||
context.setActiveRule(activeRule.orElse(null)); | |||
context.setActiveRuleParams(activeRuleParams); | |||
} | |||
} | |||
Optional<RuleDefinitionDto> getRule(DbSession dbSession, RuleKey ruleKey) { | |||
return Optional.ofNullable(db.ruleDao().selectDefinitionByKey(dbSession, ruleKey).orElse(null)); | |||
} | |||
Collection<RuleParamDto> getRuleParams(DbSession dbSession, RuleDefinitionDto ruleDefinitionDto) { | |||
return db.ruleDao().selectRuleParamsByRuleKey(dbSession, ruleDefinitionDto.getKey()); | |||
} | |||
Optional<ActiveRuleDto> getActiveRule(DbSession dbSession, ActiveRuleKey key) { | |||
return db.activeRuleDao().selectByKey(dbSession, key); | |||
} | |||
List<ActiveRuleParamDto> getActiveRuleParams(DbSession dbSession, ActiveRuleDto activeRuleDto) { | |||
return db.activeRuleDao().selectParamsByActiveRuleId(dbSession, activeRuleDto.getId()); | |||
} | |||
} |
@@ -30,11 +30,12 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.qualityprofile.RuleActivation; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.user.UserSession; | |||
import static java.lang.String.format; | |||
import static java.util.Collections.singletonList; | |||
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01; | |||
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ACTIVATE_RULE; | |||
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY; | |||
@@ -46,11 +47,11 @@ import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters. | |||
public class ActivateRuleAction implements QProfileWsAction { | |||
private final DbClient dbClient; | |||
private final RuleActivator ruleActivator; | |||
private final QProfileRules ruleActivator; | |||
private final UserSession userSession; | |||
private final QProfileWsSupport wsSupport; | |||
public ActivateRuleAction(DbClient dbClient, RuleActivator ruleActivator, UserSession userSession, QProfileWsSupport wsSupport) { | |||
public ActivateRuleAction(DbClient dbClient, QProfileRules ruleActivator, UserSession userSession, QProfileWsSupport wsSupport) { | |||
this.dbClient = dbClient; | |||
this.ruleActivator = ruleActivator; | |||
this.userSession = userSession; | |||
@@ -104,7 +105,7 @@ public class ActivateRuleAction implements QProfileWsAction { | |||
OrganizationDto organization = wsSupport.getOrganization(dbSession, profile); | |||
wsSupport.checkCanEdit(dbSession, organization, profile); | |||
RuleActivation activation = readActivation(request); | |||
ruleActivator.activateAndCommit(dbSession, activation, profile); | |||
ruleActivator.activateAndCommit(dbSession, profile, singletonList(activation)); | |||
} | |||
response.noContent(); |
@@ -28,7 +28,7 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.server.qualityprofile.BulkChangeResult; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.rule.ws.RuleQueryFactory; | |||
import org.sonar.server.user.UserSession; | |||
@@ -44,14 +44,14 @@ public class ActivateRulesAction implements QProfileWsAction { | |||
private final RuleQueryFactory ruleQueryFactory; | |||
private final UserSession userSession; | |||
private final RuleActivator ruleActivator; | |||
private final QProfileRules qProfileRules; | |||
private final DbClient dbClient; | |||
private final QProfileWsSupport wsSupport; | |||
public ActivateRulesAction(RuleQueryFactory ruleQueryFactory, UserSession userSession, RuleActivator ruleActivator, QProfileWsSupport wsSupport, DbClient dbClient) { | |||
public ActivateRulesAction(RuleQueryFactory ruleQueryFactory, UserSession userSession, QProfileRules qProfileRules, QProfileWsSupport wsSupport, DbClient dbClient) { | |||
this.ruleQueryFactory = ruleQueryFactory; | |||
this.userSession = userSession; | |||
this.ruleActivator = ruleActivator; | |||
this.qProfileRules = qProfileRules; | |||
this.dbClient = dbClient; | |||
this.wsSupport = wsSupport; | |||
} | |||
@@ -93,7 +93,7 @@ public class ActivateRulesAction implements QProfileWsAction { | |||
OrganizationDto organization = wsSupport.getOrganization(dbSession, profile); | |||
wsSupport.checkCanEdit(dbSession, organization, profile); | |||
wsSupport.checkNotBuiltInt(profile); | |||
result = ruleActivator.bulkActivateAndCommit(dbSession, ruleQueryFactory.createRuleQuery(dbSession, request), profile, request.param(PARAM_TARGET_SEVERITY)); | |||
result = qProfileRules.bulkActivateAndCommit(dbSession, profile, ruleQueryFactory.createRuleQuery(dbSession, request), request.param(PARAM_TARGET_SEVERITY)); | |||
} | |||
writeResponse(result, response); |
@@ -28,7 +28,7 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileTree; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters; | |||
@@ -40,12 +40,12 @@ import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters. | |||
public class ChangeParentAction implements QProfileWsAction { | |||
private final DbClient dbClient; | |||
private final RuleActivator ruleActivator; | |||
private final QProfileTree ruleActivator; | |||
private final Languages languages; | |||
private final QProfileWsSupport wsSupport; | |||
private final UserSession userSession; | |||
public ChangeParentAction(DbClient dbClient, RuleActivator ruleActivator, | |||
public ChangeParentAction(DbClient dbClient, QProfileTree ruleActivator, | |||
Languages languages, QProfileWsSupport wsSupport, UserSession userSession) { | |||
this.dbClient = dbClient; | |||
this.ruleActivator = ruleActivator; | |||
@@ -96,7 +96,7 @@ public class ChangeParentAction implements QProfileWsAction { | |||
String parentKey = request.param(PARAM_PARENT_KEY); | |||
String parentName = request.param(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE); | |||
if (isEmpty(parentKey) && isEmpty(parentName)) { | |||
ruleActivator.setParentAndCommit(dbSession, profile, null); | |||
ruleActivator.removeParentAndCommit(dbSession, profile); | |||
} else { | |||
String parentOrganizationKey = parentKey == null ? organization.getKey() : null; | |||
String parentLanguage = parentKey == null ? request.param(PARAM_LANGUAGE) : null; |
@@ -27,9 +27,10 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.user.UserSession; | |||
import static java.util.Collections.singletonList; | |||
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01; | |||
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_DEACTIVATE_RULE; | |||
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY; | |||
@@ -38,11 +39,11 @@ import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters. | |||
public class DeactivateRuleAction implements QProfileWsAction { | |||
private final DbClient dbClient; | |||
private final RuleActivator ruleActivator; | |||
private final QProfileRules ruleActivator; | |||
private final UserSession userSession; | |||
private final QProfileWsSupport wsSupport; | |||
public DeactivateRuleAction(DbClient dbClient, RuleActivator ruleActivator, UserSession userSession, QProfileWsSupport wsSupport) { | |||
public DeactivateRuleAction(DbClient dbClient, QProfileRules ruleActivator, UserSession userSession, QProfileWsSupport wsSupport) { | |||
this.dbClient = dbClient; | |||
this.ruleActivator = ruleActivator; | |||
this.userSession = userSession; | |||
@@ -84,7 +85,7 @@ public class DeactivateRuleAction implements QProfileWsAction { | |||
QProfileDto profile = wsSupport.getProfile(dbSession, QProfileReference.fromKey(qualityProfileKey)); | |||
OrganizationDto organization = wsSupport.getOrganization(dbSession, profile); | |||
wsSupport.checkCanEdit(dbSession, organization, profile); | |||
ruleActivator.deactivateAndCommit(dbSession, profile, ruleKey); | |||
ruleActivator.deactivateAndCommit(dbSession, profile, singletonList(ruleKey)); | |||
} | |||
response.noContent(); | |||
} |
@@ -27,7 +27,7 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.server.qualityprofile.BulkChangeResult; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.rule.ws.RuleQueryFactory; | |||
import org.sonar.server.user.UserSession; | |||
@@ -42,11 +42,11 @@ public class DeactivateRulesAction implements QProfileWsAction { | |||
private final RuleQueryFactory ruleQueryFactory; | |||
private final UserSession userSession; | |||
private final RuleActivator ruleActivator; | |||
private final QProfileRules ruleActivator; | |||
private final QProfileWsSupport wsSupport; | |||
private final DbClient dbClient; | |||
public DeactivateRulesAction(RuleQueryFactory ruleQueryFactory, UserSession userSession, RuleActivator ruleActivator, QProfileWsSupport wsSupport, DbClient dbClient) { | |||
public DeactivateRulesAction(RuleQueryFactory ruleQueryFactory, UserSession userSession, QProfileRules ruleActivator, QProfileWsSupport wsSupport, DbClient dbClient) { | |||
this.ruleQueryFactory = ruleQueryFactory; | |||
this.userSession = userSession; | |||
this.ruleActivator = ruleActivator; | |||
@@ -85,7 +85,7 @@ public class DeactivateRulesAction implements QProfileWsAction { | |||
QProfileDto profile = wsSupport.getProfile(dbSession, QProfileReference.fromKey(qualityProfileKey)); | |||
OrganizationDto organization = wsSupport.getOrganization(dbSession, profile); | |||
wsSupport.checkCanEdit(dbSession, organization, profile); | |||
result = ruleActivator.bulkDeactivateAndCommit(dbSession, ruleQueryFactory.createRuleQuery(dbSession, request), profile); | |||
result = ruleActivator.bulkDeactivateAndCommit(dbSession, profile, ruleQueryFactory.createRuleQuery(dbSession, request)); | |||
} | |||
writeResponse(result, response); | |||
} |
@@ -54,7 +54,7 @@ import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.db.rule.RuleRepositoryDto; | |||
import org.sonar.server.organization.OrganizationFlags; | |||
import org.sonar.server.qualityprofile.ActiveRuleChange; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndexer; | |||
@@ -70,7 +70,7 @@ public class RegisterRules implements Startable { | |||
private static final Logger LOG = Loggers.get(RegisterRules.class); | |||
private final RuleDefinitionsLoader defLoader; | |||
private final RuleActivator ruleActivator; | |||
private final QProfileRules qProfileRules; | |||
private final DbClient dbClient; | |||
private final RuleIndexer ruleIndexer; | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
@@ -79,11 +79,11 @@ public class RegisterRules implements Startable { | |||
private final OrganizationFlags organizationFlags; | |||
private final WebServerRuleFinder webServerRuleFinder; | |||
public RegisterRules(RuleDefinitionsLoader defLoader, RuleActivator ruleActivator, DbClient dbClient, RuleIndexer ruleIndexer, | |||
public RegisterRules(RuleDefinitionsLoader defLoader, QProfileRules qProfileRules, DbClient dbClient, RuleIndexer ruleIndexer, | |||
ActiveRuleIndexer activeRuleIndexer, Languages languages, System2 system2, OrganizationFlags organizationFlags, | |||
WebServerRuleFinder webServerRuleFinder) { | |||
this.defLoader = defLoader; | |||
this.ruleActivator = ruleActivator; | |||
this.qProfileRules = qProfileRules; | |||
this.dbClient = dbClient; | |||
this.ruleIndexer = ruleIndexer; | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
@@ -130,6 +130,8 @@ public class RegisterRules implements Startable { | |||
keysToIndex.addAll(removedRules.stream().map(RuleDefinitionDto::getKey).collect(Collectors.toList())); | |||
persistRepositories(dbSession, context.repositories()); | |||
// FIXME lack of resiliency, active rules index is corrupted if rule index fails | |||
// to be updated. Only a single DB commit should be executed. | |||
ruleIndexer.commitAndIndex(dbSession, keysToIndex); | |||
activeRuleIndexer.commitAndIndex(dbSession, changes); | |||
profiler.stopDebug(); | |||
@@ -506,7 +508,7 @@ public class RegisterRules implements Startable { | |||
* The side effect of this approach is that extended repositories will not be managed the same way. | |||
* If an extended repository do not exists anymore, then related active rules will be removed. | |||
*/ | |||
private List<ActiveRuleChange> removeActiveRulesOnStillExistingRepositories(DbSession session, Collection<RuleDefinitionDto> removedRules, RulesDefinition.Context context) { | |||
private List<ActiveRuleChange> removeActiveRulesOnStillExistingRepositories(DbSession dbSession, Collection<RuleDefinitionDto> removedRules, RulesDefinition.Context context) { | |||
List<String> repositoryKeys = newArrayList(Iterables.transform(context.repositories(), RulesDefinition.Repository::key)); | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
@@ -515,7 +517,7 @@ public class RegisterRules implements Startable { | |||
// SONAR-4642 Remove active rules only when repository still exists | |||
if (repositoryKeys.contains(rule.getRepositoryKey())) { | |||
profiler.start(); | |||
changes.addAll(ruleActivator.delete(session, rule)); | |||
changes.addAll(qProfileRules.deleteRule(dbSession, rule)); | |||
profiler.stopDebug(format("Remove active rule for rule %s", rule.getKey())); | |||
} | |||
} |
@@ -28,7 +28,7 @@ import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.rule.index.RuleIndexer; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
@@ -40,14 +40,14 @@ public class DeleteAction implements RulesWsAction { | |||
private final System2 system2; | |||
private final RuleIndexer ruleIndexer; | |||
private final DbClient dbClient; | |||
private final RuleActivator ruleActivator; | |||
private final QProfileRules qProfileRules; | |||
private final RuleWsSupport ruleWsSupport; | |||
public DeleteAction(System2 system2, RuleIndexer ruleIndexer, DbClient dbClient, RuleActivator ruleActivator, RuleWsSupport ruleWsSupport) { | |||
public DeleteAction(System2 system2, RuleIndexer ruleIndexer, DbClient dbClient, QProfileRules qProfileRules, RuleWsSupport ruleWsSupport) { | |||
this.system2 = system2; | |||
this.ruleIndexer = ruleIndexer; | |||
this.dbClient = dbClient; | |||
this.ruleActivator = ruleActivator; | |||
this.qProfileRules = qProfileRules; | |||
this.ruleWsSupport = ruleWsSupport; | |||
} | |||
@@ -80,14 +80,12 @@ public class DeleteAction implements RulesWsAction { | |||
RuleDefinitionDto rule = dbClient.ruleDao().selectOrFailDefinitionByKey(dbSession, ruleKey); | |||
checkArgument(rule.isCustomRule(), "Rule '%s' cannot be deleted because it is not a custom rule", rule.getKey().toString()); | |||
// For custom rule, first deactivate the rule on all profiles | |||
if (rule.isCustomRule()) { | |||
ruleActivator.delete(dbSession, rule); | |||
} | |||
qProfileRules.deleteRule(dbSession, rule); | |||
rule.setStatus(RuleStatus.REMOVED); | |||
rule.setUpdatedAt(system2.now()); | |||
dbClient.ruleDao().update(dbSession, rule); | |||
ruleIndexer.commitAndIndex(dbSession, ruleKey); | |||
} | |||
} |
@@ -24,7 +24,6 @@ import java.util.Optional; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; | |||
@@ -62,9 +61,8 @@ public class BuiltInQProfileUpdateImplTest { | |||
public UserSessionRule userSession = UserSessionRule.standalone(); | |||
private System2 system2 = new TestSystem2().setNow(NOW); | |||
private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class); | |||
private RuleActivatorContextFactory contextFactory = new RuleActivatorContextFactory(db.getDbClient()); | |||
private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); | |||
private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), null, contextFactory, typeValidations, activeRuleIndexer, userSession); | |||
private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession); | |||
private BuiltInQProfileUpdateImpl underTest = new BuiltInQProfileUpdateImpl(db.getDbClient(), ruleActivator, activeRuleIndexer); | |||
@@ -189,6 +187,48 @@ public class BuiltInQProfileUpdateImplTest { | |||
assertThatProfileIsMarkedAsUpdated(persistedProfile); | |||
} | |||
// @Test | |||
// public void propagate_new_activation_to_profiles() { | |||
// RuleDefinitionDto rule = createJavaRule(); | |||
// QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), | |||
// p -> p.setLanguage(rule.getLanguage()) | |||
// .setIsBuiltIn(true)); | |||
// QProfileDto childProfile = createChildProfile(profile); | |||
// QProfileDto grandchildProfile = createChildProfile(childProfile); | |||
// | |||
// List<ActiveRuleChange> changes = underTest.activateOnBuiltInRulesProfile(db.getSession(), RuleActivation.create(rule.getKey()), | |||
// RulesProfileDto.from(profile)); | |||
// | |||
// assertThat(changes).hasSize(3); | |||
// assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap()); | |||
// assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap()); | |||
// assertThatRuleIsActivated(grandchildProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap()); | |||
// } | |||
// | |||
// @Test | |||
// public void deactivateOnBuiltInProfile_activate_rule_on_child_profiles() { | |||
// RuleDefinitionDto rule = createJavaRule(); | |||
// QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), | |||
// p -> p.setLanguage(rule.getLanguage()) | |||
// .setIsBuiltIn(true)); | |||
// QProfileDto childProfile = createChildProfile(profile); | |||
// QProfileDto grandchildProfile = createChildProfile(childProfile); | |||
// | |||
// List<ActiveRuleChange> changes = underTest.activateOnBuiltInRulesProfile(db.getSession(), RuleActivation.create(rule.getKey()), | |||
// RulesProfileDto.from(profile)); | |||
// | |||
// assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap()); | |||
// assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap()); | |||
// assertThatRuleIsActivated(grandchildProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap()); | |||
// | |||
// changes = underTest.deactivateOnBuiltInRulesProfile(db.getSession(), RulesProfileDto.from(profile), rule.getKey(), false); | |||
// | |||
// assertThat(changes).hasSize(3); | |||
// assertThatRuleIsNotPresent(profile, rule); | |||
// assertThatRuleIsNotPresent(childProfile, rule); | |||
// assertThatRuleIsNotPresent(grandchildProfile, rule); | |||
// } | |||
private static void assertThatRuleIsNewlyActivated(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule, RulePriority severity) { | |||
ActiveRuleDto activeRule = findRule(activeRules, rule).get(); | |||
@@ -244,10 +284,6 @@ public class BuiltInQProfileUpdateImplTest { | |||
.findFirst(); | |||
} | |||
private static void activateRuleInDef(RulesProfile apiProfile, RuleDefinitionDto rule, RulePriority severity) { | |||
apiProfile.activateRule(org.sonar.api.rules.Rule.create(rule.getRepositoryKey(), rule.getRuleKey()), severity); | |||
} | |||
private void activateRuleInDb(RulesProfileDto profile, RuleDefinitionDto rule, RulePriority severity) { | |||
ActiveRuleDto dto = new ActiveRuleDto() | |||
.setProfileId(profile.getId()) |
@@ -26,6 +26,7 @@ import org.junit.After; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.config.internal.MapSettings; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.server.rule.RuleParamType; | |||
import org.sonar.api.utils.System2; | |||
@@ -41,10 +42,12 @@ import org.sonar.server.qualityprofile.QProfileComparison.ActiveRuleDiff; | |||
import org.sonar.server.qualityprofile.QProfileComparison.QProfileComparisonResult; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.util.IntegerTypeValidation; | |||
import org.sonar.server.util.TypeValidations; | |||
import static java.util.Collections.singleton; | |||
import static java.util.Collections.singletonList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -55,11 +58,11 @@ public class QProfileComparisonTest { | |||
@Rule | |||
public DbTester dbTester = DbTester.create(); | |||
@Rule | |||
public EsTester esTester = new EsTester(); | |||
public EsTester esTester = new EsTester(RuleIndexDefinition.createForTest(new MapSettings().asConfig())); | |||
private DbClient db; | |||
private DbSession dbSession; | |||
private RuleActivator ruleActivator; | |||
private QProfileRules qProfileRules; | |||
private QProfileComparison comparison; | |||
private RuleDto xooRule1; | |||
@@ -71,15 +74,10 @@ public class QProfileComparisonTest { | |||
public void before() { | |||
db = dbTester.getDbClient(); | |||
dbSession = db.openSession(false); | |||
ruleActivator = new RuleActivator( | |||
System2.INSTANCE, | |||
db, | |||
new RuleIndex(esTester.client(), System2.INSTANCE), | |||
new RuleActivatorContextFactory(db), | |||
new TypeValidations(singletonList(new IntegerTypeValidation())), | |||
new ActiveRuleIndexer(db, esTester.client()), | |||
userSession | |||
); | |||
RuleIndex ruleIndex = new RuleIndex(esTester.client(), System2.INSTANCE); | |||
ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db, esTester.client()); | |||
RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db, new TypeValidations(singletonList(new IntegerTypeValidation())), userSession); | |||
qProfileRules = new QProfileRulesImpl(db, ruleActivator, ruleIndex, activeRuleIndexer); | |||
comparison = new QProfileComparison(db); | |||
xooRule1 = RuleTesting.newXooX1().setSeverity("MINOR"); | |||
@@ -119,9 +117,8 @@ public class QProfileComparisonTest { | |||
public void compare_same() { | |||
RuleActivation commonActivation = RuleActivation.create(xooRule1.getKey(), Severity.CRITICAL, | |||
ImmutableMap.of("min", "7", "max", "42")); | |||
ruleActivator.activate(dbSession, commonActivation, left); | |||
ruleActivator.activate(dbSession, commonActivation, right); | |||
dbSession.commit(); | |||
qProfileRules.activateAndCommit(dbSession, left, singleton(commonActivation)); | |||
qProfileRules.activateAndCommit(dbSession, right, singleton(commonActivation)); | |||
QProfileComparisonResult result = comparison.compare(dbSession, left, right); | |||
assertThat(result.left().getKee()).isEqualTo(left.getKee()); | |||
@@ -136,8 +133,7 @@ public class QProfileComparisonTest { | |||
@Test | |||
public void compare_only_left() { | |||
RuleActivation activation = RuleActivation.create(xooRule1.getKey()); | |||
ruleActivator.activate(dbSession, activation, left); | |||
dbSession.commit(); | |||
qProfileRules.activateAndCommit(dbSession, left, singleton(activation)); | |||
QProfileComparisonResult result = comparison.compare(dbSession, left, right); | |||
assertThat(result.left().getKee()).isEqualTo(left.getKee()); | |||
@@ -151,8 +147,7 @@ public class QProfileComparisonTest { | |||
@Test | |||
public void compare_only_right() { | |||
ruleActivator.activate(dbSession, RuleActivation.create(xooRule1.getKey()), right); | |||
dbSession.commit(); | |||
qProfileRules.activateAndCommit(dbSession, right, singleton(RuleActivation.create(xooRule1.getKey()))); | |||
QProfileComparisonResult result = comparison.compare(dbSession, left, right); | |||
assertThat(result.left().getKee()).isEqualTo(left.getKee()); | |||
@@ -166,9 +161,8 @@ public class QProfileComparisonTest { | |||
@Test | |||
public void compare_disjoint() { | |||
ruleActivator.activate(dbSession, RuleActivation.create(xooRule1.getKey()), left); | |||
ruleActivator.activate(dbSession, RuleActivation.create(xooRule2.getKey()), right); | |||
dbSession.commit(); | |||
qProfileRules.activateAndCommit(dbSession, left, singleton(RuleActivation.create(xooRule1.getKey()))); | |||
qProfileRules.activateAndCommit(dbSession, right, singleton(RuleActivation.create(xooRule2.getKey()))); | |||
QProfileComparisonResult result = comparison.compare(dbSession, left, right); | |||
assertThat(result.left().getKee()).isEqualTo(left.getKee()); | |||
@@ -182,9 +176,8 @@ public class QProfileComparisonTest { | |||
@Test | |||
public void compare_modified_severity() { | |||
ruleActivator.activate(dbSession, RuleActivation.create(xooRule1.getKey(), Severity.CRITICAL, null), left); | |||
ruleActivator.activate(dbSession, RuleActivation.create(xooRule1.getKey(), Severity.BLOCKER, null), right); | |||
dbSession.commit(); | |||
qProfileRules.activateAndCommit(dbSession, left, singleton(RuleActivation.create(xooRule1.getKey(), Severity.CRITICAL, null))); | |||
qProfileRules.activateAndCommit(dbSession, right, singleton(RuleActivation.create(xooRule1.getKey(), Severity.BLOCKER, null))); | |||
QProfileComparisonResult result = comparison.compare(dbSession, left, right); | |||
assertThat(result.left().getKee()).isEqualTo(left.getKee()); | |||
@@ -203,9 +196,8 @@ public class QProfileComparisonTest { | |||
@Test | |||
public void compare_modified_param() { | |||
ruleActivator.activate(dbSession, RuleActivation.create(xooRule1.getKey(), null, ImmutableMap.of("max", "20")), left); | |||
ruleActivator.activate(dbSession, RuleActivation.create(xooRule1.getKey(), null, ImmutableMap.of("max", "30")), right); | |||
dbSession.commit(); | |||
qProfileRules.activateAndCommit(dbSession, left, singleton(RuleActivation.create(xooRule1.getKey(), null, ImmutableMap.of("max", "20")))); | |||
qProfileRules.activateAndCommit(dbSession, right, singleton(RuleActivation.create(xooRule1.getKey(), null, ImmutableMap.of("max", "30")))); | |||
QProfileComparisonResult result = comparison.compare(dbSession, left, right); | |||
assertThat(result.left().getKee()).isEqualTo(left.getKee()); | |||
@@ -227,9 +219,8 @@ public class QProfileComparisonTest { | |||
@Test | |||
public void compare_different_params() { | |||
ruleActivator.activate(dbSession, RuleActivation.create(xooRule1.getKey(), null, ImmutableMap.of("max", "20")), left); | |||
ruleActivator.activate(dbSession, RuleActivation.create(xooRule1.getKey(), null, ImmutableMap.of("min", "5")), right); | |||
dbSession.commit(); | |||
qProfileRules.activateAndCommit(dbSession, left, singleton(RuleActivation.create(xooRule1.getKey(), null, ImmutableMap.of("max", "20")))); | |||
qProfileRules.activateAndCommit(dbSession, right, singleton(RuleActivation.create(xooRule1.getKey(), null, ImmutableMap.of("min", "5")))); | |||
QProfileComparisonResult result = comparison.compare(dbSession, left, right); | |||
assertThat(result.left().getKee()).isEqualTo(left.getKee()); |
@@ -23,6 +23,7 @@ import java.io.IOException; | |||
import java.io.Reader; | |||
import java.io.StringWriter; | |||
import java.io.Writer; | |||
import java.util.Collection; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
@@ -40,7 +41,6 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
@@ -70,19 +70,17 @@ public class QProfileExportersTest { | |||
public DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); | |||
private RuleFinder ruleFinder = new DefaultRuleFinder(db.getDbClient(), defaultOrganizationProvider); | |||
private RuleActivator ruleActivator = mock(RuleActivator.class); | |||
private ProfileExporter[] exporters = new ProfileExporter[] { | |||
new StandardExporter(), new XooExporter()}; | |||
private ProfileImporter[] importers = new ProfileImporter[] { | |||
new XooProfileImporter(), new XooProfileImporterWithMessages(), new XooProfileImporterWithError()}; | |||
private RuleDefinitionDto rule; | |||
private RuleParamDto ruleParam; | |||
private QProfileExporters underTest = new QProfileExporters(db.getDbClient(), ruleFinder, ruleActivator, exporters, importers); | |||
private QProfileRules qProfileRules = mock(QProfileRules.class); | |||
private QProfileExporters underTest = new QProfileExporters(db.getDbClient(), ruleFinder, qProfileRules, exporters, importers); | |||
@Before | |||
public void setUp() { | |||
rule = db.rules().insert(r -> r.setLanguage("xoo").setRepositoryKey("SonarXoo").setRuleKey("R1")); | |||
ruleParam = db.rules().insertRuleParam(rule); | |||
} | |||
@Test | |||
@@ -108,12 +106,16 @@ public class QProfileExportersTest { | |||
underTest.importXml(profile, "XooProfileImporter", toInputStream("<xml/>", UTF_8), db.getSession()); | |||
ArgumentCaptor<QProfileDto> profileCapture = ArgumentCaptor.forClass(QProfileDto.class); | |||
ArgumentCaptor<RuleActivation> activationCapture = ArgumentCaptor.forClass(RuleActivation.class); | |||
verify(ruleActivator).activate(any(DbSession.class), activationCapture.capture(), profileCapture.capture()); | |||
Class<Collection<RuleActivation>> collectionClass = (Class<Collection<RuleActivation>>) (Class) Collection.class; | |||
ArgumentCaptor<Collection<RuleActivation>> activationCapture = ArgumentCaptor.forClass(collectionClass); | |||
verify(qProfileRules).activateAndCommit(any(DbSession.class), profileCapture.capture(), activationCapture.capture()); | |||
assertThat(profileCapture.getValue().getKee()).isEqualTo(profile.getKee()); | |||
assertThat(activationCapture.getValue().getRuleKey()).isEqualTo(rule.getKey()); | |||
assertThat(activationCapture.getValue().getSeverity()).isEqualTo("CRITICAL"); | |||
Collection<RuleActivation> activations = activationCapture.getValue(); | |||
assertThat(activations).hasSize(1); | |||
RuleActivation activation = activations.iterator().next(); | |||
assertThat(activation.getRuleKey()).isEqualTo(rule.getKey()); | |||
assertThat(activation.getSeverity()).isEqualTo("CRITICAL"); | |||
} | |||
@Test |
@@ -37,6 +37,7 @@ import org.sonar.server.util.StringTypeValidation; | |||
import org.sonar.server.util.TypeValidations; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.singleton; | |||
import static java.util.Collections.singletonList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.tuple; | |||
@@ -56,16 +57,17 @@ public class QProfileResetImplTest { | |||
private System2 system2 = new AlwaysIncreasingSystem2(); | |||
private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class); | |||
private RuleActivatorContextFactory contextFactory = new RuleActivatorContextFactory(db.getDbClient()); | |||
private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); | |||
private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), null, contextFactory, typeValidations, activeRuleIndexer, userSession); | |||
private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession); | |||
private QProfileTree qProfileTree = new QProfileTreeImpl(db.getDbClient(), ruleActivator, system2, activeRuleIndexer); | |||
private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, null, activeRuleIndexer); | |||
private QProfileResetImpl underTest = new QProfileResetImpl(db.getDbClient(), ruleActivator, activeRuleIndexer); | |||
@Test | |||
public void reset() { | |||
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(LANGUAGE)); | |||
RuleDefinitionDto existingRule = db.rules().insert(r -> r.setLanguage(LANGUAGE)); | |||
ruleActivator.activate(db.getSession(), RuleActivation.create(existingRule.getKey()), profile); | |||
qProfileRules.activateAndCommit(db.getSession(), profile, singleton(RuleActivation.create(existingRule.getKey()))); | |||
RuleDefinitionDto newRule = db.rules().insert(r -> r.setLanguage(LANGUAGE)); | |||
BulkChangeResult result = underTest.reset(db.getSession(), profile, singletonList(RuleActivation.create(newRule.getKey()))); | |||
@@ -83,10 +85,10 @@ public class QProfileResetImplTest { | |||
public void inherited_rules_are_not_disabled() { | |||
QProfileDto parentProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(LANGUAGE)); | |||
QProfileDto childProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(LANGUAGE)); | |||
ruleActivator.setParentAndCommit(db.getSession(), childProfile, parentProfile); | |||
qProfileTree.setParentAndCommit(db.getSession(), childProfile, parentProfile); | |||
RuleDefinitionDto existingRule = db.rules().insert(r -> r.setLanguage(LANGUAGE)); | |||
ruleActivator.activate(db.getSession(), RuleActivation.create(existingRule.getKey()), parentProfile); | |||
ruleActivator.activate(db.getSession(), RuleActivation.create(existingRule.getKey()), childProfile); | |||
qProfileRules.activateAndCommit(db.getSession(), parentProfile, singleton(RuleActivation.create(existingRule.getKey()))); | |||
qProfileRules.activateAndCommit(db.getSession(), childProfile, singleton(RuleActivation.create(existingRule.getKey()))); | |||
RuleDefinitionDto newRule = db.rules().insert(r -> r.setLanguage(LANGUAGE)); | |||
underTest.reset(db.getSession(), childProfile, singletonList(RuleActivation.create(newRule.getKey()))); |
@@ -40,7 +40,6 @@ import org.sonar.db.DbTester; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.OrgActiveRuleDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.qualityprofile.RulesProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
@@ -60,6 +59,7 @@ import org.sonar.server.util.TypeValidations; | |||
import static com.google.common.collect.ImmutableMap.of; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.emptyMap; | |||
import static java.util.Collections.singleton; | |||
import static java.util.Collections.singletonList; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -71,7 +71,7 @@ import static org.sonar.api.rule.Severity.MINOR; | |||
import static org.sonar.db.rule.RuleTesting.newCustomRule; | |||
import static org.sonar.server.qualityprofile.ActiveRule.Inheritance.INHERITED; | |||
public class RuleActivatorTest { | |||
public class QProfileRuleImplTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@@ -84,13 +84,12 @@ public class RuleActivatorTest { | |||
@Rule | |||
public UserSessionRule userSession = UserSessionRule.standalone(); | |||
private RuleIndex ruleIndex = new RuleIndex(es.client(), system2); | |||
private RuleActivatorContextFactory contextFactory = new RuleActivatorContextFactory(db.getDbClient()); | |||
private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db.getDbClient(), es.client()); | |||
private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient()); | |||
private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); | |||
private RuleActivator underTest = new RuleActivator(system2, db.getDbClient(), ruleIndex, contextFactory, typeValidations, activeRuleIndexer, | |||
userSession); | |||
private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession); | |||
private QProfileRules underTest = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer); | |||
@Test | |||
public void system_activates_rule_without_parameters() { | |||
@@ -343,7 +342,7 @@ public class RuleActivatorTest { | |||
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage("js")); | |||
RuleActivation activation = RuleActivation.create(rule.getKey()); | |||
expectFailure("Rule " + rule.getKey() + " and profile " + profile.getKee() + " have different languages", () -> activate(profile, activation)); | |||
expectFailure("java rule " + rule.getKey() + " cannot be activated on js profile " + profile.getKee(), () -> activate(profile, activation)); | |||
} | |||
@Test | |||
@@ -444,7 +443,7 @@ public class RuleActivatorTest { | |||
QProfileDto profile = createProfile(rule); | |||
RuleKey ruleKey = RuleKey.parse("unknown:xxx"); | |||
expectFailure("Rule not found: " + ruleKey, () -> underTest.deactivate(db.getSession(), profile, ruleKey)); | |||
expectFailure("Rule not found: " + ruleKey, () -> underTest.deactivateAndCommit(db.getSession(), profile, singleton(ruleKey))); | |||
} | |||
@Test | |||
@@ -678,37 +677,37 @@ public class RuleActivatorTest { | |||
@Test | |||
public void reset_parent_is_not_propagated_when_child_overrides() { | |||
RuleDefinitionDto rule = createRule(); | |||
QProfileDto parentProfile = createProfile(rule); | |||
QProfileDto childProfile = createChildProfile(parentProfile); | |||
QProfileDto grandchildProfile = createChildProfile(childProfile); | |||
QProfileDto baseProfile = createProfile(rule); | |||
QProfileDto childProfile = createChildProfile(baseProfile); | |||
QProfileDto grandChildProfile = createChildProfile(childProfile); | |||
RuleActivation activation = RuleActivation.create(rule.getKey(), CRITICAL, null); | |||
List<ActiveRuleChange> changes = activate(parentProfile, activation); | |||
assertThatRuleIsActivated(parentProfile, rule, changes, CRITICAL, null, emptyMap()); | |||
List<ActiveRuleChange> changes = activate(baseProfile, activation); | |||
assertThatRuleIsActivated(baseProfile, rule, changes, CRITICAL, null, emptyMap()); | |||
assertThatRuleIsActivated(childProfile, rule, changes, CRITICAL, INHERITED, emptyMap()); | |||
assertThatRuleIsActivated(grandchildProfile, rule, changes, CRITICAL, INHERITED, emptyMap()); | |||
assertThatRuleIsActivated(grandChildProfile, rule, changes, CRITICAL, INHERITED, emptyMap()); | |||
assertThat(changes).hasSize(3); | |||
RuleActivation childActivation = RuleActivation.create(rule.getKey(), BLOCKER, null); | |||
changes = activate(childProfile, childActivation); | |||
assertThatRuleIsUpdated(childProfile, rule, BLOCKER, ActiveRule.Inheritance.OVERRIDES, emptyMap()); | |||
assertThatRuleIsUpdated(grandchildProfile, rule, BLOCKER, INHERITED, emptyMap()); | |||
assertThatRuleIsUpdated(grandChildProfile, rule, BLOCKER, INHERITED, emptyMap()); | |||
assertThat(changes).hasSize(2); | |||
// Reset on parent do not change child nor grandchild | |||
RuleActivation resetActivation = RuleActivation.createReset(rule.getKey()); | |||
changes = activate(parentProfile, resetActivation); | |||
assertThatRuleIsUpdated(parentProfile, rule, rule.getSeverityString(), null, emptyMap()); | |||
changes = activate(baseProfile, resetActivation); | |||
assertThatRuleIsUpdated(baseProfile, rule, rule.getSeverityString(), null, emptyMap()); | |||
assertThatRuleIsUpdated(childProfile, rule, BLOCKER, ActiveRule.Inheritance.OVERRIDES, emptyMap()); | |||
assertThatRuleIsUpdated(grandchildProfile, rule, BLOCKER, INHERITED, emptyMap()); | |||
assertThatRuleIsUpdated(grandChildProfile, rule, BLOCKER, INHERITED, emptyMap()); | |||
assertThat(changes).hasSize(1); | |||
// Reset on child change grandchild | |||
resetActivation = RuleActivation.createReset(rule.getKey()); | |||
changes = activate(childProfile, resetActivation); | |||
assertThatRuleIsUpdated(parentProfile, rule, rule.getSeverityString(), null, emptyMap()); | |||
assertThatRuleIsUpdated(baseProfile, rule, rule.getSeverityString(), null, emptyMap()); | |||
assertThatRuleIsUpdated(childProfile, rule, rule.getSeverityString(), INHERITED, emptyMap()); | |||
assertThatRuleIsUpdated(grandchildProfile, rule, rule.getSeverityString(), INHERITED, emptyMap()); | |||
assertThatRuleIsUpdated(grandChildProfile, rule, rule.getSeverityString(), INHERITED, emptyMap()); | |||
assertThat(changes).hasSize(2); | |||
} | |||
@@ -724,119 +723,6 @@ public class RuleActivatorTest { | |||
assertThat(changes).hasSize(0); | |||
} | |||
@Test | |||
public void unset_parent_when_no_parent_does_not_fail() { | |||
RuleDefinitionDto rule = createRule(); | |||
QProfileDto profile = createProfile(rule); | |||
underTest.setParentAndCommit(db.getSession(), profile, null); | |||
} | |||
@Test | |||
public void set_itself_as_parent_fails() { | |||
RuleDefinitionDto rule = createRule(); | |||
QProfileDto profile = createProfile(rule); | |||
expectedException.expect(BadRequestException.class); | |||
expectedException.expectMessage(" can not be selected as parent of "); | |||
underTest.setParentAndCommit(db.getSession(), profile, profile); | |||
} | |||
@Test | |||
public void set_child_as_parent_fails() { | |||
RuleDefinitionDto rule = createRule(); | |||
QProfileDto parentProfile = createProfile(rule); | |||
QProfileDto childProfile = createChildProfile(parentProfile); | |||
expectedException.expect(BadRequestException.class); | |||
expectedException.expectMessage(" can not be selected as parent of "); | |||
underTest.setParentAndCommit(db.getSession(), parentProfile, childProfile); | |||
} | |||
@Test | |||
public void set_grandchild_as_parent_fails() { | |||
RuleDefinitionDto rule = createRule(); | |||
QProfileDto parentProfile = createProfile(rule); | |||
QProfileDto childProfile = createChildProfile(parentProfile); | |||
QProfileDto grandchildProfile = createChildProfile(childProfile); | |||
expectedException.expect(BadRequestException.class); | |||
expectedException.expectMessage(" can not be selected as parent of "); | |||
underTest.setParentAndCommit(db.getSession(), parentProfile, grandchildProfile); | |||
} | |||
@Test | |||
public void cannot_set_parent_if_language_is_different() { | |||
RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("foo")); | |||
RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("bar")); | |||
QProfileDto parentProfile = createProfile(rule1); | |||
List<ActiveRuleChange> changes = activate(parentProfile, RuleActivation.create(rule1.getKey())); | |||
assertThat(changes).hasSize(1); | |||
QProfileDto childProfile = createProfile(rule2); | |||
changes = activate(childProfile, RuleActivation.create(rule2.getKey())); | |||
assertThat(changes).hasSize(1); | |||
expectedException.expect(BadRequestException.class); | |||
expectedException.expectMessage("Cannot set the profile"); | |||
underTest.setParentAndCommit(db.getSession(), childProfile, parentProfile); | |||
} | |||
@Test | |||
public void set_then_unset_parent() { | |||
RuleDefinitionDto rule1 = createJavaRule(); | |||
RuleDefinitionDto rule2 = createJavaRule(); | |||
QProfileDto profile1 = createProfile(rule1); | |||
List<ActiveRuleChange> changes = activate(profile1, RuleActivation.create(rule1.getKey())); | |||
assertThat(changes).hasSize(1); | |||
QProfileDto profile2 = createProfile(rule2); | |||
changes = activate(profile2, RuleActivation.create(rule2.getKey())); | |||
assertThat(changes).hasSize(1); | |||
changes = underTest.setParentAndCommit(db.getSession(), profile2, profile1); | |||
assertThat(changes).hasSize(1); | |||
assertThatRuleIsActivated(profile2, rule1, changes, rule1.getSeverityString(), INHERITED, emptyMap()); | |||
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap()); | |||
changes = underTest.setParentAndCommit(db.getSession(), profile2, null); | |||
assertThat(changes).hasSize(1); | |||
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap()); | |||
assertThatRuleIsNotPresent(profile2, rule1); | |||
} | |||
@Test | |||
public void set_then_unset_parent_keep_overridden_rules() { | |||
RuleDefinitionDto rule1 = createJavaRule(); | |||
RuleDefinitionDto rule2 = createJavaRule(); | |||
QProfileDto profile1 = createProfile(rule1); | |||
List<ActiveRuleChange> changes = activate(profile1, RuleActivation.create(rule1.getKey())); | |||
assertThat(changes).hasSize(1); | |||
QProfileDto profile2 = createProfile(rule2); | |||
changes = activate(profile2, RuleActivation.create(rule2.getKey())); | |||
assertThat(changes).hasSize(1); | |||
changes = underTest.setParentAndCommit(db.getSession(), profile2, profile1); | |||
assertThat(changes).hasSize(1); | |||
assertThatRuleIsActivated(profile2, rule1, changes, rule1.getSeverityString(), INHERITED, emptyMap()); | |||
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap()); | |||
RuleActivation activation = RuleActivation.create(rule1.getKey(), BLOCKER, null); | |||
changes = activate(profile2, activation); | |||
assertThat(changes).hasSize(1); | |||
assertThatRuleIsUpdated(profile2, rule1, BLOCKER, ActiveRule.Inheritance.OVERRIDES, emptyMap()); | |||
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap()); | |||
changes = underTest.setParentAndCommit(db.getSession(), profile2, null); | |||
assertThat(changes).hasSize(1); | |||
// Not testing changes here since severity is not set in changelog | |||
assertThatRuleIsActivated(profile2, rule1, null, BLOCKER, null, emptyMap()); | |||
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap()); | |||
} | |||
@Test | |||
public void bulk_activation() { | |||
int bulkSize = SearchOptions.MAX_LIMIT + 10 + new Random().nextInt(100); | |||
@@ -854,7 +740,7 @@ public class RuleActivatorTest { | |||
RuleQuery ruleQuery = new RuleQuery() | |||
.setRepositories(singletonList(repositoryKey)); | |||
BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), ruleQuery, profile, MINOR); | |||
BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), profile, ruleQuery, MINOR); | |||
assertThat(bulkChangeResult.countFailed()).isEqualTo(0); | |||
assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize); | |||
@@ -881,7 +767,7 @@ public class RuleActivatorTest { | |||
RuleQuery ruleQuery = new RuleQuery() | |||
.setRepositories(singletonList(repositoryKey)); | |||
BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), ruleQuery, profile, MINOR); | |||
BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), profile, ruleQuery, MINOR); | |||
assertThat(bulkChangeResult.countFailed()).isEqualTo(0); | |||
assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize); | |||
@@ -889,7 +775,7 @@ public class RuleActivatorTest { | |||
assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)).hasSize(bulkSize); | |||
// Now deactivate all rules | |||
bulkChangeResult = underTest.bulkDeactivateAndCommit(db.getSession(), ruleQuery, profile); | |||
bulkChangeResult = underTest.bulkDeactivateAndCommit(db.getSession(), profile, ruleQuery); | |||
assertThat(bulkChangeResult.countFailed()).isEqualTo(0); | |||
assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize); | |||
@@ -913,7 +799,7 @@ public class RuleActivatorTest { | |||
RuleQuery ruleQuery = new RuleQuery() | |||
.setQProfile(childProfile); | |||
BulkChangeResult bulkChangeResult = underTest.bulkDeactivateAndCommit(db.getSession(), ruleQuery, childProfile); | |||
BulkChangeResult bulkChangeResult = underTest.bulkDeactivateAndCommit(db.getSession(), childProfile, ruleQuery); | |||
assertThat(bulkChangeResult.countFailed()).isEqualTo(1); | |||
assertThat(bulkChangeResult.countSucceeded()).isEqualTo(0); | |||
@@ -938,7 +824,7 @@ public class RuleActivatorTest { | |||
RuleQuery query = new RuleQuery() | |||
.setRuleKey(rule1.getRuleKey()) | |||
.setQProfile(parentProfile); | |||
BulkChangeResult result = underTest.bulkActivateAndCommit(db.getSession(), query, parentProfile, "BLOCKER"); | |||
BulkChangeResult result = underTest.bulkActivateAndCommit(db.getSession(), parentProfile, query, "BLOCKER"); | |||
assertThat(result.getChanges()).hasSize(3); | |||
assertThat(result.countSucceeded()).isEqualTo(1); | |||
@@ -955,69 +841,6 @@ public class RuleActivatorTest { | |||
assertThatRuleIsActivated(grandchildProfile, rule2, null, rule2.getSeverityString(), INHERITED, emptyMap()); | |||
} | |||
@Test | |||
public void activateOnBuiltInProfile_throws_IAE_when_profile_is_not_built_in() { | |||
RuleDefinitionDto rule = createJavaRule(); | |||
QProfileDto profile = createProfile(rule); | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("Rules profile must be a built-in profile: " + profile.getRulesProfileUuid()); | |||
underTest.activateOnBuiltInRulesProfile(db.getSession(), RuleActivation.create(rule.getKey()), RulesProfileDto.from(profile)); | |||
} | |||
@Test | |||
public void activateOnBuiltInProfile_activate_rule_on_child_profiles() { | |||
RuleDefinitionDto rule = createJavaRule(); | |||
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), | |||
p -> p.setLanguage(rule.getLanguage()) | |||
.setIsBuiltIn(true)); | |||
QProfileDto childProfile = createChildProfile(profile); | |||
QProfileDto grandchildProfile = createChildProfile(childProfile); | |||
List<ActiveRuleChange> changes = underTest.activateOnBuiltInRulesProfile(db.getSession(), RuleActivation.create(rule.getKey()), RulesProfileDto.from(profile)); | |||
assertThat(changes).hasSize(3); | |||
assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap()); | |||
assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap()); | |||
assertThatRuleIsActivated(grandchildProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap()); | |||
} | |||
@Test | |||
public void deactivateOnBuiltInProfile_throws_IAE_when_profile_is_not_built_in() { | |||
RuleDefinitionDto rule = createJavaRule(); | |||
QProfileDto profile = createProfile(rule); | |||
activate(profile, RuleActivation.create(rule.getKey())); | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("Rules profile must be a built-in profile: " + profile.getRulesProfileUuid()); | |||
underTest.activateOnBuiltInRulesProfile(db.getSession(), RuleActivation.create(rule.getKey()), RulesProfileDto.from(profile)); | |||
} | |||
@Test | |||
public void deactivateOnBuiltInProfile_activate_rule_on_child_profiles() { | |||
RuleDefinitionDto rule = createJavaRule(); | |||
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), | |||
p -> p.setLanguage(rule.getLanguage()) | |||
.setIsBuiltIn(true)); | |||
QProfileDto childProfile = createChildProfile(profile); | |||
QProfileDto grandchildProfile = createChildProfile(childProfile); | |||
List<ActiveRuleChange> changes = underTest.activateOnBuiltInRulesProfile(db.getSession(), RuleActivation.create(rule.getKey()), RulesProfileDto.from(profile)); | |||
assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap()); | |||
assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap()); | |||
assertThatRuleIsActivated(grandchildProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap()); | |||
changes = underTest.deactivateOnBuiltInRulesProfile(db.getSession(), RulesProfileDto.from(profile), rule.getKey(), false); | |||
assertThat(changes).hasSize(3); | |||
assertThatRuleIsNotPresent(profile, rule); | |||
assertThatRuleIsNotPresent(childProfile, rule); | |||
assertThatRuleIsNotPresent(grandchildProfile, rule); | |||
} | |||
@Test | |||
public void delete_rule_from_all_profiles() { | |||
RuleDefinitionDto rule = createRule(); | |||
@@ -1032,7 +855,7 @@ public class RuleActivatorTest { | |||
activate(grandChildProfile, overrideActivation); | |||
// Reset on parent do not change child nor grandchild | |||
List<ActiveRuleChange> changes = underTest.delete(db.getSession(), rule); | |||
List<ActiveRuleChange> changes = underTest.deleteRule(db.getSession(), rule); | |||
assertThatRuleIsNotPresent(parentProfile, rule); | |||
assertThatRuleIsNotPresent(childProfile, rule); | |||
@@ -1044,21 +867,14 @@ public class RuleActivatorTest { | |||
} | |||
@Test | |||
public void activation_errors_are_ignored_when_setting_a_parent() { | |||
RuleDefinitionDto rule1 = createJavaRule(); | |||
RuleDefinitionDto rule2 = createJavaRule(); | |||
QProfileDto parentProfile = createProfile(rule1); | |||
activate(parentProfile, RuleActivation.create(rule1.getKey())); | |||
activate(parentProfile, RuleActivation.create(rule2.getKey())); | |||
rule1.setStatus(RuleStatus.REMOVED); | |||
db.rules().update(rule1); | |||
public void activation_fails_when_profile_is_built_in() { | |||
RuleDefinitionDto rule = createRule(); | |||
QProfileDto builtInProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true)); | |||
QProfileDto childProfile = createProfile(rule1); | |||
List<ActiveRuleChange> changes = underTest.setParentAndCommit(db.getSession(), childProfile, parentProfile); | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("The built-in profile " + builtInProfile.getName() + " is read-only and can't be updated"); | |||
assertThatRuleIsNotPresent(childProfile, rule1); | |||
assertThatRuleIsActivated(childProfile, rule2, changes, rule2.getSeverityString(), INHERITED, emptyMap()); | |||
underTest.activateAndCommit(db.getSession(), builtInProfile, singleton(RuleActivation.create(rule.getKey()))); | |||
} | |||
private void assertThatProfileHasNoActiveRules(QProfileDto profile) { | |||
@@ -1067,11 +883,11 @@ public class RuleActivatorTest { | |||
} | |||
private List<ActiveRuleChange> deactivate(QProfileDto profile, RuleDefinitionDto rule) { | |||
return underTest.deactivate(db.getSession(), profile, rule.getKey()); | |||
return underTest.deactivateAndCommit(db.getSession(), profile, singleton(rule.getKey())); | |||
} | |||
private List<ActiveRuleChange> activate(QProfileDto profile, RuleActivation activation) { | |||
return underTest.activate(db.getSession(), activation, profile); | |||
return underTest.activateAndCommit(db.getSession(), profile, singleton(activation)); | |||
} | |||
private QProfileDto createProfile(RuleDefinitionDto rule) { | |||
@@ -1079,7 +895,10 @@ public class RuleActivatorTest { | |||
} | |||
private QProfileDto createChildProfile(QProfileDto parent) { | |||
return db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(parent.getLanguage()).setParentKee(parent.getKee())); | |||
return db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p | |||
.setLanguage(parent.getLanguage()) | |||
.setParentKee(parent.getKee()) | |||
.setName("Child of " + parent.getName())); | |||
} | |||
private void assertThatProfileIsUpdatedByUser(QProfileDto profile) { |
@@ -23,7 +23,8 @@ import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
/** | |||
* Utility class for tests involving quality profiles | |||
* Utility class for tests involving quality profiles. | |||
* @deprecated replaced by {@link org.sonar.db.qualityprofile.QualityProfileDbTester} | |||
*/ | |||
@Deprecated | |||
public class QProfileTesting { |
@@ -0,0 +1,272 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program 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. | |||
* | |||
* This program 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.qualityprofile; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
import javax.annotation.Nullable; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.config.internal.MapSettings; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.internal.AlwaysIncreasingSystem2; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.OrgActiveRuleDto; | |||
import org.sonar.db.qualityprofile.QProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.util.IntegerTypeValidation; | |||
import org.sonar.server.util.StringTypeValidation; | |||
import org.sonar.server.util.TypeValidations; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.emptyMap; | |||
import static java.util.Collections.singleton; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.api.rule.Severity.BLOCKER; | |||
import static org.sonar.server.qualityprofile.ActiveRule.Inheritance.INHERITED; | |||
public class QProfileTreeImplTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private System2 system2 = new AlwaysIncreasingSystem2(); | |||
@Rule | |||
public DbTester db = DbTester.create(system2); | |||
@Rule | |||
public EsTester es = new EsTester(RuleIndexDefinition.createForTest(new MapSettings().asConfig())); | |||
@Rule | |||
public UserSessionRule userSession = UserSessionRule.standalone(); | |||
private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db.getDbClient(), es.client()); | |||
private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); | |||
private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession); | |||
private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, null, activeRuleIndexer); | |||
private QProfileTree underTest = new QProfileTreeImpl(db.getDbClient(), ruleActivator, System2.INSTANCE, activeRuleIndexer); | |||
@Test | |||
public void set_itself_as_parent_fails() { | |||
RuleDefinitionDto rule = createRule(); | |||
QProfileDto profile = createProfile(rule); | |||
expectedException.expect(BadRequestException.class); | |||
expectedException.expectMessage(" can not be selected as parent of "); | |||
underTest.setParentAndCommit(db.getSession(), profile, profile); | |||
} | |||
@Test | |||
public void set_child_as_parent_fails() { | |||
RuleDefinitionDto rule = createRule(); | |||
QProfileDto parentProfile = createProfile(rule); | |||
QProfileDto childProfile = createChildProfile(parentProfile); | |||
expectedException.expect(BadRequestException.class); | |||
expectedException.expectMessage(" can not be selected as parent of "); | |||
underTest.setParentAndCommit(db.getSession(), parentProfile, childProfile); | |||
} | |||
@Test | |||
public void set_grandchild_as_parent_fails() { | |||
RuleDefinitionDto rule = createRule(); | |||
QProfileDto parentProfile = createProfile(rule); | |||
QProfileDto childProfile = createChildProfile(parentProfile); | |||
QProfileDto grandchildProfile = createChildProfile(childProfile); | |||
expectedException.expect(BadRequestException.class); | |||
expectedException.expectMessage(" can not be selected as parent of "); | |||
underTest.setParentAndCommit(db.getSession(), parentProfile, grandchildProfile); | |||
} | |||
@Test | |||
public void cannot_set_parent_if_language_is_different() { | |||
RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("foo")); | |||
RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("bar")); | |||
QProfileDto parentProfile = createProfile(rule1); | |||
List<ActiveRuleChange> changes = activate(parentProfile, RuleActivation.create(rule1.getKey())); | |||
assertThat(changes).hasSize(1); | |||
QProfileDto childProfile = createProfile(rule2); | |||
changes = activate(childProfile, RuleActivation.create(rule2.getKey())); | |||
assertThat(changes).hasSize(1); | |||
expectedException.expect(BadRequestException.class); | |||
expectedException.expectMessage("Cannot set the profile"); | |||
underTest.setParentAndCommit(db.getSession(), childProfile, parentProfile); | |||
} | |||
@Test | |||
public void set_then_unset_parent() { | |||
RuleDefinitionDto rule1 = createJavaRule(); | |||
RuleDefinitionDto rule2 = createJavaRule(); | |||
QProfileDto profile1 = createProfile(rule1); | |||
List<ActiveRuleChange> changes = activate(profile1, RuleActivation.create(rule1.getKey())); | |||
assertThat(changes).hasSize(1); | |||
QProfileDto profile2 = createProfile(rule2); | |||
changes = activate(profile2, RuleActivation.create(rule2.getKey())); | |||
assertThat(changes).hasSize(1); | |||
changes = underTest.setParentAndCommit(db.getSession(), profile2, profile1); | |||
assertThat(changes).hasSize(1); | |||
assertThatRuleIsActivated(profile2, rule1, changes, rule1.getSeverityString(), INHERITED, emptyMap()); | |||
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap()); | |||
changes = underTest.removeParentAndCommit(db.getSession(), profile2); | |||
assertThat(changes).hasSize(1); | |||
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap()); | |||
assertThatRuleIsNotPresent(profile2, rule1); | |||
} | |||
@Test | |||
public void set_then_unset_parent_keep_overridden_rules() { | |||
RuleDefinitionDto rule1 = createJavaRule(); | |||
RuleDefinitionDto rule2 = createJavaRule(); | |||
QProfileDto profile1 = createProfile(rule1); | |||
List<ActiveRuleChange> changes = activate(profile1, RuleActivation.create(rule1.getKey())); | |||
assertThat(changes).hasSize(1); | |||
QProfileDto profile2 = createProfile(rule2); | |||
changes = activate(profile2, RuleActivation.create(rule2.getKey())); | |||
assertThat(changes).hasSize(1); | |||
changes = underTest.setParentAndCommit(db.getSession(), profile2, profile1); | |||
assertThat(changes).hasSize(1); | |||
assertThatRuleIsActivated(profile2, rule1, changes, rule1.getSeverityString(), INHERITED, emptyMap()); | |||
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap()); | |||
RuleActivation activation = RuleActivation.create(rule1.getKey(), BLOCKER, null); | |||
changes = activate(profile2, activation); | |||
assertThat(changes).hasSize(1); | |||
assertThatRuleIsUpdated(profile2, rule1, BLOCKER, ActiveRule.Inheritance.OVERRIDES, emptyMap()); | |||
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap()); | |||
changes = underTest.removeParentAndCommit(db.getSession(), profile2); | |||
assertThat(changes).hasSize(1); | |||
// Not testing changes here since severity is not set in changelog | |||
assertThatRuleIsActivated(profile2, rule1, null, BLOCKER, null, emptyMap()); | |||
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap()); | |||
} | |||
@Test | |||
public void activation_errors_are_ignored_when_setting_a_parent() { | |||
RuleDefinitionDto rule1 = createJavaRule(); | |||
RuleDefinitionDto rule2 = createJavaRule(); | |||
QProfileDto parentProfile = createProfile(rule1); | |||
activate(parentProfile, RuleActivation.create(rule1.getKey())); | |||
activate(parentProfile, RuleActivation.create(rule2.getKey())); | |||
rule1.setStatus(RuleStatus.REMOVED); | |||
db.rules().update(rule1); | |||
QProfileDto childProfile = createProfile(rule1); | |||
List<ActiveRuleChange> changes = underTest.setParentAndCommit(db.getSession(), childProfile, parentProfile); | |||
assertThatRuleIsNotPresent(childProfile, rule1); | |||
assertThatRuleIsActivated(childProfile, rule2, changes, rule2.getSeverityString(), INHERITED, emptyMap()); | |||
} | |||
private List<ActiveRuleChange> activate(QProfileDto profile, RuleActivation activation) { | |||
return qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation)); | |||
} | |||
private QProfileDto createProfile(RuleDefinitionDto rule) { | |||
return db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(rule.getLanguage())); | |||
} | |||
private QProfileDto createChildProfile(QProfileDto parent) { | |||
return db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p | |||
.setLanguage(parent.getLanguage()) | |||
.setParentKee(parent.getKee()) | |||
.setName("Child of " + parent.getName())); | |||
} | |||
private void assertThatRuleIsActivated(QProfileDto profile, RuleDefinitionDto rule, @Nullable List<ActiveRuleChange> changes, | |||
String expectedSeverity, @Nullable ActiveRule.Inheritance expectedInheritance, Map<String, String> expectedParams) { | |||
OrgActiveRuleDto activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile) | |||
.stream() | |||
.filter(ar -> ar.getRuleKey().equals(rule.getKey())) | |||
.findFirst() | |||
.orElseThrow(IllegalStateException::new); | |||
assertThat(activeRule.getSeverityString()).isEqualTo(expectedSeverity); | |||
assertThat(activeRule.getInheritance()).isEqualTo(expectedInheritance != null ? expectedInheritance.name() : null); | |||
assertThat(activeRule.getCreatedAt()).isNotNull(); | |||
assertThat(activeRule.getUpdatedAt()).isNotNull(); | |||
List<ActiveRuleParamDto> params = db.getDbClient().activeRuleDao().selectParamsByActiveRuleId(db.getSession(), activeRule.getId()); | |||
assertThat(params).hasSize(expectedParams.size()); | |||
if (changes != null) { | |||
ActiveRuleChange change = changes.stream() | |||
.filter(c -> c.getActiveRule().getId().equals(activeRule.getId())) | |||
.findFirst().orElseThrow(IllegalStateException::new); | |||
assertThat(change.getInheritance()).isEqualTo(expectedInheritance); | |||
assertThat(change.getSeverity()).isEqualTo(expectedSeverity); | |||
assertThat(change.getType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED); | |||
} | |||
} | |||
private void assertThatRuleIsNotPresent(QProfileDto profile, RuleDefinitionDto rule) { | |||
Optional<OrgActiveRuleDto> activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile) | |||
.stream() | |||
.filter(ar -> ar.getRuleKey().equals(rule.getKey())) | |||
.findFirst(); | |||
assertThat(activeRule).isEmpty(); | |||
} | |||
private void assertThatRuleIsUpdated(QProfileDto profile, RuleDefinitionDto rule, | |||
String expectedSeverity, @Nullable ActiveRule.Inheritance expectedInheritance, Map<String, String> expectedParams) { | |||
OrgActiveRuleDto activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile) | |||
.stream() | |||
.filter(ar -> ar.getRuleKey().equals(rule.getKey())) | |||
.findFirst() | |||
.orElseThrow(IllegalStateException::new); | |||
assertThat(activeRule.getSeverityString()).isEqualTo(expectedSeverity); | |||
assertThat(activeRule.getInheritance()).isEqualTo(expectedInheritance != null ? expectedInheritance.name() : null); | |||
assertThat(activeRule.getCreatedAt()).isNotNull(); | |||
assertThat(activeRule.getUpdatedAt()).isNotNull(); | |||
List<ActiveRuleParamDto> params = db.getDbClient().activeRuleDao().selectParamsByActiveRuleId(db.getSession(), activeRule.getId()); | |||
assertThat(params).hasSize(expectedParams.size()); | |||
} | |||
private RuleDefinitionDto createRule() { | |||
return db.rules().insert(r -> r.setSeverity(Severity.MAJOR)); | |||
} | |||
private RuleDefinitionDto createJavaRule() { | |||
return db.rules().insert(r -> r.setSeverity(Severity.MAJOR).setLanguage("java")); | |||
} | |||
} |
@@ -47,6 +47,7 @@ import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.util.TypeValidations; | |||
import static java.util.Collections.singleton; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.apache.commons.lang.math.RandomUtils.nextLong; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -78,22 +79,22 @@ public class RegisterQualityProfilesNotificationTest { | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public BuiltInQProfileRepositoryRule builtInQProfileRepositoryRule = new BuiltInQProfileRepositoryRule(); | |||
@Rule | |||
public LogTester logTester = new LogTester(); | |||
private DbClient dbClient = db.getDbClient(); | |||
private TypeValidations typeValidations = mock(TypeValidations.class); | |||
private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class); | |||
private BuiltInQProfileInsert builtInQProfileInsert = new BuiltInQProfileInsertImpl(dbClient, system2, UuidFactoryFast.getInstance(), typeValidations, activeRuleIndexer); | |||
private RuleActivator ruleActivator = new RuleActivator(system2, dbClient, mock(RuleIndex.class), new RuleActivatorContextFactory(dbClient), typeValidations, activeRuleIndexer, | |||
userSessionRule); | |||
private RuleActivator ruleActivator = new RuleActivator(system2, dbClient, typeValidations, userSessionRule); | |||
private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, mock(RuleIndex.class), activeRuleIndexer); | |||
private BuiltInQProfileUpdate builtInQProfileUpdate = new BuiltInQProfileUpdateImpl(dbClient, ruleActivator, activeRuleIndexer); | |||
private BuiltInQualityProfilesUpdateListener builtInQualityProfilesNotification = mock(BuiltInQualityProfilesUpdateListener.class); | |||
private RegisterQualityProfiles underTest = new RegisterQualityProfiles(builtInQProfileRepositoryRule, dbClient, | |||
builtInQProfileInsert, builtInQProfileUpdate, builtInQualityProfilesNotification, system2); | |||
@Test | |||
public void does_not_send_notification_on_new_profile() { | |||
public void do_not_send_notification_on_new_profile() { | |||
String language = newLanguageKey(); | |||
builtInQProfileRepositoryRule.add(newLanguage(language), "Sonar way"); | |||
builtInQProfileRepositoryRule.initialize(); | |||
@@ -104,7 +105,7 @@ public class RegisterQualityProfilesNotificationTest { | |||
} | |||
@Test | |||
public void does_not_send_notification_when_built_in_profile_is_not_updated() { | |||
public void do_not_send_notification_when_profile_is_not_updated() { | |||
String language = newLanguageKey(); | |||
RuleDefinitionDto dbRule = db.rules().insert(r -> r.setLanguage(language)); | |||
RulesProfileDto dbProfile = insertBuiltInProfile(language); | |||
@@ -118,7 +119,7 @@ public class RegisterQualityProfilesNotificationTest { | |||
} | |||
@Test | |||
public void send_notification_when_built_in_profile_contains_new_rule() { | |||
public void send_notification_when_a_new_rule_is_activated() { | |||
String language = newLanguageKey(); | |||
RuleDefinitionDto existingRule = db.rules().insert(r -> r.setLanguage(language)); | |||
RulesProfileDto dbProfile = insertBuiltInProfile(language); | |||
@@ -141,7 +142,7 @@ public class RegisterQualityProfilesNotificationTest { | |||
} | |||
@Test | |||
public void send_notification_when_built_in_profile_contains_deactivated_rule() { | |||
public void send_notification_when_a_rule_is_deactivated() { | |||
String language = newLanguageKey(); | |||
RuleDefinitionDto existingRule = db.rules().insert(r -> r.setLanguage(language)); | |||
RulesProfileDto dbProfile = insertBuiltInProfile(language); | |||
@@ -163,7 +164,7 @@ public class RegisterQualityProfilesNotificationTest { | |||
} | |||
@Test | |||
public void only_send_one_notification_when_several_built_in_profiles_contain_new_rules() { | |||
public void send_a_single_notification_when_multiple_rules_are_activated() { | |||
String language = newLanguageKey(); | |||
RuleDefinitionDto existingRule1 = db.rules().insert(r -> r.setLanguage(language)); | |||
@@ -197,7 +198,7 @@ public class RegisterQualityProfilesNotificationTest { | |||
} | |||
@Test | |||
public void do_not_include_inherited_quality_profile_change_on_new_rule() { | |||
public void notification_does_not_include_inherited_profiles_when_rule_is_added() { | |||
String language = newLanguageKey(); | |||
RuleDefinitionDto newRule = db.rules().insert(r -> r.setLanguage(language)); | |||
OrganizationDto organization = db.organizations().insert(); | |||
@@ -221,18 +222,18 @@ public class RegisterQualityProfilesNotificationTest { | |||
} | |||
@Test | |||
public void do_not_include_inherited_quality_profile_change_on_existing_rule() { | |||
public void notification_does_not_include_inherited_profiled_when_rule_is_changed() { | |||
String language = newLanguageKey(); | |||
RuleDefinitionDto ruleDefinitionDto = db.rules().insert(r -> r.setLanguage(language).setSeverity(Severity.MINOR)); | |||
RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage(language).setSeverity(Severity.MINOR)); | |||
OrganizationDto organization = db.organizations().insert(); | |||
QProfileDto builtInQProfileDto = insertProfile(organization, orgQProfile -> orgQProfile.setIsBuiltIn(true).setLanguage(language)); | |||
ruleActivator.activate(db.getSession(), RuleActivation.create(ruleDefinitionDto.getKey()), builtInQProfileDto); | |||
db.qualityProfiles().activateRule(builtInQProfileDto, rule); | |||
QProfileDto childQProfileDto = insertProfile(organization, orgQProfile -> orgQProfile.setIsBuiltIn(false).setLanguage(language).setParentKee(builtInQProfileDto.getKee())); | |||
ruleActivator.activate(db.getSession(), RuleActivation.create(ruleDefinitionDto.getKey()), childQProfileDto); | |||
db.commit(); | |||
addPluginProfile(builtInQProfileDto, ruleDefinitionDto); | |||
qProfileRules.activateAndCommit(db.getSession(), childQProfileDto, singleton(RuleActivation.create(rule.getKey()))); | |||
addPluginProfile(builtInQProfileDto, rule); | |||
builtInQProfileRepositoryRule.initialize(); | |||
db.commit(); | |||
underTest.start(); | |||
@@ -244,21 +245,21 @@ public class RegisterQualityProfilesNotificationTest { | |||
.containsExactlyInAnyOrder(tuple(builtInQProfileDto.getName(), builtInQProfileDto.getLanguage())); | |||
assertThat(updatedProfiles.values()) | |||
.extracting(value -> value.getActiveRule().getRuleId(), ActiveRuleChange::getType) | |||
.containsExactlyInAnyOrder(tuple(ruleDefinitionDto.getId(), UPDATED)); | |||
.containsExactlyInAnyOrder(tuple(rule.getId(), UPDATED)); | |||
} | |||
@Test | |||
public void do_not_include_inherited_quality_profile_change_on_deactivated_rule() { | |||
public void notification_does_not_include_inherited_profiles_when_rule_is_deactivated() { | |||
String language = newLanguageKey(); | |||
RuleDefinitionDto ruleDefinitionDto = db.rules().insert(r -> r.setLanguage(language).setSeverity(Severity.MINOR)); | |||
RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage(language).setSeverity(Severity.MINOR)); | |||
OrganizationDto organization = db.organizations().insert(); | |||
QProfileDto builtInQProfileDto = insertProfile(organization, | |||
orgQProfile -> orgQProfile.setIsBuiltIn(true).setLanguage(language)); | |||
ruleActivator.activate(db.getSession(), RuleActivation.create(ruleDefinitionDto.getKey()), builtInQProfileDto); | |||
db.qualityProfiles().activateRule(builtInQProfileDto, rule); | |||
QProfileDto childQProfileDto = insertProfile(organization, | |||
orgQProfile -> orgQProfile.setIsBuiltIn(false).setLanguage(language).setParentKee(builtInQProfileDto.getKee())); | |||
ruleActivator.activate(db.getSession(), RuleActivation.create(ruleDefinitionDto.getKey()), childQProfileDto); | |||
qProfileRules.activateAndCommit(db.getSession(), childQProfileDto, singleton(RuleActivation.create(rule.getKey()))); | |||
db.commit(); | |||
addPluginProfile(builtInQProfileDto); | |||
@@ -274,11 +275,11 @@ public class RegisterQualityProfilesNotificationTest { | |||
.containsExactlyInAnyOrder(tuple(builtInQProfileDto.getName(), builtInQProfileDto.getLanguage())); | |||
assertThat(updatedProfiles.values()) | |||
.extracting(value -> value.getActiveRule().getRuleId(), ActiveRuleChange::getType) | |||
.containsExactlyInAnyOrder(tuple(ruleDefinitionDto.getId(), DEACTIVATED)); | |||
.containsExactlyInAnyOrder(tuple(rule.getId(), DEACTIVATED)); | |||
} | |||
@Test | |||
public void send_start_and_end_date() { | |||
public void notification_contains_send_start_and_end_date() { | |||
String language = newLanguageKey(); | |||
RuleDefinitionDto existingRule = db.rules().insert(r -> r.setLanguage(language)); | |||
RulesProfileDto dbProfile = insertBuiltInProfile(language); |
@@ -20,6 +20,7 @@ | |||
package org.sonar.server.qualityprofile.ws; | |||
import java.net.HttpURLConnection; | |||
import java.util.Collection; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
@@ -40,8 +41,8 @@ import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.UnauthorizedException; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.qualityprofile.RuleActivation; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.TestRequest; | |||
import org.sonar.server.ws.TestResponse; | |||
@@ -50,6 +51,7 @@ import org.sonar.server.ws.WsActionTester; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Matchers.any; | |||
import static org.mockito.Matchers.anyCollection; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE; | |||
@@ -66,10 +68,10 @@ public class ActivateRuleActionTest { | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private DbClient dbClient = db.getDbClient(); | |||
private RuleActivator ruleActivator = mock(RuleActivator.class); | |||
private QProfileRules qProfileRules = mock(QProfileRules.class); | |||
private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession, TestDefaultOrganizationProvider.from(db)); | |||
private WsActionTester ws = new WsActionTester(new ActivateRuleAction(dbClient, ruleActivator, userSession, wsSupport)); | |||
private WsActionTester ws = new WsActionTester(new ActivateRuleAction(dbClient, qProfileRules, userSession, wsSupport)); | |||
private OrganizationDto defaultOrganization; | |||
private OrganizationDto organization; | |||
@@ -150,12 +152,17 @@ public class ActivateRuleActionTest { | |||
TestResponse response = request.execute(); | |||
assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT); | |||
ArgumentCaptor<RuleActivation> captor = ArgumentCaptor.forClass(RuleActivation.class); | |||
verify(ruleActivator).activateAndCommit(any(DbSession.class), captor.capture(), any(QProfileDto.class)); | |||
RuleActivation value = captor.getValue(); | |||
assertThat(value.getRuleKey()).isEqualTo(ruleKey); | |||
assertThat(value.getSeverity()).isEqualTo(Severity.BLOCKER); | |||
assertThat(value.isReset()).isFalse(); | |||
Class<Collection<RuleActivation>> collectionClass = (Class<Collection<RuleActivation>>) (Class) Collection.class; | |||
ArgumentCaptor<Collection<RuleActivation>> ruleActivationCaptor = ArgumentCaptor.forClass(collectionClass); | |||
verify(qProfileRules).activateAndCommit(any(DbSession.class), any(QProfileDto.class), ruleActivationCaptor.capture()); | |||
Collection<RuleActivation> activations = ruleActivationCaptor.getValue(); | |||
assertThat(activations).hasSize(1); | |||
RuleActivation activation = activations.iterator().next(); | |||
assertThat(activation.getRuleKey()).isEqualTo(ruleKey); | |||
assertThat(activation.getSeverity()).isEqualTo(Severity.BLOCKER); | |||
assertThat(activation.isReset()).isFalse(); | |||
} | |||
@Test | |||
@@ -174,11 +181,16 @@ public class ActivateRuleActionTest { | |||
TestResponse response = request.execute(); | |||
assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT); | |||
ArgumentCaptor<RuleActivation> captor = ArgumentCaptor.forClass(RuleActivation.class); | |||
verify(ruleActivator).activateAndCommit(any(DbSession.class), captor.capture(), any(QProfileDto.class)); | |||
assertThat(captor.getValue().getRuleKey()).isEqualTo(ruleKey); | |||
assertThat(captor.getValue().getSeverity()).isEqualTo(Severity.BLOCKER); | |||
assertThat(captor.getValue().isReset()).isFalse(); | |||
Class<Collection<RuleActivation>> collectionClass = (Class<Collection<RuleActivation>>) (Class) Collection.class; | |||
ArgumentCaptor<Collection<RuleActivation>> ruleActivationCaptor = ArgumentCaptor.forClass(collectionClass); | |||
verify(qProfileRules).activateAndCommit(any(DbSession.class), any(QProfileDto.class), ruleActivationCaptor.capture()); | |||
Collection<RuleActivation> activations = ruleActivationCaptor.getValue(); | |||
assertThat(activations).hasSize(1); | |||
RuleActivation activation = activations.iterator().next(); | |||
assertThat(activation.getRuleKey()).isEqualTo(ruleKey); | |||
assertThat(activation.getSeverity()).isEqualTo(Severity.BLOCKER); | |||
assertThat(activation.isReset()).isFalse(); | |||
} | |||
@Test | |||
@@ -198,6 +210,6 @@ public class ActivateRuleActionTest { | |||
.setParam("reset", "false") | |||
.execute(); | |||
verify(ruleActivator).activateAndCommit(any(DbSession.class), any(RuleActivation.class), any(QProfileDto.class)); | |||
verify(qProfileRules).activateAndCommit(any(DbSession.class), any(QProfileDto.class), anyCollection()); | |||
} | |||
} |
@@ -23,6 +23,7 @@ import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.mockito.Mockito; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbTester; | |||
@@ -34,7 +35,7 @@ import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.UnauthorizedException; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.rule.ws.RuleQueryFactory; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.TestRequest; | |||
@@ -43,7 +44,6 @@ import org.sonar.server.ws.WsActionTester; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Matchers.any; | |||
import static org.mockito.Mockito.RETURNS_DEEP_STUBS; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES; | |||
@@ -61,11 +61,11 @@ public class ActivateRulesActionTest { | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private DbClient dbClient = db.getDbClient(); | |||
private RuleActivator ruleActivator = mock(RuleActivator.class, RETURNS_DEEP_STUBS); | |||
private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession, TestDefaultOrganizationProvider.from(db)); | |||
private RuleQueryFactory ruleQueryFactory = mock(RuleQueryFactory.class); | |||
private WsActionTester ws = new WsActionTester(new ActivateRulesAction(ruleQueryFactory, userSession, ruleActivator, wsSupport, dbClient)); | |||
private QProfileRules qProfileRules = mock(QProfileRules.class, Mockito.RETURNS_DEEP_STUBS); | |||
private WsActionTester ws = new WsActionTester(new ActivateRulesAction(ruleQueryFactory, userSession, qProfileRules, wsSupport, dbClient)); | |||
private OrganizationDto defaultOrganization; | |||
private OrganizationDto organization; | |||
@@ -120,7 +120,7 @@ public class ActivateRulesActionTest { | |||
.setParam(PARAM_TARGET_KEY, qualityProfile.getKee()) | |||
.execute(); | |||
verify(ruleActivator).bulkActivateAndCommit(any(), any(), any(), any()); | |||
verify(qProfileRules).bulkActivateAndCommit(any(), any(), any(), any()); | |||
} | |||
@Test | |||
@@ -138,7 +138,7 @@ public class ActivateRulesActionTest { | |||
.setParam(PARAM_TARGET_KEY, qualityProfile.getKee()) | |||
.execute(); | |||
verify(ruleActivator).bulkActivateAndCommit(any(), any(), any(), any()); | |||
verify(qProfileRules).bulkActivateAndCommit(any(), any(), any(), any()); | |||
} | |||
@Test |
@@ -52,8 +52,8 @@ import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.language.LanguageTesting; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.QProfileTreeImpl; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.RuleActivatorContextFactory; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
@@ -95,9 +95,9 @@ public class ChangeParentActionTest { | |||
private ActiveRuleIndexer activeRuleIndexer; | |||
private WsActionTester ws; | |||
private OrganizationDto organization; | |||
private RuleActivator ruleActivator; | |||
private Language language = LanguageTesting.newLanguage(randomAlphanumeric(20)); | |||
private String ruleRepository = randomAlphanumeric(5); | |||
private QProfileTreeImpl qProfileTree; | |||
@Before | |||
public void setUp() { | |||
@@ -107,20 +107,12 @@ public class ChangeParentActionTest { | |||
ruleIndex = new RuleIndex(esClient, System2.INSTANCE); | |||
ruleIndexer = new RuleIndexer(esClient, dbClient); | |||
activeRuleIndexer = new ActiveRuleIndexer(dbClient, esClient); | |||
RuleActivatorContextFactory ruleActivatorContextFactory = new RuleActivatorContextFactory(dbClient); | |||
TypeValidations typeValidations = new TypeValidations(Collections.emptyList()); | |||
ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, ruleIndex, ruleActivatorContextFactory, typeValidations, activeRuleIndexer, userSession); | |||
RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, typeValidations, userSession); | |||
qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer); | |||
ChangeParentAction underTest = new ChangeParentAction( | |||
dbClient, | |||
new RuleActivator( | |||
System2.INSTANCE, | |||
dbClient, | |||
ruleIndex, | |||
ruleActivatorContextFactory, | |||
typeValidations, | |||
activeRuleIndexer, | |||
userSession), | |||
qProfileTree, | |||
new Languages(), | |||
new QProfileWsSupport( | |||
dbClient, | |||
@@ -188,7 +180,7 @@ public class ChangeParentActionTest { | |||
activeRuleIndexer.indexOnStartup(emptySet()); | |||
// Set parent 1 | |||
ruleActivator.setParentAndCommit(dbSession, child, parent1); | |||
qProfileTree.setParentAndCommit(dbSession, child, parent1); | |||
// Set parent 2 through WS | |||
ws.newRequest() | |||
@@ -216,7 +208,7 @@ public class ChangeParentActionTest { | |||
activeRuleIndexer.indexOnStartup(emptySet()); | |||
// Set parent | |||
ruleActivator.setParentAndCommit(dbSession, child, parent); | |||
qProfileTree.setParentAndCommit(dbSession, child, parent); | |||
// Remove parent through WS | |||
ws.newRequest() | |||
@@ -305,7 +297,7 @@ public class ChangeParentActionTest { | |||
assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty(); | |||
// Set parent | |||
ruleActivator.setParentAndCommit(dbSession, child, parent); | |||
qProfileTree.setParentAndCommit(dbSession, child, parent); | |||
// Remove parent | |||
ws.newRequest() | |||
@@ -332,7 +324,7 @@ public class ChangeParentActionTest { | |||
ruleIndexer.commitAndIndex(dbSession, asList(rule1.getKey(), rule2.getKey())); | |||
activeRuleIndexer.indexOnStartup(emptySet()); | |||
// Set parent 1 | |||
ruleActivator.setParentAndCommit(dbSession, child, parent1); | |||
qProfileTree.setParentAndCommit(dbSession, child, parent1); | |||
UserDto user = db.users().insertUser(); | |||
db.qualityProfiles().addUserPermission(child, user); | |||
userSession.logIn(user); |
@@ -50,8 +50,9 @@ import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.QProfileExporters; | |||
import org.sonar.server.qualityprofile.QProfileFactoryImpl; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.qualityprofile.QProfileRulesImpl; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.RuleActivatorContextFactory; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
@@ -67,7 +68,6 @@ import org.sonarqube.ws.Qualityprofiles.CreateWsResponse; | |||
import org.sonarqube.ws.Qualityprofiles.CreateWsResponse.QualityProfile; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES; | |||
import static org.sonar.server.language.LanguageTesting.newLanguages; | |||
@@ -94,9 +94,9 @@ public class CreateActionTest { | |||
private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), dbClient); | |||
private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(dbClient, es.client()); | |||
private ProfileImporter[] profileImporters = createImporters(); | |||
private QProfileExporters qProfileExporters = new QProfileExporters(dbClient, null, | |||
new RuleActivator(mock(System2.class), dbClient, ruleIndex, new RuleActivatorContextFactory(dbClient), null, activeRuleIndexer, userSession), | |||
profileImporters); | |||
private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, null, userSession); | |||
private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer); | |||
private QProfileExporters qProfileExporters = new QProfileExporters(dbClient, null, qProfileRules, profileImporters); | |||
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); | |||
private CreateAction underTest = new CreateAction(dbClient, new QProfileFactoryImpl(dbClient, UuidFactoryFast.getInstance(), System2.INSTANCE, activeRuleIndexer), |
@@ -20,6 +20,7 @@ | |||
package org.sonar.server.qualityprofile.ws; | |||
import java.net.HttpURLConnection; | |||
import java.util.Collection; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
@@ -39,7 +40,7 @@ import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.UnauthorizedException; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.TestRequest; | |||
import org.sonar.server.ws.TestResponse; | |||
@@ -48,6 +49,7 @@ import org.sonar.server.ws.WsActionTester; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Matchers.any; | |||
import static org.mockito.Matchers.anyCollection; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE; | |||
@@ -64,9 +66,9 @@ public class DeactivateRuleActionTest { | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private DbClient dbClient = db.getDbClient(); | |||
private RuleActivator ruleActivator = mock(RuleActivator.class); | |||
private QProfileRules qProfileRules = mock(QProfileRules.class); | |||
private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession, TestDefaultOrganizationProvider.from(db)); | |||
private DeactivateRuleAction underTest = new DeactivateRuleAction(dbClient, ruleActivator, userSession, wsSupport); | |||
private DeactivateRuleAction underTest = new DeactivateRuleAction(dbClient, qProfileRules, userSession, wsSupport); | |||
private WsActionTester ws = new WsActionTester(underTest); | |||
private OrganizationDto defaultOrganization; | |||
private OrganizationDto organization; | |||
@@ -102,10 +104,11 @@ public class DeactivateRuleActionTest { | |||
TestResponse response = request.execute(); | |||
assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT); | |||
ArgumentCaptor<RuleKey> ruleKeyCaptor = ArgumentCaptor.forClass(RuleKey.class); | |||
Class<Collection<RuleKey>> collectionClass = (Class<Collection<RuleKey>>) (Class) Collection.class; | |||
ArgumentCaptor<Collection<RuleKey>> ruleKeyCaptor = ArgumentCaptor.forClass(collectionClass); | |||
ArgumentCaptor<QProfileDto> qProfileDtoCaptor = ArgumentCaptor.forClass(QProfileDto.class); | |||
verify(ruleActivator).deactivateAndCommit(any(DbSession.class), qProfileDtoCaptor.capture(), ruleKeyCaptor.capture()); | |||
assertThat(ruleKeyCaptor.getValue()).isEqualTo(ruleKey); | |||
verify(qProfileRules).deactivateAndCommit(any(DbSession.class), qProfileDtoCaptor.capture(), ruleKeyCaptor.capture()); | |||
assertThat(ruleKeyCaptor.getValue()).containsExactly(ruleKey); | |||
assertThat(qProfileDtoCaptor.getValue().getKee()).isEqualTo(qualityProfile.getKee()); | |||
} | |||
@@ -123,10 +126,11 @@ public class DeactivateRuleActionTest { | |||
TestResponse response = request.execute(); | |||
assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT); | |||
ArgumentCaptor<RuleKey> captor = ArgumentCaptor.forClass(RuleKey.class); | |||
Class<Collection<RuleKey>> collectionClass = (Class<Collection<RuleKey>>) (Class) Collection.class; | |||
ArgumentCaptor<Collection<RuleKey>> ruleKeyCaptor = ArgumentCaptor.forClass(collectionClass); | |||
ArgumentCaptor<QProfileDto> qProfileDtoCaptor = ArgumentCaptor.forClass(QProfileDto.class); | |||
verify(ruleActivator).deactivateAndCommit(any(DbSession.class), qProfileDtoCaptor.capture(), captor.capture()); | |||
assertThat(captor.getValue()).isEqualTo(ruleKey); | |||
verify(qProfileRules).deactivateAndCommit(any(DbSession.class), qProfileDtoCaptor.capture(), ruleKeyCaptor.capture()); | |||
assertThat(ruleKeyCaptor.getValue()).containsExactly(ruleKey); | |||
assertThat(qProfileDtoCaptor.getValue().getKee()).isEqualTo(qualityProfile.getKee()); | |||
} | |||
@@ -145,7 +149,7 @@ public class DeactivateRuleActionTest { | |||
.setParam(PARAM_KEY, qualityProfile.getKee()) | |||
.execute(); | |||
verify(ruleActivator).deactivateAndCommit(any(DbSession.class), any(QProfileDto.class), any(RuleKey.class)); | |||
verify(qProfileRules).deactivateAndCommit(any(DbSession.class), any(QProfileDto.class), anyCollection()); | |||
} | |||
@Test |
@@ -34,7 +34,7 @@ import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.UnauthorizedException; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.rule.ws.RuleQueryFactory; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.TestRequest; | |||
@@ -61,10 +61,10 @@ public class DeactivateRulesActionTest { | |||
public ExpectedException thrown = ExpectedException.none(); | |||
private DbClient dbClient = db.getDbClient(); | |||
private RuleActivator ruleActivator = mock(RuleActivator.class, RETURNS_DEEP_STUBS); | |||
private QProfileRules qProfileRules = mock(QProfileRules.class, RETURNS_DEEP_STUBS); | |||
private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession, TestDefaultOrganizationProvider.from(db)); | |||
private RuleQueryFactory ruleQueryFactory = mock(RuleQueryFactory.class); | |||
private DeactivateRulesAction underTest = new DeactivateRulesAction(ruleQueryFactory, userSession, ruleActivator, wsSupport, dbClient); | |||
private DeactivateRulesAction underTest = new DeactivateRulesAction(ruleQueryFactory, userSession, qProfileRules, wsSupport, dbClient); | |||
private WsActionTester ws = new WsActionTester(underTest); | |||
private OrganizationDto defaultOrganization; | |||
private OrganizationDto organization; | |||
@@ -117,7 +117,7 @@ public class DeactivateRulesActionTest { | |||
.setParam(PARAM_TARGET_KEY, qualityProfile.getKee()) | |||
.execute(); | |||
verify(ruleActivator).bulkDeactivateAndCommit(any(), any(), any()); | |||
verify(qProfileRules).bulkDeactivateAndCommit(any(), any(), any()); | |||
} | |||
@Test | |||
@@ -135,7 +135,7 @@ public class DeactivateRulesActionTest { | |||
.setParam(PARAM_TARGET_KEY, qualityProfile.getKee()) | |||
.execute(); | |||
verify(ruleActivator).bulkDeactivateAndCommit(any(), any(), any()); | |||
verify(qProfileRules).bulkDeactivateAndCommit(any(), any(), any()); | |||
} | |||
@Test |
@@ -46,9 +46,12 @@ import org.sonar.server.es.EsTester; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.QProfileName; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.qualityprofile.QProfileRulesImpl; | |||
import org.sonar.server.qualityprofile.QProfileTree; | |||
import org.sonar.server.qualityprofile.QProfileTreeImpl; | |||
import org.sonar.server.qualityprofile.RuleActivation; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.RuleActivatorContextFactory; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
@@ -59,6 +62,7 @@ import org.sonar.server.ws.WsActionTester; | |||
import org.sonarqube.ws.Qualityprofiles.InheritanceWsResponse; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.singleton; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.server.qualityprofile.QProfileTesting.newQProfileDto; | |||
import static org.sonar.test.JsonAssert.assertJson; | |||
@@ -79,7 +83,8 @@ public class InheritanceActionTest { | |||
private EsClient esClient; | |||
private RuleIndexer ruleIndexer; | |||
private ActiveRuleIndexer activeRuleIndexer; | |||
private RuleActivator ruleActivator; | |||
private QProfileRules qProfileRules; | |||
private QProfileTree qProfileTree; | |||
private OrganizationDto organization; | |||
private InheritanceAction underTest; | |||
@@ -97,15 +102,12 @@ public class InheritanceActionTest { | |||
dbClient, | |||
new QProfileWsSupport(dbClient, userSession, defaultOrganizationProvider), | |||
new Languages()); | |||
ws = new WsActionTester(underTest); | |||
ruleActivator = new RuleActivator( | |||
System2.INSTANCE, | |||
dbClient, | |||
new RuleIndex(esClient, System2.INSTANCE), | |||
new RuleActivatorContextFactory(dbClient), | |||
new TypeValidations(new ArrayList<>()), | |||
activeRuleIndexer, | |||
userSession); | |||
RuleIndex ruleIndex = new RuleIndex(esClient, System2.INSTANCE); | |||
RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, new TypeValidations(new ArrayList<>()), userSession); | |||
qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer); | |||
qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer); | |||
organization = dbTester.organizations().insert(); | |||
} | |||
@@ -251,7 +253,7 @@ public class InheritanceActionTest { | |||
} | |||
private void setParent(QProfileDto profile, QProfileDto parent) { | |||
ruleActivator.setParentAndCommit(dbSession, parent, profile); | |||
qProfileTree.setParentAndCommit(dbSession, parent, profile); | |||
} | |||
private RuleDefinitionDto createRule(String lang, String id) { | |||
@@ -278,8 +280,8 @@ public class InheritanceActionTest { | |||
} | |||
private void overrideActiveRuleSeverity(RuleDefinitionDto rule, QProfileDto profile, String severity) { | |||
ruleActivator.activate(dbSession, RuleActivation.create(rule.getKey(), severity, null), profile); | |||
dbSession.commit(); | |||
activeRuleIndexer.indexOnStartup(activeRuleIndexer.getIndexTypes()); | |||
qProfileRules.activateAndCommit(dbSession, profile, singleton(RuleActivation.create(rule.getKey(), severity, null))); | |||
// dbSession.commit(); | |||
// activeRuleIndexer.indexOnStartup(activeRuleIndexer.getIndexTypes()); | |||
} | |||
} |
@@ -46,9 +46,10 @@ import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.QProfileName; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.qualityprofile.QProfileRulesImpl; | |||
import org.sonar.server.qualityprofile.QProfileTesting; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.RuleActivatorContextFactory; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
@@ -60,17 +61,17 @@ import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.util.TypeValidations; | |||
import org.sonar.server.ws.WsActionTester; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.emptyList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.junit.Assert.fail; | |||
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES; | |||
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE; | |||
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY; | |||
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_RESET; | |||
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_RULE; | |||
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_SEVERITY; | |||
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_KEY; | |||
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_SEVERITY; | |||
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES; | |||
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE; | |||
public class QProfilesWsMediumTest { | |||
@@ -87,19 +88,19 @@ public class QProfilesWsMediumTest { | |||
private RuleIndex ruleIndex = new RuleIndex(esTester.client(), System2.INSTANCE); | |||
private RuleIndexer ruleIndexer = new RuleIndexer(esTester.client(), dbClient); | |||
private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(dbClient, esTester.client()); | |||
private RuleActivatorContextFactory ruleActivatorContextFactory = new RuleActivatorContextFactory(dbClient); | |||
private TypeValidations typeValidations = new TypeValidations(asList()); | |||
private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, ruleIndex, ruleActivatorContextFactory, typeValidations, activeRuleIndexer, userSessionRule); | |||
private TypeValidations typeValidations = new TypeValidations(emptyList()); | |||
private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, typeValidations, userSessionRule); | |||
private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer); | |||
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester); | |||
private QProfileWsSupport qProfileWsSupport = new QProfileWsSupport(dbClient, userSessionRule, defaultOrganizationProvider); | |||
private RuleWsSupport ruleWsSupport = new RuleWsSupport(dbClient, userSessionRule, defaultOrganizationProvider); | |||
private RuleQueryFactory ruleQueryFactory = new RuleQueryFactory(dbClient, ruleWsSupport); | |||
private OrganizationDto organization; | |||
private WsActionTester wsDeactivateRule = new WsActionTester(new DeactivateRuleAction(dbClient, ruleActivator, userSessionRule, qProfileWsSupport)); | |||
private WsActionTester wsDeactivateRules = new WsActionTester(new DeactivateRulesAction(ruleQueryFactory, userSessionRule, ruleActivator, qProfileWsSupport, dbClient)); | |||
private WsActionTester wsActivateRule = new WsActionTester(new ActivateRuleAction(dbClient, ruleActivator, userSessionRule, qProfileWsSupport)); | |||
private WsActionTester wsActivateRules = new WsActionTester(new ActivateRulesAction(ruleQueryFactory, userSessionRule, ruleActivator, qProfileWsSupport, dbClient)); | |||
private WsActionTester wsDeactivateRule = new WsActionTester(new DeactivateRuleAction(dbClient, qProfileRules, userSessionRule, qProfileWsSupport)); | |||
private WsActionTester wsDeactivateRules = new WsActionTester(new DeactivateRulesAction(ruleQueryFactory, userSessionRule, qProfileRules, qProfileWsSupport, dbClient)); | |||
private WsActionTester wsActivateRule = new WsActionTester(new ActivateRuleAction(dbClient, qProfileRules, userSessionRule, qProfileWsSupport)); | |||
private WsActionTester wsActivateRules = new WsActionTester(new ActivateRulesAction(ruleQueryFactory, userSessionRule, qProfileRules, qProfileWsSupport, dbClient)); | |||
@Before | |||
public void setUp() throws Exception { | |||
@@ -244,7 +245,7 @@ public class QProfilesWsMediumTest { | |||
dbSession.clearCache(); | |||
fail(); | |||
} catch (BadRequestException e) { | |||
assertThat(e.getMessage()).isEqualTo("Rule blah:toto and profile pjava have different languages"); | |||
assertThat(e.getMessage()).isEqualTo("php rule blah:toto cannot be activated on java profile Pjava"); | |||
} | |||
} | |||
@@ -49,7 +49,7 @@ import org.sonar.server.es.SearchOptions; | |||
import org.sonar.server.organization.OrganizationFlags; | |||
import org.sonar.server.organization.TestOrganizationFlags; | |||
import org.sonar.server.plugins.ServerPluginRepository; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
@@ -88,7 +88,7 @@ public class RegisterRulesTest { | |||
@org.junit.Rule | |||
public LogTester logTester = new LogTester(); | |||
private RuleActivator ruleActivator = mock(RuleActivator.class); | |||
private QProfileRules qProfileRules = mock(QProfileRules.class); | |||
private WebServerRuleFinder webServerRuleFinder = mock(WebServerRuleFinder.class); | |||
private DbClient dbClient = dbTester.getDbClient(); | |||
private RuleIndexer ruleIndexer; | |||
@@ -535,7 +535,7 @@ public class RegisterRulesTest { | |||
when(languages.get("java")).thenReturn(mock(Language.class)); | |||
reset(webServerRuleFinder); | |||
RegisterRules task = new RegisterRules(loader, ruleActivator, dbClient, ruleIndexer, activeRuleIndexer, languages, system, organizationFlags, webServerRuleFinder); | |||
RegisterRules task = new RegisterRules(loader, qProfileRules, dbClient, ruleIndexer, activeRuleIndexer, languages, system, organizationFlags, webServerRuleFinder); | |||
task.start(); | |||
// Execute a commit to refresh session state as the task is using its own session | |||
dbTester.getSession().commit(); |
@@ -34,7 +34,7 @@ import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.UnauthorizedException; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.rule.index.RuleIndexer; | |||
import org.sonar.server.tester.UserSessionRule; | |||
@@ -63,10 +63,10 @@ public class DeleteActionTest { | |||
private DbClient dbClient = dbTester.getDbClient(); | |||
private DbSession dbSession = dbTester.getSession(); | |||
private RuleIndexer ruleIndexer = spy(new RuleIndexer(esTester.client(), dbClient)); | |||
private RuleActivator ruleActivator = mock(RuleActivator.class); | |||
private QProfileRules qProfileRules = mock(QProfileRules.class); | |||
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.fromUuid("ORG1"); | |||
private RuleWsSupport ruleWsSupport = new RuleWsSupport(mock(DbClient.class), userSession, defaultOrganizationProvider); | |||
private DeleteAction underTest = new DeleteAction(System2.INSTANCE, ruleIndexer, dbClient, ruleActivator, ruleWsSupport); | |||
private DeleteAction underTest = new DeleteAction(System2.INSTANCE, ruleIndexer, dbClient, qProfileRules, ruleWsSupport); | |||
private WsActionTester tester = new WsActionTester(underTest); | |||
@Test |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonar.server.rule.ws; | |||
import java.io.IOException; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.function.Consumer; | |||
@@ -51,9 +50,10 @@ import org.sonar.server.language.LanguageTesting; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.ActiveRuleChange; | |||
import org.sonar.server.qualityprofile.QProfileRules; | |||
import org.sonar.server.qualityprofile.QProfileRulesImpl; | |||
import org.sonar.server.qualityprofile.RuleActivation; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.RuleActivatorContextFactory; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
@@ -72,6 +72,7 @@ import org.sonarqube.ws.Rules.SearchResponse; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Arrays.stream; | |||
import static java.util.Collections.singleton; | |||
import static java.util.Collections.singletonList; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -115,11 +116,9 @@ public class SearchActionTest { | |||
private MacroInterpreter macroInterpreter = mock(MacroInterpreter.class); | |||
private RuleMapper ruleMapper = new RuleMapper(languages, macroInterpreter); | |||
private SearchAction underTest = new SearchAction(ruleIndex, activeRuleCompleter, ruleQueryFactory, db.getDbClient(), ruleMapper); | |||
private RuleActivatorContextFactory contextFactory = new RuleActivatorContextFactory(db.getDbClient()); | |||
private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); | |||
private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), ruleIndex, contextFactory, typeValidations, activeRuleIndexer, | |||
userSession); | |||
private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db.getDbClient(), typeValidations, userSession); | |||
private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer); | |||
private WsActionTester ws = new WsActionTester(underTest); | |||
@Before | |||
@@ -615,7 +614,7 @@ public class SearchActionTest { | |||
QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage("java")); | |||
RuleDefinitionDto rule = createJavaRule(); | |||
RuleActivation activation = RuleActivation.create(rule.getKey(), BLOCKER, null); | |||
ruleActivator.activate(db.getSession(), activation, profile); | |||
qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation)); | |||
indexRules(); | |||
@@ -662,8 +661,8 @@ public class SearchActionTest { | |||
.setName("empty_var")); | |||
RuleActivation activation = RuleActivation.create(rule.getKey()); | |||
List<ActiveRuleChange> activeRuleChanges1 = ruleActivator.activate(db.getSession(), activation, profile); | |||
ruleActivator.activate(db.getSession(), activation, waterproofProfile); | |||
List<ActiveRuleChange> activeRuleChanges1 = qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation)); | |||
qProfileRules.activateAndCommit(db.getSession(), waterproofProfile, singleton(activation)); | |||
assertThat(activeRuleChanges1).hasSize(1); | |||
@@ -718,7 +717,7 @@ public class SearchActionTest { | |||
.setName("my_var")); | |||
RuleActivation activation = RuleActivation.create(rule.getKey()); | |||
List<ActiveRuleChange> activeRuleChanges = ruleActivator.activate(db.getSession(), activation, profile); | |||
List<ActiveRuleChange> activeRuleChanges = qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation)); | |||
// Insert directly in database a rule parameter with a null value | |||
ActiveRuleParamDto activeRuleParam = ActiveRuleParamDto.createFor(ruleParam).setValue(null); | |||
@@ -781,7 +780,7 @@ public class SearchActionTest { | |||
.setStatus(RuleStatus.DEPRECATED) | |||
.setType(RuleType.VULNERABILITY)); | |||
RuleActivation activation = RuleActivation.create(rule2.getKey(), null, null); | |||
ruleActivator.activate(db.getSession(), activation, profile); | |||
qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation)); | |||
// on other language, not activated => no match | |||
RuleDefinitionDto rule3 = db.rules().insert(r -> r |