summaryrefslogtreecommitdiff
path: root/core/src/main/java/org/elasticsearch/script/ScriptSettings.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/java/org/elasticsearch/script/ScriptSettings.java')
-rw-r--r--core/src/main/java/org/elasticsearch/script/ScriptSettings.java165
1 files changed, 165 insertions, 0 deletions
diff --git a/core/src/main/java/org/elasticsearch/script/ScriptSettings.java b/core/src/main/java/org/elasticsearch/script/ScriptSettings.java
new file mode 100644
index 0000000000..8ececfe25b
--- /dev/null
+++ b/core/src/main/java/org/elasticsearch/script/ScriptSettings.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.script;
+
+import org.elasticsearch.common.collect.Tuple;
+import org.elasticsearch.common.settings.Setting;
+import org.elasticsearch.common.settings.Settings;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class ScriptSettings {
+
+ public final static String DEFAULT_LANG = "groovy";
+
+ private final static Map<ScriptService.ScriptType, Setting<ScriptMode>> SCRIPT_TYPE_SETTING_MAP;
+
+ static {
+ Map<ScriptService.ScriptType, Setting<ScriptMode>> scriptTypeSettingMap = new HashMap<>();
+ for (ScriptService.ScriptType scriptType : ScriptService.ScriptType.values()) {
+ scriptTypeSettingMap.put(scriptType, new Setting<>(
+ ScriptModes.sourceKey(scriptType),
+ scriptType.getDefaultScriptMode().getMode(),
+ ScriptMode::parse,
+ false,
+ Setting.Scope.CLUSTER));
+ }
+ SCRIPT_TYPE_SETTING_MAP = Collections.unmodifiableMap(scriptTypeSettingMap);
+ }
+
+ private final Map<ScriptContext, Setting<ScriptMode>> scriptContextSettingMap;
+ private final List<Setting<ScriptMode>> scriptLanguageSettings;
+ private final Setting<String> defaultScriptLanguageSetting;
+
+ public ScriptSettings(ScriptEngineRegistry scriptEngineRegistry, ScriptContextRegistry scriptContextRegistry) {
+ Map<ScriptContext, Setting<ScriptMode>> scriptContextSettingMap = contextSettings(scriptContextRegistry);
+ this.scriptContextSettingMap = Collections.unmodifiableMap(scriptContextSettingMap);
+
+ List<Setting<ScriptMode>> scriptLanguageSettings = languageSettings(SCRIPT_TYPE_SETTING_MAP, scriptContextSettingMap, scriptEngineRegistry, scriptContextRegistry);
+ this.scriptLanguageSettings = Collections.unmodifiableList(scriptLanguageSettings);
+
+ this.defaultScriptLanguageSetting = new Setting<>("script.default_lang", DEFAULT_LANG, setting -> {
+ if (!"groovy".equals(setting) && !scriptEngineRegistry.getRegisteredLanguages().containsKey(setting)) {
+ throw new IllegalArgumentException("unregistered default language [" + setting + "]");
+ }
+ return setting;
+ }, false, Setting.Scope.CLUSTER);
+ }
+
+ private static Map<ScriptContext, Setting<ScriptMode>> contextSettings(ScriptContextRegistry scriptContextRegistry) {
+ Map<ScriptContext, Setting<ScriptMode>> scriptContextSettingMap = new HashMap<>();
+ for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
+ scriptContextSettingMap.put(scriptContext, new Setting<>(
+ ScriptModes.operationKey(scriptContext),
+ ScriptMode.OFF.getMode(),
+ ScriptMode::parse,
+ false,
+ Setting.Scope.CLUSTER
+ ));
+ }
+ return scriptContextSettingMap;
+ }
+
+ private static List<Setting<ScriptMode>> languageSettings(
+ Map<ScriptService.ScriptType, Setting<ScriptMode>> scriptTypeSettingMap,
+ Map<ScriptContext, Setting<ScriptMode>> scriptContextSettingMap,
+ ScriptEngineRegistry scriptEngineRegistry,
+ ScriptContextRegistry scriptContextRegistry) {
+ List<Setting<ScriptMode>> scriptModeSettings = new ArrayList<>();
+ for (Class<? extends ScriptEngineService> scriptEngineService : scriptEngineRegistry.getRegisteredScriptEngineServices()) {
+ List<String> languages = scriptEngineRegistry.getLanguages(scriptEngineService);
+
+ for (String language : languages) {
+ if (NativeScriptEngineService.TYPES.contains(language)) {
+ // native scripts are always enabled, and their settings can not be changed
+ continue;
+ }
+ for (ScriptService.ScriptType scriptType : ScriptService.ScriptType.values()) {
+ for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
+ Function<Settings, String> defaultSetting = settings -> {
+ // fallback logic for script mode settings
+
+ // the first fallback is other types registered by the same script engine service
+ // e.g., "py.inline.aggs" is in the settings but a script with lang "python" is executed
+ Map<String, List<String>> languageSettings =
+ languages
+ .stream()
+ .map(lang -> Tuple.tuple(lang, settings.get(ScriptModes.getKey(lang, scriptType, scriptContext))))
+ .filter(tuple -> tuple.v2() != null)
+ .collect(Collectors.groupingBy(Tuple::v2, Collectors.mapping(Tuple::v1, Collectors.toList())));
+ if (!languageSettings.isEmpty()) {
+ if (languageSettings.size() > 1) {
+ throw new IllegalArgumentException("conflicting settings [" + languageSettings.toString() + "] for language [" + language + "]");
+ }
+ return languageSettings.keySet().iterator().next();
+ }
+
+ // the next fallback is global operation-based settings (e.g., "script.aggs: false")
+ Setting<ScriptMode> setting = scriptContextSettingMap.get(scriptContext);
+ if (setting.exists(settings)) {
+ return setting.get(settings).getMode();
+ }
+
+ // the next fallback is global source-based settings (e.g., "script.inline: false")
+ Setting<ScriptMode> scriptTypeSetting = scriptTypeSettingMap.get(scriptType);
+ if (scriptTypeSetting.exists(settings)) {
+ return scriptTypeSetting.get(settings).getMode();
+ }
+
+ // the final fallback is the default for the type
+ return scriptType.getDefaultScriptMode().toString();
+ };
+ Setting<ScriptMode> setting =
+ new Setting<>(
+ ScriptModes.getKey(language, scriptType, scriptContext),
+ defaultSetting,
+ ScriptMode::parse,
+ false,
+ Setting.Scope.CLUSTER);
+ scriptModeSettings.add(setting);
+ }
+ }
+ }
+ }
+ return scriptModeSettings;
+ }
+
+ public Iterable<Setting<ScriptMode>> getScriptTypeSettings() {
+ return Collections.unmodifiableCollection(SCRIPT_TYPE_SETTING_MAP.values());
+ }
+
+ public Iterable<Setting<ScriptMode>> getScriptContextSettings() {
+ return Collections.unmodifiableCollection(scriptContextSettingMap.values());
+ }
+
+ public Iterable<Setting<ScriptMode>> getScriptLanguageSettings() {
+ return scriptLanguageSettings;
+ }
+
+ public Setting<String> getDefaultScriptLanguageSetting() {
+ return defaultScriptLanguageSetting;
+ }
+}