A new elasticsearch type “ruleExtension” is added to the rules index. It stores either system tags, or tags for one, specific organization.tags/6.4-RC1
@@ -29,6 +29,7 @@ import org.sonar.api.rules.RuleQuery; | |||
import org.sonar.db.Dao; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.RowNotFoundException; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import static com.google.common.base.Preconditions.checkNotNull; | |||
import static org.sonar.db.DatabaseUtils.executeLargeInputs; | |||
@@ -45,6 +46,10 @@ public class RuleDao implements Dao { | |||
return Optional.fromNullable(mapper(session).selectDefinitionByKey(key)); | |||
} | |||
public java.util.Optional<RuleMetadataDto> selectMetadataByKey(DbSession session, RuleKey key, OrganizationDto organization) { | |||
return java.util.Optional.ofNullable(mapper(session).selectMetadataByKey(key, organization.getUuid())); | |||
} | |||
public RuleDto selectOrFailByKey(DbSession session, String organizationUuid, RuleKey key) { | |||
RuleDto rule = mapper(session).selectByKey(organizationUuid, key); | |||
if (rule == null) { | |||
@@ -122,6 +127,10 @@ public class RuleDao implements Dao { | |||
mapper(session).insertDefinition(dto); | |||
} | |||
public void insert(DbSession session, RuleMetadataDto dto) { | |||
mapper(session).insertMetadata(dto); | |||
} | |||
public void update(DbSession session, RuleDefinitionDto dto) { | |||
mapper(session).updateDefinition(dto); | |||
} |
@@ -45,6 +45,8 @@ public interface RuleMapper { | |||
RuleDefinitionDto selectDefinitionByKey(RuleKey ruleKey); | |||
RuleMetadataDto selectMetadataByKey(@Param("ruleKey") RuleKey ruleKey, @Param("organizationUuid") String organizationUuid); | |||
List<RuleDto> selectByKeys(@Param("organizationUuid") String organizationUuid, @Param("ruleKeys") List<RuleKey> keys); | |||
List<RuleDefinitionDto> selectDefinitionByKeys(@Param("ruleKeys") List<RuleKey> keys); |
@@ -139,6 +139,29 @@ | |||
and r.plugin_rule_key=#{rule,jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectMetadataByKey" parameterType="map" resultType="org.sonar.db.rule.RuleMetadataDto"> | |||
select | |||
rm.rule_id as "ruleId", | |||
rm.organization_uuid as "organizationUuid", | |||
rm.note_data as "noteData", | |||
rm.note_user_login as "noteUserLogin", | |||
rm.note_created_at as "noteCreatedAt", | |||
rm.note_updated_at as "noteUpdatedAt", | |||
rm.remediation_function as "remediationFunction", | |||
rm.remediation_gap_mult as "remediationGapMultiplier", | |||
rm.remediation_base_effort as "remediationBaseEffort", | |||
rm.tags as "tagsField", | |||
rm.created_at as "createdAt", | |||
rm.updated_at as "updatedAt" | |||
from | |||
rules_metadata rm | |||
inner join rules r on rm.rule_id = r.id | |||
where | |||
r.plugin_name=#{ruleKey.repository,jdbcType=VARCHAR} | |||
and r.plugin_rule_key=#{ruleKey.rule,jdbcType=VARCHAR} | |||
and rm.organization_uuid = #{organizationUuid,jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectByKeys" parameterType="map" resultType="Rule"> | |||
select | |||
<include refid="selectJoinedTablesColumns"/> |
@@ -67,9 +67,9 @@ public class ActiveRuleDaoTest { | |||
private QualityProfileDto profile1 = QualityProfileDto.createFor("qp1").setOrganizationUuid(organization.getUuid()).setName("QProfile1"); | |||
private QualityProfileDto profile2 = QualityProfileDto.createFor("qp2").setOrganizationUuid(organization.getUuid()).setName("QProfile2"); | |||
private RuleDefinitionDto rule1 = RuleTesting.newDto(RuleTesting.XOO_X1).getDefinition(); | |||
private RuleDefinitionDto rule2 = RuleTesting.newDto(RuleTesting.XOO_X2).getDefinition(); | |||
private RuleDefinitionDto rule3 = RuleTesting.newDto(RuleTesting.XOO_X3).getDefinition(); | |||
private RuleDefinitionDto rule1 = RuleTesting.newRule(RuleTesting.XOO_X1); | |||
private RuleDefinitionDto rule2 = RuleTesting.newRule(RuleTesting.XOO_X2); | |||
private RuleDefinitionDto rule3 = RuleTesting.newRule(RuleTesting.XOO_X3); | |||
private RuleParamDto rule1Param1; | |||
private RuleParamDto rule1Param2; | |||
@@ -200,7 +200,7 @@ public class ActiveRuleDaoTest { | |||
@Test | |||
public void select_by_profile_ignore_removed_rules() throws Exception { | |||
RuleDefinitionDto removedRule = RuleTesting.newDto(RuleKey.of("removed", "rule")).setStatus(RuleStatus.REMOVED).getDefinition(); | |||
RuleDefinitionDto removedRule = RuleTesting.newRule(RuleKey.of("removed", "rule")).setStatus(RuleStatus.REMOVED); | |||
dbTester.rules().insert(removedRule); | |||
ActiveRuleDto activeRule = createFor(profile1, removedRule).setSeverity(BLOCKER); | |||
underTest.insert(dbTester.getSession(), activeRule); |
@@ -27,6 +27,7 @@ import org.sonar.api.server.rule.RuleParamType; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import static org.sonar.db.rule.RuleTesting.newRule; | |||
import static org.sonar.db.rule.RuleTesting.newRuleDto; | |||
public class RuleDbTester { | |||
@@ -38,21 +39,22 @@ public class RuleDbTester { | |||
} | |||
public RuleDefinitionDto insert() { | |||
return insert(RuleTesting.newRule()); | |||
return insert(newRule()); | |||
} | |||
public RuleDefinitionDto insert(RuleKey key) { | |||
return insert(RuleTesting.newRule(key)); | |||
return insert(newRule(key)); | |||
} | |||
public RuleDefinitionDto insert(Consumer<RuleDefinitionDto> populater) { | |||
RuleDefinitionDto rule = RuleTesting.newRule(); | |||
populater.accept(rule); | |||
@SafeVarargs | |||
public final RuleDefinitionDto insert(Consumer<RuleDefinitionDto>... populaters) { | |||
RuleDefinitionDto rule = newRule(); | |||
Arrays.asList(populaters).forEach(populater -> populater.accept(rule)); | |||
return insert(rule); | |||
} | |||
public RuleDefinitionDto insert(RuleKey key, Consumer<RuleDefinitionDto> populater) { | |||
RuleDefinitionDto rule = RuleTesting.newRule(key); | |||
RuleDefinitionDto rule = newRule(key); | |||
populater.accept(rule); | |||
return insert(rule); | |||
} | |||
@@ -63,13 +65,10 @@ public class RuleDbTester { | |||
return rule; | |||
} | |||
public RuleMetadataDto insertOrUpdateMetadata(RuleDefinitionDto rule, OrganizationDto organization) { | |||
return insertOrUpdateMetadata(rule, organization, r -> {}); | |||
} | |||
public RuleMetadataDto insertOrUpdateMetadata(RuleDefinitionDto rule, OrganizationDto organization, Consumer<RuleMetadataDto> populater) { | |||
@SafeVarargs | |||
public final RuleMetadataDto insertOrUpdateMetadata(RuleDefinitionDto rule, OrganizationDto organization, Consumer<RuleMetadataDto>... populaters) { | |||
RuleMetadataDto dto = RuleTesting.newRuleMetadata(rule, organization); | |||
populater.accept(dto); | |||
Arrays.asList(populaters).forEach(populater -> populater.accept(dto)); | |||
return insertOrUpdateMetadata(dto); | |||
} | |||
@@ -92,12 +91,10 @@ public class RuleDbTester { | |||
} | |||
public RuleDto insertRule(RuleDto ruleDto) { | |||
RuleDao ruleDao = db.getDbClient().ruleDao(); | |||
ruleDao.insert(db.getSession(), ruleDto.getDefinition()); | |||
db.commit(); | |||
insert(ruleDto.getDefinition()); | |||
RuleMetadataDto metadata = ruleDto.getMetadata(); | |||
if (metadata.getOrganizationUuid() != null) { | |||
ruleDao.insertOrUpdate(db.getSession(), metadata.setRuleId(ruleDto.getId())); | |||
db.getDbClient().ruleDao().insertOrUpdate(db.getSession(), metadata.setRuleId(ruleDto.getId())); | |||
db.commit(); | |||
} | |||
return ruleDto; | |||
@@ -111,7 +108,8 @@ public class RuleDbTester { | |||
}); | |||
} | |||
public RuleDto insertRule(OrganizationDto organization, Consumer<RuleDto>... populaters) { | |||
@SafeVarargs | |||
public final RuleDto insertRule(OrganizationDto organization, Consumer<RuleDto>... populaters) { | |||
RuleDto ruleDto = newRuleDto(organization); | |||
Arrays.asList(populaters).forEach(populater -> populater.accept(ruleDto)); | |||
return insertRule(ruleDto); |
@@ -21,6 +21,7 @@ package org.sonar.db.rule; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Date; | |||
import java.util.function.Consumer; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
@@ -31,6 +32,7 @@ import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleDto.Format; | |||
import static com.google.common.base.Preconditions.checkNotNull; | |||
import static com.google.common.collect.ImmutableSet.copyOf; | |||
import static com.google.common.collect.Sets.newHashSet; | |||
import static java.util.Objects.requireNonNull; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; | |||
@@ -223,6 +225,10 @@ public class RuleTesting { | |||
.setIsTemplate(true); | |||
} | |||
/** | |||
* @deprecated use {@link #newCustomRule(RuleDefinitionDto)} | |||
*/ | |||
@Deprecated | |||
public static RuleDto newCustomRule(RuleDto templateRule) { | |||
checkNotNull(templateRule.getId(), "The template rule need to be persisted before creating this custom rule."); | |||
return newDto(RuleKey.of(templateRule.getRepositoryKey(), templateRule.getRuleKey() + "_" + System.currentTimeMillis())) | |||
@@ -231,7 +237,72 @@ public class RuleTesting { | |||
.setType(templateRule.getType()); | |||
} | |||
public static RuleDefinitionDto newCustomRule(RuleDefinitionDto templateRule) { | |||
checkNotNull(templateRule.getId(), "The template rule need to be persisted before creating this custom rule."); | |||
return newRule(RuleKey.of(templateRule.getRepositoryKey(), templateRule.getRuleKey() + "_" + System.currentTimeMillis())) | |||
.setLanguage(templateRule.getLanguage()) | |||
.setTemplateId(templateRule.getId()) | |||
.setType(templateRule.getType()); | |||
} | |||
public static RuleKey randomRuleKey() { | |||
return RuleKey.of("repo_" + randomAlphanumeric(3), "rule_" + randomAlphanumeric(3)); | |||
} | |||
public static Consumer<RuleDefinitionDto> setRepositoryKey(String repositoryKey) { | |||
return rule -> rule.setRepositoryKey(repositoryKey); | |||
} | |||
public static Consumer<RuleDefinitionDto> setCreatedAt(long createdAt) { | |||
return rule -> rule.setCreatedAt(createdAt); | |||
} | |||
public static Consumer<RuleDefinitionDto> setUpdatedAt(long updatedtAt) { | |||
return rule -> rule.setUpdatedAt(updatedtAt); | |||
} | |||
public static Consumer<RuleDefinitionDto> setRuleKey(String ruleKey) { | |||
return rule -> rule.setRuleKey(ruleKey); | |||
} | |||
public static Consumer<RuleDefinitionDto> setName(String name) { | |||
return rule -> rule.setName(name); | |||
} | |||
public static Consumer<RuleDefinitionDto> setLanguage(String language) { | |||
return rule -> rule.setLanguage(language); | |||
} | |||
public static Consumer<RuleDefinitionDto> setSeverity(String severity) { | |||
return rule -> rule.setSeverity(severity); | |||
} | |||
public static Consumer<RuleDefinitionDto> setStatus(RuleStatus status) { | |||
return rule -> rule.setStatus(status); | |||
} | |||
public static Consumer<RuleDefinitionDto> setType(RuleType type) { | |||
return rule -> rule.setType(type); | |||
} | |||
public static Consumer<RuleDefinitionDto> setIsTemplate(boolean isTemplate) { | |||
return rule -> rule.setIsTemplate(isTemplate); | |||
} | |||
public static Consumer<RuleDefinitionDto> setTemplateId(@Nullable Integer templateId) { | |||
return rule -> rule.setTemplateId(templateId); | |||
} | |||
public static Consumer<RuleDefinitionDto> setSystemTags(String... tags) { | |||
return rule -> rule.setSystemTags(copyOf(tags)); | |||
} | |||
public static Consumer<RuleMetadataDto> setOrganizationUuid(String organizationUuid) { | |||
return rule -> rule.setOrganizationUuid(organizationUuid); | |||
} | |||
public static Consumer<RuleMetadataDto> setTags(String... tags) { | |||
return rule -> rule.setTags(copyOf(tags)); | |||
} | |||
} |
@@ -73,10 +73,14 @@ public class IndexerStartupTask { | |||
} | |||
private Set<IndexType> getUninitializedTypes(StartupIndexer indexer) { | |||
return indexer.getIndexTypes().stream().filter(this::getUninitialized).collect(toSet()); | |||
return indexer.getIndexTypes().stream().filter(this::isUninitialized).collect(toSet()); | |||
} | |||
private boolean getUninitialized(IndexType indexType) { | |||
private boolean isUninitialized(IndexType indexType) { | |||
return isUninitialized(indexType, esClient); | |||
} | |||
public static boolean isUninitialized(IndexType indexType, EsClient esClient) { | |||
String setting = esClient.nativeClient().admin().indices().prepareGetSettings(indexType.getIndex()).get().getSetting(indexType.getIndex(), | |||
getInitializedSettingName(indexType)); | |||
return !"true".equals(setting); |
@@ -22,6 +22,7 @@ package org.sonar.server.es; | |||
import java.util.Arrays; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.function.Function; | |||
import java.util.stream.Collector; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.Nullable; | |||
@@ -62,12 +63,35 @@ public class StickyFacetBuilder { | |||
} | |||
public AggregationBuilder buildStickyFacet(String fieldName, String facetName, Object... selected) { | |||
return buildStickyFacet(fieldName, facetName, FACET_DEFAULT_SIZE, selected); | |||
return buildStickyFacet(fieldName, facetName, t -> t, selected); | |||
} | |||
/** | |||
* Creates an aggregation, that will return the top-terms for <code>fieldName</code>. | |||
* | |||
* It will filter according to the filters of every of the <em>other</em> fields, but will not apply filters to <em>this</em> field (so that the user can see all terms, even | |||
* after having chosen for one of the terms). | |||
* | |||
* If special filtering is required (like for nested types), additional functionality can be passed into the method in the <code>additionalAggregationFilter</code> parameter. | |||
* | |||
* @param fieldName the name of the field that contains the terms | |||
* @param facetName the name of the aggregation (use this for to find the corresponding results in the response) | |||
* @param additionalAggregationFilter additional features (like filtering using childQuery) | |||
* @param selected the terms, that the user already has selected | |||
* @return the (global) aggregation, that can be added on top level of the elasticsearch request | |||
*/ | |||
public AggregationBuilder buildStickyFacet(String fieldName, String facetName, Function<TermsBuilder, AggregationBuilder<?>> additionalAggregationFilter, Object... selected) { | |||
return buildStickyFacet(fieldName, facetName, FACET_DEFAULT_SIZE, additionalAggregationFilter, selected); | |||
} | |||
public AggregationBuilder buildStickyFacet(String fieldName, String facetName, int size, Object... selected) { | |||
return buildStickyFacet(fieldName, facetName, size, t -> t, selected); | |||
} | |||
private AggregationBuilder buildStickyFacet(String fieldName, String facetName, int size, Function<TermsBuilder, AggregationBuilder<?>> additionalAggregationFilter, | |||
Object... selected) { | |||
BoolQueryBuilder facetFilter = getStickyFacetFilter(fieldName); | |||
FilterAggregationBuilder facetTopAggregation = buildTopFacetAggregation(fieldName, facetName, facetFilter, size); | |||
FilterAggregationBuilder facetTopAggregation = buildTopFacetAggregation(fieldName, facetName, facetFilter, size, additionalAggregationFilter); | |||
facetTopAggregation = addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, selected); | |||
return AggregationBuilders | |||
@@ -86,6 +110,20 @@ public class StickyFacetBuilder { | |||
} | |||
public FilterAggregationBuilder buildTopFacetAggregation(String fieldName, String facetName, BoolQueryBuilder facetFilter, int size) { | |||
return buildTopFacetAggregation(fieldName, facetName, facetFilter, size, t -> t); | |||
} | |||
private FilterAggregationBuilder buildTopFacetAggregation(String fieldName, String facetName, BoolQueryBuilder facetFilter, int size, | |||
Function<TermsBuilder, AggregationBuilder<?>> additionalAggregationFilter) { | |||
TermsBuilder termsAggregation = buildTermsFacetAggregation(fieldName, facetName, size); | |||
AggregationBuilder<?> innerAggregation = additionalAggregationFilter.apply(termsAggregation); | |||
return AggregationBuilders | |||
.filter(facetName + "_filter") | |||
.filter(facetFilter) | |||
.subAggregation(innerAggregation); | |||
} | |||
private TermsBuilder buildTermsFacetAggregation(String fieldName, String facetName, int size) { | |||
TermsBuilder termsAggregation = AggregationBuilders.terms(facetName) | |||
.field(fieldName) | |||
.order(order) | |||
@@ -94,10 +132,7 @@ public class StickyFacetBuilder { | |||
if (subAggregation != null) { | |||
termsAggregation = termsAggregation.subAggregation(subAggregation); | |||
} | |||
return AggregationBuilders | |||
.filter(facetName + "_filter") | |||
.filter(facetFilter) | |||
.subAggregation(termsAggregation); | |||
return termsAggregation; | |||
} | |||
public FilterAggregationBuilder addSelectedItemsToFacet(String fieldName, String facetName, FilterAggregationBuilder facetTopAggregation, Object... selected) { | |||
@@ -118,4 +153,5 @@ public class StickyFacetBuilder { | |||
facetTopAggregation.subAggregation(selectedTerms); | |||
return facetTopAggregation; | |||
} | |||
} |
@@ -22,9 +22,7 @@ package org.sonar.server.issue.index; | |||
import com.google.common.base.Function; | |||
import com.google.common.base.Preconditions; | |||
import com.google.common.collect.ImmutableList; | |||
import com.google.common.collect.Lists; | |||
import com.google.common.collect.Maps; | |||
import com.google.common.collect.Sets; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.Date; | |||
@@ -34,7 +32,6 @@ import java.util.List; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.Optional; | |||
import java.util.SortedSet; | |||
import java.util.TimeZone; | |||
import java.util.regex.Pattern; | |||
import javax.annotation.CheckForNull; | |||
@@ -51,8 +48,6 @@ import org.elasticsearch.index.query.QueryBuilders; | |||
import org.elasticsearch.search.aggregations.AggregationBuilder; | |||
import org.elasticsearch.search.aggregations.AggregationBuilders; | |||
import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder; | |||
import org.elasticsearch.search.aggregations.bucket.global.Global; | |||
import org.elasticsearch.search.aggregations.bucket.global.GlobalBuilder; | |||
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval; | |||
import org.elasticsearch.search.aggregations.bucket.terms.Terms; | |||
import org.elasticsearch.search.aggregations.bucket.terms.Terms.Order; | |||
@@ -75,7 +70,6 @@ import org.sonar.server.es.Sorting; | |||
import org.sonar.server.es.StickyFacetBuilder; | |||
import org.sonar.server.issue.IssueQuery; | |||
import org.sonar.server.permission.index.AuthorizationTypeSupport; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonar.server.view.index.ViewIndexDefinition; | |||
@@ -86,6 +80,8 @@ import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; | |||
import static org.elasticsearch.index.query.QueryBuilders.termQuery; | |||
import static org.elasticsearch.index.query.QueryBuilders.termsQuery; | |||
import static org.sonar.server.es.EsUtils.escapeSpecialRegexChars; | |||
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_ORGANIZATION_UUID; | |||
import static org.sonar.server.issue.index.IssueIndexDefinition.INDEX_TYPE_ISSUE; | |||
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_FACET_MODE_DEBT; | |||
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_PARAM_ACTION_PLANS; | |||
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_ASSIGNED_TO_ME; | |||
@@ -157,6 +153,7 @@ public class IssueIndex { | |||
return new IssueDoc(input); | |||
} | |||
}; | |||
public static final String AGGREGATION_NAME_FOR_TAGS = "tags__issues"; | |||
private final Sorting sorting; | |||
private final EsClient client; | |||
@@ -169,6 +166,7 @@ public class IssueIndex { | |||
this.system = system; | |||
this.userSession = userSession; | |||
this.authorizationTypeSupport = authorizationTypeSupport; | |||
this.sorting = new Sorting(); | |||
this.sorting.add(IssueQuery.SORT_BY_ASSIGNEE, IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE); | |||
this.sorting.add(IssueQuery.SORT_BY_STATUS, IssueIndexDefinition.FIELD_ISSUE_STATUS); | |||
@@ -192,7 +190,7 @@ public class IssueIndex { | |||
public SearchResult<IssueDoc> search(IssueQuery query, SearchOptions options) { | |||
SearchRequestBuilder requestBuilder = client | |||
.prepareSearch(IssueIndexDefinition.INDEX_TYPE_ISSUE); | |||
.prepareSearch(INDEX_TYPE_ISSUE); | |||
configureSorting(query, requestBuilder); | |||
configurePagination(options, requestBuilder); | |||
@@ -478,7 +476,7 @@ public class IssueIndex { | |||
private Optional<Long> getMinCreatedAt(Map<String, QueryBuilder> filters, QueryBuilder esQuery) { | |||
String facetNameAndField = IssueIndexDefinition.FIELD_ISSUE_FUNC_CREATED_AT; | |||
SearchRequestBuilder esRequest = client | |||
.prepareSearch(IssueIndexDefinition.INDEX_TYPE_ISSUE) | |||
.prepareSearch(INDEX_TYPE_ISSUE) | |||
.setSize(0); | |||
BoolQueryBuilder esFilter = boolQuery(); | |||
filters.values().stream().filter(Objects::nonNull).forEach(esFilter::must); | |||
@@ -592,42 +590,27 @@ public class IssueIndex { | |||
return value == null ? null : termQuery(field, value); | |||
} | |||
public List<String> listTags(@Nullable String textQuery, int maxNumberOfTags) { | |||
public List<String> listTags(String organizationUuid, @Nullable String textQuery, int maxNumberOfTags) { | |||
SearchRequestBuilder requestBuilder = client | |||
.prepareSearch(IssueIndexDefinition.INDEX_TYPE_ISSUE, RuleIndexDefinition.INDEX_TYPE_RULE); | |||
requestBuilder.setQuery(boolQuery().must(matchAllQuery()).filter(createBoolFilter( | |||
IssueQuery.builder().checkAuthorization(false).build()))); | |||
GlobalBuilder topAggreg = AggregationBuilders.global("tags"); | |||
String tagsOnIssuesSubAggregation = "tags__issues"; | |||
String tagsOnRulesSubAggregation = "tags__rules"; | |||
.prepareSearch(INDEX_TYPE_ISSUE) | |||
.setQuery(boolQuery() | |||
.filter(termQuery(FIELD_ISSUE_ORGANIZATION_UUID, organizationUuid))) | |||
.setSize(0); | |||
TermsBuilder issueTags = AggregationBuilders.terms(tagsOnIssuesSubAggregation) | |||
TermsBuilder termsAggregation = AggregationBuilders.terms(AGGREGATION_NAME_FOR_TAGS) | |||
.field(IssueIndexDefinition.FIELD_ISSUE_TAGS) | |||
.size(maxNumberOfTags) | |||
.order(Terms.Order.term(true)) | |||
.minDocCount(1L); | |||
TermsBuilder ruleTags = AggregationBuilders.terms(tagsOnRulesSubAggregation) | |||
.field(RuleIndexDefinition.FIELD_RULE_ALL_TAGS) | |||
.size(maxNumberOfTags) | |||
.order(Terms.Order.term(true)) | |||
.minDocCount(1L); | |||
if (textQuery != null) { | |||
String escapedTextQuery = escapeSpecialRegexChars(textQuery); | |||
issueTags.include(format(SUBSTRING_MATCH_REGEXP, escapedTextQuery)); | |||
ruleTags.include(format(SUBSTRING_MATCH_REGEXP, escapedTextQuery)); | |||
termsAggregation.include(format(SUBSTRING_MATCH_REGEXP, escapedTextQuery)); | |||
} | |||
requestBuilder.addAggregation(termsAggregation); | |||
SearchResponse searchResponse = requestBuilder.addAggregation(topAggreg.subAggregation(issueTags).subAggregation(ruleTags)).get(); | |||
Global allTags = searchResponse.getAggregations().get("tags"); | |||
SortedSet<String> result = Sets.newTreeSet(); | |||
Terms issuesResult = allTags.getAggregations().get(tagsOnIssuesSubAggregation); | |||
Terms rulesResult = allTags.getAggregations().get(tagsOnRulesSubAggregation); | |||
result.addAll(EsUtils.termsKeys(issuesResult)); | |||
result.addAll(EsUtils.termsKeys(rulesResult)); | |||
List<String> resultAsList = Lists.newArrayList(result); | |||
return resultAsList.size() > maxNumberOfTags && maxNumberOfTags > 0 ? resultAsList.subList(0, maxNumberOfTags) : resultAsList; | |||
SearchResponse searchResponse = requestBuilder.get(); | |||
Terms issuesResult = searchResponse.getAggregations().get(AGGREGATION_NAME_FOR_TAGS); | |||
return EsUtils.termsKeys(issuesResult); | |||
} | |||
public Map<String, Long> countTags(IssueQuery query, int maxNumberOfTags) { | |||
@@ -642,7 +625,7 @@ public class IssueIndex { | |||
private Terms listTermsMatching(String fieldName, IssueQuery query, @Nullable String textQuery, Terms.Order termsOrder, int maxNumberOfTags) { | |||
SearchRequestBuilder requestBuilder = client | |||
.prepareSearch(IssueIndexDefinition.INDEX_TYPE_ISSUE) | |||
.prepareSearch(INDEX_TYPE_ISSUE) | |||
// Avoids returning search hits | |||
.setSize(0); | |||
@@ -692,7 +675,7 @@ public class IssueIndex { | |||
} | |||
SearchRequestBuilder requestBuilder = client | |||
.prepareSearch(IssueIndexDefinition.INDEX_TYPE_ISSUE) | |||
.prepareSearch(INDEX_TYPE_ISSUE) | |||
.setSearchType(SearchType.SCAN) | |||
.setScroll(TimeValue.timeValueMinutes(EsUtils.SCROLL_TIME_IN_MINUTES)) | |||
.setSize(10_000) |
@@ -19,8 +19,12 @@ | |||
*/ | |||
package org.sonar.server.issue.ws; | |||
import com.google.common.collect.Lists; | |||
import com.google.common.collect.Sets; | |||
import com.google.common.io.Resources; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.SortedSet; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.Response; | |||
@@ -29,6 +33,8 @@ import org.sonar.api.server.ws.WebService.NewAction; | |||
import org.sonar.api.server.ws.WebService.Param; | |||
import org.sonar.api.utils.text.JsonWriter; | |||
import org.sonar.server.issue.index.IssueIndex; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE; | |||
@@ -39,9 +45,13 @@ import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE; | |||
public class TagsAction implements IssuesWsAction { | |||
private final IssueIndex issueIndex; | |||
private final RuleIndex ruleIndex; | |||
private final DefaultOrganizationProvider defaultOrganizationProvider; | |||
public TagsAction(IssueIndex issueIndex) { | |||
public TagsAction(IssueIndex issueIndex, RuleIndex ruleIndex, DefaultOrganizationProvider defaultOrganizationProvider) { | |||
this.issueIndex = issueIndex; | |||
this.ruleIndex = ruleIndex; | |||
this.defaultOrganizationProvider = defaultOrganizationProvider; | |||
} | |||
@Override | |||
@@ -64,12 +74,19 @@ public class TagsAction implements IssuesWsAction { | |||
public void handle(Request request, Response response) throws Exception { | |||
String query = request.param(Param.TEXT_QUERY); | |||
int pageSize = request.mandatoryParamAsInt("ps"); | |||
List<String> tags = listTags(query, pageSize); | |||
List<String> tags = listTags(query, pageSize == 0 ? Integer.MAX_VALUE : pageSize); | |||
writeTags(response, tags); | |||
} | |||
private List<String> listTags(@Nullable String textQuery, int pageSize) { | |||
return issueIndex.listTags(textQuery, pageSize); | |||
Collection<String> issueTags = issueIndex.listTags(defaultOrganizationProvider.get().getUuid(), textQuery, pageSize); | |||
Collection<String> ruleTags = ruleIndex.listTags(defaultOrganizationProvider.get().getUuid(), textQuery, pageSize); | |||
SortedSet<String> result = Sets.newTreeSet(); | |||
result.addAll(issueTags); | |||
result.addAll(ruleTags); | |||
List<String> resultAsList = Lists.newArrayList(result); | |||
return resultAsList.size() > pageSize && pageSize > 0 ? resultAsList.subList(0, pageSize) : resultAsList; | |||
} | |||
private static void writeTags(Response response, List<String> tags) { |
@@ -166,7 +166,6 @@ import org.sonar.server.rule.RuleDeleter; | |||
import org.sonar.server.rule.RuleUpdater; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.rule.index.RuleIndexer; | |||
import org.sonar.server.rule.index.RuleIteratorFactory; | |||
import org.sonar.server.rule.ws.ActiveRuleCompleter; | |||
import org.sonar.server.rule.ws.RepositoriesAction; | |||
import org.sonar.server.rule.ws.RuleMapper; | |||
@@ -282,7 +281,6 @@ public class PlatformLevel4 extends PlatformLevel { | |||
// rule | |||
RuleIndexDefinition.class, | |||
RuleIndexer.class, | |||
RuleIteratorFactory.class, | |||
AnnotationRuleParser.class, | |||
XMLRuleParser.class, | |||
DefaultRuleFinder.class, |
@@ -27,7 +27,7 @@ import org.sonar.server.qualityprofile.ActiveRule; | |||
import static com.google.common.base.Preconditions.checkNotNull; | |||
import static org.apache.commons.lang.StringUtils.containsIgnoreCase; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_ORGANIZATION_UUID; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_ORGANIZATION_UUID; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_CREATED_AT; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_KEY; | |||
@@ -71,11 +71,11 @@ public class ActiveRuleDoc extends BaseDoc { | |||
} | |||
String organizationUuid() { | |||
return getField(FIELD_ACTIVE_ORGANIZATION_UUID); | |||
return getField(FIELD_ACTIVE_RULE_ORGANIZATION_UUID); | |||
} | |||
public ActiveRuleDoc setOrganizationUuid(String s) { | |||
setField(FIELD_ACTIVE_ORGANIZATION_UUID, s); | |||
setField(FIELD_ACTIVE_RULE_ORGANIZATION_UUID, s); | |||
return this; | |||
} | |||
@@ -28,6 +28,7 @@ import java.util.Collections; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.ObjectUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
@@ -45,14 +46,12 @@ import org.sonar.api.utils.log.Profiler; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto.Format; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.db.rule.RuleRepositoryDto; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.ActiveRuleChange; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
@@ -75,10 +74,9 @@ public class RegisterRules implements Startable { | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
private final Languages languages; | |||
private final System2 system2; | |||
private final DefaultOrganizationProvider defaultOrganizationProvider; | |||
public RegisterRules(RuleDefinitionsLoader defLoader, RuleActivator ruleActivator, DbClient dbClient, RuleIndexer ruleIndexer, | |||
ActiveRuleIndexer activeRuleIndexer, Languages languages, System2 system2, DefaultOrganizationProvider defaultOrganizationProvider) { | |||
ActiveRuleIndexer activeRuleIndexer, Languages languages, System2 system2) { | |||
this.defLoader = defLoader; | |||
this.ruleActivator = ruleActivator; | |||
this.dbClient = dbClient; | |||
@@ -86,7 +84,6 @@ public class RegisterRules implements Startable { | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
this.languages = languages; | |||
this.system2 = system2; | |||
this.defaultOrganizationProvider = defaultOrganizationProvider; | |||
} | |||
@Override | |||
@@ -111,22 +108,15 @@ public class RegisterRules implements Startable { | |||
List<RuleDefinitionDto> removedRules = processRemainingDbRules(allRules.values(), session); | |||
List<ActiveRuleChange> changes = removeActiveRulesOnStillExistingRepositories(session, removedRules, context); | |||
session.commit(); | |||
keysToIndex.addAll(removedRules.stream().map(RuleDefinitionDto::getKey).collect(Collectors.toList())); | |||
persistRepositories(session, context.repositories()); | |||
ruleIndexer.delete(removedRules.stream().map(RuleDefinitionDto::getKey).collect(MoreCollectors.toList(removedRules.size()))); | |||
ruleIndexer.index(getDefaultOrganization(), keysToIndex); | |||
ruleIndexer.indexRuleDefinitions(keysToIndex); | |||
activeRuleIndexer.index(changes); | |||
profiler.stopDebug(); | |||
} | |||
} | |||
private OrganizationDto getDefaultOrganization() { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
return dbClient.organizationDao().selectByUuid(dbSession, defaultOrganizationProvider.get().getUuid()) | |||
.orElseThrow(() -> new IllegalStateException("Cannot load default organization")); | |||
} | |||
} | |||
private void persistRepositories(DbSession dbSession, List<RulesDefinition.Repository> repositories) { | |||
dbClient.ruleRepositoryDao().truncate(dbSession); | |||
List<RuleRepositoryDto> dtos = repositories |
@@ -88,7 +88,7 @@ public class RuleCreator { | |||
.orElseGet(() -> createCustomRule(customRuleKey, newRule, templateRule, dbSession)); | |||
dbSession.commit(); | |||
ruleIndexer.index(defaultOrganization, customRuleKey); | |||
ruleIndexer.indexRuleDefinition(customRuleKey); | |||
return customRuleKey; | |||
} | |||
@@ -61,7 +61,7 @@ public class RuleDeleter { | |||
dbClient.ruleDao().update(dbSession, rule); | |||
dbSession.commit(); | |||
ruleIndexer.delete(ruleKey); | |||
ruleIndexer.indexRuleDefinition(ruleKey); | |||
} | |||
} | |||
} |
@@ -39,7 +39,6 @@ import org.sonar.api.server.debt.DebtRemediationFunction; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
@@ -91,17 +90,14 @@ public class RuleUpdater { | |||
return false; | |||
} | |||
String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid(); | |||
OrganizationDto organization = dbClient.organizationDao().selectByUuid(dbSession, defaultOrganizationUuid) | |||
.orElseThrow(() -> new IllegalStateException(String.format("Could not find default organization '%s'", defaultOrganizationUuid))); | |||
RuleDto rule = getRuleDto(update); | |||
// validate only the changes, not all the rule fields | |||
apply(update, rule, userSession); | |||
update(dbSession, rule); | |||
updateParameters(dbSession, update, rule); | |||
dbSession.commit(); | |||
ruleIndexer.index(organization, rule.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule.getKey()); | |||
return true; | |||
} | |||
@@ -20,7 +20,6 @@ | |||
package org.sonar.server.rule.index; | |||
import com.google.common.collect.Maps; | |||
import java.util.Collection; | |||
import java.util.Map; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
@@ -40,7 +39,7 @@ public class RuleDoc extends BaseDoc { | |||
} | |||
public RuleDoc() { | |||
super(Maps.newHashMapWithExpectedSize(16)); | |||
super(Maps.newHashMapWithExpectedSize(15)); | |||
} | |||
@Override | |||
@@ -166,15 +165,6 @@ public class RuleDoc extends BaseDoc { | |||
return this; | |||
} | |||
public Collection<String> allTags() { | |||
return getField(RuleIndexDefinition.FIELD_RULE_ALL_TAGS); | |||
} | |||
public RuleDoc setAllTags(@Nullable Collection<String> l) { | |||
setField(RuleIndexDefinition.FIELD_RULE_ALL_TAGS, l); | |||
return this; | |||
} | |||
public RuleType type() { | |||
return RuleType.valueOf(getField(RuleIndexDefinition.FIELD_RULE_TYPE)); | |||
} |
@@ -17,28 +17,24 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.rule.index; | |||
import java.util.List; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import static java.util.Arrays.asList; | |||
package org.sonar.server.rule.index; | |||
public class RuleIteratorFactory { | |||
public class RuleDocWithSystemScope { | |||
private final DbClient dbClient; | |||
private final RuleDoc ruleDoc; | |||
private final RuleExtensionDoc ruleExtensionDoc; | |||
public RuleIteratorFactory(DbClient dbClient) { | |||
this.dbClient = dbClient; | |||
public RuleDocWithSystemScope(RuleDoc ruleDoc, RuleExtensionDoc ruleExtensionDoc) { | |||
this.ruleDoc = ruleDoc; | |||
this.ruleExtensionDoc = ruleExtensionDoc; | |||
} | |||
public RuleIterator createForKey(OrganizationDto organization, RuleKey ruleKey) { | |||
return new RuleIteratorForSingleChunk(dbClient, organization, asList(ruleKey)); | |||
public RuleDoc getRuleDoc() { | |||
return ruleDoc; | |||
} | |||
public RuleIterator createForKeys(OrganizationDto organization, List<RuleKey> ruleKeys) { | |||
return new RuleIteratorForMultipleChunks(dbClient, organization, ruleKeys); | |||
public RuleExtensionDoc getRuleExtensionDoc() { | |||
return ruleExtensionDoc; | |||
} | |||
} |
@@ -0,0 +1,94 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.rule.index; | |||
import com.google.common.collect.Maps; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import org.apache.commons.lang.builder.ReflectionToStringBuilder; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.rule.RuleMetadataDto; | |||
import org.sonar.server.es.BaseDoc; | |||
public class RuleExtensionDoc extends BaseDoc { | |||
public RuleExtensionDoc(Map<String, Object> fields) { | |||
super(fields); | |||
} | |||
public RuleExtensionDoc() { | |||
super(Maps.newHashMapWithExpectedSize(4)); | |||
} | |||
@Override | |||
public String getId() { | |||
// the Id is generated by elasticsearch | |||
return null; | |||
} | |||
@Override | |||
public String getRouting() { | |||
return null; | |||
} | |||
@Override | |||
public String getParent() { | |||
return getRuleKey().toString(); | |||
} | |||
public RuleKey getRuleKey() { | |||
return getField(RuleIndexDefinition.FIELD_RULE_EXTENSION_RULE_KEY); | |||
} | |||
public RuleExtensionDoc setRuleKey(RuleKey ruleKey) { | |||
setField(RuleIndexDefinition.FIELD_RULE_EXTENSION_RULE_KEY, ruleKey); | |||
return this; | |||
} | |||
public RuleExtensionScope getScope() { | |||
return RuleExtensionScope.parse(getField(RuleIndexDefinition.FIELD_RULE_EXTENSION_SCOPE)); | |||
} | |||
public RuleExtensionDoc setScope(RuleExtensionScope scope) { | |||
setField(RuleIndexDefinition.FIELD_RULE_EXTENSION_SCOPE, scope.getScope()); | |||
return this; | |||
} | |||
public Set<String> getTags() { | |||
return getField(RuleIndexDefinition.FIELD_RULE_EXTENSION_TAGS); | |||
} | |||
public RuleExtensionDoc setTags(Set<String> tags) { | |||
setField(RuleIndexDefinition.FIELD_RULE_EXTENSION_TAGS, tags); | |||
return this; | |||
} | |||
public static RuleExtensionDoc of(RuleKey key, RuleExtensionScope scope, RuleMetadataDto ruleExtension) { | |||
return new RuleExtensionDoc() | |||
.setRuleKey(key) | |||
.setScope(scope) | |||
.setTags(ruleExtension.getTags()); | |||
} | |||
@Override | |||
public String toString() { | |||
return ReflectionToStringBuilder.toString(this); | |||
} | |||
} |
@@ -0,0 +1,62 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.rule.index; | |||
import java.util.Optional; | |||
import javax.annotation.Nullable; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
public class RuleExtensionScope { | |||
private static final String FAKE_UUID_FOR_SYSTEM = "system"; | |||
private final Optional<String> organizationUuid; | |||
private RuleExtensionScope(@Nullable String organizationUuid) { | |||
this.organizationUuid = Optional.ofNullable(organizationUuid); | |||
} | |||
public static RuleExtensionScope system() { | |||
return new RuleExtensionScope(null); | |||
} | |||
public static RuleExtensionScope organization(OrganizationDto organization) { | |||
return organization(organization.getUuid()); | |||
} | |||
public static RuleExtensionScope organization(String organizationUuid) { | |||
checkArgument(!FAKE_UUID_FOR_SYSTEM.equals(organizationUuid), "The organization uuid '%s' is reserved for to store system tags in the rules index.", FAKE_UUID_FOR_SYSTEM); | |||
return new RuleExtensionScope(organizationUuid); | |||
} | |||
public String getScope() { | |||
return organizationUuid.orElse(FAKE_UUID_FOR_SYSTEM); | |||
} | |||
public static RuleExtensionScope parse(String scope) { | |||
if (FAKE_UUID_FOR_SYSTEM.equals(scope)) { | |||
return system(); | |||
} | |||
return new RuleExtensionScope(scope); | |||
} | |||
} |
@@ -30,7 +30,9 @@ import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import java.util.function.Function; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.elasticsearch.action.search.SearchRequestBuilder; | |||
@@ -43,8 +45,11 @@ import org.elasticsearch.index.query.MatchQueryBuilder; | |||
import org.elasticsearch.index.query.QueryBuilder; | |||
import org.elasticsearch.index.query.QueryBuilders; | |||
import org.elasticsearch.index.query.SimpleQueryStringBuilder; | |||
import org.elasticsearch.index.query.TermsQueryBuilder; | |||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; | |||
import org.elasticsearch.search.aggregations.AggregationBuilder; | |||
import org.elasticsearch.search.aggregations.AggregationBuilders; | |||
import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder; | |||
import org.elasticsearch.search.aggregations.bucket.terms.Terms; | |||
import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder; | |||
import org.elasticsearch.search.sort.FieldSortBuilder; | |||
@@ -55,24 +60,29 @@ import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.rules.RuleType; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.EsUtils; | |||
import org.sonar.server.es.SearchIdResult; | |||
import org.sonar.server.es.SearchOptions; | |||
import org.sonar.server.es.StickyFacetBuilder; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery; | |||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; | |||
import static org.elasticsearch.index.query.QueryBuilders.matchQuery; | |||
import static org.elasticsearch.index.query.QueryBuilders.simpleQueryStringQuery; | |||
import static org.elasticsearch.index.query.QueryBuilders.termsQuery; | |||
import static org.sonar.server.es.DefaultIndexSettingsElement.SEARCH_WORDS_ANALYZER; | |||
import static org.sonar.server.es.DefaultIndexSettingsElement.SORTABLE_ANALYZER; | |||
import static org.sonar.server.es.EsUtils.SCROLL_TIME_IN_MINUTES; | |||
import static org.sonar.server.es.EsUtils.escapeSpecialRegexChars; | |||
import static org.sonar.server.es.EsUtils.scrollIds; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_ORGANIZATION_UUID; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_ALL_TAGS; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_CREATED_AT; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_EXTENSION_SCOPE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_EXTENSION_TAGS; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_HTML_DESCRIPTION; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_INTERNAL_KEY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_IS_TEMPLATE; | |||
@@ -88,6 +98,7 @@ import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_TYPE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_UPDATED_AT; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX_TYPE_ACTIVE_RULE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX_TYPE_RULE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX_TYPE_RULE_EXTENSION; | |||
/** | |||
* The unique entry-point to interact with Elasticsearch index "rules". | |||
@@ -108,6 +119,7 @@ public class RuleIndex { | |||
Collections2.filter( | |||
Collections2.transform(Arrays.asList(RuleStatus.values()), RuleStatus::toString), | |||
input -> !RuleStatus.REMOVED.toString().equals(input))); | |||
private static final String AGGREGATION_NAME_FOR_TAGS = "tagsAggregation"; | |||
private final EsClient client; | |||
public RuleIndex(EsClient client) { | |||
@@ -196,13 +208,6 @@ public class RuleIndex { | |||
.boost(boost); | |||
} | |||
private static QueryBuilder termAnyQuery(String field, String query, float boost) { | |||
return QueryBuilders.multiMatchQuery(query, | |||
field, SEARCH_WORDS_ANALYZER.subField(field)) | |||
.operator(MatchQueryBuilder.Operator.OR) | |||
.boost(boost); | |||
} | |||
/* Build main filter (match based) */ | |||
private static Map<String, QueryBuilder> buildFilters(RuleQuery query) { | |||
@@ -245,8 +250,16 @@ public class RuleIndex { | |||
} | |||
if (isNotEmpty(query.getTags())) { | |||
filters.put(FIELD_RULE_ALL_TAGS, | |||
QueryBuilders.termsQuery(FIELD_RULE_ALL_TAGS, query.getTags())); | |||
BoolQueryBuilder q = boolQuery(); | |||
String organizationUuid = query.getOrganizationUuid(); | |||
checkArgument(organizationUuid != null, "Cannot filter on tags '%s', if no organization is specified.", query.getTags()); | |||
query.getTags().stream() | |||
.map(tag -> boolQuery() | |||
.filter(QueryBuilders.termQuery(FIELD_RULE_EXTENSION_TAGS, tag)) | |||
.filter(termsQuery(FIELD_RULE_EXTENSION_SCOPE, RuleExtensionScope.system().getScope(), RuleExtensionScope.organization(organizationUuid).getScope()))) | |||
.map(childQuery -> QueryBuilders.hasChildQuery(INDEX_TYPE_RULE_EXTENSION.getType(), childQuery)) | |||
.forEach(q::filter); | |||
filters.put(FIELD_RULE_EXTENSION_TAGS, q); | |||
} | |||
if (isNotEmpty(query.getTypes())) { | |||
@@ -285,6 +298,7 @@ public class RuleIndex { | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_PROFILE_KEY, query.getQProfileKey()); | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance()); | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_SEVERITY, query.getActiveSeverities()); | |||
addTermFilter(childrenFilter, FIELD_ACTIVE_RULE_ORGANIZATION_UUID, query.getOrganizationUuid()); | |||
// ChildQuery | |||
QueryBuilder childQuery; | |||
@@ -294,7 +308,7 @@ public class RuleIndex { | |||
childQuery = matchAllQuery(); | |||
} | |||
/** Implementation of activation query */ | |||
/* Implementation of activation query */ | |||
if (Boolean.TRUE.equals(query.getActivation())) { | |||
filters.put("activation", | |||
QueryBuilders.hasChildQuery(INDEX_TYPE_ACTIVE_RULE.getType(), | |||
@@ -354,8 +368,24 @@ public class RuleIndex { | |||
} | |||
if (options.getFacets().contains(FACET_TAGS) || options.getFacets().contains(FACET_OLD_DEFAULT)) { | |||
Collection<String> tags = query.getTags(); | |||
String organizationUuid = query.getOrganizationUuid(); | |||
checkArgument(organizationUuid != null, "Cannot use tags facet, if no organization is specified.", query.getTags()); | |||
Function<TermsBuilder, AggregationBuilder<?>> childFeature = termsAggregation -> { | |||
FilterAggregationBuilder scopeAggregation = AggregationBuilders.filter("scope_filter_for_" + FACET_TAGS).filter( | |||
termsQuery(FIELD_RULE_EXTENSION_SCOPE, | |||
RuleExtensionScope.system().getScope(), | |||
RuleExtensionScope.organization(organizationUuid).getScope())) | |||
.subAggregation(termsAggregation); | |||
return AggregationBuilders.children("children_for_" + FACET_TAGS) | |||
.childType(INDEX_TYPE_RULE_EXTENSION.getType()) | |||
.subAggregation(scopeAggregation); | |||
}; | |||
aggregations.put(FACET_TAGS, | |||
stickyFacetBuilder.buildStickyFacet(FIELD_RULE_ALL_TAGS, FACET_TAGS, | |||
stickyFacetBuilder.buildStickyFacet(FIELD_RULE_EXTENSION_TAGS, FACET_TAGS, childFeature, | |||
(tags == null) ? (new String[0]) : tags.toArray())); | |||
} | |||
if (options.getFacets().contains(FACET_TYPES)) { | |||
@@ -482,7 +512,10 @@ public class RuleIndex { | |||
.addAggregation(termsAggregation); | |||
SearchResponse esResponse = request.get(); | |||
return extractAggregationTerms(aggregationKey, esResponse); | |||
} | |||
private static Set<String> extractAggregationTerms(String aggregationKey, SearchResponse esResponse) { | |||
Set<String> terms = new HashSet<>(); | |||
Terms aggregation = esResponse.getAggregations().get(aggregationKey); | |||
if (aggregation != null) { | |||
@@ -491,8 +524,32 @@ public class RuleIndex { | |||
return terms; | |||
} | |||
public Set<String> listTags(String organizationUuid, @Nullable String query, int size) { | |||
TermsQueryBuilder scopeFilter = QueryBuilders.termsQuery( | |||
FIELD_RULE_EXTENSION_SCOPE, | |||
RuleExtensionScope.system().getScope(), | |||
RuleExtensionScope.organization(organizationUuid).getScope()); | |||
TermsBuilder termsAggregation = AggregationBuilders.terms(AGGREGATION_NAME_FOR_TAGS) | |||
.field(FIELD_RULE_EXTENSION_TAGS) | |||
.size(size) | |||
.minDocCount(1); | |||
Optional.ofNullable(query) | |||
.map(EsUtils::escapeSpecialRegexChars) | |||
.map(queryString -> ".*" + queryString + ".*") | |||
.ifPresent(termsAggregation::include); | |||
SearchRequestBuilder request = client | |||
.prepareSearch(INDEX_TYPE_RULE_EXTENSION) | |||
.setQuery(boolQuery().filter(scopeFilter)) | |||
.setSize(0) | |||
.addAggregation(termsAggregation); | |||
SearchResponse esResponse = request.get(); | |||
return extractAggregationTerms(AGGREGATION_NAME_FOR_TAGS, esResponse); | |||
} | |||
private static boolean isNotEmpty(@Nullable Collection list) { | |||
return list != null && !list.isEmpty(); | |||
} | |||
} |
@@ -52,20 +52,26 @@ public class RuleIndexDefinition implements IndexDefinition { | |||
public static final String FIELD_RULE_LANGUAGE = "lang"; | |||
public static final String FIELD_RULE_IS_TEMPLATE = "isTemplate"; | |||
public static final String FIELD_RULE_TEMPLATE_KEY = "templateKey"; | |||
public static final String FIELD_RULE_ALL_TAGS = "allTags"; | |||
public static final String FIELD_RULE_TYPE = "type"; | |||
public static final String FIELD_RULE_CREATED_AT = "createdAt"; | |||
public static final String FIELD_RULE_UPDATED_AT = "updatedAt"; | |||
public static final Set<String> SORT_FIELDS = ImmutableSet.of( | |||
RuleIndexDefinition.FIELD_RULE_NAME, | |||
RuleIndexDefinition.FIELD_RULE_UPDATED_AT, | |||
RuleIndexDefinition.FIELD_RULE_CREATED_AT, | |||
RuleIndexDefinition.FIELD_RULE_KEY); | |||
FIELD_RULE_NAME, | |||
FIELD_RULE_UPDATED_AT, | |||
FIELD_RULE_CREATED_AT, | |||
FIELD_RULE_KEY); | |||
// Rule extension fields | |||
public static final IndexType INDEX_TYPE_RULE_EXTENSION = new IndexType(INDEX, "ruleExtension"); | |||
/** The uuid of a {@link RuleExtensionScope} */ | |||
public static final String FIELD_RULE_EXTENSION_SCOPE = "scope"; | |||
public static final String FIELD_RULE_EXTENSION_RULE_KEY = "ruleKey"; | |||
public static final String FIELD_RULE_EXTENSION_TAGS = "tags"; | |||
// Active rule fields | |||
public static final IndexType INDEX_TYPE_ACTIVE_RULE = new IndexType(INDEX, "activeRule"); | |||
public static final String FIELD_ACTIVE_ORGANIZATION_UUID = "organizationUuid"; | |||
public static final String FIELD_ACTIVE_RULE_ORGANIZATION_UUID = "organizationUuid"; | |||
public static final String FIELD_ACTIVE_RULE_KEY = "key"; | |||
public static final String FIELD_ACTIVE_RULE_REPOSITORY = "repo"; | |||
public static final String FIELD_ACTIVE_RULE_INHERITANCE = "inheritance"; | |||
@@ -89,23 +95,32 @@ public class RuleIndexDefinition implements IndexDefinition { | |||
index.configureShards(settings, 1); | |||
// Active rule type | |||
NewIndex.NewIndexType activeRuleMapping = index.createType(RuleIndexDefinition.INDEX_TYPE_ACTIVE_RULE.getType()); | |||
NewIndex.NewIndexType activeRuleMapping = index.createType(INDEX_TYPE_ACTIVE_RULE.getType()); | |||
activeRuleMapping.setEnableSource(false); | |||
activeRuleMapping.setAttribute("_parent", ImmutableMap.of("type", RuleIndexDefinition.INDEX_TYPE_RULE.getType())); | |||
activeRuleMapping.setAttribute("_parent", ImmutableMap.of("type", INDEX_TYPE_RULE.getType())); | |||
activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_ORGANIZATION_UUID).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_KEY).addSubFields(SORTABLE_ANALYZER).build(); | |||
activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_RULE_KEY).addSubFields(SORTABLE_ANALYZER).build(); | |||
activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_REPOSITORY).build(); | |||
activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_ORGANIZATION_UUID).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_KEY).addSubFields(SORTABLE_ANALYZER).build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_RULE_KEY).addSubFields(SORTABLE_ANALYZER).build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_REPOSITORY).build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_PROFILE_KEY).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_INHERITANCE).disableNorms().build(); | |||
activeRuleMapping.stringFieldBuilder(FIELD_ACTIVE_RULE_SEVERITY).disableNorms().build(); | |||
activeRuleMapping.createLongField(RuleIndexDefinition.FIELD_ACTIVE_RULE_CREATED_AT); | |||
activeRuleMapping.createLongField(RuleIndexDefinition.FIELD_ACTIVE_RULE_UPDATED_AT); | |||
activeRuleMapping.createLongField(FIELD_ACTIVE_RULE_CREATED_AT); | |||
activeRuleMapping.createLongField(FIELD_ACTIVE_RULE_UPDATED_AT); | |||
// Rule extension type | |||
NewIndex.NewIndexType ruleExtensionType = index.createType(INDEX_TYPE_RULE_EXTENSION.getType()); | |||
ruleExtensionType.setEnableSource(false); | |||
ruleExtensionType.setAttribute("_parent", ImmutableMap.of("type", INDEX_TYPE_RULE.getType())); | |||
ruleExtensionType.stringFieldBuilder(FIELD_RULE_EXTENSION_SCOPE).disableNorms().build(); | |||
ruleExtensionType.stringFieldBuilder(FIELD_RULE_EXTENSION_RULE_KEY).disableNorms().build(); | |||
ruleExtensionType.stringFieldBuilder(FIELD_RULE_EXTENSION_TAGS).build(); | |||
// Rule type | |||
NewIndex.NewIndexType ruleMapping = index.createType(RuleIndexDefinition.INDEX_TYPE_RULE.getType()); | |||
NewIndex.NewIndexType ruleMapping = index.createType(INDEX_TYPE_RULE.getType()); | |||
ruleMapping.setEnableSource(false); | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_KEY).addSubFields(SORTABLE_ANALYZER).build(); | |||
@@ -125,8 +140,7 @@ public class RuleIndexDefinition implements IndexDefinition { | |||
ruleMapping.createBooleanField(FIELD_RULE_IS_TEMPLATE); | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_TEMPLATE_KEY).disableNorms().build(); | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_ALL_TAGS).addSubFields(SEARCH_WORDS_ANALYZER).build(); | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_TYPE).disableNorms().build(); | |||
ruleMapping.createLongField(FIELD_RULE_CREATED_AT); |
@@ -19,8 +19,8 @@ | |||
*/ | |||
package org.sonar.server.rule.index; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Arrays; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
@@ -34,98 +34,103 @@ import org.sonar.server.es.BulkIndexer.Size; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.IndexType; | |||
import org.sonar.server.es.StartupIndexer; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import static java.util.Collections.singletonList; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX_TYPE_RULE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX_TYPE_RULE_EXTENSION; | |||
public class RuleIndexer implements StartupIndexer { | |||
private final EsClient esClient; | |||
private final DbClient dbClient; | |||
private final RuleIteratorFactory ruleIteratorFactory; | |||
private final DefaultOrganizationProvider defaultOrganizationProvider; | |||
public RuleIndexer(EsClient esClient, DbClient dbClient, RuleIteratorFactory ruleIteratorFactory, DefaultOrganizationProvider defaultOrganizationProvider) { | |||
public RuleIndexer(EsClient esClient, DbClient dbClient) { | |||
this.esClient = esClient; | |||
this.dbClient = dbClient; | |||
this.ruleIteratorFactory = ruleIteratorFactory; | |||
this.defaultOrganizationProvider = defaultOrganizationProvider; | |||
} | |||
@Override | |||
public Set<IndexType> getIndexTypes() { | |||
return ImmutableSet.of(INDEX_TYPE_RULE); | |||
return ImmutableSet.of(INDEX_TYPE_RULE, INDEX_TYPE_RULE_EXTENSION); | |||
} | |||
@Override | |||
public void indexOnStartup(Set<IndexType> uninitializedIndexTypes) { | |||
BulkIndexer bulk = new BulkIndexer(esClient, RuleIndexDefinition.INDEX).setSize(Size.LARGE); | |||
bulk.start(); | |||
// index all definitions and system extensions | |||
if (uninitializedIndexTypes.contains(INDEX_TYPE_RULE)) { | |||
try(DbSession dbSession = dbClient.openSession(false)) { | |||
String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid(); | |||
OrganizationDto defaultOrganization = dbClient.organizationDao().selectByUuid(dbSession, defaultOrganizationUuid) | |||
.orElseThrow(() -> new IllegalStateException(String.format("Cannot load default organization for uuid '%s'", defaultOrganizationUuid))); | |||
try (RuleIterator rules = new RuleIteratorForSingleChunk(dbClient, null)) { | |||
doIndexRuleDefinitions(rules, bulk); | |||
} | |||
} | |||
try (RuleIterator rules = new RuleIteratorForSingleChunk(dbClient, defaultOrganization, null)) { | |||
doIndex(bulk, rules); | |||
} | |||
// index all organization extensions | |||
if (uninitializedIndexTypes.contains(INDEX_TYPE_RULE_EXTENSION)) { | |||
try (RuleMetadataIterator metadatas = new RuleMetadataIterator(dbClient)) { | |||
doIndexRuleExtensions(metadatas, bulk); | |||
} | |||
} | |||
bulk.stop(); | |||
} | |||
public void index(OrganizationDto organization, RuleKey ruleKey) { | |||
BulkIndexer bulk = createBulkIndexer(Size.REGULAR); | |||
try (RuleIterator rules = ruleIteratorFactory.createForKey(organization, ruleKey)) { | |||
doIndex(bulk, rules); | |||
} | |||
public void indexRuleDefinition(RuleKey ruleKey) { | |||
indexRuleDefinitions(singletonList(ruleKey)); | |||
} | |||
public void index(OrganizationDto organization, List<RuleKey> ruleKeys) { | |||
BulkIndexer bulk = createBulkIndexer(Size.REGULAR); | |||
try (RuleIterator rules = ruleIteratorFactory.createForKeys(organization, ruleKeys)) { | |||
doIndex(bulk, rules); | |||
public void indexRuleDefinitions(List<RuleKey> ruleKeys) { | |||
BulkIndexer bulk = new BulkIndexer(esClient, RuleIndexDefinition.INDEX).setSize(Size.REGULAR); | |||
bulk.start(); | |||
try (RuleIterator rules = new RuleIteratorForMultipleChunks(dbClient, ruleKeys)) { | |||
doIndexRuleDefinitions(rules, bulk); | |||
} | |||
bulk.stop(); | |||
} | |||
@VisibleForTesting | |||
public void index(Iterator<RuleDoc> rules) { | |||
doIndex(createBulkIndexer(Size.REGULAR), rules); | |||
public void indexRuleExtension(OrganizationDto organization, RuleKey ruleKey) { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
dbClient.ruleDao() | |||
.selectMetadataByKey(dbSession, ruleKey, organization) | |||
.map(ruleExtension -> RuleExtensionDoc.of(ruleKey, RuleExtensionScope.organization(organization), ruleExtension)) | |||
.map(Arrays::asList) | |||
.map(List::iterator) | |||
.ifPresent(metadatas -> { | |||
BulkIndexer bulk = new BulkIndexer(esClient, RuleIndexDefinition.INDEX).setSize(Size.REGULAR); | |||
bulk.start(); | |||
doIndexRuleExtensions(metadatas, bulk); | |||
bulk.stop(); | |||
}); | |||
} | |||
} | |||
private static void doIndex(BulkIndexer bulk, Iterator<RuleDoc> rules) { | |||
bulk.start(); | |||
private static void doIndexRuleDefinitions(Iterator<RuleDocWithSystemScope> rules, BulkIndexer bulk) { | |||
while (rules.hasNext()) { | |||
RuleDoc rule = rules.next(); | |||
bulk.add(newIndexRequest(rule)); | |||
RuleDocWithSystemScope ruleWithExtension = rules.next(); | |||
bulk.add(newIndexRequest(ruleWithExtension.getRuleDoc())); | |||
bulk.add(newIndexRequest(ruleWithExtension.getRuleExtensionDoc())); | |||
} | |||
bulk.stop(); | |||
} | |||
private BulkIndexer createBulkIndexer(Size size) { | |||
BulkIndexer bulk = new BulkIndexer(esClient, INDEX_TYPE_RULE.getIndex()); | |||
bulk.setSize(size); | |||
return bulk; | |||
private static void doIndexRuleExtensions(Iterator<RuleExtensionDoc> metadatas, BulkIndexer bulk) { | |||
while (metadatas.hasNext()) { | |||
RuleExtensionDoc metadata = metadatas.next(); | |||
bulk.add(newIndexRequest(metadata)); | |||
} | |||
} | |||
private static IndexRequest newIndexRequest(RuleDoc rule) { | |||
return new IndexRequest(INDEX_TYPE_RULE.getIndex(), INDEX_TYPE_RULE.getType(), rule.key().toString()).source(rule.getFields()); | |||
} | |||
public void delete(RuleKey ruleKey) { | |||
esClient.prepareDelete(INDEX_TYPE_RULE, ruleKey.toString()) | |||
.setRefresh(true) | |||
.get(); | |||
} | |||
public void delete(List<RuleKey> rules) { | |||
BulkIndexer bulk = createBulkIndexer(Size.REGULAR); | |||
bulk.start(); | |||
for (RuleKey rule : rules) { | |||
bulk.addDeletion(INDEX_TYPE_RULE, rule.toString()); | |||
} | |||
bulk.stop(); | |||
private static IndexRequest newIndexRequest(RuleExtensionDoc ruleExtension) { | |||
return new IndexRequest(INDEX_TYPE_RULE_EXTENSION.getIndex(), INDEX_TYPE_RULE_EXTENSION.getType()) | |||
.source(ruleExtension.getFields()) | |||
.parent(ruleExtension.getParent()); | |||
} | |||
} |
@@ -21,7 +21,7 @@ package org.sonar.server.rule.index; | |||
import java.util.Iterator; | |||
public interface RuleIterator extends Iterator<RuleDoc>, AutoCloseable { | |||
public interface RuleIterator extends Iterator<RuleDocWithSystemScope>, AutoCloseable { | |||
@Override | |||
void close(); |
@@ -26,20 +26,17 @@ import java.util.NoSuchElementException; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.DatabaseUtils; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import static java.util.Optional.ofNullable; | |||
public class RuleIteratorForMultipleChunks implements RuleIterator { | |||
private final DbClient dbClient; | |||
private final OrganizationDto organization; | |||
private final Iterator<List<RuleKey>> iteratorOverChunks; | |||
private RuleIteratorForSingleChunk currentChunk; | |||
public RuleIteratorForMultipleChunks(DbClient dbClient, OrganizationDto organization, Collection<RuleKey> keys) { | |||
public RuleIteratorForMultipleChunks(DbClient dbClient, Collection<RuleKey> keys) { | |||
this.dbClient = dbClient; | |||
this.organization = organization; | |||
iteratorOverChunks = DatabaseUtils.toUniqueAndSortedPartitions(keys).iterator(); | |||
} | |||
@@ -58,7 +55,7 @@ public class RuleIteratorForMultipleChunks implements RuleIterator { | |||
} | |||
@Override | |||
public RuleDoc next() { | |||
public RuleDocWithSystemScope next() { | |||
for (;;) { | |||
if (currentChunk != null && currentChunk.hasNext()) { | |||
return currentChunk.next(); | |||
@@ -73,7 +70,7 @@ public class RuleIteratorForMultipleChunks implements RuleIterator { | |||
private RuleIteratorForSingleChunk nextChunk() { | |||
List<RuleKey> nextInput = iteratorOverChunks.next(); | |||
return new RuleIteratorForSingleChunk(dbClient, organization, nextInput); | |||
return new RuleIteratorForSingleChunk(dbClient, nextInput); | |||
} | |||
@Override |
@@ -21,7 +21,6 @@ package org.sonar.server.rule.index; | |||
import com.google.common.base.Splitter; | |||
import com.google.common.collect.ImmutableSet; | |||
import com.google.common.collect.Sets; | |||
import java.sql.PreparedStatement; | |||
import java.sql.ResultSet; | |||
import java.sql.SQLException; | |||
@@ -36,7 +35,6 @@ import org.sonar.db.DatabaseUtils; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.ResultSetIterator; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.SeverityUtil; | |||
import org.sonar.markdown.Markdown; | |||
@@ -59,11 +57,10 @@ public class RuleIteratorForSingleChunk implements RuleIterator { | |||
"r.priority", | |||
"r.status", | |||
"r.is_template", | |||
"rm.tags", | |||
"r.system_tags", | |||
"t.plugin_rule_key", | |||
// column 11 | |||
"t.plugin_rule_key", | |||
"t.plugin_name", | |||
"r.plugin_config_key", | |||
"r.language", | |||
@@ -73,23 +70,19 @@ public class RuleIteratorForSingleChunk implements RuleIterator { | |||
}; | |||
private static final String SQL_ALL = "SELECT " + StringUtils.join(FIELDS, ",") + " FROM rules r " + | |||
"LEFT OUTER JOIN rules t ON t.id=r.template_id " + | |||
"LEFT OUTER JOIN rules_metadata rm ON rm.rule_id = r.id and rm.organization_uuid=?"; | |||
"LEFT OUTER JOIN rules t ON t.id=r.template_id"; | |||
private static final Splitter TAGS_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings(); | |||
private final DbSession session; | |||
private final OrganizationDto organization; | |||
private final List<RuleKey> ruleKeys; | |||
private final PreparedStatement stmt; | |||
private final ResultSetIterator<RuleDoc> iterator; | |||
private final ResultSetIterator<RuleDocWithSystemScope> iterator; | |||
RuleIteratorForSingleChunk(DbClient dbClient, OrganizationDto organization, @Nullable List<RuleKey> ruleKeys) { | |||
RuleIteratorForSingleChunk(DbClient dbClient, @Nullable List<RuleKey> ruleKeys) { | |||
checkArgument(ruleKeys == null || ruleKeys.size() <= DatabaseUtils.PARTITION_SIZE_FOR_ORACLE, | |||
"Cannot search for more than " + DatabaseUtils.PARTITION_SIZE_FOR_ORACLE + " rule keys at once. Please provide the keys in smaller chunks."); | |||
this.organization = organization; | |||
this.ruleKeys = ruleKeys; | |||
this.session = dbClient.openSession(false); | |||
@@ -119,7 +112,7 @@ public class RuleIteratorForSingleChunk implements RuleIterator { | |||
} | |||
@Override | |||
public RuleDoc next() { | |||
public RuleDocWithSystemScope next() { | |||
return iterator.next(); | |||
} | |||
@@ -137,7 +130,6 @@ public class RuleIteratorForSingleChunk implements RuleIterator { | |||
private void setParameters(PreparedStatement stmt) throws SQLException { | |||
AtomicInteger index = new AtomicInteger(1); | |||
stmt.setString(index.getAndIncrement(), organization.getUuid()); | |||
if (ruleKeys != null && !ruleKeys.isEmpty()) { | |||
for (RuleKey ruleKey : ruleKeys) { | |||
stmt.setString(index.getAndIncrement(), ruleKey.repository()); | |||
@@ -156,19 +148,21 @@ public class RuleIteratorForSingleChunk implements RuleIterator { | |||
} | |||
} | |||
private static final class RuleIteratorInternal extends ResultSetIterator<RuleDoc> { | |||
private static final class RuleIteratorInternal extends ResultSetIterator<RuleDocWithSystemScope> { | |||
public RuleIteratorInternal(PreparedStatement stmt) throws SQLException { | |||
super(stmt); | |||
} | |||
@Override | |||
protected RuleDoc read(ResultSet rs) throws SQLException { | |||
protected RuleDocWithSystemScope read(ResultSet rs) throws SQLException { | |||
RuleDoc doc = new RuleDoc(); | |||
RuleExtensionDoc extensionDoc = new RuleExtensionDoc().setScope(RuleExtensionScope.system()); | |||
String ruleKey = rs.getString(1); | |||
String repositoryKey = rs.getString(2); | |||
RuleKey key = RuleKey.of(repositoryKey, ruleKey); | |||
extensionDoc.setRuleKey(key); | |||
// all the fields must be present, even if value is null | |||
doc.setKey(key.toString()); | |||
@@ -191,23 +185,23 @@ public class RuleIteratorForSingleChunk implements RuleIterator { | |||
doc.setSeverity(SeverityUtil.getSeverityFromOrdinal(rs.getInt(6))); | |||
doc.setStatus(rs.getString(7)); | |||
doc.setIsTemplate(rs.getBoolean(8)); | |||
doc.setAllTags(Sets.union(stringTagsToSet(rs.getString(9)), stringTagsToSet(rs.getString(10)))); | |||
extensionDoc.setTags(stringTagsToSet(rs.getString(9))); | |||
String templateRuleKey = rs.getString(11); | |||
String templateRepoKey = rs.getString(12); | |||
String templateRuleKey = rs.getString(10); | |||
String templateRepoKey = rs.getString(11); | |||
if (templateRepoKey != null && templateRuleKey != null) { | |||
doc.setTemplateKey(RuleKey.of(templateRepoKey, templateRuleKey).toString()); | |||
} else { | |||
doc.setTemplateKey(null); | |||
} | |||
doc.setInternalKey(rs.getString(13)); | |||
doc.setLanguage(rs.getString(14)); | |||
doc.setType(RuleType.valueOf(rs.getInt(15))); | |||
doc.setCreatedAt(rs.getLong(16)); | |||
doc.setUpdatedAt(rs.getLong(17)); | |||
doc.setInternalKey(rs.getString(12)); | |||
doc.setLanguage(rs.getString(13)); | |||
doc.setType(RuleType.valueOf(rs.getInt(14))); | |||
doc.setCreatedAt(rs.getLong(15)); | |||
doc.setUpdatedAt(rs.getLong(16)); | |||
return doc; | |||
return new RuleDocWithSystemScope(doc, extensionDoc); | |||
} | |||
private static Set<String> stringTagsToSet(@Nullable String tags) { |
@@ -0,0 +1,126 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.rule.index; | |||
import com.google.common.base.Splitter; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.sql.PreparedStatement; | |||
import java.sql.ResultSet; | |||
import java.sql.SQLException; | |||
import java.util.Iterator; | |||
import java.util.Set; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.DatabaseUtils; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.ResultSetIterator; | |||
/** | |||
* Scrolls over table RULES_METADATA and reads documents to populate the rule extension index type | |||
*/ | |||
public class RuleMetadataIterator implements Iterator<RuleExtensionDoc>, AutoCloseable { | |||
private static final String[] FIELDS = { | |||
"r.plugin_name", | |||
"r.plugin_rule_key", | |||
"rm.organization_uuid", | |||
"rm.tags" | |||
}; | |||
private static final String SQL_ALL = "SELECT " + StringUtils.join(FIELDS, ",") + " FROM rules r " + | |||
"INNER JOIN rules_metadata rm ON rm.rule_id = r.id " + | |||
"WHERE rm.tags is not null AND rm.tags != ''"; | |||
private static final Splitter TAGS_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings(); | |||
private final DbSession session; | |||
private final PreparedStatement stmt; | |||
private final ResultSetIterator<RuleExtensionDoc> iterator; | |||
RuleMetadataIterator(DbClient dbClient) { | |||
this.session = dbClient.openSession(false); | |||
try { | |||
String sql = SQL_ALL; | |||
stmt = dbClient.getMyBatis().newScrollingSelectStatement(session, sql); | |||
iterator = createIterator(); | |||
} catch (Exception e) { | |||
session.close(); | |||
throw new IllegalStateException("Fail to prepare SQL request to select all rules", e); | |||
} | |||
} | |||
private RuleMetadataIteratorInternal createIterator() { | |||
try { | |||
return new RuleMetadataIteratorInternal(stmt); | |||
} catch (SQLException e) { | |||
DatabaseUtils.closeQuietly(stmt); | |||
throw new IllegalStateException("Fail to prepare SQL request to select all rules", e); | |||
} | |||
} | |||
@Override | |||
public boolean hasNext() { | |||
return iterator.hasNext(); | |||
} | |||
@Override | |||
public RuleExtensionDoc next() { | |||
return iterator.next(); | |||
} | |||
@Override | |||
public void close() { | |||
try { | |||
iterator.close(); | |||
} finally { | |||
DatabaseUtils.closeQuietly(stmt); | |||
session.close(); | |||
} | |||
} | |||
private static final class RuleMetadataIteratorInternal extends ResultSetIterator<RuleExtensionDoc> { | |||
public RuleMetadataIteratorInternal(PreparedStatement stmt) throws SQLException { | |||
super(stmt); | |||
} | |||
@Override | |||
protected RuleExtensionDoc read(ResultSet rs) throws SQLException { | |||
RuleExtensionDoc doc = new RuleExtensionDoc(); | |||
String ruleKey = rs.getString(1); | |||
String repositoryKey = rs.getString(2); | |||
RuleKey key = RuleKey.of(repositoryKey, ruleKey); | |||
doc.setRuleKey(key); | |||
doc.setScope(RuleExtensionScope.organization(rs.getString(3))); | |||
doc.setTags(stringTagsToSet(rs.getString(4))); | |||
return doc; | |||
} | |||
private static Set<String> stringTagsToSet(@Nullable String tags) { | |||
return ImmutableSet.copyOf(TAGS_SPLITTER.split(tags == null ? "" : tags)); | |||
} | |||
} | |||
} |
@@ -50,6 +50,7 @@ public class RuleQuery { | |||
private boolean ascendingSort = true; | |||
private String internalKey; | |||
private String ruleKey; | |||
private String organizationUuid; | |||
@CheckForNull | |||
public String getQProfileKey() { | |||
@@ -258,4 +259,14 @@ public class RuleQuery { | |||
public String getRuleKey() { | |||
return ruleKey; | |||
} | |||
@CheckForNull | |||
public String getOrganizationUuid() { | |||
return organizationUuid; | |||
} | |||
public RuleQuery setOrganizationUuid(@Nullable String organizationUuid) { | |||
this.organizationUuid = organizationUuid; | |||
return this; | |||
} | |||
} |
@@ -20,22 +20,34 @@ | |||
package org.sonar.server.rule.ws; | |||
import com.google.common.io.Resources; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.api.server.ws.WebService.NewAction; | |||
import org.sonar.api.server.ws.WebService.Param; | |||
import org.sonar.api.utils.text.JsonWriter; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.ws.WsUtils; | |||
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION; | |||
public class TagsAction implements RulesWsAction { | |||
private final RuleIndex ruleIndex; | |||
private final DbClient dbClient; | |||
private final DefaultOrganizationProvider defaultOrganizationProvider; | |||
public TagsAction(RuleIndex ruleIndex) { | |||
public TagsAction(RuleIndex ruleIndex, DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider) { | |||
this.ruleIndex = ruleIndex; | |||
this.dbClient = dbClient; | |||
this.defaultOrganizationProvider = defaultOrganizationProvider; | |||
} | |||
@Override | |||
@@ -54,18 +66,41 @@ public class TagsAction implements RulesWsAction { | |||
.setDescription("The size of the list to return, 0 for all tags") | |||
.setExampleValue("25") | |||
.setDefaultValue("0"); | |||
action | |||
.createParam(PARAM_ORGANIZATION) | |||
.setDescription("Organization key") | |||
.setRequired(false) | |||
.setInternal(true) | |||
.setExampleValue("my-org") | |||
.setSince("6.4"); | |||
} | |||
@Override | |||
public void handle(Request request, Response response) { | |||
OrganizationDto organization = getOrganization(request.param(PARAM_ORGANIZATION)); | |||
String query = request.param(Param.TEXT_QUERY); | |||
int pageSize = request.mandatoryParamAsInt("ps"); | |||
Set<String> tags = ruleIndex.terms(RuleIndexDefinition.FIELD_RULE_ALL_TAGS, query, pageSize); | |||
Set<String> tags = ruleIndex.listTags(organization.getUuid(), query, pageSize == 0 ? Integer.MAX_VALUE : pageSize); | |||
writeResponse(response, tags); | |||
} | |||
private OrganizationDto getOrganization(@Nullable String organizationKey) { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
String organizationOrDefaultKey = Optional.ofNullable(organizationKey) | |||
.orElseGet(defaultOrganizationProvider.get()::getKey); | |||
return WsUtils.checkFoundWithOptional( | |||
dbClient.organizationDao().selectByKey(dbSession, organizationOrDefaultKey), | |||
"No organization with key '%s'", organizationOrDefaultKey); | |||
} | |||
} | |||
private static void writeResponse(Response response, Set<String> tags) { | |||
JsonWriter json = response.newJsonWriter().beginObject(); | |||
json.name("tags").beginArray(); | |||
for (String tag : tags) { | |||
json.value(tag); | |||
} | |||
tags.forEach(json::value); | |||
json.endArray().endObject().close(); | |||
} | |||
} |
@@ -35,7 +35,7 @@ import org.sonar.db.component.SnapshotDto; | |||
import org.sonar.db.component.SnapshotTesting; | |||
import org.sonar.db.issue.IssueDto; | |||
import org.sonar.db.issue.IssueTesting; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
import org.sonar.server.es.ProjectIndexer; | |||
@@ -131,9 +131,9 @@ public class ComponentCleanerServiceTest { | |||
String suffix = String.valueOf(id); | |||
ComponentDto project = newProjectDto(db.organizations().insert(), "project-uuid-" + suffix) | |||
.setKey("project-key-" + suffix); | |||
RuleDto rule = RuleTesting.newDto(RuleKey.of("sonarqube", "rule-" + suffix)); | |||
dbClient.ruleDao().insert(dbSession, rule.getDefinition()); | |||
IssueDto issue = IssueTesting.newDto(rule, project, project).setKee("issue-key-" + suffix).setUpdatedAt(new Date().getTime()); | |||
RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("sonarqube", "rule-" + suffix)); | |||
dbClient.ruleDao().insert(dbSession, rule); | |||
IssueDto issue = IssueTesting.newIssue(rule, project, project).setKee("issue-key-" + suffix).setUpdatedAt(new Date().getTime()); | |||
dbClient.componentDao().insert(dbSession, project); | |||
SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, SnapshotTesting.newAnalysis(project)); | |||
dbClient.issueDao().insert(dbSession, issue); |
@@ -39,7 +39,7 @@ import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.issue.IssueDto; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
import org.sonar.scanner.protocol.output.ScannerReport; | |||
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule; | |||
@@ -95,8 +95,8 @@ public class PersistIssuesStepTest extends BaseStepTest { | |||
@Test | |||
public void insert_new_issue() { | |||
RuleDto rule = RuleTesting.newDto(RuleKey.of("xoo", "S01")); | |||
dbTester.rules().insertRule(rule); | |||
RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01")); | |||
dbTester.rules().insert(rule); | |||
OrganizationDto organizationDto = dbTester.organizations().insert(); | |||
ComponentDto project = ComponentTesting.newProjectDto(organizationDto); | |||
dbClient.componentDao().insert(session, project); |
@@ -47,7 +47,6 @@ import org.sonar.server.es.SearchResult; | |||
import org.sonar.server.issue.index.IssueDoc; | |||
import org.sonar.server.issue.index.IssueIndex; | |||
import org.sonar.server.issue.index.IssueIndexer; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import org.sonar.server.permission.GroupPermissionChange; | |||
import org.sonar.server.permission.PermissionChange; | |||
import org.sonar.server.permission.PermissionUpdater; | |||
@@ -74,7 +73,6 @@ public class IssueServiceMediumTest { | |||
private DbSession session; | |||
private IssueService service; | |||
private RuleIndexer ruleIndexer; | |||
private OrganizationDto defaultOrganization; | |||
@Before | |||
public void setUp() { | |||
@@ -83,9 +81,6 @@ public class IssueServiceMediumTest { | |||
session = db.openSession(false); | |||
service = tester.get(IssueService.class); | |||
ruleIndexer = tester.get(RuleIndexer.class); | |||
String defaultOrganizationUuid = tester.get(DefaultOrganizationProvider.class).get().getUuid(); | |||
defaultOrganization = db.organizationDao().selectByUuid(session, defaultOrganizationUuid) | |||
.orElseThrow(() -> new IllegalStateException(String.format("Could not find defautl organization '%s'", defaultOrganizationUuid))); | |||
} | |||
@After | |||
@@ -95,7 +90,7 @@ public class IssueServiceMediumTest { | |||
@Test | |||
public void set_tags() { | |||
RuleDto rule = newRule(defaultOrganization); | |||
RuleDto rule = newRule(); | |||
ComponentDto project = newProject(); | |||
ComponentDto file = newFile(project); | |||
userSessionRule.logIn("john").addProjectUuidPermissions(UserRole.USER, project.uuid()); | |||
@@ -130,7 +125,7 @@ public class IssueServiceMediumTest { | |||
@Test | |||
public void list_component_tags() { | |||
RuleDto rule = newRule(defaultOrganization); | |||
RuleDto rule = newRule(); | |||
ComponentDto project = newProject(); | |||
ComponentDto file = newFile(project); | |||
saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "java8", "bug"))); | |||
@@ -150,7 +145,7 @@ public class IssueServiceMediumTest { | |||
@Test | |||
public void test_listAuthors() { | |||
RuleDto rule = newRule(defaultOrganization); | |||
RuleDto rule = newRule(); | |||
ComponentDto project = newProject(); | |||
ComponentDto file = newFile(project); | |||
saveIssue(IssueTesting.newDto(rule, file, project).setAuthorLogin("luke.skywalker")); | |||
@@ -167,7 +162,7 @@ public class IssueServiceMediumTest { | |||
@Test | |||
public void listAuthors_escapes_regexp_special_characters() { | |||
saveIssue(IssueTesting.newDto(newRule(defaultOrganization), newFile(newProject()), newProject()).setAuthorLogin("name++")); | |||
saveIssue(IssueTesting.newDto(newRule(), newFile(newProject()), newProject()).setAuthorLogin("name++")); | |||
assertThat(service.listAuthors("invalidRegexp[", 5)).isEmpty(); | |||
assertThat(service.listAuthors("nam+", 5)).isEmpty(); | |||
@@ -175,18 +170,18 @@ public class IssueServiceMediumTest { | |||
assertThat(service.listAuthors(".*", 5)).isEmpty(); | |||
} | |||
private RuleDto newRule(OrganizationDto organization) { | |||
return newRule(organization, RuleTesting.newXooX1()); | |||
private RuleDto newRule() { | |||
return newRule(RuleTesting.newXooX1()); | |||
} | |||
private RuleDto newRule(OrganizationDto organization, RuleDto rule) { | |||
private RuleDto newRule(RuleDto rule) { | |||
RuleDao ruleDao = tester.get(RuleDao.class); | |||
ruleDao.insert(session, rule.getDefinition()); | |||
if (rule.getOrganizationUuid() != null) { | |||
ruleDao.insertOrUpdate(session, rule.getMetadata().setRuleId(rule.getId())); | |||
} | |||
session.commit(); | |||
ruleIndexer.index(organization, rule.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule.getDefinition().getKey()); | |||
return rule; | |||
} | |||
@@ -21,10 +21,9 @@ package org.sonar.server.issue; | |||
import com.google.common.collect.HashMultiset; | |||
import com.google.common.collect.Multiset; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.rule.RuleDto; | |||
import java.util.Collection; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
public class RulesAggregation { | |||
@@ -34,7 +33,7 @@ public class RulesAggregation { | |||
this.rules = HashMultiset.create(); | |||
} | |||
public RulesAggregation add(RuleDto ruleDto) { | |||
public RulesAggregation add(RuleDefinitionDto ruleDto) { | |||
rules.add(new Rule(ruleDto.getKey(), ruleDto.getName())); | |||
return this; | |||
} |
@@ -21,7 +21,7 @@ package org.sonar.server.issue; | |||
import org.junit.Test; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -38,7 +38,7 @@ public class RulesAggregationTest { | |||
public void count_rules() { | |||
RulesAggregation rulesAggregation = new RulesAggregation(); | |||
RuleKey ruleKey = RuleKey.of("xoo", "S001"); | |||
RuleDto ruleDto = RuleTesting.newDto(ruleKey).setName("Rule name"); | |||
RuleDefinitionDto ruleDto = RuleTesting.newRule(ruleKey).setName("Rule name"); | |||
rulesAggregation.add(ruleDto); | |||
rulesAggregation.add(ruleDto); | |||
@@ -53,10 +53,10 @@ public class RulesAggregationTest { | |||
public void count_rules_with_different_rules() { | |||
RulesAggregation rulesAggregation = new RulesAggregation(); | |||
RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("xoo", "S001")).setName("Rule name 1"); | |||
RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("xoo", "S001")).setName("Rule name 1"); | |||
rulesAggregation.add(ruleDto); | |||
rulesAggregation.add(ruleDto); | |||
rulesAggregation.add(RuleTesting.newDto(RuleKey.of("xoo", "S002")).setName("Rule name 2")); | |||
rulesAggregation.add(RuleTesting.newRule(RuleKey.of("xoo", "S002")).setName("Rule name 2")); | |||
assertThat(rulesAggregation.rules()).hasSize(2); | |||
} |
@@ -20,7 +20,6 @@ | |||
package org.sonar.server.issue.index; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.google.common.collect.ImmutableSet; | |||
import com.google.common.collect.Iterators; | |||
import com.google.common.collect.Lists; | |||
import java.util.Date; | |||
@@ -40,9 +39,11 @@ import org.sonar.api.rule.Severity; | |||
import org.sonar.api.utils.Duration; | |||
import org.sonar.api.utils.KeyValueFormat; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.user.GroupDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.es.EsTester; | |||
@@ -52,8 +53,6 @@ import org.sonar.server.issue.IssueQuery; | |||
import org.sonar.server.permission.index.AuthorizationTypeSupport; | |||
import org.sonar.server.permission.index.PermissionIndexerDao; | |||
import org.sonar.server.permission.index.PermissionIndexerTester; | |||
import org.sonar.server.rule.index.RuleDoc; | |||
import org.sonar.server.rule.index.RuleDocTesting; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.rule.index.RuleIndexer; | |||
import org.sonar.server.tester.UserSessionRule; | |||
@@ -61,6 +60,7 @@ import org.sonar.server.view.index.ViewDoc; | |||
import org.sonar.server.view.index.ViewIndexDefinition; | |||
import org.sonar.server.view.index.ViewIndexer; | |||
import static com.google.common.collect.ImmutableSet.of; | |||
import static com.google.common.collect.Lists.newArrayList; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -73,8 +73,6 @@ import static org.sonar.api.utils.DateUtils.parseDateTime; | |||
import static org.sonar.db.component.ComponentTesting.newFileDto; | |||
import static org.sonar.db.component.ComponentTesting.newProjectDto; | |||
import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; | |||
import static org.sonar.db.rule.RuleTesting.XOO_X1; | |||
import static org.sonar.db.rule.RuleTesting.XOO_X2; | |||
import static org.sonar.db.user.GroupTesting.newGroupDto; | |||
import static org.sonar.db.user.UserTesting.newUserDto; | |||
import static org.sonar.server.issue.IssueDocTesting.newDoc; | |||
@@ -89,16 +87,19 @@ public class IssueIndexTest { | |||
new ViewIndexDefinition(new MapSettings()), | |||
new RuleIndexDefinition(new MapSettings())); | |||
@Rule | |||
public DbTester db = DbTester.create(system2); | |||
@Rule | |||
public UserSessionRule userSessionRule = UserSessionRule.standalone(); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private IssueIndexer issueIndexer = new IssueIndexer(tester.client(), new IssueIteratorFactory(null)); | |||
private ViewIndexer viewIndexer = new ViewIndexer(null, tester.client()); | |||
private RuleIndexer ruleIndexer = new RuleIndexer(tester.client(), null, null, null); | |||
private RuleIndexer ruleIndexer = new RuleIndexer(tester.client(), db.getDbClient()); | |||
private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(tester, issueIndexer); | |||
private IssueIndex underTest = new IssueIndex(tester.client(), system2, userSessionRule, new AuthorizationTypeSupport(userSessionRule)); | |||
private IssueIndex underTest = new IssueIndex(tester.client(), system2, userSessionRule, new AuthorizationTypeSupport(userSessionRule) | |||
); | |||
@Before | |||
public void setUp() { | |||
@@ -1326,24 +1327,27 @@ public class IssueIndexTest { | |||
@Test | |||
public void list_tags() { | |||
indexRules( | |||
RuleDocTesting.newDoc(XOO_X1).setAllTags(asList("tag1", "systag1")), | |||
RuleDocTesting.newDoc(XOO_X2).setAllTags(asList("tag2", "systag2"))); | |||
RuleDefinitionDto r1 = db.rules().insert(); | |||
ruleIndexer.indexRuleDefinition(r1.getKey()); | |||
RuleDefinitionDto r2 = db.rules().insert(); | |||
ruleIndexer.indexRuleDefinition(r2.getKey()); | |||
OrganizationDto org = db.organizations().insert(); | |||
ComponentDto project = newProjectDto(newOrganizationDto()); | |||
ComponentDto file = newFileDto(project, null); | |||
indexIssues( | |||
newDoc("ISSUE1", file).setRuleKey(XOO_X1.toString()).setTags(ImmutableSet.of("convention", "java8", "bug")), | |||
newDoc("ISSUE2", file).setRuleKey(XOO_X1.toString()).setTags(ImmutableSet.of("convention", "bug")), | |||
newDoc("ISSUE3", file).setRuleKey(XOO_X2.toString()), | |||
newDoc("ISSUE4", file).setRuleKey(XOO_X1.toString()).setTags(ImmutableSet.of("convention"))); | |||
newDoc("ISSUE1", file).setOrganizationUuid(org.getUuid()).setRuleKey(r1.getKey().toString()).setTags(of("convention", "java8", "bug")), | |||
newDoc("ISSUE2", file).setOrganizationUuid(org.getUuid()).setRuleKey(r1.getKey().toString()).setTags(of("convention", "bug")), | |||
newDoc("ISSUE3", file).setOrganizationUuid(org.getUuid()).setRuleKey(r2.getKey().toString()), | |||
newDoc("ISSUE4", file).setOrganizationUuid(org.getUuid()).setRuleKey(r1.getKey().toString()).setTags(of("convention"))); | |||
assertThat(underTest.listTags(null, 5)).containsOnly("convention", "java8", "bug", "systag1", "systag2"); | |||
assertThat(underTest.listTags(null, 2)).containsOnly("bug", "convention"); | |||
assertThat(underTest.listTags("vent", 5)).containsOnly("convention"); | |||
assertThat(underTest.listTags("sys", 5)).containsOnly("systag1", "systag2"); | |||
assertThat(underTest.listTags(null, 1)).containsOnly("bug"); | |||
assertThat(underTest.listTags(null, Integer.MAX_VALUE)).containsOnly("convention", "java8", "bug", "systag1", "systag2", "tag1", "tag2"); | |||
assertThat(underTest.listTags("invalidRegexp[", 5)).isEmpty(); | |||
assertThat(underTest.listTags(org.getUuid(), null, Integer.MAX_VALUE)).containsOnly("convention", "java8", "bug"); | |||
assertThat(underTest.listTags(org.getUuid(), null, 2)).containsOnly("bug", "convention"); | |||
assertThat(underTest.listTags(org.getUuid(), "vent", Integer.MAX_VALUE)).containsOnly("convention"); | |||
assertThat(underTest.listTags(org.getUuid(), null, 1)).containsOnly("bug"); | |||
assertThat(underTest.listTags(org.getUuid(), null, Integer.MAX_VALUE)).containsOnly("convention", "java8", "bug"); | |||
assertThat(underTest.listTags(org.getUuid(), "invalidRegexp[", Integer.MAX_VALUE)).isEmpty(); | |||
} | |||
@Test | |||
@@ -1405,8 +1409,4 @@ public class IssueIndexTest { | |||
private void indexView(String viewUuid, List<String> projects) { | |||
viewIndexer.index(new ViewDoc().setUuid(viewUuid).setProjects(projects)); | |||
} | |||
private void indexRules(RuleDoc... rules) { | |||
ruleIndexer.index(asList(rules).iterator()); | |||
} | |||
} |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonar.server.issue.ws; | |||
import com.google.common.collect.ImmutableSet; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
@@ -32,25 +31,26 @@ import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.issue.IssueDto; | |||
import org.sonar.db.issue.IssueTesting; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.issue.index.IssueIndex; | |||
import org.sonar.server.issue.index.IssueIndexDefinition; | |||
import org.sonar.server.issue.index.IssueIndexer; | |||
import org.sonar.server.issue.index.IssueIteratorFactory; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.permission.index.AuthorizationTypeSupport; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.rule.index.RuleIndexer; | |||
import org.sonar.server.rule.index.RuleIteratorFactory; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.WsActionTester; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.emptySet; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.api.web.UserRole.USER; | |||
import static org.sonar.db.component.ComponentTesting.newFileDto; | |||
import static org.sonar.db.rule.RuleTesting.newRuleDto; | |||
import static org.sonar.db.rule.RuleTesting.setSystemTags; | |||
import static org.sonar.db.rule.RuleTesting.setTags; | |||
import static org.sonar.test.JsonAssert.assertJson; | |||
public class TagsActionTest { | |||
@@ -63,10 +63,11 @@ public class TagsActionTest { | |||
public EsTester es = new EsTester(new IssueIndexDefinition(new MapSettings()), new RuleIndexDefinition(new MapSettings())); | |||
private IssueIndexer issueIndexer = new IssueIndexer(es.client(), new IssueIteratorFactory(db.getDbClient())); | |||
private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), null, new RuleIteratorFactory(db.getDbClient()), null); | |||
private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient()); | |||
private IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSession, new AuthorizationTypeSupport(userSession)); | |||
private RuleIndex ruleIndex = new RuleIndex(es.client()); | |||
private WsActionTester tester = new WsActionTester(new TagsAction(issueIndex)); | |||
private WsActionTester tester = new WsActionTester(new TagsAction(issueIndex, ruleIndex, TestDefaultOrganizationProvider.from(db))); | |||
private OrganizationDto organization; | |||
@Before | |||
@@ -86,10 +87,15 @@ public class TagsActionTest { | |||
@Test | |||
public void return_tags_from_rules() throws Exception { | |||
RuleDto r = db.rules().insertRule(organization, rule -> rule.setSystemTags(ImmutableSet.of("tag1")), rule -> rule.setTags(ImmutableSet.of("tag2"))); | |||
RuleDto r2 = db.rules().insertRule(organization, rule -> rule.setSystemTags(ImmutableSet.of("tag3")), rule -> rule.setTags(ImmutableSet.of("tag4", "tag5"))); | |||
db.commit(); | |||
ruleIndexer.index(organization, asList(r.getKey(), r2.getKey())); | |||
RuleDefinitionDto r = db.rules().insert(setSystemTags("tag1")); | |||
ruleIndexer.indexRuleDefinition(r.getKey()); | |||
db.rules().insertOrUpdateMetadata(r, organization, setTags("tag2")); | |||
ruleIndexer.indexRuleExtension(organization, r.getKey()); | |||
RuleDefinitionDto r2 = db.rules().insert(setSystemTags("tag3")); | |||
ruleIndexer.indexRuleDefinition(r2.getKey()); | |||
db.rules().insertOrUpdateMetadata(r2, organization, setTags("tag4", "tag5")); | |||
ruleIndexer.indexRuleExtension(organization, r2.getKey()); | |||
String result = tester.newRequest().execute().getInput(); | |||
assertJson(result).isSimilarTo("{\"tags\":[\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]}"); | |||
@@ -100,8 +106,11 @@ public class TagsActionTest { | |||
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag1", "tag2"); | |||
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag3", "tag4", "tag5"); | |||
issueIndexer.indexOnStartup(null); | |||
RuleDto r = db.rules().insertRule(db.getDefaultOrganization(), rule -> rule.setSystemTags(ImmutableSet.of("tag6")).setTags(ImmutableSet.of("tag7"))); | |||
ruleIndexer.index(organization, r.getKey()); | |||
RuleDefinitionDto r = db.rules().insert(setSystemTags("tag6")); | |||
ruleIndexer.indexRuleDefinition(r.getKey()); | |||
db.rules().insertOrUpdateMetadata(r, organization, setTags("tag7")); | |||
ruleIndexer.indexRuleExtension(organization, r.getKey()); | |||
String result = tester.newRequest().execute().getInput(); | |||
assertJson(result).isSimilarTo("{\"tags\":[\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\", \"tag6\", \"tag7\"]}"); | |||
@@ -137,8 +146,11 @@ public class TagsActionTest { | |||
public void test_example() throws Exception { | |||
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "convention"); | |||
issueIndexer.indexOnStartup(null); | |||
RuleDto r = db.rules().insertRule(db.getDefaultOrganization(), rule -> rule.setSystemTags(ImmutableSet.of("cwe")).setTags(ImmutableSet.of("security"))); | |||
ruleIndexer.index(organization, r.getKey()); | |||
RuleDefinitionDto r = db.rules().insert(setSystemTags("cwe")); | |||
ruleIndexer.indexRuleDefinition(r.getKey()); | |||
db.rules().insertOrUpdateMetadata(r, organization, setTags("security")); | |||
ruleIndexer.indexRuleExtension(organization, r.getKey()); | |||
String result = tester.newRequest().execute().getInput(); | |||
assertJson(result).isSimilarTo(tester.getDef().responseExampleAsString()); | |||
@@ -154,27 +166,27 @@ public class TagsActionTest { | |||
assertThat(action.params()).hasSize(2); | |||
Param query = action.param("q"); | |||
assertThat(query).isNotNull(); | |||
assertThat(query.isRequired()).isFalse(); | |||
assertThat(query.description()).isNotEmpty(); | |||
assertThat(query.exampleValue()).isNotEmpty(); | |||
Param pageSize = action.param("ps"); | |||
assertThat(pageSize).isNotNull(); | |||
assertThat(pageSize.isRequired()).isFalse(); | |||
assertThat(pageSize.defaultValue()).isEqualTo("10"); | |||
assertThat(pageSize.description()).isNotEmpty(); | |||
assertThat(pageSize.exampleValue()).isNotEmpty(); | |||
} | |||
private RuleDto insertRuleWithoutTags() { | |||
RuleDto ruleDto = newRuleDto(db.getDefaultOrganization()).setTags(emptySet()).setSystemTags(emptySet()); | |||
db.rules().insertRule(ruleDto); | |||
return ruleDto; | |||
private RuleDefinitionDto insertRuleWithoutTags() { | |||
return db.rules().insert(setSystemTags()); | |||
} | |||
private IssueDto insertIssue(RuleDto rule, String... tags) { | |||
private IssueDto insertIssue(RuleDefinitionDto rule, String... tags) { | |||
ComponentDto project = db.components().insertProject(organization); | |||
ComponentDto file = db.components().insertComponent(newFileDto(project)); | |||
IssueDto issueDto = IssueTesting.newDto(rule, file, project).setTags(asList(tags)); | |||
IssueDto issueDto = IssueTesting.newIssue(rule, file, project).setTags(asList(tags)); | |||
return db.issues().insertIssue(issueDto); | |||
} | |||
@@ -182,7 +194,7 @@ public class TagsActionTest { | |||
userSession.logIn("john").addProjectUuidPermissions(USER, issue.getProjectUuid()); | |||
} | |||
private IssueDto insertIssueWithBrowsePermission(RuleDto rule, String... tags) { | |||
private IssueDto insertIssueWithBrowsePermission(RuleDefinitionDto rule, String... tags) { | |||
IssueDto issue = insertIssue(rule, tags); | |||
setUserWithBrowsePermission(issue); | |||
return issue; |
@@ -42,6 +42,7 @@ import org.sonar.db.qualityprofile.ActiveRuleDao; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.QualityProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
@@ -51,14 +52,13 @@ import org.sonar.server.rule.index.RuleQuery; | |||
import org.sonar.server.tester.ServerTester; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.junit.Assert.fail; | |||
import static org.sonar.db.qualityprofile.ActiveRuleDto.INHERITED; | |||
import static org.sonar.db.qualityprofile.ActiveRuleDto.OVERRIDES; | |||
import static org.sonar.db.rule.RuleTesting.XOO_X1; | |||
import static org.sonar.db.rule.RuleTesting.XOO_X2; | |||
import static org.sonar.db.rule.RuleTesting.newDto; | |||
import static org.sonar.db.rule.RuleTesting.newRule; | |||
import static org.sonar.db.rule.RuleTesting.newXooX1; | |||
import static org.sonar.db.rule.RuleTesting.newXooX2; | |||
import static org.sonar.server.qualityprofile.QProfileTesting.XOO_P1_KEY; | |||
@@ -94,16 +94,19 @@ public class QProfileBackuperMediumTest { | |||
// create pre-defined rules | |||
RuleDto xooRule1 = newXooX1().setSeverity("MINOR").setLanguage("xoo"); | |||
RuleDto xooRule2 = newXooX2().setSeverity("MAJOR").setLanguage("xoo"); | |||
db.ruleDao().insert(dbSession, xooRule1.getDefinition()); | |||
db.ruleDao().insert(dbSession, xooRule2.getDefinition()); | |||
db.ruleDao().insertRuleParam(dbSession, xooRule1.getDefinition(), RuleParamDto.createFor(xooRule1.getDefinition()) | |||
.setName("max").setDefaultValue("10").setType(RuleParamType.INTEGER.type())); | |||
dbSession.commit(); | |||
dbSession.clearCache(); | |||
ruleIndexer.indexRuleDefinition(xooRule1.getDefinition().getKey()); | |||
RuleDto xooRule2 = newXooX2().setSeverity("MAJOR").setLanguage("xoo"); | |||
db.ruleDao().insert(dbSession, xooRule2.getDefinition()); | |||
dbSession.commit(); | |||
ruleIndexer.indexRuleDefinition(xooRule2.getDefinition().getKey()); | |||
this.organization = OrganizationTesting.newOrganizationDto(); | |||
db.organizationDao().insert(dbSession, organization); | |||
ruleIndexer.index(organization, asList(xooRule1.getKey(), xooRule2.getKey())); | |||
} | |||
@After | |||
@@ -114,11 +117,10 @@ public class QProfileBackuperMediumTest { | |||
@Test | |||
public void backup() throws Exception { | |||
RuleKey blahRuleKey = RuleKey.of("blah", "my-rule"); | |||
RuleDto blahRule = newDto(blahRuleKey).setSeverity("INFO").setLanguage("xoo"); | |||
db.ruleDao().insert(dbSession, blahRule.getDefinition()); | |||
RuleDefinitionDto blahRule = newRule(blahRuleKey).setSeverity("INFO").setLanguage("xoo"); | |||
db.ruleDao().insert(dbSession, blahRule); | |||
dbSession.commit(); | |||
dbSession.clearCache(); | |||
ruleIndexer.index(organization, blahRuleKey); | |||
ruleIndexer.indexRuleDefinition(blahRule.getKey()); | |||
// create profile P1 with rules x2 and x1 activated | |||
QualityProfileDto profile = newXooP1(organization); |
@@ -36,6 +36,7 @@ import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.qualityprofile.QualityProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
@@ -46,7 +47,6 @@ import org.sonar.server.rule.index.RuleQuery; | |||
import org.sonar.server.tester.ServerTester; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.junit.Assert.fail; | |||
import static org.sonar.server.qualityprofile.QProfileTesting.getDefaultOrganization; | |||
@@ -80,17 +80,23 @@ public class QProfileCopierMediumTest { | |||
// create pre-defined rules | |||
RuleDto xooRule1 = RuleTesting.newXooX1().setSeverity("MINOR"); | |||
RuleDto xooRule2 = RuleTesting.newXooX2().setSeverity("MAJOR"); | |||
db.ruleDao().insert(dbSession, xooRule1.getDefinition()); | |||
db.ruleDao().insert(dbSession, xooRule2.getDefinition()); | |||
db.ruleDao().insertRuleParam(dbSession, xooRule1.getDefinition(), RuleParamDto.createFor(xooRule1.getDefinition()) | |||
RuleDefinitionDto xooRule1Definition = xooRule1.getDefinition(); | |||
db.ruleDao().insert(dbSession, xooRule1Definition); | |||
db.ruleDao().insertRuleParam(dbSession, xooRule1Definition, RuleParamDto.createFor(xooRule1Definition) | |||
.setName("max").setDefaultValue("10").setType(RuleParamType.INTEGER.type())); | |||
dbSession.commit(); | |||
ruleIndexer.indexRuleDefinition(xooRule1Definition.getKey()); | |||
RuleDto xooRule2 = RuleTesting.newXooX2().setSeverity("MAJOR"); | |||
RuleDefinitionDto xooRule2Definition = xooRule2.getDefinition(); | |||
db.ruleDao().insert(dbSession, xooRule2Definition); | |||
dbSession.commit(); | |||
ruleIndexer.indexRuleDefinition(xooRule2Definition.getKey()); | |||
// create pre-defined profile | |||
sourceProfile = QProfileTesting.newXooP1(organization); | |||
db.qualityProfileDao().insert(dbSession, sourceProfile); | |||
dbSession.commit(); | |||
ruleIndexer.index(organization, asList(xooRule1.getKey(), xooRule2.getKey())); | |||
} | |||
@After |
@@ -146,7 +146,7 @@ public class RuleActivatorMediumTest { | |||
// index all rules | |||
dbSession.commit(); | |||
ruleIndexer.index(organization, asList(javaRule, xooRule1, xooRule2, xooTemplateRule1, xooCustomRule1).stream().map(RuleDto::getKey).collect(Collectors.toList())); | |||
ruleIndexer.indexRuleDefinitions(asList(javaRule, xooRule1, xooRule2, xooTemplateRule1, xooCustomRule1).stream().map(RuleDto::getKey).collect(Collectors.toList())); | |||
} | |||
@After | |||
@@ -914,7 +914,7 @@ public class RuleActivatorMediumTest { | |||
keys.add(ruleDefinitionDto.getKey()); | |||
} | |||
dbSession.commit(); | |||
ruleIndexer.index(organization, keys); | |||
ruleIndexer.indexRuleDefinitions(keys); | |||
// 0. No active rules so far (base case) and plenty rules available | |||
verifyZeroActiveRules(XOO_P1_KEY); |
@@ -142,7 +142,7 @@ public class ActiveRuleIndexerTest { | |||
long now = 2000000L; | |||
// Index one active rule | |||
RuleDefinitionDto rule = RuleTesting.newDto(RULE_KEY_1).getDefinition(); | |||
RuleDefinitionDto rule = RuleTesting.newRule(RULE_KEY_1); | |||
dbTester.rules().insert(rule); | |||
QualityProfileDto profile = QualityProfileDto.createFor("qp") | |||
.setOrganizationUuid(organization.getUuid()) | |||
@@ -159,7 +159,7 @@ public class ActiveRuleIndexerTest { | |||
assertThat(esTester.getIds(INDEX_TYPE_ACTIVE_RULE)).containsOnly(activeRule.getKey().toString()); | |||
// Index another active rule | |||
RuleDefinitionDto rule2 = RuleTesting.newDto(RULE_KEY_2).getDefinition(); | |||
RuleDefinitionDto rule2 = RuleTesting.newRule(RULE_KEY_2); | |||
dbTester.rules().insert(rule2); | |||
ActiveRuleDto activeRule2 = ActiveRuleDto.createFor(profile, rule2).setSeverity(Severity.CRITICAL) | |||
.setCreatedAt(now).setUpdatedAt(now); |
@@ -42,7 +42,7 @@ import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.QualityProfileDto; | |||
import org.sonar.db.qualityprofile.QualityProfileTesting; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.EsTester; | |||
@@ -56,7 +56,6 @@ 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.rule.index.RuleIndexer; | |||
import org.sonar.server.rule.index.RuleIteratorFactory; | |||
import org.sonar.server.rule.index.RuleQuery; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.util.TypeValidations; | |||
@@ -105,10 +104,7 @@ public class ChangeParentActionTest { | |||
TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester); | |||
ruleIndexer = new RuleIndexer( | |||
esClient, | |||
null, | |||
new RuleIteratorFactory(dbClient), | |||
null | |||
); | |||
dbClient); | |||
activeRuleIndexer = new ActiveRuleIndexer( | |||
System2.INSTANCE, | |||
dbClient, | |||
@@ -160,9 +156,9 @@ public class ChangeParentActionTest { | |||
QualityProfileDto parent1 = createProfile(); | |||
QualityProfileDto child = createProfile(); | |||
RuleDto rule1 = createRule(); | |||
RuleDefinitionDto rule1 = createRule(); | |||
createActiveRule(rule1, parent1); | |||
ruleIndexer.index(organization, rule1.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule1.getKey()); | |||
activeRuleIndexer.index(); | |||
assertThat(dbClient.activeRuleDao().selectByProfileKey(dbSession, child.getKey())).isEmpty(); | |||
@@ -188,11 +184,11 @@ public class ChangeParentActionTest { | |||
QualityProfileDto parent2 = createProfile(); | |||
QualityProfileDto child = createProfile(); | |||
RuleDto rule1 = createRule(); | |||
RuleDto rule2 = createRule(); | |||
RuleDefinitionDto rule1 = createRule(); | |||
RuleDefinitionDto rule2 = createRule(); | |||
createActiveRule(rule1, parent1); | |||
createActiveRule(rule2, parent2); | |||
ruleIndexer.index(organization, Stream.of(rule1, rule2).map(RuleDto::getKey).collect(MoreCollectors.toList())); | |||
ruleIndexer.indexRuleDefinitions(Stream.of(rule1, rule2).map(RuleDefinitionDto::getKey).collect(MoreCollectors.toList())); | |||
activeRuleIndexer.index(); | |||
// Set parent 1 | |||
@@ -218,9 +214,9 @@ public class ChangeParentActionTest { | |||
QualityProfileDto parent = createProfile(); | |||
QualityProfileDto child = createProfile(); | |||
RuleDto rule1 = createRule(); | |||
RuleDefinitionDto rule1 = createRule(); | |||
createActiveRule(rule1, parent); | |||
ruleIndexer.index(organization, rule1.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule1.getKey()); | |||
activeRuleIndexer.index(); | |||
// Set parent | |||
@@ -245,11 +241,11 @@ public class ChangeParentActionTest { | |||
QualityProfileDto parent2 = createProfile(); | |||
QualityProfileDto child = createProfile(); | |||
RuleDto rule1 = createRule(); | |||
RuleDto rule2 = createRule(); | |||
RuleDefinitionDto rule1 = createRule(); | |||
RuleDefinitionDto rule2 = createRule(); | |||
createActiveRule(rule1, parent1); | |||
createActiveRule(rule2, parent2); | |||
ruleIndexer.index(organization, rule1.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule1.getKey()); | |||
activeRuleIndexer.index(); | |||
assertThat(dbClient.activeRuleDao().selectByProfileKey(dbSession, child.getKey())).isEmpty(); | |||
@@ -306,9 +302,9 @@ public class ChangeParentActionTest { | |||
QualityProfileDto parent = createProfile(); | |||
QualityProfileDto child = createProfile(); | |||
RuleDto rule1 = createRule(); | |||
RuleDefinitionDto rule1 = createRule(); | |||
createActiveRule(rule1, parent); | |||
ruleIndexer.index(organization, rule1.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule1.getKey()); | |||
activeRuleIndexer.index(); | |||
assertThat(dbClient.activeRuleDao().selectByProfileKey(dbSession, child.getKey())).isEmpty(); | |||
@@ -404,18 +400,18 @@ public class ChangeParentActionTest { | |||
return profile; | |||
} | |||
private RuleDto createRule() { | |||
RuleDto rule = RuleTesting.newDto(RuleKey.of(ruleRepository, randomAlphanumeric(5))) | |||
private RuleDefinitionDto createRule() { | |||
RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of(ruleRepository, randomAlphanumeric(5))) | |||
.setLanguage(language.getKey()) | |||
.setSeverity(Severity.BLOCKER) | |||
.setStatus(RuleStatus.READY); | |||
dbClient.ruleDao().insert(dbSession, rule.getDefinition()); | |||
dbClient.ruleDao().insert(dbSession, rule); | |||
dbSession.commit(); | |||
return rule; | |||
} | |||
private ActiveRuleDto createActiveRule(RuleDto rule, QualityProfileDto profile) { | |||
ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule.getDefinition()) | |||
private ActiveRuleDto createActiveRule(RuleDefinitionDto rule, QualityProfileDto profile) { | |||
ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule) | |||
.setSeverity(rule.getSeverityString()); | |||
dbClient.activeRuleDao().insert(dbSession, activeRule); | |||
dbSession.commit(); |
@@ -31,7 +31,7 @@ import org.sonar.db.DbTester; | |||
import org.sonar.db.qualityprofile.QProfileChangeDto; | |||
import org.sonar.db.qualityprofile.QProfileChangeQuery; | |||
import org.sonar.db.qualityprofile.QualityProfileTesting; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.db.user.UserTesting; | |||
@@ -159,8 +159,8 @@ public class ChangelogLoaderTest { | |||
} | |||
private void insertRule(RuleKey key, String name) { | |||
RuleDto dto = RuleTesting.newDto(key).setName(name); | |||
dbTester.rules().insertRule(dto); | |||
RuleDefinitionDto dto = RuleTesting.newRule(key).setName(name); | |||
dbTester.rules().insert(dto); | |||
dbTester.getSession().commit(); | |||
} | |||
@@ -55,7 +55,6 @@ 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.rule.index.RuleIndexer; | |||
import org.sonar.server.rule.index.RuleIteratorFactory; | |||
import org.sonar.server.rule.index.RuleQuery; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.TestRequest; | |||
@@ -94,7 +93,7 @@ public class CreateActionTest { | |||
private DbSession dbSession = dbTester.getSession(); | |||
private RuleIndex ruleIndex = new RuleIndex(esTester.client()); | |||
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester); | |||
private RuleIndexer ruleIndexer = new RuleIndexer(esTester.client(), null, new RuleIteratorFactory(dbClient), null); | |||
private RuleIndexer ruleIndexer = new RuleIndexer(esTester.client(), dbClient); | |||
private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(system2, dbClient, esTester.client()); | |||
private ProfileImporter[] profileImporters = createImporters(); | |||
private QProfileExporters qProfileExporters = new QProfileExporters(dbClient, null, | |||
@@ -243,7 +242,7 @@ public class CreateActionTest { | |||
private void insertRule(RuleDefinitionDto ruleDto) { | |||
dbClient.ruleDao().insert(dbSession, ruleDto); | |||
dbSession.commit(); | |||
ruleIndexer.index(organization, ruleDto.getKey()); | |||
ruleIndexer.indexRuleDefinition(ruleDto.getKey()); | |||
} | |||
private CreateWsResponse executeRequest(String name, String language) { |
@@ -37,7 +37,6 @@ import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.QualityProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.EsTester; | |||
@@ -53,14 +52,11 @@ 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.rule.index.RuleIndexer; | |||
import org.sonar.server.rule.index.RuleIteratorFactory; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.util.TypeValidations; | |||
import org.sonar.server.ws.WsActionTester; | |||
import org.sonar.test.JsonAssert; | |||
import static java.util.Arrays.asList; | |||
public class InheritanceActionTest { | |||
@Rule | |||
@@ -85,7 +81,7 @@ public class InheritanceActionTest { | |||
dbClient = dbTester.getDbClient(); | |||
dbSession = dbTester.getSession(); | |||
esClient = esTester.client(); | |||
ruleIndexer = new RuleIndexer(esClient, null, new RuleIteratorFactory(dbClient), null); | |||
ruleIndexer = new RuleIndexer(esClient, dbClient); | |||
activeRuleIndexer = new ActiveRuleIndexer(System2.INSTANCE, dbClient, esClient); | |||
TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester); | |||
underTest = new InheritanceAction( | |||
@@ -119,7 +115,6 @@ public class InheritanceActionTest { | |||
createActiveRule(rule2, groupWide); | |||
dbSession.commit(); | |||
ruleIndexer.index(organization, asList(rule1.getKey(), rule2.getKey(), rule3.getKey())); | |||
activeRuleIndexer.index(); | |||
QualityProfileDto companyWide = createProfile("xoo", "My Company Profile", "xoo-my-company-profile-12345"); | |||
@@ -181,14 +176,16 @@ public class InheritanceActionTest { | |||
private RuleDefinitionDto createRule(String lang, String id) { | |||
long now = new Date().getTime(); | |||
RuleDto rule = RuleTesting.newDto(RuleKey.of("blah", id)) | |||
RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("blah", id)) | |||
.setLanguage(lang) | |||
.setSeverity(Severity.BLOCKER) | |||
.setStatus(RuleStatus.READY) | |||
.setUpdatedAt(now) | |||
.setCreatedAt(now); | |||
dbClient.ruleDao().insert(dbSession, rule.getDefinition()); | |||
return rule.getDefinition(); | |||
dbClient.ruleDao().insert(dbSession, rule); | |||
dbSession.commit(); | |||
ruleIndexer.indexRuleDefinition(rule.getKey()); | |||
return rule; | |||
} | |||
private ActiveRuleDto createActiveRule(RuleDefinitionDto rule, QualityProfileDto profile) { |
@@ -39,7 +39,6 @@ import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.qualityprofile.QualityProfileDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
import org.sonar.server.es.SearchOptions; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
@@ -103,7 +102,7 @@ public class QProfilesWsMediumTest { | |||
RuleDefinitionDto rule = createRule(profile.getLanguage(), "toto"); | |||
createActiveRule(rule, profile); | |||
session.commit(); | |||
ruleIndexer.index(organization, rule.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule.getKey()); | |||
activeRuIndexer.index(); | |||
// 0. Assert No Active Rule for profile | |||
@@ -203,7 +202,7 @@ public class QProfilesWsMediumTest { | |||
QualityProfileDto profile = createProfile("java"); | |||
RuleDefinitionDto rule = createRule(profile.getLanguage(), "toto"); | |||
session.commit(); | |||
ruleIndexer.index(organization, rule.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule.getKey()); | |||
// 0. Assert No Active Rule for profile | |||
assertThat(db.activeRuleDao().selectByProfileKey(session, profile.getKey())).isEmpty(); | |||
@@ -224,7 +223,7 @@ public class QProfilesWsMediumTest { | |||
QualityProfileDto profile = createProfile("java"); | |||
RuleDefinitionDto rule = createRule("php", "toto"); | |||
session.commit(); | |||
ruleIndexer.index(organization, rule.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule.getKey()); | |||
// 0. Assert No Active Rule for profile | |||
assertThat(db.activeRuleDao().selectByProfileKey(session, profile.getKey())).isEmpty(); | |||
@@ -247,7 +246,7 @@ public class QProfilesWsMediumTest { | |||
QualityProfileDto profile = createProfile("java"); | |||
RuleDefinitionDto rule = createRule(profile.getLanguage(), "toto"); | |||
session.commit(); | |||
ruleIndexer.index(organization, rule.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule.getKey()); | |||
// 0. Assert No Active Rule for profile | |||
assertThat(db.activeRuleDao().selectByProfileKey(session, profile.getKey())).isEmpty(); | |||
@@ -439,14 +438,14 @@ public class QProfilesWsMediumTest { | |||
} | |||
private RuleDefinitionDto createRule(String lang, String id) { | |||
RuleDto rule = RuleTesting.newDto(RuleKey.of("blah", id)) | |||
RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("blah", id)) | |||
.setLanguage(lang) | |||
.setSeverity(Severity.BLOCKER) | |||
.setStatus(RuleStatus.READY); | |||
db.ruleDao().insert(session, rule.getDefinition()); | |||
db.ruleDao().insert(session, rule); | |||
session.commit(); | |||
ruleIndexer.index(organization, rule.getKey()); | |||
return rule.getDefinition(); | |||
ruleIndexer.indexRuleDefinition(rule.getKey()); | |||
return rule; | |||
} | |||
private ActiveRuleDto createActiveRule(RuleDefinitionDto rule, QualityProfileDto profile) { |
@@ -42,13 +42,11 @@ import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.db.rule.RuleRepositoryDto; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.es.SearchOptions; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
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.rule.index.RuleIndexer; | |||
import org.sonar.server.rule.index.RuleIteratorFactory; | |||
import org.sonar.server.rule.index.RuleQuery; | |||
import static com.google.common.collect.Sets.newHashSet; | |||
@@ -86,7 +84,7 @@ public class RegisterRulesTest { | |||
@Before | |||
public void before() { | |||
when(system.now()).thenReturn(DATE1.getTime()); | |||
ruleIndexer = new RuleIndexer(esTester.client(), null, new RuleIteratorFactory(dbClient), null); | |||
ruleIndexer = new RuleIndexer(esTester.client(), dbClient); | |||
ruleIndex = new RuleIndex(esTester.client()); | |||
activeRuleIndexer = new ActiveRuleIndexer(system, dbClient, esTester.client()); | |||
} | |||
@@ -124,6 +122,7 @@ public class RegisterRulesTest { | |||
// verify repositories | |||
assertThat(dbClient.ruleRepositoryDao().selectAll(dbTester.getSession())).extracting(RuleRepositoryDto::getKey).containsOnly("fake"); | |||
} | |||
@Test | |||
public void insert_then_remove_rule() { | |||
String ruleKey = randomAlphanumeric(5); | |||
@@ -457,7 +456,7 @@ public class RegisterRulesTest { | |||
Languages languages = mock(Languages.class); | |||
when(languages.get("java")).thenReturn(mock(Language.class)); | |||
RegisterRules task = new RegisterRules(loader, ruleActivator, dbClient, ruleIndexer, activeRuleIndexer, languages, system, TestDefaultOrganizationProvider.from(dbTester)); | |||
RegisterRules task = new RegisterRules(loader, ruleActivator, dbClient, ruleIndexer, activeRuleIndexer, languages, system); | |||
task.start(); | |||
// Execute a commit to refresh session state as the task is using its own session | |||
dbTester.getSession().commit(); |
@@ -52,6 +52,7 @@ import org.sonar.server.tester.UserSessionRule; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.junit.Assert.fail; | |||
import static org.sonar.db.rule.RuleTesting.newRule; | |||
// TODO replace ServerTester by EsTester / DbTester | |||
public class RuleCreatorMediumTest { | |||
@@ -160,7 +161,7 @@ public class RuleCreatorMediumTest { | |||
@Test | |||
public void create_custom_rule_with_no_parameter_value() { | |||
// insert template rule | |||
RuleDto templateRule = createTemplateRuleWithIntArrayParam(); | |||
RuleDefinitionDto templateRule = createTemplateRuleWithIntArrayParam(); | |||
NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) | |||
.setName("My custom") | |||
@@ -184,7 +185,7 @@ public class RuleCreatorMediumTest { | |||
@Test | |||
public void create_custom_rule_with_multiple_parameter_values() { | |||
// insert template rule | |||
RuleDto templateRule = createTemplateRuleWithIntArrayParam(); | |||
RuleDefinitionDto templateRule = createTemplateRuleWithIntArrayParam(); | |||
NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) | |||
.setName("My custom") | |||
@@ -209,7 +210,7 @@ public class RuleCreatorMediumTest { | |||
@Test | |||
public void create_custom_rule_with_invalid_parameter() { | |||
// insert template rule | |||
RuleDto templateRule = createTemplateRuleWithIntArrayParam(); | |||
RuleDefinitionDto templateRule = createTemplateRuleWithIntArrayParam(); | |||
// Create custom rule | |||
NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) | |||
@@ -231,7 +232,7 @@ public class RuleCreatorMediumTest { | |||
@Test | |||
public void create_custom_rule_with_invalid_parameters() { | |||
// insert template rule | |||
RuleDto templateRule = createTemplateRuleWithTwoIntParams(); | |||
RuleDefinitionDto templateRule = createTemplateRuleWithTwoIntParams(); | |||
// Create custom rule | |||
NewCustomRule newRule = NewCustomRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey()) | |||
@@ -481,8 +482,8 @@ public class RuleCreatorMediumTest { | |||
@Test | |||
public void fail_to_create_custom_rule_when_wrong_rule_template() { | |||
// insert rule | |||
RuleDto rule = RuleTesting.newDto(RuleKey.of("java", "S001")).setIsTemplate(false); | |||
dao.insert(dbSession, rule.getDefinition()); | |||
RuleDefinitionDto rule = newRule(RuleKey.of("java", "S001")).setIsTemplate(false); | |||
dao.insert(dbSession, rule); | |||
dbSession.commit(); | |||
// Create custom rule with unknown template rule | |||
@@ -519,12 +520,12 @@ public class RuleCreatorMediumTest { | |||
RuleParamDto ruleParamDto = RuleParamDto.createFor(templateRule.getDefinition()).setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(".*"); | |||
dao.insertRuleParam(dbSession, templateRule.getDefinition(), ruleParamDto); | |||
dbSession.commit(); | |||
ruleIndexer.index(defaultOrganization, templateRule.getKey()); | |||
ruleIndexer.indexRuleDefinition(templateRule.getDefinition().getKey()); | |||
return templateRule; | |||
} | |||
private RuleDto createTemplateRuleWithIntArrayParam() { | |||
RuleDto templateRule = RuleTesting.newDto(RuleKey.of("java", "S002")) | |||
private RuleDefinitionDto createTemplateRuleWithIntArrayParam() { | |||
RuleDefinitionDto templateRule = newRule(RuleKey.of("java", "S002")) | |||
.setIsTemplate(true) | |||
.setLanguage("java") | |||
.setConfigKey("S002") | |||
@@ -534,17 +535,17 @@ public class RuleCreatorMediumTest { | |||
.setGapDescription("desc") | |||
.setCreatedAt(new Date().getTime()) | |||
.setUpdatedAt(new Date().getTime()); | |||
dao.insert(dbSession, templateRule.getDefinition()); | |||
RuleParamDto ruleParamDto = RuleParamDto.createFor(templateRule.getDefinition()) | |||
dao.insert(dbSession, templateRule); | |||
RuleParamDto ruleParamDto = RuleParamDto.createFor(templateRule) | |||
.setName("myIntegers").setType("INTEGER,multiple=true,values=1;2;3").setDescription("My Integers").setDefaultValue("1"); | |||
dao.insertRuleParam(dbSession, templateRule.getDefinition(), ruleParamDto); | |||
dao.insertRuleParam(dbSession, templateRule, ruleParamDto); | |||
dbSession.commit(); | |||
ruleIndexer.index(defaultOrganization, templateRule.getKey()); | |||
ruleIndexer.indexRuleDefinition(templateRule.getKey()); | |||
return templateRule; | |||
} | |||
private RuleDto createTemplateRuleWithTwoIntParams() { | |||
RuleDto templateRule = RuleTesting.newDto(RuleKey.of("java", "S003")) | |||
private RuleDefinitionDto createTemplateRuleWithTwoIntParams() { | |||
RuleDefinitionDto templateRule = newRule(RuleKey.of("java", "S003")) | |||
.setIsTemplate(true) | |||
.setLanguage("java") | |||
.setConfigKey("S003") | |||
@@ -554,13 +555,13 @@ public class RuleCreatorMediumTest { | |||
.setGapDescription("desc") | |||
.setCreatedAt(new Date().getTime()) | |||
.setUpdatedAt(new Date().getTime()); | |||
dao.insert(dbSession, templateRule.getDefinition()); | |||
RuleParamDto ruleParam1Dto = RuleParamDto.createFor(templateRule.getDefinition()) | |||
dao.insert(dbSession, templateRule); | |||
RuleParamDto ruleParam1Dto = RuleParamDto.createFor(templateRule) | |||
.setName("first").setType("INTEGER").setDescription("First integer").setDefaultValue("0"); | |||
dao.insertRuleParam(dbSession, templateRule.getDefinition(), ruleParam1Dto); | |||
RuleParamDto ruleParam2Dto = RuleParamDto.createFor(templateRule.getDefinition()) | |||
dao.insertRuleParam(dbSession, templateRule, ruleParam1Dto); | |||
RuleParamDto ruleParam2Dto = RuleParamDto.createFor(templateRule) | |||
.setName("second").setType("INTEGER").setDescription("Second integer").setDefaultValue("0"); | |||
dao.insertRuleParam(dbSession, templateRule.getDefinition(), ruleParam2Dto); | |||
dao.insertRuleParam(dbSession, templateRule, ruleParam2Dto); | |||
dbSession.commit(); | |||
return templateRule; | |||
} |
@@ -88,7 +88,7 @@ public class RuleDeleterMediumTest { | |||
.setUpdatedAt(PAST); | |||
dao.insert(dbSession, templateRule.getDefinition()); | |||
dbSession.commit(); | |||
ruleIndexer.index(organization, templateRule.getKey()); | |||
ruleIndexer.indexRuleDefinition(templateRule.getDefinition().getKey()); | |||
// Verify in index | |||
assertThat(index.searchAll(new RuleQuery())).containsOnly(templateRule.getKey()); | |||
@@ -100,7 +100,7 @@ public class RuleDeleterMediumTest { | |||
.setUpdatedAt(PAST); | |||
dao.insert(dbSession, customRule.getDefinition()); | |||
dbSession.commit(); | |||
ruleIndexer.index(organization, customRule.getKey()); | |||
ruleIndexer.indexRuleDefinition(customRule.getDefinition().getKey()); | |||
// Verify in index | |||
assertThat(index.searchAll(new RuleQuery())).containsOnly(templateRule.getKey(), customRule.getKey()); | |||
@@ -134,7 +134,7 @@ public class RuleDeleterMediumTest { | |||
public void fail_to_delete_if_not_custom() { | |||
// Create rule | |||
RuleKey ruleKey = RuleKey.of("java", "S001"); | |||
dao.insert(dbSession, RuleTesting.newDto(ruleKey).getDefinition()); | |||
dao.insert(dbSession, RuleTesting.newRule(ruleKey)); | |||
dbSession.commit(); | |||
try { |
@@ -31,6 +31,7 @@ import javax.annotation.Nonnull; | |||
import org.junit.After; | |||
import org.junit.Before; | |||
import org.junit.ClassRule; | |||
import org.junit.Ignore; | |||
import org.junit.Test; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
@@ -55,7 +56,6 @@ import org.sonar.server.qualityprofile.QProfileTesting; | |||
import org.sonar.server.qualityprofile.RuleActivation; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.rule.index.RuleQuery; | |||
import org.sonar.server.tester.ServerTester; | |||
import org.sonar.server.tester.UserSessionRule; | |||
@@ -96,7 +96,7 @@ public class RuleUpdaterMediumTest { | |||
@Test | |||
public void do_not_update_rule_with_removed_status() { | |||
ruleDao.insert(dbSession, RuleTesting.newDto(RULE_KEY).setStatus(RuleStatus.REMOVED).getDefinition()); | |||
ruleDao.insert(dbSession, RuleTesting.newRule(RULE_KEY).setStatus(RuleStatus.REMOVED)); | |||
dbSession.commit(); | |||
RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setTags(Sets.newHashSet("java9")); | |||
@@ -190,6 +190,7 @@ public class RuleUpdaterMediumTest { | |||
assertThat(rule.getNoteUpdatedAt()).isNull(); | |||
} | |||
@Ignore | |||
@Test | |||
public void set_tags() { | |||
// insert db | |||
@@ -202,13 +203,12 @@ public class RuleUpdaterMediumTest { | |||
RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setTags(Sets.newHashSet("bug", "java8")); | |||
underTest.update(update, userSessionRule); | |||
dbSession.clearCache(); | |||
RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), RULE_KEY); | |||
assertThat(rule.getTags()).containsOnly("bug"); | |||
assertThat(rule.getSystemTags()).containsOnly("java8", "javadoc"); | |||
// verify that tags are indexed in index | |||
Set<String> tags = tester.get(RuleIndex.class).terms(RuleIndexDefinition.FIELD_RULE_ALL_TAGS); | |||
Set<String> tags = ruleIndex.listTags(defaultOrganization.getUuid(), null, 10); | |||
assertThat(tags).containsOnly("bug", "java8", "javadoc"); | |||
} | |||
@@ -230,17 +230,16 @@ public class RuleUpdaterMediumTest { | |||
assertThat(rule.getSystemTags()).containsOnly("java8", "javadoc"); | |||
// verify that tags are indexed in index | |||
Set<String> tags = tester.get(RuleIndex.class).terms(RuleIndexDefinition.FIELD_RULE_ALL_TAGS); | |||
Set<String> tags = ruleIndex.listTags(defaultOrganization.getUuid(), null, 10); | |||
assertThat(tags).containsOnly("java8", "javadoc"); | |||
} | |||
@Test | |||
public void override_debt() { | |||
ruleDao.insert(dbSession, RuleTesting.newDto(RULE_KEY) | |||
ruleDao.insert(dbSession, RuleTesting.newRule(RULE_KEY) | |||
.setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) | |||
.setDefRemediationGapMultiplier("1d") | |||
.setDefRemediationBaseEffort("5min") | |||
.getDefinition()); | |||
.setDefRemediationBaseEffort("5min")); | |||
dbSession.commit(); | |||
DefaultDebtRemediationFunction fn = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "1min"); | |||
@@ -262,11 +261,10 @@ public class RuleUpdaterMediumTest { | |||
@Test | |||
public void override_debt_only_offset() { | |||
ruleDao.insert(dbSession, RuleTesting.newDto(RULE_KEY) | |||
ruleDao.insert(dbSession, RuleTesting.newRule(RULE_KEY) | |||
.setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR.name()) | |||
.setDefRemediationGapMultiplier("1d") | |||
.setDefRemediationBaseEffort(null) | |||
.getDefinition()); | |||
.setDefRemediationBaseEffort(null)); | |||
dbSession.commit(); | |||
RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) | |||
@@ -287,11 +285,10 @@ public class RuleUpdaterMediumTest { | |||
@Test | |||
public void override_debt_from_linear_with_offset_to_constant() { | |||
ruleDao.insert(dbSession, RuleTesting.newDto(RULE_KEY) | |||
ruleDao.insert(dbSession, RuleTesting.newRule(RULE_KEY) | |||
.setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) | |||
.setDefRemediationGapMultiplier("1d") | |||
.setDefRemediationBaseEffort("5min") | |||
.getDefinition()); | |||
.setDefRemediationBaseEffort("5min")); | |||
dbSession.commit(); | |||
RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY) | |||
@@ -546,8 +543,8 @@ public class RuleUpdaterMediumTest { | |||
@Test | |||
public void fail_to_update_plugin_rule_if_name_is_set() { | |||
// Create rule rule | |||
RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("squid", "S01")); | |||
ruleDao.insert(dbSession, ruleDto.getDefinition()); | |||
RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("squid", "S01")); | |||
ruleDao.insert(dbSession, ruleDto); | |||
dbSession.commit(); | |||
@@ -564,8 +561,8 @@ public class RuleUpdaterMediumTest { | |||
@Test | |||
public void fail_to_update_plugin_rule_if_description_is_set() { | |||
// Create rule rule | |||
RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("squid", "S01")); | |||
ruleDao.insert(dbSession, ruleDto.getDefinition()); | |||
RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("squid", "S01")); | |||
ruleDao.insert(dbSession, ruleDto); | |||
dbSession.commit(); | |||
@@ -582,8 +579,8 @@ public class RuleUpdaterMediumTest { | |||
@Test | |||
public void fail_to_update_plugin_rule_if_severity_is_set() { | |||
// Create rule rule | |||
RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("squid", "S01")); | |||
ruleDao.insert(dbSession, ruleDto.getDefinition()); | |||
RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("squid", "S01")); | |||
ruleDao.insert(dbSession, ruleDto); | |||
dbSession.commit(); | |||
@@ -20,7 +20,6 @@ | |||
package org.sonar.server.rule.index; | |||
import com.google.common.collect.Maps; | |||
import java.util.Arrays; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
@@ -44,7 +43,6 @@ public class RuleDocTesting { | |||
.setStatus(RuleStatus.READY.name()) | |||
.setLanguage("xoo") | |||
.setIsTemplate(false) | |||
.setAllTags(Arrays.asList("spring", "performance")) | |||
.setType(RuleType.CODE_SMELL) | |||
.setCreatedAt(1_500_000_000L) | |||
.setUpdatedAt(1_600_000_000L); |
@@ -54,7 +54,7 @@ public class RuleIndexDefinitionTest { | |||
assertThat(context.getIndices()).hasSize(1); | |||
NewIndex ruleIndex = context.getIndices().get("rules"); | |||
assertThat(ruleIndex).isNotNull(); | |||
assertThat(ruleIndex.getTypes().keySet()).containsOnly("rule", "activeRule"); | |||
assertThat(ruleIndex.getTypes().keySet()).containsOnly("activeRule", "ruleExtension", "rule"); | |||
// no cluster by default | |||
assertThat(ruleIndex.getSettings().get("index.number_of_shards")).isEqualTo("1"); |
@@ -19,18 +19,15 @@ | |||
*/ | |||
package org.sonar.server.rule.index; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.config.MapSettings; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.rules.RuleType; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.server.es.EsTester; | |||
@@ -41,15 +38,14 @@ import static org.assertj.core.api.Assertions.assertThat; | |||
public class RuleIndexerTest { | |||
private System2 system2 = System2.INSTANCE; | |||
@Rule | |||
public EsTester esTester = new EsTester(new RuleIndexDefinition(new MapSettings())); | |||
@Rule | |||
public DbTester dbTester = DbTester.create(system2); | |||
public DbTester dbTester = DbTester.create(); | |||
private DbClient dbClient = dbTester.getDbClient(); | |||
private final RuleIndexer underTest = new RuleIndexer(esTester.client(), dbClient); | |||
private DbSession dbSession = dbTester.getSession(); | |||
private RuleDefinitionDto rule = new RuleDefinitionDto() | |||
.setRuleKey("S001") | |||
@@ -66,17 +62,10 @@ public class RuleIndexerTest { | |||
.setType(RuleType.BUG) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1600000000000L); | |||
private OrganizationDto organization; | |||
@Before | |||
public void before() { | |||
organization = dbTester.getDefaultOrganization(); | |||
} | |||
@Test | |||
public void index_nothing() { | |||
RuleIndexer indexer = createIndexer(); | |||
// indexer.index(Iterators.emptyIterator()); | |||
// underTest.index(Iterators.emptyIterator()); | |||
assertThat(esTester.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isEqualTo(0L); | |||
} | |||
@@ -85,44 +74,24 @@ public class RuleIndexerTest { | |||
dbClient.ruleDao().insert(dbSession, rule); | |||
dbSession.commit(); | |||
RuleIndexer indexer = createIndexer(); | |||
indexer.index(organization, rule.getKey()); | |||
underTest.indexRuleDefinition(rule.getKey()); | |||
assertThat(esTester.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isEqualTo(1); | |||
} | |||
@Test | |||
public void removed_rule_is_not_removed_from_index() { | |||
RuleIndexer indexer = createIndexer(); | |||
// Create and Index rule | |||
dbClient.ruleDao().insert(dbSession, rule.setStatus(RuleStatus.READY)); | |||
dbSession.commit(); | |||
indexer.index(organization, rule.getKey()); | |||
underTest.indexRuleDefinition(rule.getKey()); | |||
assertThat(esTester.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isEqualTo(1); | |||
// Remove rule | |||
dbTester.getDbClient().ruleDao().update(dbTester.getSession(), rule.setStatus(RuleStatus.READY).setUpdatedAt(2000000000000L)); | |||
dbTester.getSession().commit(); | |||
indexer.index(organization, rule.getKey()); | |||
assertThat(esTester.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isEqualTo(1); | |||
} | |||
@Test | |||
public void index_on_startup() { | |||
RuleIndexer indexer = createIndexer(); | |||
// Create and Index rule | |||
dbClient.ruleDao().insert(dbSession, rule.setStatus(RuleStatus.READY)); | |||
dbSession.commit(); | |||
underTest.indexRuleDefinition(rule.getKey()); | |||
indexer.indexOnStartup(indexer.getIndexTypes()); | |||
assertThat(esTester.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isEqualTo(1); | |||
} | |||
private RuleIndexer createIndexer() { | |||
return new RuleIndexer(esTester.client(), dbClient, new RuleIteratorFactory(dbTester.getDbClient()), TestDefaultOrganizationProvider.from(dbTester)); | |||
} | |||
} |
@@ -46,12 +46,12 @@ public class RuleIteratorForSingleChunkTest { | |||
private DbClient dbClient = dbTester.getDbClient(); | |||
private DbSession dbSession = dbTester.getSession(); | |||
private RuleDto templateRule; | |||
private RuleDefinitionDto templateRule; | |||
private RuleDefinitionDto customRule; | |||
@Before | |||
public void setUp() throws Exception { | |||
templateRule = new RuleDto() | |||
templateRule = new RuleDefinitionDto() | |||
.setRuleKey("S001") | |||
.setRepositoryKey("xoo") | |||
.setConfigKey("S1") | |||
@@ -65,9 +65,7 @@ public class RuleIteratorForSingleChunkTest { | |||
.setSystemTags(newHashSet("cwe")) | |||
.setType(RuleType.BUG) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1600000000000L) | |||
.setOrganizationUuid(dbTester.getDefaultOrganization().getUuid()) | |||
.setTags(newHashSet("performance")); | |||
.setUpdatedAt(1600000000000L); | |||
customRule = new RuleDefinitionDto() | |||
.setRuleKey("S002") | |||
@@ -87,13 +85,15 @@ public class RuleIteratorForSingleChunkTest { | |||
@Test | |||
public void iterator_over_one_rule() { | |||
dbTester.rules().insertRule(templateRule); | |||
dbTester.rules().insert(templateRule); | |||
List<RuleDoc> results = getResults(); | |||
List<RuleDocWithSystemScope> results = getResults(); | |||
assertThat(results).hasSize(1); | |||
RuleDoc templateDoc = getRuleDoc(results, templateRule.getRuleKey()); | |||
RuleDocWithSystemScope ruleDocWithSystemScope = getRuleDoc(results, templateRule.getRuleKey()); | |||
RuleDoc templateDoc = ruleDocWithSystemScope.getRuleDoc(); | |||
RuleExtensionDoc templateExtensionDoc = ruleDocWithSystemScope.getRuleExtensionDoc(); | |||
assertThat(templateDoc).isNotNull(); | |||
assertThat(templateDoc.key()).isEqualTo(RuleKey.of("xoo", "S001")); | |||
assertThat(templateDoc.ruleKey()).isEqualTo("S001"); | |||
@@ -105,22 +105,24 @@ public class RuleIteratorForSingleChunkTest { | |||
assertThat(templateDoc.severity()).isEqualTo(Severity.BLOCKER); | |||
assertThat(templateDoc.status()).isEqualTo(RuleStatus.READY); | |||
assertThat(templateDoc.isTemplate()).isTrue(); | |||
assertThat(templateDoc.allTags()).containsOnly("performance", "cwe"); | |||
assertThat(templateExtensionDoc.getTags()).containsOnly("cwe"); | |||
assertThat(templateDoc.createdAt()).isEqualTo(1500000000000L); | |||
assertThat(templateDoc.updatedAt()).isEqualTo(1600000000000L); | |||
} | |||
@Test | |||
public void iterator_over_rules() { | |||
dbTester.rules().insertRule(templateRule); | |||
dbTester.rules().insert(templateRule); | |||
dbClient.ruleDao().insert(dbSession, customRule); | |||
dbSession.commit(); | |||
List<RuleDoc> results = getResults(); | |||
List<RuleDocWithSystemScope> results = getResults(); | |||
assertThat(results).hasSize(2); | |||
RuleDoc templateDoc = getRuleDoc(results, templateRule.getRuleKey()); | |||
RuleDocWithSystemScope templateDocWithSystemScope = getRuleDoc(results, templateRule.getRuleKey()); | |||
RuleDoc templateDoc = templateDocWithSystemScope.getRuleDoc(); | |||
RuleExtensionDoc templateExtensionDoc = templateDocWithSystemScope.getRuleExtensionDoc(); | |||
assertThat(templateDoc.key()).isEqualTo(RuleKey.of("xoo", "S001")); | |||
assertThat(templateDoc.ruleKey()).isEqualTo("S001"); | |||
assertThat(templateDoc.repository()).isEqualTo("xoo"); | |||
@@ -131,11 +133,13 @@ public class RuleIteratorForSingleChunkTest { | |||
assertThat(templateDoc.severity()).isEqualTo(Severity.BLOCKER); | |||
assertThat(templateDoc.status()).isEqualTo(RuleStatus.READY); | |||
assertThat(templateDoc.isTemplate()).isTrue(); | |||
assertThat(templateDoc.allTags()).containsOnly("performance", "cwe"); | |||
assertThat(templateExtensionDoc.getTags()).containsOnly("cwe"); | |||
assertThat(templateDoc.createdAt()).isEqualTo(1500000000000L); | |||
assertThat(templateDoc.updatedAt()).isEqualTo(1600000000000L); | |||
RuleDoc customDoc = getRuleDoc(results, customRule.getRuleKey()); | |||
RuleDocWithSystemScope customDocWithSystemScope = getRuleDoc(results, customRule.getRuleKey()); | |||
RuleDoc customDoc = customDocWithSystemScope.getRuleDoc(); | |||
RuleExtensionDoc customExtensionDoc = customDocWithSystemScope.getRuleExtensionDoc(); | |||
assertThat(customDoc.key()).isEqualTo(RuleKey.of("xoo", "S002")); | |||
assertThat(customDoc.ruleKey()).isEqualTo("S002"); | |||
assertThat(customDoc.repository()).isEqualTo("xoo"); | |||
@@ -146,48 +150,50 @@ public class RuleIteratorForSingleChunkTest { | |||
assertThat(customDoc.severity()).isEqualTo(Severity.MAJOR); | |||
assertThat(customDoc.status()).isEqualTo(RuleStatus.BETA); | |||
assertThat(customDoc.isTemplate()).isFalse(); | |||
assertThat(customDoc.allTags()).isEmpty(); | |||
assertThat(customExtensionDoc.getTags()).isEmpty(); | |||
assertThat(customDoc.createdAt()).isEqualTo(2000000000000L); | |||
assertThat(customDoc.updatedAt()).isEqualTo(2100000000000L); | |||
} | |||
@Test | |||
public void custom_rule() { | |||
dbTester.rules().insertRule(templateRule); | |||
dbTester.rules().insert(templateRule); | |||
dbClient.ruleDao().insert(dbSession, customRule.setTemplateId(templateRule.getId())); | |||
dbSession.commit(); | |||
List<RuleDoc> results = getResults(); | |||
List<RuleDocWithSystemScope> results = getResults(); | |||
assertThat(results).hasSize(2); | |||
RuleDoc templateDoc = getRuleDoc(results, templateRule.getRuleKey()); | |||
RuleDocWithSystemScope templateDocWithSystemScope = getRuleDoc(results, templateRule.getRuleKey()); | |||
RuleDoc templateDoc = templateDocWithSystemScope.getRuleDoc(); | |||
assertThat(templateDoc.isTemplate()).isTrue(); | |||
assertThat(templateDoc.templateKey()).isNull(); | |||
RuleDoc customDoc = getRuleDoc(results, customRule.getRuleKey()); | |||
RuleDocWithSystemScope customDocWithSystemScope = getRuleDoc(results, customRule.getRuleKey()); | |||
RuleDoc customDoc = customDocWithSystemScope.getRuleDoc(); | |||
assertThat(customDoc.isTemplate()).isFalse(); | |||
assertThat(customDoc.templateKey()).isEqualTo(RuleKey.of("xoo", "S001")); | |||
} | |||
@Test | |||
public void removed_rule_is_returned() { | |||
dbTester.rules().insertRule(templateRule.setStatus(RuleStatus.REMOVED)); | |||
dbTester.rules().insert(templateRule.setStatus(RuleStatus.REMOVED)); | |||
dbSession.commit(); | |||
List<RuleDoc> results = getResults(); | |||
List<RuleDocWithSystemScope> results = getResults(); | |||
assertThat(results).hasSize(1); | |||
} | |||
private List<RuleDoc> getResults() { | |||
return Lists.newArrayList(new RuleIteratorForSingleChunk(dbTester.getDbClient(), dbTester.getDefaultOrganization(), null)); | |||
private List<RuleDocWithSystemScope> getResults() { | |||
return Lists.newArrayList(new RuleIteratorForSingleChunk(dbTester.getDbClient(), null)); | |||
} | |||
private RuleDoc getRuleDoc(List<RuleDoc> results, String ruleKey) { | |||
RuleDoc rule; | |||
private RuleDocWithSystemScope getRuleDoc(List<RuleDocWithSystemScope> results, String ruleKey) { | |||
RuleDocWithSystemScope rule; | |||
rule = results.stream() | |||
.filter(r -> ruleKey.equals(r.key().rule())) | |||
.filter(r -> ruleKey.equals(r.getRuleDoc().key().rule())) | |||
.findAny() | |||
.orElseThrow(() -> new NotFoundException("Rule not found in results")); | |||
return rule; |
@@ -50,8 +50,8 @@ public class ListActionTest { | |||
@Test | |||
public void return_rules_in_protobuf() throws Exception { | |||
dbTester.rules().insertRule(RuleTesting.newDto(RuleKey.of("java", "S001")).setConfigKey(null).setName(null)); | |||
dbTester.rules().insertRule(RuleTesting.newDto(RuleKey.of("java", "S002")).setConfigKey("I002").setName("Rule Two")); | |||
dbTester.rules().insert(RuleTesting.newRule(RuleKey.of("java", "S001")).setConfigKey(null).setName(null)); | |||
dbTester.rules().insert(RuleTesting.newRule(RuleKey.of("java", "S002")).setConfigKey("I002").setName("Rule Two")); | |||
dbTester.getSession().commit(); | |||
TestResponse response = tester.newRequest() |
@@ -19,16 +19,12 @@ | |||
*/ | |||
package org.sonar.server.rule.ws; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Collections; | |||
import java.util.stream.Stream; | |||
import org.junit.After; | |||
import org.junit.Before; | |||
import org.junit.ClassRule; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
@@ -120,7 +116,7 @@ public class RulesWsMediumTest { | |||
tester.get(ActiveRuleDao.class).insert(session, activeRuleDto); | |||
session.commit(); | |||
ruleIndexer.index(defaultOrganization, rule.getKey()); | |||
ruleIndexer.indexRuleDefinition(rule.getDefinition().getKey()); | |||
activeRuleIndexer.index(); | |||
// 1. With Activation | |||
@@ -136,32 +132,4 @@ public class RulesWsMediumTest { | |||
result = request.execute(); | |||
result.assertJson(this.getClass(), "show_rule_no_active.json"); | |||
} | |||
@Test | |||
public void get_tags() throws Exception { | |||
QualityProfileDto profile = QProfileTesting.newXooP1(defaultOrganization); | |||
tester.get(QualityProfileDao.class).insert(session, profile); | |||
RuleDto rule = RuleTesting.newXooX1(defaultOrganization) | |||
.setTags(ImmutableSet.of("hello", "world")) | |||
.setSystemTags(Collections.<String>emptySet()); | |||
ruleDao.insert(session, rule.getDefinition()); | |||
ruleDao.insertOrUpdate(session, rule.getMetadata().setRuleId(rule.getId())); | |||
RuleDto rule2 = RuleTesting.newXooX2(defaultOrganization) | |||
.setTags(ImmutableSet.of("hello", "java")) | |||
.setSystemTags(ImmutableSet.of("sys1")); | |||
ruleDao.insert(session, rule2.getDefinition()); | |||
ruleDao.insertOrUpdate(session, rule2.getMetadata().setRuleId(rule2.getId())); | |||
session.commit(); | |||
ruleIndexer.index(defaultOrganization, Stream.of(rule, rule2).map(RuleDto::getKey).collect(MoreCollectors.toList())); | |||
tester.wsTester().newGetRequest(API_ENDPOINT, API_TAGS_METHOD).execute().assertJson(this.getClass(), "get_tags.json"); | |||
tester.wsTester().newGetRequest(API_ENDPOINT, API_TAGS_METHOD) | |||
.setParam("ps", "1").execute().assertJson(this.getClass(), "get_tags_limited.json"); | |||
tester.wsTester().newGetRequest(API_ENDPOINT, API_TAGS_METHOD) | |||
.setParam("q", "ll").execute().assertJson(this.getClass(), "get_tags_filtered.json"); | |||
} | |||
} |
@@ -24,6 +24,7 @@ import java.util.Date; | |||
import org.junit.After; | |||
import org.junit.Before; | |||
import org.junit.ClassRule; | |||
import org.junit.Ignore; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.rule.RuleKey; | |||
@@ -56,6 +57,7 @@ import org.sonar.server.tester.ServerTester; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.WsTester; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVATION; | |||
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_AVAILABLE_SINCE; | |||
@@ -208,7 +210,7 @@ public class SearchActionMediumTest { | |||
@Test | |||
public void return_lang_key_field_when_language_name_is_not_available() throws Exception { | |||
insertRule(RuleTesting.newDto(RuleKey.of("other", "rule")).setLanguage("unknown").getDefinition()); | |||
insertRule(RuleTesting.newRule(RuleKey.of("other", "rule")).setLanguage("unknown")); | |||
dbSession.commit(); | |||
WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD).setParam(WebService.Param.FIELDS, "langName"); | |||
@@ -496,16 +498,13 @@ public class SearchActionMediumTest { | |||
result.assertJson(this.getClass(), "get_note_as_markdown_and_html.json"); | |||
} | |||
@Ignore | |||
@Test | |||
public void filter_by_tags() throws Exception { | |||
insertRule(RuleTesting.newXooX1() | |||
.setSystemTags(ImmutableSet.of("tag1")) | |||
.getDefinition()); | |||
insertRule(RuleTesting.newXooX2() | |||
.setSystemTags(ImmutableSet.of("tag2")) | |||
.getDefinition()); | |||
dbSession.commit(); | |||
insertRule(RuleTesting.newRule() | |||
.setSystemTags(ImmutableSet.of("tag1"))); | |||
insertRule(RuleTesting.newRule() | |||
.setSystemTags(ImmutableSet.of("tag2"))); | |||
activeRuleIndexer.index(); | |||
@@ -640,6 +639,6 @@ public class SearchActionMediumTest { | |||
private void insertRule(RuleDefinitionDto definition) { | |||
ruleDao.insert(dbSession, definition); | |||
dbSession.commit(); | |||
ruleIndexer.index(defaultOrganizationDto, definition.getKey()); | |||
ruleIndexer.indexRuleDefinition(definition.getKey()); | |||
} | |||
} |
@@ -192,7 +192,7 @@ public class ShowActionMediumTest { | |||
@Test | |||
public void show_rule_with_no_default_and_no_overridden_debt() throws Exception { | |||
RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001")) | |||
RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("java", "S001")) | |||
.setName("Rule S001") | |||
.setDescription("Rule S001 <b>description</b>") | |||
.setDescriptionFormat(Format.HTML) | |||
@@ -203,7 +203,7 @@ public class ShowActionMediumTest { | |||
.setDefRemediationFunction(null) | |||
.setDefRemediationGapMultiplier(null) | |||
.setDefRemediationBaseEffort(null); | |||
ruleDao.insert(session, ruleDto.getDefinition()); | |||
ruleDao.insert(session, ruleDto); | |||
session.commit(); | |||
session.clearCache(); | |||
@@ -259,7 +259,7 @@ public class ShowActionMediumTest { | |||
@Test | |||
public void show_rule_when_activated() throws Exception { | |||
RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001")) | |||
RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("java", "S001")) | |||
.setName("Rule S001") | |||
.setDescription("Rule S001 <b>description</b>") | |||
.setDescriptionFormat(Format.HTML) | |||
@@ -269,12 +269,11 @@ public class ShowActionMediumTest { | |||
.setType(RuleType.BUG) | |||
.setCreatedAt(new Date().getTime()) | |||
.setUpdatedAt(new Date().getTime()); | |||
RuleDefinitionDto definition = ruleDto.getDefinition(); | |||
ruleDao.insert(session, definition); | |||
ruleDao.insert(session, ruleDto); | |||
session.commit(); | |||
ruleIndexer.index(defaultOrganization, definition.getKey()); | |||
RuleParamDto regexParam = RuleParamDto.createFor(definition).setName("regex").setType("STRING").setDescription("Reg *exp*").setDefaultValue(".*"); | |||
ruleDao.insertRuleParam(session, definition, regexParam); | |||
ruleIndexer.indexRuleDefinition(ruleDto.getKey()); | |||
RuleParamDto regexParam = RuleParamDto.createFor(ruleDto).setName("regex").setType("STRING").setDescription("Reg *exp*").setDefaultValue(".*"); | |||
ruleDao.insertRuleParam(session, ruleDto, regexParam); | |||
QualityProfileDto profile = QualityProfileDto.createFor("profile") | |||
.setOrganizationUuid(defaultOrganizationProvider.get().getUuid()) |
@@ -0,0 +1,118 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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.rule.ws; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.config.MapSettings; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
import org.sonar.server.rule.index.RuleIndex; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.rule.index.RuleIndexer; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.WsActionTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.db.rule.RuleTesting.setSystemTags; | |||
import static org.sonar.db.rule.RuleTesting.setTags; | |||
import static org.sonar.test.JsonAssert.assertJson; | |||
public class TagsActionTest { | |||
@Rule | |||
public UserSessionRule userSession = UserSessionRule.standalone(); | |||
@Rule | |||
public DbTester dbTester = DbTester.create(); | |||
@Rule | |||
public EsTester esTester = new EsTester(new RuleIndexDefinition(new MapSettings())); | |||
private DbClient dbClient = dbTester.getDbClient(); | |||
private EsClient esClient = esTester.client(); | |||
private RuleIndex ruleIndex = new RuleIndex(esClient); | |||
private RuleIndexer ruleIndexer = new RuleIndexer(esClient, dbClient); | |||
private WsActionTester tester = new WsActionTester(new org.sonar.server.rule.ws.TagsAction(ruleIndex, dbClient, TestDefaultOrganizationProvider.from(dbTester))); | |||
private OrganizationDto organization; | |||
@Before | |||
public void before() { | |||
organization = dbTester.organizations().insert(); | |||
} | |||
@Test | |||
public void test_definition() { | |||
WebService.Action action = tester.getDef(); | |||
assertThat(action.description()).isNotEmpty(); | |||
assertThat(action.responseExampleAsString()).isNotEmpty(); | |||
assertThat(action.isPost()).isFalse(); | |||
assertThat(action.isInternal()).isFalse(); | |||
assertThat(action.params()).hasSize(3); | |||
WebService.Param query = action.param("q"); | |||
assertThat(query).isNotNull(); | |||
assertThat(query.isRequired()).isFalse(); | |||
assertThat(query.description()).isNotEmpty(); | |||
assertThat(query.exampleValue()).isNotEmpty(); | |||
WebService.Param pageSize = action.param("ps"); | |||
assertThat(pageSize).isNotNull(); | |||
assertThat(pageSize.isRequired()).isFalse(); | |||
assertThat(pageSize.defaultValue()).isEqualTo("0"); | |||
assertThat(pageSize.description()).isNotEmpty(); | |||
assertThat(pageSize.exampleValue()).isNotEmpty(); | |||
WebService.Param organization = action.param("organization"); | |||
assertThat(organization).isNotNull(); | |||
assertThat(organization.isRequired()).isFalse(); | |||
assertThat(organization.isInternal()).isTrue(); | |||
assertThat(organization.description()).isNotEmpty(); | |||
assertThat(organization.exampleValue()).isNotEmpty(); | |||
assertThat(organization.since()).isEqualTo("6.4"); | |||
} | |||
@Test | |||
public void return_system_tag() throws Exception { | |||
RuleDefinitionDto r = dbTester.rules().insert(setSystemTags("tag")); | |||
ruleIndexer.indexRuleDefinition(r.getKey()); | |||
String result = tester.newRequest().execute().getInput(); | |||
assertJson(result).isSimilarTo("{\"tags\":[\"tag\"]}"); | |||
} | |||
@Test | |||
public void return_tag() throws Exception { | |||
RuleDefinitionDto r = dbTester.rules().insert(setSystemTags()); | |||
ruleIndexer.indexRuleDefinition(r.getKey()); | |||
dbTester.rules().insertOrUpdateMetadata(r, organization, setTags("tag")); | |||
ruleIndexer.indexRuleExtension(organization, r.getKey()); | |||
String result = tester.newRequest().setParam("organization", organization.getKey()).execute().getInput(); | |||
assertJson(result).isSimilarTo("{\"tags\":[\"tag\"]}"); | |||
} | |||
} |
@@ -125,7 +125,8 @@ public class ViewIndexerTest { | |||
@Test | |||
public void clear_views_lookup_cache_on_index_view_uuid() { | |||
IssueIndex issueIndex = new IssueIndex(esTester.client(), System2.INSTANCE, userSessionRule, new AuthorizationTypeSupport(userSessionRule)); | |||
IssueIndex issueIndex = new IssueIndex(esTester.client(), System2.INSTANCE, userSessionRule, new AuthorizationTypeSupport(userSessionRule) | |||
); | |||
IssueIndexer issueIndexer = new IssueIndexer(esTester.client(), new IssueIteratorFactory(dbClient)); | |||
String viewUuid = "ABCD"; |
@@ -1,8 +0,0 @@ | |||
{ | |||
"tags": [ | |||
"sys1", | |||
"java", | |||
"world", | |||
"hello" | |||
] | |||
} |