*/ | */ | ||||
String ENABLE_STOP_COMMAND = "sonar.enableStopCommand"; | String ENABLE_STOP_COMMAND = "sonar.enableStopCommand"; | ||||
// Constants declared by the ES plugin ListUpdate (see sonar-search) | |||||
// that are used by sonar-server | |||||
String ES_PLUGIN_LISTUPDATE_SCRIPT_NAME = "listUpdate"; | |||||
String ES_PLUGIN_LISTUPDATE_ID_FIELD = "idField"; | |||||
String ES_PLUGIN_LISTUPDATE_ID_VALUE = "idValue"; | |||||
String ES_PLUGIN_LISTUPDATE_FIELD = "field"; | |||||
String ES_PLUGIN_LISTUPDATE_VALUE = "value"; | |||||
} | } |
private void configurePlugins(ImmutableSettings.Builder builder) { | private void configurePlugins(ImmutableSettings.Builder builder) { | ||||
builder | builder | ||||
.put("script.default_lang", "native") | .put("script.default_lang", "native") | ||||
.put("script.native." + ListUpdate.NAME + ".type", ListUpdate.UpdateListScriptFactory.class.getName()); | |||||
.put(String.format("script.native.%s.type", ProcessConstants.ES_PLUGIN_LISTUPDATE_SCRIPT_NAME), | |||||
ListUpdate.UpdateListScriptFactory.class.getName()); | |||||
} | } | ||||
private void configureNetwork(ImmutableSettings.Builder builder) { | private void configureNetwork(ImmutableSettings.Builder builder) { |
import org.elasticsearch.script.AbstractExecutableScript; | import org.elasticsearch.script.AbstractExecutableScript; | ||||
import org.elasticsearch.script.ExecutableScript; | import org.elasticsearch.script.ExecutableScript; | ||||
import org.elasticsearch.script.NativeScriptFactory; | import org.elasticsearch.script.NativeScriptFactory; | ||||
import org.sonar.process.ProcessConstants; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Collection; | import java.util.Collection; | ||||
public class ListUpdate extends AbstractExecutableScript { | public class ListUpdate extends AbstractExecutableScript { | ||||
public static final String NAME = "listUpdate"; | |||||
public static final String ID_FIELD = "idField"; | |||||
public static final String ID_VALUE = "idValue"; | |||||
public static final String FIELD = "field"; | |||||
public static final String VALUE = "value"; | |||||
public static class UpdateListScriptFactory implements NativeScriptFactory { | public static class UpdateListScriptFactory implements NativeScriptFactory { | ||||
@Override | @Override | ||||
public ExecutableScript newScript(@Nullable Map<String, Object> params) { | public ExecutableScript newScript(@Nullable Map<String, Object> params) { | ||||
String idField = XContentMapValues.nodeStringValue(params.get(ID_FIELD), null); | |||||
String idValue = XContentMapValues.nodeStringValue(params.get(ID_VALUE), null); | |||||
String field = XContentMapValues.nodeStringValue(params.get(FIELD), null); | |||||
String idField = XContentMapValues.nodeStringValue(params.get(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD), null); | |||||
String idValue = XContentMapValues.nodeStringValue(params.get(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE), null); | |||||
String field = XContentMapValues.nodeStringValue(params.get(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD), null); | |||||
Map value = null; | Map value = null; | ||||
if (idField == null) { | if (idField == null) { | ||||
throw new IllegalStateException("Missing '" + ID_FIELD + "' parameter"); | |||||
throw new IllegalStateException(String.format("Missing '%s' parameter", ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD)); | |||||
} | } | ||||
if (idValue == null) { | if (idValue == null) { | ||||
throw new IllegalStateException("Missing '" + ID_VALUE + "' parameter"); | |||||
throw new IllegalStateException(String.format("Missing '%s' parameter", ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE)); | |||||
} | } | ||||
if (field == null) { | if (field == null) { | ||||
throw new IllegalStateException("Missing '" + FIELD + "' parameter"); | |||||
throw new IllegalStateException(String.format("Missing '%s' parameter", ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD)); | |||||
} | } | ||||
//NULL case is deletion of nested item | //NULL case is deletion of nested item | ||||
if (params.containsKey(VALUE)) { | |||||
Object obj = params.get(VALUE); | |||||
if (params.containsKey(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE)) { | |||||
Object obj = params.get(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE); | |||||
if (obj != null) { | if (obj != null) { | ||||
value = XContentMapValues.nodeMapValue(params.get(VALUE), "Update item"); | |||||
value = XContentMapValues.nodeMapValue(params.get(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE), "Update item"); | |||||
} | } | ||||
} | } | ||||
private final String idValue; | private final String idValue; | ||||
private final String field; | private final String field; | ||||
private final Map<String, Object> value; | private final Map<String, Object> value; | ||||
private Map<String, Object> ctx; | private Map<String, Object> ctx; | ||||
public ListUpdate(String idField, String idValue, String field, @Nullable Map<String, Object> value) { | public ListUpdate(String idField, String idValue, String field, @Nullable Map<String, Object> value) { |
import org.elasticsearch.script.ExecutableScript; | import org.elasticsearch.script.ExecutableScript; | ||||
import org.junit.Before; | import org.junit.Before; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
import org.sonar.process.ProcessConstants; | |||||
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.HashMap; | import java.util.HashMap; | ||||
} | } | ||||
// Missing ID_VALUE | // Missing ID_VALUE | ||||
params.put(ListUpdate.ID_FIELD, "test"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD, "test"); | |||||
try { | try { | ||||
factory.newScript(params); | factory.newScript(params); | ||||
fail(); | fail(); | ||||
} | } | ||||
// Missing FIELD | // Missing FIELD | ||||
params.put(ListUpdate.ID_VALUE, "test"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE, "test"); | |||||
try { | try { | ||||
factory.newScript(params); | factory.newScript(params); | ||||
fail(); | fail(); | ||||
} | } | ||||
// Has all required attributes and Null Value | // Has all required attributes and Null Value | ||||
params.put(ListUpdate.FIELD, "test"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD, "test"); | |||||
ExecutableScript script = factory.newScript(params); | ExecutableScript script = factory.newScript(params); | ||||
assertThat(script).isNotNull(); | assertThat(script).isNotNull(); | ||||
// Has all required attributes and VALUE of wrong type | // Has all required attributes and VALUE of wrong type | ||||
params.put(ListUpdate.VALUE, new Integer(52)); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, new Integer(52)); | |||||
try { | try { | ||||
factory.newScript(params); | factory.newScript(params); | ||||
fail(); | fail(); | ||||
} | } | ||||
// Has all required attributes and Proper VALUE | // Has all required attributes and Proper VALUE | ||||
params.put(ListUpdate.VALUE, ImmutableMap.of("key", "value")); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, ImmutableMap.of("key", "value")); | |||||
script = factory.newScript(params); | script = factory.newScript(params); | ||||
assertThat(script).isNotNull(); | assertThat(script).isNotNull(); | ||||
// Missing ID_FIELD | // Missing ID_FIELD | ||||
params.remove(ListUpdate.ID_FIELD); | |||||
params.remove(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD); | |||||
try { | try { | ||||
factory.newScript(params); | factory.newScript(params); | ||||
fail(); | fail(); | ||||
// 0 Create list when field does not exists | // 0 Create list when field does not exists | ||||
Map<String, Object> params = new HashMap<String, Object>(); | Map<String, Object> params = new HashMap<String, Object>(); | ||||
params.put(ListUpdate.FIELD, listField); | |||||
params.put(ListUpdate.ID_FIELD, "key"); | |||||
params.put(ListUpdate.ID_VALUE, "1"); | |||||
params.put(ListUpdate.VALUE, mapOf("key", "1", "value", "A")); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD, listField); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD, "key"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE, "1"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, mapOf("key", "1", "value", "A")); | |||||
ExecutableScript script = factory.newScript(params); | ExecutableScript script = factory.newScript(params); | ||||
script.setNextVar("ctx", ImmutableMap.of("_source", source)); | script.setNextVar("ctx", ImmutableMap.of("_source", source)); | ||||
// Add item to existing list | // Add item to existing list | ||||
params = new HashMap<String, Object>(); | params = new HashMap<String, Object>(); | ||||
params.put(ListUpdate.FIELD, listField); | |||||
params.put(ListUpdate.ID_FIELD, "key"); | |||||
params.put(ListUpdate.ID_VALUE, "2"); | |||||
params.put(ListUpdate.VALUE, mapOf("key", "2", "value", "B")); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD, listField); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD, "key"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE, "2"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, mapOf("key", "2", "value", "B")); | |||||
script = factory.newScript(params); | script = factory.newScript(params); | ||||
script.setNextVar("ctx", ImmutableMap.of("_source", source)); | script.setNextVar("ctx", ImmutableMap.of("_source", source)); | ||||
script.run(); | script.run(); | ||||
// updated first item in list | // updated first item in list | ||||
params = new HashMap<String, Object>(); | params = new HashMap<String, Object>(); | ||||
params.put(ListUpdate.FIELD, listField); | |||||
params.put(ListUpdate.ID_FIELD, "key"); | |||||
params.put(ListUpdate.ID_VALUE, "1"); | |||||
params.put(ListUpdate.VALUE, mapOf("key", "1", "value", "a")); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD, listField); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD, "key"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE, "1"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, mapOf("key", "1", "value", "a")); | |||||
script = factory.newScript(params); | script = factory.newScript(params); | ||||
script.setNextVar("ctx", ImmutableMap.of("_source", source)); | script.setNextVar("ctx", ImmutableMap.of("_source", source)); | ||||
script.run(); | script.run(); | ||||
// updated second item in list | // updated second item in list | ||||
params = new HashMap<String, Object>(); | params = new HashMap<String, Object>(); | ||||
params.put(ListUpdate.FIELD, listField); | |||||
params.put(ListUpdate.ID_FIELD, "key"); | |||||
params.put(ListUpdate.ID_VALUE, "2"); | |||||
params.put(ListUpdate.VALUE, mapOf("key", "2", "value", "b")); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD, listField); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD, "key"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE, "2"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, mapOf("key", "2", "value", "b")); | |||||
script = factory.newScript(params); | script = factory.newScript(params); | ||||
script.setNextVar("ctx", ImmutableMap.of("_source", source)); | script.setNextVar("ctx", ImmutableMap.of("_source", source)); | ||||
script.run(); | script.run(); | ||||
// delete first item | // delete first item | ||||
params = new HashMap<String, Object>(); | params = new HashMap<String, Object>(); | ||||
params.put(ListUpdate.FIELD, listField); | |||||
params.put(ListUpdate.ID_FIELD, "key"); | |||||
params.put(ListUpdate.ID_VALUE, "1"); | |||||
params.put(ListUpdate.VALUE, null); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD, listField); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD, "key"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE, "1"); | |||||
params.put(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, null); | |||||
script = factory.newScript(params); | script = factory.newScript(params); | ||||
script.setNextVar("ctx", ImmutableMap.of("_source", source)); | script.setNextVar("ctx", ImmutableMap.of("_source", source)); | ||||
script.run(); | script.run(); |
<groupId>org.codehaus.sonar</groupId> | <groupId>org.codehaus.sonar</groupId> | ||||
<artifactId>sonar-search</artifactId> | <artifactId>sonar-search</artifactId> | ||||
<version>${project.version}</version> | <version>${project.version}</version> | ||||
<scope>provided</scope> | |||||
<scope>test</scope> | |||||
</dependency> | </dependency> | ||||
</dependencies> | </dependencies> | ||||
import org.sonar.core.qualityprofile.db.ActiveRuleKey; | import org.sonar.core.qualityprofile.db.ActiveRuleKey; | ||||
import org.sonar.core.qualityprofile.db.ActiveRuleParamDto; | import org.sonar.core.qualityprofile.db.ActiveRuleParamDto; | ||||
import org.sonar.core.qualityprofile.db.QualityProfileDto; | import org.sonar.core.qualityprofile.db.QualityProfileDto; | ||||
import org.sonar.search.script.ListUpdate; | |||||
import org.sonar.process.ProcessConstants; | |||||
import org.sonar.server.db.DbClient; | import org.sonar.server.db.DbClient; | ||||
import org.sonar.server.qualityprofile.ActiveRule; | import org.sonar.server.qualityprofile.ActiveRule; | ||||
import org.sonar.server.search.BaseNormalizer; | import org.sonar.server.search.BaseNormalizer; | ||||
.replicationType(ReplicationType.ASYNC) | .replicationType(ReplicationType.ASYNC) | ||||
.routing(key.ruleKey().toString()) | .routing(key.ruleKey().toString()) | ||||
.id(key.toString()) | .id(key.toString()) | ||||
.script(ListUpdate.NAME) | |||||
.addScriptParam(ListUpdate.FIELD, ActiveRuleField.PARAMS.field()) | |||||
.addScriptParam(ListUpdate.VALUE, newParam) | |||||
.addScriptParam(ListUpdate.ID_FIELD, ActiveRuleParamField.NAME.field()) | |||||
.addScriptParam(ListUpdate.ID_VALUE, param.getKey()) | |||||
.script(ProcessConstants.ES_PLUGIN_LISTUPDATE_SCRIPT_NAME) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD, ActiveRuleField.PARAMS.field()) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, newParam) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD, ActiveRuleParamField.NAME.field()) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE, param.getKey()) | |||||
); | ); | ||||
} | } | ||||
.replicationType(ReplicationType.ASYNC) | .replicationType(ReplicationType.ASYNC) | ||||
.routing(key.ruleKey().toString()) | .routing(key.ruleKey().toString()) | ||||
.id(key.toString()) | .id(key.toString()) | ||||
.script(ListUpdate.NAME) | |||||
.addScriptParam(ListUpdate.FIELD, ActiveRuleField.PARAMS.field()) | |||||
.addScriptParam(ListUpdate.VALUE, null) | |||||
.addScriptParam(ListUpdate.ID_FIELD, ActiveRuleParamField.NAME.field()) | |||||
.addScriptParam(ListUpdate.ID_VALUE, param.getKey()) | |||||
.script(ProcessConstants.ES_PLUGIN_LISTUPDATE_SCRIPT_NAME) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD, ActiveRuleField.PARAMS.field()) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, null) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD, ActiveRuleParamField.NAME.field()) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE, param.getKey()) | |||||
); | ); | ||||
} | } | ||||
} | } |
import org.sonar.core.rule.RuleParamDto; | import org.sonar.core.rule.RuleParamDto; | ||||
import org.sonar.core.technicaldebt.db.CharacteristicDto; | import org.sonar.core.technicaldebt.db.CharacteristicDto; | ||||
import org.sonar.markdown.Markdown; | import org.sonar.markdown.Markdown; | ||||
import org.sonar.search.script.ListUpdate; | |||||
import org.sonar.process.ProcessConstants; | |||||
import org.sonar.server.db.DbClient; | import org.sonar.server.db.DbClient; | ||||
import org.sonar.server.search.BaseNormalizer; | import org.sonar.server.search.BaseNormalizer; | ||||
import org.sonar.server.search.IndexField; | import org.sonar.server.search.IndexField; | ||||
return ImmutableList.of(new UpdateRequest() | return ImmutableList.of(new UpdateRequest() | ||||
.id(key.toString()) | .id(key.toString()) | ||||
.script(ListUpdate.NAME) | |||||
.addScriptParam(ListUpdate.FIELD, RuleField.PARAMS.field()) | |||||
.addScriptParam(ListUpdate.VALUE, newParam) | |||||
.addScriptParam(ListUpdate.ID_FIELD, RuleParamField.NAME.field()) | |||||
.addScriptParam(ListUpdate.ID_VALUE, param.getName()) | |||||
.script(ProcessConstants.ES_PLUGIN_LISTUPDATE_SCRIPT_NAME) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD, RuleField.PARAMS.field()) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, newParam) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD, RuleParamField.NAME.field()) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE, param.getName()) | |||||
); | ); | ||||
} | } | ||||
private List<UpdateRequest> nestedDelete(RuleParamDto param, RuleKey key) { | private List<UpdateRequest> nestedDelete(RuleParamDto param, RuleKey key) { | ||||
return ImmutableList.of(new UpdateRequest() | return ImmutableList.of(new UpdateRequest() | ||||
.id(key.toString()) | .id(key.toString()) | ||||
.script(ListUpdate.NAME) | |||||
.addScriptParam(ListUpdate.FIELD, RuleField.PARAMS.field()) | |||||
.addScriptParam(ListUpdate.VALUE, null) | |||||
.addScriptParam(ListUpdate.ID_FIELD, RuleParamField.NAME.field()) | |||||
.addScriptParam(ListUpdate.ID_VALUE, param.getName()) | |||||
.script(ProcessConstants.ES_PLUGIN_LISTUPDATE_SCRIPT_NAME) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_FIELD, RuleField.PARAMS.field()) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_VALUE, null) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_FIELD, RuleParamField.NAME.field()) | |||||
.addScriptParam(ProcessConstants.ES_PLUGIN_LISTUPDATE_ID_VALUE, param.getName()) | |||||
); | ); | ||||
} | } | ||||