All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.script.ScriptSettings Maven / Gradle / Ivy

There is a newer version: 8.14.1
Show newest version
/*
 * 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.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
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;

public class ScriptSettings {

    static final String LEGACY_DEFAULT_LANG = "groovy";

    /**
     * The default script language to use for scripts that are stored in documents that have no script lang set explicitly.
     * This setting is legacy setting and only applies for indices created on ES versions prior to version 5.0
     *
     * This constant will be removed in the next major release.
     */
    @Deprecated
    public static final String LEGACY_SCRIPT_SETTING = "script.legacy.default_lang";

    private static final Map> SCRIPT_TYPE_SETTING_MAP;

    static {
        Map> scriptTypeSettingMap = new HashMap<>();
        for (ScriptType scriptType : ScriptType.values()) {
            scriptTypeSettingMap.put(scriptType, Setting.boolSetting(
                ScriptModes.sourceKey(scriptType),
                scriptType.isDefaultEnabled(),
                Property.NodeScope));
        }
        SCRIPT_TYPE_SETTING_MAP = Collections.unmodifiableMap(scriptTypeSettingMap);
    }

    private final Map> scriptContextSettingMap;
    private final List> scriptLanguageSettings;
    private final Setting defaultLegacyScriptLanguageSetting;

    public ScriptSettings(ScriptEngineRegistry scriptEngineRegistry, ScriptContextRegistry scriptContextRegistry) {
        Map> scriptContextSettingMap = contextSettings(scriptContextRegistry);
        this.scriptContextSettingMap = Collections.unmodifiableMap(scriptContextSettingMap);

        List> scriptLanguageSettings = languageSettings(SCRIPT_TYPE_SETTING_MAP, scriptContextSettingMap, scriptEngineRegistry, scriptContextRegistry);
        this.scriptLanguageSettings = Collections.unmodifiableList(scriptLanguageSettings);

        this.defaultLegacyScriptLanguageSetting = new Setting<>(LEGACY_SCRIPT_SETTING, LEGACY_DEFAULT_LANG, setting -> {
            if (!LEGACY_DEFAULT_LANG.equals(setting) && !scriptEngineRegistry.getRegisteredLanguages().containsKey(setting)) {
                throw new IllegalArgumentException("unregistered default language [" + setting + "]");
            }
            return setting;
        }, Property.NodeScope);
    }

    private static Map> contextSettings(ScriptContextRegistry scriptContextRegistry) {
        Map> scriptContextSettingMap = new HashMap<>();
        for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
            scriptContextSettingMap.put(scriptContext,
                    Setting.boolSetting(ScriptModes.operationKey(scriptContext), false, Property.NodeScope));
        }
        return scriptContextSettingMap;
    }

    private static List> languageSettings(Map> scriptTypeSettingMap,
                                                              Map> scriptContextSettingMap,
                                                              ScriptEngineRegistry scriptEngineRegistry,
                                                              ScriptContextRegistry scriptContextRegistry) {
        final List> scriptModeSettings = new ArrayList<>();

        for (final Class scriptEngineService : scriptEngineRegistry.getRegisteredScriptEngineServices()) {
            if (scriptEngineService == NativeScriptEngineService.class) {
                // native scripts are always enabled, and their settings can not be changed
                continue;
            }
            final String language = scriptEngineRegistry.getLanguage(scriptEngineService);
            for (final ScriptType scriptType : ScriptType.values()) {
                // Top level, like "script.engine.groovy.inline"
                final boolean defaultNonFileScriptMode = scriptEngineRegistry.getDefaultInlineScriptEnableds().get(language);
                boolean defaultLangAndType = defaultNonFileScriptMode;
                // Files are treated differently because they are never default-deny
                if (ScriptType.FILE == scriptType) {
                    defaultLangAndType = ScriptType.FILE.isDefaultEnabled();
                }
                final boolean defaultIfNothingSet = defaultLangAndType;

                Function defaultLangAndTypeFn = settings -> {
                    final Setting globalTypeSetting = scriptTypeSettingMap.get(scriptType);
                    final Setting langAndTypeSetting = Setting.boolSetting(ScriptModes.getGlobalKey(language, scriptType),
                            defaultIfNothingSet, Property.NodeScope);

                    if (langAndTypeSetting.exists(settings)) {
                        // fine-grained e.g. script.engine.groovy.inline
                        return langAndTypeSetting.get(settings).toString();
                    } else if (globalTypeSetting.exists(settings)) {
                        // global type - script.inline
                        return globalTypeSetting.get(settings).toString();
                    } else {
                        return Boolean.toString(defaultIfNothingSet);
                    }
                };

                // Setting for something like "script.engine.groovy.inline"
                final Setting langAndTypeSetting = Setting.boolSetting(ScriptModes.getGlobalKey(language, scriptType),
                        defaultLangAndTypeFn, Property.NodeScope);
                scriptModeSettings.add(langAndTypeSetting);

                for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
                    final String langAndTypeAndContextName = ScriptModes.getKey(language, scriptType, scriptContext);
                    // A function that, given a setting, will return what the default should be. Since the fine-grained script settings
                    // read from a bunch of different places this is implemented in this way.
                    Function defaultSettingFn = settings -> {
                        final Setting globalOpSetting = scriptContextSettingMap.get(scriptContext);
                        final Setting globalTypeSetting = scriptTypeSettingMap.get(scriptType);
                        final Setting langAndTypeAndContextSetting = Setting.boolSetting(langAndTypeAndContextName,
                                defaultIfNothingSet, Property.NodeScope);

                        // fallback logic for script mode settings
                        if (langAndTypeAndContextSetting.exists(settings)) {
                            // like: "script.engine.groovy.inline.aggs: true"
                            return langAndTypeAndContextSetting.get(settings).toString();
                        } else if (langAndTypeSetting.exists(settings)) {
                            // like: "script.engine.groovy.inline: true"
                            return langAndTypeSetting.get(settings).toString();
                        } else if (globalOpSetting.exists(settings)) {
                            // like: "script.aggs: true"
                            return globalOpSetting.get(settings).toString();
                        } else if (globalTypeSetting.exists(settings)) {
                            // like: "script.inline: true"
                            return globalTypeSetting.get(settings).toString();
                        } else {
                            // Nothing is set!
                            return Boolean.toString(defaultIfNothingSet);
                        }
                    };
                    // The actual setting for finest grained script settings
                    Setting setting = Setting.boolSetting(langAndTypeAndContextName, defaultSettingFn, Property.NodeScope);
                    scriptModeSettings.add(setting);
                }
            }
        }
        return scriptModeSettings;
    }

    public List> getSettings() {
        List> settings = new ArrayList<>();
        settings.addAll(SCRIPT_TYPE_SETTING_MAP.values());
        settings.addAll(scriptContextSettingMap.values());
        settings.addAll(scriptLanguageSettings);
        settings.add(defaultLegacyScriptLanguageSetting);
        return settings;
    }

    public Iterable> getScriptLanguageSettings() {
        return scriptLanguageSettings;
    }

    public Setting getDefaultLegacyScriptLanguageSetting() {
        return defaultLegacyScriptLanguageSetting;
    }

    public static String getLegacyDefaultLang(Settings settings) {
        return settings.get(LEGACY_SCRIPT_SETTING, ScriptSettings.LEGACY_DEFAULT_LANG);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy