summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2013-12-17 11:33:29 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2013-12-17 11:33:29 +0100
commit15daf634efb55ce0fe4e651483c7fbc8098db116 (patch)
tree443c405d41066aa3c53ca3b4c42646cd8a6aa42d
parent5072079eee5072af70d379f42ce384c7f2aab012 (diff)
downloadsonarqube-15daf634efb55ce0fe4e651483c7fbc8098db116.tar.gz
sonarqube-15daf634efb55ce0fe4e651483c7fbc8098db116.zip
SONAR-4535 Index active rules when creating profile from xml
-rw-r--r--sonar-check-api/src/main/java/org/sonar/check/Priority.java5
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleParamDto.java10
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/rule/Severity.java4
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/rules/RulePriority.java3
-rw-r--r--sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java22
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule/RuleRegistry.java131
-rw-r--r--sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileOperationsTest.java12
-rw-r--r--sonar-server/src/test/java/org/sonar/server/rule/RuleRegistryTest.java31
8 files changed, 164 insertions, 54 deletions
diff --git a/sonar-check-api/src/main/java/org/sonar/check/Priority.java b/sonar-check-api/src/main/java/org/sonar/check/Priority.java
index 94e301481e4..e7b562dcad2 100644
--- a/sonar-check-api/src/main/java/org/sonar/check/Priority.java
+++ b/sonar-check-api/src/main/java/org/sonar/check/Priority.java
@@ -19,6 +19,11 @@
*/
package org.sonar.check;
+/**
+ * @deprecated since 4.2
+ * @see org.sonar.api.rule.Severity
+ */
+@Deprecated
public enum Priority {
/**
* WARNING : DO NOT CHANGE THE ENUMERATION ORDER
diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleParamDto.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleParamDto.java
index 20dcad77895..babadef3556 100644
--- a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleParamDto.java
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleParamDto.java
@@ -25,6 +25,7 @@ public class ActiveRuleParamDto {
private Integer id;
private Integer activeRuleId;
private Integer rulesParameterId;
+ private String key;
private String value;
public Integer getId() {
@@ -54,6 +55,15 @@ public class ActiveRuleParamDto {
return this;
}
+ public String getKey() {
+ return key;
+ }
+
+ public ActiveRuleParamDto setKey(String key) {
+ this.key = key;
+ return this;
+ }
+
public String getValue() {
return value;
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rule/Severity.java b/sonar-plugin-api/src/main/java/org/sonar/api/rule/Severity.java
index 775f76d189e..7fe9fe68348 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/rule/Severity.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/rule/Severity.java
@@ -39,6 +39,10 @@ public final class Severity {
*/
public static final List<String> ALL = ImmutableList.of(INFO, MINOR, MAJOR, CRITICAL, BLOCKER);
+ public static String get(int ordinal) {
+ return ALL.get(ordinal);
+ }
+
private Severity() {
// utility
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rules/RulePriority.java b/sonar-plugin-api/src/main/java/org/sonar/api/rules/RulePriority.java
index faf640d4ac1..35f0a000582 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/rules/RulePriority.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/rules/RulePriority.java
@@ -22,7 +22,8 @@ package org.sonar.api.rules;
import org.sonar.check.Priority;
/**
- * A class to hold rules priority
+ * @deprecated since 4.2
+ * @see org.sonar.api.rule.Severity
*/
public enum RulePriority {
diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java
index f35a723ae18..dddee702a9c 100644
--- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java
+++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileOperations.java
@@ -22,8 +22,10 @@ package org.sonar.server.qualityprofile;
import com.google.common.base.Function;
import com.google.common.base.Strings;
+import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.sonar.api.ServerComponent;
@@ -45,6 +47,7 @@ import org.sonar.core.qualityprofile.db.*;
import org.sonar.core.resource.ResourceDao;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.rule.RuleRegistry;
import org.sonar.server.user.UserSession;
import org.sonar.server.util.Validation;
@@ -69,14 +72,15 @@ public class QProfileOperations implements ServerComponent {
private final List<ProfileExporter> exporters;
private final List<ProfileImporter> importers;
private final PreviewCache dryRunCache;
+ private final RuleRegistry ruleRegistry;
public QProfileOperations(MyBatis myBatis, QualityProfileDao dao, ActiveRuleDao activeRuleDao, ResourceDao resourceDao, PropertiesDao propertiesDao,
- PreviewCache dryRunCache) {
- this(myBatis, dao, activeRuleDao, resourceDao, propertiesDao, Lists.<ProfileExporter>newArrayList(), Lists.<ProfileImporter>newArrayList(), dryRunCache);
+ PreviewCache dryRunCache, RuleRegistry ruleRegistry) {
+ this(myBatis, dao, activeRuleDao, resourceDao, propertiesDao, Lists.<ProfileExporter>newArrayList(), Lists.<ProfileImporter>newArrayList(), dryRunCache, ruleRegistry);
}
public QProfileOperations(MyBatis myBatis, QualityProfileDao dao, ActiveRuleDao activeRuleDao, ResourceDao resourceDao, PropertiesDao propertiesDao,
- List<ProfileExporter> exporters, List<ProfileImporter> importers, PreviewCache dryRunCache) {
+ List<ProfileExporter> exporters, List<ProfileImporter> importers, PreviewCache dryRunCache, RuleRegistry ruleRegistry) {
this.myBatis = myBatis;
this.dao = dao;
this.activeRuleDao = activeRuleDao;
@@ -85,6 +89,7 @@ public class QProfileOperations implements ServerComponent {
this.exporters = exporters;
this.importers = importers;
this.dryRunCache = dryRunCache;
+ this.ruleRegistry = ruleRegistry;
}
public NewProfileResult newProfile(String name, String language, Map<String, String> xmlProfilesByPlugin, UserSession userSession) {
@@ -180,13 +185,19 @@ public class QProfileOperations implements ServerComponent {
}
private void importProfile(QualityProfileDto qualityProfileDto, RulesProfile rulesProfile, SqlSession sqlSession) {
+ List<ActiveRuleDto> activeRuleDtos = newArrayList();
+ Multimap<Integer, ActiveRuleParamDto> paramsByActiveRule = ArrayListMultimap.create();
for (ActiveRule activeRule : rulesProfile.getActiveRules()) {
ActiveRuleDto activeRuleDto = toActiveRuleDto(activeRule, qualityProfileDto);
activeRuleDao.insert(activeRuleDto, sqlSession);
+ activeRuleDtos.add(activeRuleDto);
for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) {
- activeRuleDao.insert(toActiveRuleParamDto(activeRuleParam, activeRuleDto), sqlSession);
+ ActiveRuleParamDto activeRuleParamDto = toActiveRuleParamDto(activeRuleParam, activeRuleDto);
+ activeRuleDao.insert(activeRuleParamDto, sqlSession);
+ paramsByActiveRule.put(activeRuleDto.getId(), activeRuleParamDto);
}
}
+ ruleRegistry.bulkIndexActiveRules(activeRuleDtos, paramsByActiveRule);
}
public ProfileImporter getProfileImporter(String exporterKey) {
@@ -219,13 +230,14 @@ public class QProfileOperations implements ServerComponent {
}
private Integer toSeverityLevel(RulePriority rulePriority) {
- return rulePriority.ordinal() + 1;
+ return rulePriority.ordinal();
}
private ActiveRuleParamDto toActiveRuleParamDto(ActiveRuleParam activeRuleParam, ActiveRuleDto activeRuleDto) {
return new ActiveRuleParamDto()
.setActiveRuleId(activeRuleDto.getId())
.setRulesParameterId(activeRuleParam.getRuleParam().getId())
+ .setKey(activeRuleParam.getKey())
.setValue(activeRuleParam.getValue());
}
diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleRegistry.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleRegistry.java
index 708281476b1..71e9085607c 100644
--- a/sonar-server/src/main/java/org/sonar/server/rule/RuleRegistry.java
+++ b/sonar-server/src/main/java/org/sonar/server/rule/RuleRegistry.java
@@ -29,10 +29,13 @@ import org.elasticsearch.common.io.BytesStream;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.sonar.api.database.DatabaseSession;
+import org.sonar.api.rule.Severity;
import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.ActiveRuleParam;
import org.sonar.api.rules.Rule;
import org.sonar.api.utils.TimeProfiler;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
+import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
import org.sonar.core.rule.RuleDao;
import org.sonar.core.rule.RuleDto;
import org.sonar.core.rule.RuleParamDto;
@@ -47,6 +50,7 @@ import java.util.Map;
/**
* Fill search index with rules
+ *
* @since 4.1
*/
public class RuleRegistry {
@@ -82,13 +86,13 @@ public class RuleRegistry {
profiler.stop();
Multimap<Long, RuleParamDto> paramsByRule = ArrayListMultimap.create();
- for (RuleParamDto param: flatParams) {
+ for (RuleParamDto param : flatParams) {
paramsByRule.put(param.getRuleId(), param);
}
try {
bulkIndex(rules, paramsByRule);
- } catch(IOException ioe) {
+ } catch (IOException ioe) {
throw new IllegalStateException("Unable to index rules", ioe);
}
}
@@ -108,13 +112,14 @@ public class RuleRegistry {
/**
* <p>Find rule IDs matching the given criteria.</p>
+ *
* @param query <p>A collection of (optional) criteria with the following meaning:
- * <ul>
- * <li><em>nameOrKey</em>: will be used as a query string over the "name" field</li>
- * <li><em>&lt;anyField&gt;</em>: will be used to match the given field against the passed value(s);
- * mutiple values must be separated by the '<code>|</code>' (vertical bar) character</li>
- * </ul>
- * </p>
+ * <ul>
+ * <li><em>nameOrKey</em>: will be used as a query string over the "name" field</li>
+ * <li><em>&lt;anyField&gt;</em>: will be used to match the given field against the passed value(s);
+ * mutiple values must be separated by the '<code>|</code>' (vertical bar) character</li>
+ * </ul>
+ * </p>
* @return
*/
public List<Integer> findIds(Map<String, String> query) {
@@ -126,27 +131,28 @@ public class RuleRegistry {
if (params.containsKey(PARAM_NAMEORKEY)) {
searchQuery.searchString(params.remove(PARAM_NAMEORKEY));
}
- if (! params.containsKey(PARAM_STATUS)) {
+ if (!params.containsKey(PARAM_STATUS)) {
searchQuery.notField(PARAM_STATUS, Rule.STATUS_REMOVED);
}
- for(Map.Entry<String, String> param: params.entrySet()) {
+ for (Map.Entry<String, String> param : params.entrySet()) {
searchQuery.field(param.getKey(), param.getValue().split("\\|"));
}
try {
List<Integer> result = Lists.newArrayList();
- for(String docId: searchIndex.findDocumentIds(searchQuery)) {
+ for (String docId : searchIndex.findDocumentIds(searchQuery)) {
result.add(Integer.parseInt(docId));
}
return result;
- } catch(ElasticSearchException searchException) {
+ } catch (ElasticSearchException searchException) {
throw new IllegalArgumentException("Unable to perform search, please check query", searchException);
}
}
/**
* Create or update definition of rule identified by <code>ruleId</code>
+ *
* @param ruleId
*/
public void saveOrUpdate(int ruleId) {
@@ -154,8 +160,8 @@ public class RuleRegistry {
Collection<RuleParamDto> params = ruleDao.selectParameters(rule.getId());
try {
searchIndex.putSynchronous(INDEX_RULES, TYPE_RULE, Long.toString(rule.getId()), ruleDocument(rule, params));
- } catch(IOException ioexception) {
- throw new IllegalStateException("Unable to index rule with id="+ruleId, ioexception);
+ } catch (IOException ioexception) {
+ throw new IllegalStateException("Unable to index rule with id=" + ruleId, ioexception);
}
}
@@ -165,14 +171,14 @@ public class RuleRegistry {
int index = 0;
TimeProfiler profiler = new TimeProfiler();
profiler.start("Build rules documents");
- for (RuleDto rule: rules) {
+ for (RuleDto rule : rules) {
ids[index] = rule.getId().toString();
docs[index] = ruleDocument(rule, paramsByRule.get(rule.getId()));
- index ++;
+ index++;
}
profiler.stop();
- if (! rules.isEmpty()) {
+ if (!rules.isEmpty()) {
profiler.start("Index rules");
searchIndex.bulkIndex(INDEX_RULES, TYPE_RULE, ids, docs);
profiler.stop();
@@ -180,7 +186,7 @@ public class RuleRegistry {
List<String> indexIds = searchIndex.findDocumentIds(SearchQuery.create().index(INDEX_RULES).type(TYPE_RULE));
indexIds.removeAll(Arrays.asList(ids));
- if (! indexIds.isEmpty()) {
+ if (!indexIds.isEmpty()) {
profiler.start("Remove deleted rule documents");
searchIndex.bulkDelete(INDEX_RULES, TYPE_RULE, indexIds.toArray(new String[0]));
profiler.stop();
@@ -194,11 +200,11 @@ public class RuleRegistry {
int index = 0;
TimeProfiler profiler = new TimeProfiler();
profiler.start("Build active rules documents");
- for (ActiveRule rule: rules) {
+ for (ActiveRule rule : rules) {
ids[index] = rule.getId().toString();
docs[index] = activeRuleDocument(rule);
parentIds[index] = rule.getRule().getId().toString();
- index ++;
+ index++;
}
profiler.stop();
profiler.start("Index active rules");
@@ -207,31 +213,30 @@ public class RuleRegistry {
List<String> indexIds = searchIndex.findDocumentIds(SearchQuery.create().index(INDEX_RULES).type(TYPE_ACTIVE_RULE));
indexIds.removeAll(Arrays.asList(ids));
- if (! indexIds.isEmpty()) {
+ if (!indexIds.isEmpty()) {
profiler.start("Remove deleted active rule documents");
searchIndex.bulkDelete(INDEX_RULES, TYPE_ACTIVE_RULE, indexIds.toArray(new String[0]));
profiler.stop();
}
}
-
private XContentBuilder ruleDocument(RuleDto rule, Collection<RuleParamDto> params) throws IOException {
XContentBuilder document = XContentFactory.jsonBuilder()
- .startObject()
- .field(RuleDocument.FIELD_ID, rule.getId())
- .field(RuleDocument.FIELD_KEY, rule.getRuleKey())
- .field(RuleDocument.FIELD_LANGUAGE, rule.getLanguage())
- .field(RuleDocument.FIELD_NAME, rule.getName())
- .field(RuleDocument.FIELD_DESCRIPTION, rule.getDescription())
- .field(RuleDocument.FIELD_PARENT_KEY, rule.getParentId() == null ? null : rule.getParentId())
- .field(RuleDocument.FIELD_REPOSITORY_KEY, rule.getRepositoryKey())
- .field(RuleDocument.FIELD_SEVERITY, rule.getPriority())
- .field(RuleDocument.FIELD_STATUS, rule.getStatus())
- .field(RuleDocument.FIELD_CREATED_AT, rule.getCreatedAt())
- .field(RuleDocument.FIELD_UPDATED_AT, rule.getUpdatedAt());
- if(!params.isEmpty()) {
+ .startObject()
+ .field(RuleDocument.FIELD_ID, rule.getId())
+ .field(RuleDocument.FIELD_KEY, rule.getRuleKey())
+ .field(RuleDocument.FIELD_LANGUAGE, rule.getLanguage())
+ .field(RuleDocument.FIELD_NAME, rule.getName())
+ .field(RuleDocument.FIELD_DESCRIPTION, rule.getDescription())
+ .field(RuleDocument.FIELD_PARENT_KEY, rule.getParentId() == null ? null : rule.getParentId())
+ .field(RuleDocument.FIELD_REPOSITORY_KEY, rule.getRepositoryKey())
+ .field(RuleDocument.FIELD_SEVERITY, rule.getPriority())
+ .field(RuleDocument.FIELD_STATUS, rule.getStatus())
+ .field(RuleDocument.FIELD_CREATED_AT, rule.getCreatedAt())
+ .field(RuleDocument.FIELD_UPDATED_AT, rule.getUpdatedAt());
+ if (!params.isEmpty()) {
document.startArray(RuleDocument.FIELD_PARAMS);
- for (RuleParamDto param: params) {
+ for (RuleParamDto param : params) {
document.startObject()
.field(RuleDocument.FIELD_PARAM_KEY, param.getName())
.field(RuleDocument.FIELD_PARAM_TYPE, param.getType())
@@ -247,14 +252,54 @@ public class RuleRegistry {
private XContentBuilder activeRuleDocument(ActiveRule rule) throws IOException {
XContentBuilder document = XContentFactory.jsonBuilder()
- .startObject()
- .field(ActiveRuleDocument.FIELD_ID, rule.getId())
- .field(ActiveRuleDocument.FIELD_SEVERITY, rule.getSeverity())
- .field(ActiveRuleDocument.FIELD_PROFILE_ID, rule.getRulesProfile().getId())
- .field(ActiveRuleDocument.FIELD_INHERITANCE, rule.getInheritance());
- if(!rule.getActiveRuleParams().isEmpty()) {
+ .startObject()
+ .field(ActiveRuleDocument.FIELD_ID, rule.getId())
+ .field(ActiveRuleDocument.FIELD_SEVERITY, rule.getSeverity())
+ .field(ActiveRuleDocument.FIELD_PROFILE_ID, rule.getRulesProfile().getId())
+ .field(ActiveRuleDocument.FIELD_INHERITANCE, rule.getInheritance());
+ if (!rule.getActiveRuleParams().isEmpty()) {
+ document.startArray(ActiveRuleDocument.FIELD_PARAMS);
+ for (ActiveRuleParam param : rule.getActiveRuleParams()) {
+ document.startObject()
+ .field(ActiveRuleDocument.FIELD_PARAM_KEY, param.getKey())
+ .field(ActiveRuleDocument.FIELD_PARAM_VALUE, param.getValue())
+ .endObject();
+ }
+ document.endArray();
+ }
+ document.endObject();
+ return document;
+ }
+
+ public void bulkIndexActiveRules(List<ActiveRuleDto> activeRules, Multimap<Integer, ActiveRuleParamDto> paramsByActiveRule) {
+ try {
+ int size = activeRules.size();
+ String[] ids = new String[size];
+ BytesStream[] docs = new BytesStream[size];
+ String[] parentIds = new String[size];
+ int index = 0;
+ for (ActiveRuleDto activeRule : activeRules) {
+ ids[index] = activeRule.getId().toString();
+ docs[index] = activeRuleDocument(activeRule, paramsByActiveRule.get(activeRule.getId()));
+ parentIds[index] = activeRule.getRulId().toString();
+ index++;
+ }
+ searchIndex.bulkIndex(INDEX_RULES, TYPE_ACTIVE_RULE, ids, docs, parentIds);
+ } catch (IOException e) {
+ throw new IllegalStateException("Unable to index active rules", e);
+ }
+ }
+
+ private XContentBuilder activeRuleDocument(ActiveRuleDto activeRule, Collection<ActiveRuleParamDto> params) throws IOException {
+ XContentBuilder document = XContentFactory.jsonBuilder()
+ .startObject()
+ .field(ActiveRuleDocument.FIELD_ID, activeRule.getId())
+ .field(ActiveRuleDocument.FIELD_SEVERITY, Severity.get(activeRule.getSeverity()))
+ .field(ActiveRuleDocument.FIELD_PROFILE_ID, activeRule.getProfileId())
+ .field(ActiveRuleDocument.FIELD_INHERITANCE, activeRule.getInheritance());
+ if (!params.isEmpty()) {
document.startArray(ActiveRuleDocument.FIELD_PARAMS);
- for (ActiveRuleParam param: rule.getActiveRuleParams()) {
+ for (ActiveRuleParamDto param : params) {
document.startObject()
.field(ActiveRuleDocument.FIELD_PARAM_KEY, param.getKey())
.field(ActiveRuleDocument.FIELD_PARAM_VALUE, param.getValue())
diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileOperationsTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileOperationsTest.java
index 37f3e86f92c..3cf15824308 100644
--- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileOperationsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileOperationsTest.java
@@ -21,6 +21,7 @@
package org.sonar.server.qualityprofile;
import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;
@@ -48,6 +49,7 @@ import org.sonar.core.resource.ResourceDao;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.rule.RuleRegistry;
import org.sonar.server.user.MockUserSession;
import java.io.Reader;
@@ -84,6 +86,9 @@ public class QProfileOperationsTest {
@Mock
PreviewCache dryRunCache;
+ @Mock
+ RuleRegistry ruleRegistry;
+
List<ProfileExporter> exporters = newArrayList();
List<ProfileImporter> importers = newArrayList();
@@ -93,7 +98,7 @@ public class QProfileOperationsTest {
@Before
public void setUp() throws Exception {
when(myBatis.openSession()).thenReturn(session);
- operations = new QProfileOperations(myBatis, dao, activeRuleDao, resourceDao, propertiesDao, exporters, importers, dryRunCache);
+ operations = new QProfileOperations(myBatis, dao, activeRuleDao, resourceDao, propertiesDao, exporters, importers, dryRunCache, ruleRegistry);
}
@Test
@@ -174,11 +179,14 @@ public class QProfileOperationsTest {
ArgumentCaptor<ActiveRuleDto> activeRuleArgument = ArgumentCaptor.forClass(ActiveRuleDto.class);
verify(activeRuleDao).insert(activeRuleArgument.capture(), eq(session));
assertThat(activeRuleArgument.getValue().getRulId()).isEqualTo(10);
- assertThat(activeRuleArgument.getValue().getSeverity()).isEqualTo(5);
+ assertThat(activeRuleArgument.getValue().getSeverity()).isEqualTo(4);
ArgumentCaptor<ActiveRuleParamDto> activeRuleParamArgument = ArgumentCaptor.forClass(ActiveRuleParamDto.class);
verify(activeRuleDao).insert(activeRuleParamArgument.capture(), eq(session));
+ assertThat(activeRuleParamArgument.getValue().getKey()).isEqualTo("paramKey");
assertThat(activeRuleParamArgument.getValue().getValue()).isEqualTo("paramValue");
+
+ verify(ruleRegistry).bulkIndexActiveRules(anyListOf(ActiveRuleDto.class), any(Multimap.class));
}
@Test
diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RuleRegistryTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RuleRegistryTest.java
index 66ee278bf1a..d2f1972e0c2 100644
--- a/sonar-server/src/test/java/org/sonar/server/rule/RuleRegistryTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/rule/RuleRegistryTest.java
@@ -21,8 +21,10 @@
package org.sonar.server.rule;
import com.github.tlrx.elasticsearch.test.EsSetup;
+import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Multimap;
import org.apache.commons.io.IOUtils;
import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.search.SearchHit;
@@ -36,6 +38,8 @@ import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.ActiveRuleParam;
import org.sonar.api.rules.Rule;
import org.sonar.core.profiling.Profiling;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
+import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
import org.sonar.core.rule.RuleDao;
import org.sonar.core.rule.RuleDto;
import org.sonar.core.rule.RuleParamDto;
@@ -43,12 +47,12 @@ import org.sonar.server.search.SearchIndex;
import org.sonar.server.search.SearchNode;
import org.sonar.test.TestUtils;
+import java.io.IOException;
import java.util.HashMap;
import java.util.List;
-import static org.elasticsearch.index.query.FilterBuilders.hasChildFilter;
-import static org.elasticsearch.index.query.FilterBuilders.hasParentFilter;
-import static org.elasticsearch.index.query.FilterBuilders.termFilter;
+import static com.google.common.collect.Lists.newArrayList;
+import static org.elasticsearch.index.query.FilterBuilders.*;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -258,6 +262,27 @@ public class RuleRegistryTest {
).execute().actionGet().getHits().getHits();
assertThat(childHit).hasSize(1);
assertThat(childHit[0].getId()).isEqualTo("1");
+ }
+
+ @Test
+ public void bulk_index_active_rules() throws IOException {
+ List<ActiveRuleDto> activeRules = newArrayList(new ActiveRuleDto().setId(1).setProfileId(10).setRuleId(1).setSeverity(2));
+ Multimap<Integer, ActiveRuleParamDto> paramsByActiveRule = ArrayListMultimap.create();
+ paramsByActiveRule.putAll(1, newArrayList(new ActiveRuleParamDto().setId(1).setActiveRuleId(1).setRulesParameterId(1).setKey("key").setValue("RuleWithParameters")));
+
+ registry.bulkIndexActiveRules(activeRules, paramsByActiveRule);
+ assertThat(esSetup.exists("rules", "active_rule", "1"));
+ SearchHit[] parentHit = esSetup.client().prepareSearch("rules").setFilter(
+ hasChildFilter("active_rule", termFilter("profileId", 10))
+ ).execute().actionGet().getHits().getHits();
+ assertThat(parentHit).hasSize(1);
+ assertThat(parentHit[0].getId()).isEqualTo("1");
+
+ SearchHit[] childHit = esSetup.client().prepareSearch("rules").setFilter(
+ hasParentFilter("rule", termFilter("key", "RuleWithParameters"))
+ ).execute().actionGet().getHits().getHits();
+ assertThat(childHit).hasSize(1);
+ assertThat(childHit[0].getId()).isEqualTo("1");
}
}