diff --git a/core/src/main/java/org/elasticsearch/node/Node.java b/core/src/main/java/org/elasticsearch/node/Node.java index dae76019ed4..ea9d0be1eec 100644 --- a/core/src/main/java/org/elasticsearch/node/Node.java +++ b/core/src/main/java/org/elasticsearch/node/Node.java @@ -188,11 +188,12 @@ public class Node implements Releasable { modules.add(pluginModule); } modules.add(new PluginsModule(pluginsService)); - modules.add(new SettingsModule(this.settings, settingsFilter)); + SettingsModule settingsModule = new SettingsModule(this.settings, settingsFilter); + modules.add(settingsModule); modules.add(new EnvironmentModule(environment)); modules.add(new NodeModule(this, monitorService)); modules.add(new NetworkModule(networkService, settings, false, namedWriteableRegistry)); - modules.add(new ScriptModule(this.settings)); + modules.add(new ScriptModule(settingsModule)); modules.add(new NodeEnvironmentModule(nodeEnvironment)); modules.add(new ClusterNameModule(this.settings)); modules.add(new ThreadPoolModule(threadPool)); diff --git a/core/src/main/java/org/elasticsearch/script/NativeScriptEngineService.java b/core/src/main/java/org/elasticsearch/script/NativeScriptEngineService.java index 19bc4478884..62e5d7167a8 100644 --- a/core/src/main/java/org/elasticsearch/script/NativeScriptEngineService.java +++ b/core/src/main/java/org/elasticsearch/script/NativeScriptEngineService.java @@ -27,6 +27,8 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.search.lookup.SearchLookup; import java.io.IOException; +import java.util.Collections; +import java.util.List; import java.util.Map; import static java.util.Collections.unmodifiableMap; @@ -38,6 +40,8 @@ public class NativeScriptEngineService extends AbstractComponent implements Scri public static final String NAME = "native"; + public static final List TYPES = Collections.singletonList(NAME); + private final Map scripts; @Inject @@ -47,13 +51,13 @@ public class NativeScriptEngineService extends AbstractComponent implements Scri } @Override - public String[] types() { - return new String[]{NAME}; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return new String[0]; + public List extensions() { + return Collections.emptyList(); } @Override diff --git a/core/src/main/java/org/elasticsearch/script/ScriptEngineRegistry.java b/core/src/main/java/org/elasticsearch/script/ScriptEngineRegistry.java new file mode 100644 index 00000000000..91891b58281 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/script/ScriptEngineRegistry.java @@ -0,0 +1,88 @@ +/* + * 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 java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public class ScriptEngineRegistry { + + private final Map, List> registeredScriptEngineServices; + private final Map> registeredLanguages; + + public ScriptEngineRegistry(Iterable registrations) { + Objects.requireNonNull(registrations); + Map, List> registeredScriptEngineServices = new HashMap<>(); + Map> registeredLanguages = new HashMap<>(); + for (ScriptEngineRegistration registration : registrations) { + List languages = + registeredScriptEngineServices.putIfAbsent(registration.getScriptEngineService(), Collections.unmodifiableList(registration.getScriptEngineLanguages())); + if (languages != null) { + throw new IllegalArgumentException("script engine service [" + registration.getScriptEngineService() + "] already registered for languages [" + String.join(",", languages) + "]"); + } + + for (String language : registration.getScriptEngineLanguages()) { + Class scriptEngineServiceClazz = + registeredLanguages.putIfAbsent(language, registration.getScriptEngineService()); + if (scriptEngineServiceClazz != null) { + throw new IllegalArgumentException("scripting language [" + language + "] already registered for script engine service [" + scriptEngineServiceClazz.getCanonicalName() + "]"); + } + } + } + + this.registeredScriptEngineServices = Collections.unmodifiableMap(registeredScriptEngineServices); + this.registeredLanguages = Collections.unmodifiableMap(registeredLanguages); + } + + Iterable> getRegisteredScriptEngineServices() { + return registeredScriptEngineServices.keySet(); + } + + List getLanguages(Class scriptEngineService) { + Objects.requireNonNull(scriptEngineService); + return registeredScriptEngineServices.get(scriptEngineService); + } + + Map> getRegisteredLanguages() { + return registeredLanguages; + } + + public static class ScriptEngineRegistration { + private final Class scriptEngineService; + private final List scriptEngineLanguages; + + public ScriptEngineRegistration(Class scriptEngineService, List scriptEngineLanguages) { + this.scriptEngineService = scriptEngineService; + this.scriptEngineLanguages = scriptEngineLanguages; + } + + Class getScriptEngineService() { + return scriptEngineService; + } + + List getScriptEngineLanguages() { + return scriptEngineLanguages; + } + } + +} diff --git a/core/src/main/java/org/elasticsearch/script/ScriptEngineService.java b/core/src/main/java/org/elasticsearch/script/ScriptEngineService.java index 41befc9406f..a2106c1bb9b 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptEngineService.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptEngineService.java @@ -23,6 +23,7 @@ import org.elasticsearch.common.Nullable; import org.elasticsearch.search.lookup.SearchLookup; import java.io.Closeable; +import java.util.List; import java.util.Map; /** @@ -30,9 +31,9 @@ import java.util.Map; */ public interface ScriptEngineService extends Closeable { - String[] types(); + List types(); - String[] extensions(); + List extensions(); boolean sandboxed(); diff --git a/core/src/main/java/org/elasticsearch/script/ScriptMode.java b/core/src/main/java/org/elasticsearch/script/ScriptMode.java index b35dda716e4..12caf7a0878 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptMode.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptMode.java @@ -19,37 +19,48 @@ package org.elasticsearch.script; -import org.elasticsearch.common.Booleans; - -import java.util.Locale; +import java.util.HashMap; +import java.util.Map; /** * Mode for a specific script, used for script settings. - * Defines whether a certain script or catefory of scripts can be executed or not, or whether it can + * Defines whether a certain script or category of scripts can be executed or not, or whether it can * only be executed by a sandboxed scripting language. */ enum ScriptMode { - ON, - OFF, - SANDBOX; + ON("on"), + OFF("off"), + SANDBOX("sandbox"); - static ScriptMode parse(String input) { - input = input.toLowerCase(Locale.ROOT); - if (Booleans.isExplicitTrue(input)) { - return ON; - } - if (Booleans.isExplicitFalse(input)) { - return OFF; - } - if (SANDBOX.toString().equals(input)) { - return SANDBOX; - } - throw new IllegalArgumentException("script mode [" + input + "] not supported"); + private final String mode; + + ScriptMode(String mode) { + this.mode = mode; } + private static final Map SCRIPT_MODES; + + static { + SCRIPT_MODES = new HashMap<>(); + for (ScriptMode scriptMode : ScriptMode.values()) { + SCRIPT_MODES.put(scriptMode.mode, scriptMode); + } + } + + static ScriptMode parse(String input) { + ScriptMode scriptMode = SCRIPT_MODES.get(input); + if (scriptMode == null) { + throw new IllegalArgumentException("script mode [" + input + "] not supported"); + } + return scriptMode; + } + + public String getMode() { + return mode; + } @Override public String toString() { - return name().toLowerCase(Locale.ROOT); + return mode; } } diff --git a/core/src/main/java/org/elasticsearch/script/ScriptModes.java b/core/src/main/java/org/elasticsearch/script/ScriptModes.java index cfa3a592d8e..baaec009350 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptModes.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptModes.java @@ -19,127 +19,32 @@ package org.elasticsearch.script; -import org.elasticsearch.common.Strings; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.script.ScriptService.ScriptType; +import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.Set; import java.util.TreeMap; -import static java.util.Collections.unmodifiableMap; - /** * Holds the {@link org.elasticsearch.script.ScriptMode}s for each of the different scripting languages available, * each script source and each scripted operation. */ public class ScriptModes { - static final String SCRIPT_SETTINGS_PREFIX = "script."; - static final String ENGINE_SETTINGS_PREFIX = "script.engine"; + private static final String SCRIPT_SETTINGS_PREFIX = "script"; + private static final String ENGINE_SETTINGS_PREFIX = "script.engine"; final Map scriptModes; - ScriptModes(Map scriptEngines, ScriptContextRegistry scriptContextRegistry, Settings settings) { - //filter out the native engine as we don't want to apply fine grained settings to it. - //native scripts are always on as they are static by definition. - Map filteredEngines = new HashMap<>(scriptEngines); - filteredEngines.remove(NativeScriptEngineService.NAME); - this.scriptModes = buildScriptModeSettingsMap(settings, filteredEngines, scriptContextRegistry); - } - - private static Map buildScriptModeSettingsMap(Settings settings, Map scriptEngines, ScriptContextRegistry scriptContextRegistry) { - HashMap scriptModesMap = new HashMap<>(); - - //file scripts are enabled by default, for any language - addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, ScriptType.FILE, ScriptMode.ON, scriptModesMap); - //indexed scripts are enabled by default only for sandboxed languages - addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, ScriptType.INDEXED, ScriptMode.SANDBOX, scriptModesMap); - //dynamic scripts are enabled by default only for sandboxed languages - addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, ScriptType.INLINE, ScriptMode.SANDBOX, scriptModesMap); - - processSourceBasedGlobalSettings(settings, scriptEngines, scriptContextRegistry, scriptModesMap); - processOperationBasedGlobalSettings(settings, scriptEngines, scriptContextRegistry, scriptModesMap); - processEngineSpecificSettings(settings, scriptEngines, scriptContextRegistry, scriptModesMap); - return unmodifiableMap(scriptModesMap); - } - - private static void processSourceBasedGlobalSettings(Settings settings, Map scriptEngines, ScriptContextRegistry scriptContextRegistry, Map scriptModes) { - //read custom source based settings for all operations (e.g. script.indexed: on) - for (ScriptType scriptType : ScriptType.values()) { - String scriptTypeSetting = settings.get(SCRIPT_SETTINGS_PREFIX + scriptType); - if (Strings.hasLength(scriptTypeSetting)) { - ScriptMode scriptTypeMode = ScriptMode.parse(scriptTypeSetting); - addGlobalScriptTypeModes(scriptEngines.keySet(), scriptContextRegistry, scriptType, scriptTypeMode, scriptModes); - } + ScriptModes(ScriptSettings scriptSettings, Settings settings) { + HashMap scriptModes = new HashMap<>(); + for (Setting scriptModeSetting : scriptSettings.getScriptLanguageSettings()) { + scriptModes.put(scriptModeSetting.getKey(), scriptModeSetting.get(settings)); } - } - - private static void processOperationBasedGlobalSettings(Settings settings, Map scriptEngines, ScriptContextRegistry scriptContextRegistry, Map scriptModes) { - //read custom op based settings for all sources (e.g. script.aggs: off) - //op based settings take precedence over source based settings, hence they get expanded later - for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) { - ScriptMode scriptMode = getScriptContextMode(settings, SCRIPT_SETTINGS_PREFIX, scriptContext); - if (scriptMode != null) { - addGlobalScriptContextModes(scriptEngines.keySet(), scriptContext, scriptMode, scriptModes); - } - } - } - - private static void processEngineSpecificSettings(Settings settings, Map scriptEngines, ScriptContextRegistry scriptContextRegistry, Map scriptModes) { - Map langGroupedSettings = settings.getGroups(ENGINE_SETTINGS_PREFIX, true); - for (Map.Entry langSettings : langGroupedSettings.entrySet()) { - //read engine specific settings that refer to a non existing script lang will be ignored - ScriptEngineService scriptEngineService = scriptEngines.get(langSettings.getKey()); - if (scriptEngineService != null) { - for (ScriptType scriptType : ScriptType.values()) { - String scriptTypePrefix = scriptType + "."; - for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) { - ScriptMode scriptMode = getScriptContextMode(langSettings.getValue(), scriptTypePrefix, scriptContext); - if (scriptMode != null) { - addScriptMode(scriptEngineService, scriptType, scriptContext, scriptMode, scriptModes); - } - } - } - } - } - } - - private static ScriptMode getScriptContextMode(Settings settings, String prefix, ScriptContext scriptContext) { - String settingValue = settings.get(prefix + scriptContext.getKey()); - if (Strings.hasLength(settingValue)) { - return ScriptMode.parse(settingValue); - } - return null; - } - - private static void addGlobalScriptTypeModes(Set langs, ScriptContextRegistry scriptContextRegistry, ScriptType scriptType, ScriptMode scriptMode, Map scriptModes) { - for (String lang : langs) { - for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) { - addScriptMode(lang, scriptType, scriptContext, scriptMode, scriptModes); - } - } - } - - private static void addGlobalScriptContextModes(Set langs, ScriptContext scriptContext, ScriptMode scriptMode, Map scriptModes) { - for (String lang : langs) { - for (ScriptType scriptType : ScriptType.values()) { - addScriptMode(lang, scriptType, scriptContext, scriptMode, scriptModes); - } - } - } - - private static void addScriptMode(ScriptEngineService scriptEngineService, ScriptType scriptType, ScriptContext scriptContext, - ScriptMode scriptMode, Map scriptModes) { - //expand the lang specific settings to all of the different names given to each scripting language - for (String scriptEngineName : scriptEngineService.types()) { - addScriptMode(scriptEngineName, scriptType, scriptContext, scriptMode, scriptModes); - } - } - - private static void addScriptMode(String lang, ScriptType scriptType, ScriptContext scriptContext, ScriptMode scriptMode, Map scriptModes) { - scriptModes.put(ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext.getKey(), scriptMode); + this.scriptModes = Collections.unmodifiableMap(scriptModes); } /** @@ -156,13 +61,25 @@ public class ScriptModes { if (NativeScriptEngineService.NAME.equals(lang)) { return ScriptMode.ON; } - ScriptMode scriptMode = scriptModes.get(ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext.getKey()); + ScriptMode scriptMode = scriptModes.get(getKey(lang, scriptType, scriptContext)); if (scriptMode == null) { throw new IllegalArgumentException("script mode not found for lang [" + lang + "], script_type [" + scriptType + "], operation [" + scriptContext.getKey() + "]"); } return scriptMode; } + static String operationKey(ScriptContext scriptContext) { + return SCRIPT_SETTINGS_PREFIX + "." + scriptContext.getKey(); + } + + static String sourceKey(ScriptType scriptType) { + return SCRIPT_SETTINGS_PREFIX + "." + scriptType.getScriptType(); + } + + static String getKey(String lang, ScriptType scriptType, ScriptContext scriptContext) { + return ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext.getKey(); + } + @Override public String toString() { //order settings by key before printing them out, for readability diff --git a/core/src/main/java/org/elasticsearch/script/ScriptModule.java b/core/src/main/java/org/elasticsearch/script/ScriptModule.java index f3bdad64b66..f4700440cd9 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptModule.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptModule.java @@ -22,12 +22,14 @@ package org.elasticsearch.script; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.multibindings.MapBinder; import org.elasticsearch.common.inject.multibindings.Multibinder; -import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.settings.Setting; +import org.elasticsearch.common.settings.SettingsModule; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; /** * An {@link org.elasticsearch.common.inject.Module} which manages {@link ScriptEngineService}s, as well @@ -35,20 +37,25 @@ import java.util.Map; */ public class ScriptModule extends AbstractModule { - private final Settings settings; + private final SettingsModule settingsModule; - private final List> scriptEngines = new ArrayList<>(); + private final List scriptEngineRegistrations = new ArrayList<>(); + + { + scriptEngineRegistrations.add(new ScriptEngineRegistry.ScriptEngineRegistration(NativeScriptEngineService.class, NativeScriptEngineService.TYPES)); + } private final Map> scripts = new HashMap<>(); private final List customScriptContexts = new ArrayList<>(); - public ScriptModule(Settings settings) { - this.settings = settings; + public ScriptModule(SettingsModule settingsModule) { + this.settingsModule = settingsModule; } - public void addScriptEngine(Class scriptEngine) { - scriptEngines.add(scriptEngine); + public void addScriptEngine(ScriptEngineRegistry.ScriptEngineRegistration scriptEngineRegistration) { + Objects.requireNonNull(scriptEngineRegistration); + scriptEngineRegistrations.add(scriptEngineRegistration); } public void registerScript(String name, Class script) { @@ -74,11 +81,22 @@ public class ScriptModule extends AbstractModule { Multibinder multibinder = Multibinder.newSetBinder(binder(), ScriptEngineService.class); multibinder.addBinding().to(NativeScriptEngineService.class); - for (Class scriptEngine : scriptEngines) { - multibinder.addBinding().to(scriptEngine).asEagerSingleton(); + for (ScriptEngineRegistry.ScriptEngineRegistration scriptEngineRegistration : scriptEngineRegistrations) { + multibinder.addBinding().to(scriptEngineRegistration.getScriptEngineService()).asEagerSingleton(); } - bind(ScriptContextRegistry.class).toInstance(new ScriptContextRegistry(customScriptContexts)); + ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customScriptContexts); + ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(scriptEngineRegistrations); + + ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); + + scriptSettings.getScriptTypeSettings().forEach(settingsModule::registerSetting); + scriptSettings.getScriptContextSettings().forEach(settingsModule::registerSetting); + scriptSettings.getScriptLanguageSettings().forEach(settingsModule::registerSetting); + + bind(ScriptContextRegistry.class).toInstance(scriptContextRegistry); + bind(ScriptEngineRegistry.class).toInstance(scriptEngineRegistry); + bind(ScriptSettings.class).toInstance(scriptSettings); bind(ScriptService.class).asEagerSingleton(); } } diff --git a/core/src/main/java/org/elasticsearch/script/ScriptService.java b/core/src/main/java/org/elasticsearch/script/ScriptService.java index 87b1911a1f4..3e40c0b1d8c 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptService.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptService.java @@ -72,6 +72,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentMap; @@ -138,8 +139,11 @@ public class ScriptService extends AbstractComponent implements Closeable { @Inject public ScriptService(Settings settings, Environment env, Set scriptEngines, - ResourceWatcherService resourceWatcherService, ScriptContextRegistry scriptContextRegistry) throws IOException { + ResourceWatcherService resourceWatcherService, ScriptEngineRegistry scriptEngineRegistry, ScriptContextRegistry scriptContextRegistry, ScriptSettings scriptSettings) throws IOException { super(settings); + Objects.requireNonNull(scriptEngineRegistry); + Objects.requireNonNull(scriptContextRegistry); + Objects.requireNonNull(scriptSettings); this.parseFieldMatcher = new ParseFieldMatcher(settings); if (Strings.hasLength(settings.get(DISABLE_DYNAMIC_SCRIPTING_SETTING))) { throw new IllegalArgumentException(DISABLE_DYNAMIC_SCRIPTING_SETTING + " is not a supported setting, replace with fine-grained script settings. \n" + @@ -168,8 +172,8 @@ public class ScriptService extends AbstractComponent implements Closeable { Map enginesByLangBuilder = new HashMap<>(); Map enginesByExtBuilder = new HashMap<>(); for (ScriptEngineService scriptEngine : scriptEngines) { - for (String type : scriptEngine.types()) { - enginesByLangBuilder.put(type, scriptEngine); + for (String language : scriptEngineRegistry.getLanguages(scriptEngine.getClass())) { + enginesByLangBuilder.put(language, scriptEngine); } for (String ext : scriptEngine.extensions()) { enginesByExtBuilder.put(ext, scriptEngine); @@ -178,7 +182,7 @@ public class ScriptService extends AbstractComponent implements Closeable { this.scriptEnginesByLang = unmodifiableMap(enginesByLangBuilder); this.scriptEnginesByExt = unmodifiableMap(enginesByExtBuilder); - this.scriptModes = new ScriptModes(this.scriptEnginesByLang, scriptContextRegistry, settings); + this.scriptModes = new ScriptModes(scriptSettings, settings); // add file watcher for static scripts scriptsDirectory = env.scriptsFile(); @@ -538,12 +542,12 @@ public class ScriptService extends AbstractComponent implements Closeable { try { //we don't know yet what the script will be used for, but if all of the operations for this lang // with file scripts are disabled, it makes no sense to even compile it and cache it. - if (isAnyScriptContextEnabled(engineService.types()[0], engineService, ScriptType.FILE)) { + if (isAnyScriptContextEnabled(engineService.types().get(0), engineService, ScriptType.FILE)) { logger.info("compiling script file [{}]", file.toAbsolutePath()); try(InputStreamReader reader = new InputStreamReader(Files.newInputStream(file), StandardCharsets.UTF_8)) { String script = Streams.copyToString(reader); CacheKey cacheKey = new CacheKey(engineService, scriptNameExt.v1(), null, Collections.emptyMap()); - staticCache.put(cacheKey, new CompiledScript(ScriptType.FILE, scriptNameExt.v1(), engineService.types()[0], engineService.compile(script, Collections.emptyMap()))); + staticCache.put(cacheKey, new CompiledScript(ScriptType.FILE, scriptNameExt.v1(), engineService.types().get(0), engineService.compile(script, Collections.emptyMap()))); scriptMetrics.onCompilation(); } } else { @@ -585,14 +589,16 @@ public class ScriptService extends AbstractComponent implements Closeable { * - loaded from an index * - loaded from file */ - public static enum ScriptType { + public enum ScriptType { - INLINE(0, "inline"), - INDEXED(1, "id"), - FILE(2, "file"); + INLINE(0, "inline", "inline", ScriptMode.SANDBOX), + INDEXED(1, "id", "indexed", ScriptMode.SANDBOX), + FILE(2, "file", "file", ScriptMode.ON); private final int val; private final ParseField parseField; + private final String scriptType; + private final ScriptMode defaultScriptMode; public static ScriptType readFrom(StreamInput in) throws IOException { int scriptTypeVal = in.readVInt(); @@ -613,19 +619,30 @@ public class ScriptService extends AbstractComponent implements Closeable { } } - private ScriptType(int val, String name) { + ScriptType(int val, String name, String scriptType, ScriptMode defaultScriptMode) { this.val = val; this.parseField = new ParseField(name); + this.scriptType = scriptType; + this.defaultScriptMode = defaultScriptMode; } public ParseField getParseField() { return parseField; } + public ScriptMode getDefaultScriptMode() { + return defaultScriptMode; + } + + public String getScriptType() { + return scriptType; + } + @Override public String toString() { return name().toLowerCase(Locale.ROOT); } + } private static final class CacheKey { @@ -635,7 +652,7 @@ public class ScriptService extends AbstractComponent implements Closeable { final Map params; private CacheKey(final ScriptEngineService service, final String name, final String code, final Map params) { - this.lang = service.types()[0]; + this.lang = service.types().get(0); this.name = name; this.code = code; this.params = params; 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 00000000000..99418f082fb --- /dev/null +++ b/core/src/main/java/org/elasticsearch/script/ScriptSettings.java @@ -0,0 +1,151 @@ +/* + * 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 { + + private final static Map> SCRIPT_TYPE_SETTING_MAP; + + static { + Map> 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> scriptContextSettingMap; + private final List> scriptLanguageSettings; + + 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); + } + + private static Map> contextSettings(ScriptContextRegistry scriptContextRegistry) { + Map> 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> languageSettings( + Map> scriptTypeSettingMap, + Map> scriptContextSettingMap, + ScriptEngineRegistry scriptEngineRegistry, + ScriptContextRegistry scriptContextRegistry) { + List> scriptModeSettings = new ArrayList<>(); + for (Class scriptEngineService : scriptEngineRegistry.getRegisteredScriptEngineServices()) { + List 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 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> 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: off") + Setting 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: off") + Setting 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 setting = + new Setting<>( + ScriptModes.getKey(language, scriptType, scriptContext), + defaultSetting, + ScriptMode::parse, + false, + Setting.Scope.CLUSTER); + scriptModeSettings.add(setting); + } + } + } + } + return scriptModeSettings; + } + + public Iterable> getScriptTypeSettings() { + return Collections.unmodifiableCollection(SCRIPT_TYPE_SETTING_MAP.values()); + } + + public Iterable> getScriptContextSettings() { + return Collections.unmodifiableCollection(scriptContextSettingMap.values()); + } + + public Iterable> getScriptLanguageSettings() { + return scriptLanguageSettings; + } +} diff --git a/core/src/test/java/org/elasticsearch/index/IndexModuleTests.java b/core/src/test/java/org/elasticsearch/index/IndexModuleTests.java index 26656296498..582c4f4ebe7 100644 --- a/core/src/test/java/org/elasticsearch/index/IndexModuleTests.java +++ b/core/src/test/java/org/elasticsearch/index/IndexModuleTests.java @@ -18,15 +18,6 @@ */ package org.elasticsearch.index; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; - import org.apache.lucene.index.AssertingDirectoryReader; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.FieldInvertState; @@ -70,7 +61,9 @@ import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCacheListener; import org.elasticsearch.indices.mapper.MapperRegistry; import org.elasticsearch.indices.query.IndicesQueriesRegistry; import org.elasticsearch.script.ScriptContextRegistry; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineService; +import org.elasticsearch.script.ScriptSettings; import org.elasticsearch.script.ScriptService; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.IndexSettingsModule; @@ -78,6 +71,14 @@ import org.elasticsearch.test.engine.MockEngineFactory; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.watcher.ResourceWatcherService; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; + import static java.util.Collections.emptyMap; public class IndexModuleTests extends ESTestCase { @@ -106,9 +107,12 @@ public class IndexModuleTests extends ESTestCase { PageCacheRecycler recycler = new PageCacheRecycler(settings, threadPool); BigArrays bigArrays = new BigArrays(recycler, circuitBreakerService); IndicesFieldDataCache indicesFieldDataCache = new IndicesFieldDataCache(settings, new IndicesFieldDataCacheListener(circuitBreakerService), threadPool); - Set scriptEngines = new HashSet<>(); + Set scriptEngines = Collections.emptySet(); scriptEngines.addAll(Arrays.asList(scriptEngineServices)); - ScriptService scriptService = new ScriptService(settings, environment, scriptEngines, new ResourceWatcherService(settings, threadPool), new ScriptContextRegistry(Collections.emptyList())); + ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.emptyList()); + ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); + ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); + ScriptService scriptService = new ScriptService(settings, environment, scriptEngines, new ResourceWatcherService(settings, threadPool), scriptEngineRegistry, scriptContextRegistry, scriptSettings); IndicesQueriesRegistry indicesQueriesRegistry = new IndicesQueriesRegistry(settings, emptyMap()); return new NodeServicesProvider(threadPool, indicesQueryCache, null, warmer, bigArrays, client, scriptService, indicesQueriesRegistry, indicesFieldDataCache, circuitBreakerService); } diff --git a/core/src/test/java/org/elasticsearch/index/query/AbstractQueryTestCase.java b/core/src/test/java/org/elasticsearch/index/query/AbstractQueryTestCase.java index 456a630ea03..7aba2997b20 100644 --- a/core/src/test/java/org/elasticsearch/index/query/AbstractQueryTestCase.java +++ b/core/src/test/java/org/elasticsearch/index/query/AbstractQueryTestCase.java @@ -22,7 +22,6 @@ package org.elasticsearch.index.query; import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.io.JsonStringEncoder; - import org.apache.lucene.search.BoostQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; @@ -88,7 +87,9 @@ import org.elasticsearch.script.MockScriptEngine; import org.elasticsearch.script.Script.ScriptParseException; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptContextRegistry; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineService; +import org.elasticsearch.script.ScriptSettings; import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.ScriptService; import org.elasticsearch.search.SearchModule; @@ -214,7 +215,7 @@ public abstract class AbstractQueryTestCase> bindMapperExtension(); } }, - new ScriptModule(settings) { + new ScriptModule(settingsModule) { @Override protected void configure() { Settings settings = Settings.builder() @@ -228,9 +229,14 @@ public abstract class AbstractQueryTestCase> Set engines = new HashSet<>(); engines.add(mockScriptEngine); List customContexts = new ArrayList<>(); - bind(ScriptContextRegistry.class).toInstance(new ScriptContextRegistry(customContexts)); + ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES))); + bind(ScriptEngineRegistry.class).toInstance(scriptEngineRegistry); + ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts); + bind(ScriptContextRegistry.class).toInstance(scriptContextRegistry); + ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); + bind(ScriptSettings.class).toInstance(scriptSettings); try { - ScriptService scriptService = new ScriptService(settings, new Environment(settings), engines, null, new ScriptContextRegistry(customContexts)); + ScriptService scriptService = new ScriptService(settings, new Environment(settings), engines, null, scriptEngineRegistry, scriptContextRegistry, scriptSettings); bind(ScriptService.class).toInstance(scriptService); } catch(IOException e) { throw new IllegalStateException("error while binding ScriptService", e); diff --git a/core/src/test/java/org/elasticsearch/script/FileScriptTests.java b/core/src/test/java/org/elasticsearch/script/FileScriptTests.java index 0fdb42b5bd6..5e8db069dd8 100644 --- a/core/src/test/java/org/elasticsearch/script/FileScriptTests.java +++ b/core/src/test/java/org/elasticsearch/script/FileScriptTests.java @@ -45,13 +45,16 @@ public class FileScriptTests extends ESTestCase { .put(settings) .build(); Set engines = new HashSet<>(Collections.singletonList(new MockScriptEngine())); - return new ScriptService(settings, new Environment(settings), engines, null, new ScriptContextRegistry(Collections.emptyList())); + ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES))); + ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); + ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); + return new ScriptService(settings, new Environment(settings), engines, null, scriptEngineRegistry, scriptContextRegistry, scriptSettings); } public void testFileScriptFound() throws Exception { ContextAndHeaderHolder contextAndHeaders = new ContextAndHeaderHolder(); Settings settings = Settings.builder() - .put("script.engine." + MockScriptEngine.NAME + ".file.aggs", false).build(); + .put("script.engine." + MockScriptEngine.NAME + ".file.aggs", "off").build(); ScriptService scriptService = makeScriptService(settings); Script script = new Script("script1", ScriptService.ScriptType.FILE, MockScriptEngine.NAME, null); assertNotNull(scriptService.compile(script, ScriptContext.Standard.SEARCH, contextAndHeaders, Collections.emptyMap())); @@ -60,10 +63,10 @@ public class FileScriptTests extends ESTestCase { public void testAllOpsDisabled() throws Exception { ContextAndHeaderHolder contextAndHeaders = new ContextAndHeaderHolder(); Settings settings = Settings.builder() - .put("script.engine." + MockScriptEngine.NAME + ".file.aggs", false) - .put("script.engine." + MockScriptEngine.NAME + ".file.search", false) - .put("script.engine." + MockScriptEngine.NAME + ".file.mapping", false) - .put("script.engine." + MockScriptEngine.NAME + ".file.update", false) + .put("script.engine." + MockScriptEngine.NAME + ".file.aggs", "false") + .put("script.engine." + MockScriptEngine.NAME + ".file.search", "false") + .put("script.engine." + MockScriptEngine.NAME + ".file.mapping", "false") + .put("script.engine." + MockScriptEngine.NAME + ".file.update", "false") .put("script.engine." + MockScriptEngine.NAME + ".file.ingest", false).build(); ScriptService scriptService = makeScriptService(settings); Script script = new Script("script1", ScriptService.ScriptType.FILE, MockScriptEngine.NAME, null); diff --git a/core/src/test/java/org/elasticsearch/script/NativeScriptTests.java b/core/src/test/java/org/elasticsearch/script/NativeScriptTests.java index 0e8d477d0e3..a6db61b88aa 100644 --- a/core/src/test/java/org/elasticsearch/script/NativeScriptTests.java +++ b/core/src/test/java/org/elasticsearch/script/NativeScriptTests.java @@ -52,7 +52,8 @@ public class NativeScriptTests extends ESTestCase { .put("name", "testNativeScript") .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir()) .build(); - ScriptModule scriptModule = new ScriptModule(settings); + SettingsModule settingsModule = new SettingsModule(settings, new SettingsFilter(settings)); + ScriptModule scriptModule = new ScriptModule(settingsModule); scriptModule.registerScript("my", MyNativeScriptFactory.class); Injector injector = new ModulesBuilder().add( new EnvironmentModule(new Environment(settings)), @@ -73,10 +74,10 @@ public class NativeScriptTests extends ESTestCase { Settings.Builder builder = Settings.settingsBuilder(); if (randomBoolean()) { ScriptType scriptType = randomFrom(ScriptType.values()); - builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + scriptType, randomFrom(ScriptMode.values())); + builder.put("script" + "." + scriptType.getScriptType(), randomFrom(ScriptMode.values())); } else { - String scriptContext = randomFrom(ScriptContext.Standard.values()).getKey(); - builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + scriptContext, randomFrom(ScriptMode.values())); + ScriptContext scriptContext = randomFrom(ScriptContext.Standard.values()); + builder.put("script" + "." + scriptContext.getKey(), randomFrom(ScriptMode.values())); } Settings settings = builder.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir()).build(); Environment environment = new Environment(settings); @@ -84,8 +85,10 @@ public class NativeScriptTests extends ESTestCase { Map nativeScriptFactoryMap = new HashMap<>(); nativeScriptFactoryMap.put("my", new MyNativeScriptFactory()); Set scriptEngineServices = singleton(new NativeScriptEngineService(settings, nativeScriptFactoryMap)); - ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(new ArrayList()); - ScriptService scriptService = new ScriptService(settings, environment, scriptEngineServices, resourceWatcherService, scriptContextRegistry); + ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(NativeScriptEngineService.class, NativeScriptEngineService.TYPES))); + ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(new ArrayList<>()); + ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); + ScriptService scriptService = new ScriptService(settings, environment, scriptEngineServices, resourceWatcherService, scriptEngineRegistry, scriptContextRegistry, scriptSettings); for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) { assertThat(scriptService.compile(new Script("my", ScriptType.INLINE, NativeScriptEngineService.NAME, null), scriptContext, diff --git a/core/src/test/java/org/elasticsearch/script/ScriptContextTests.java b/core/src/test/java/org/elasticsearch/script/ScriptContextTests.java index 4505b2b0d9a..b8622f1872c 100644 --- a/core/src/test/java/org/elasticsearch/script/ScriptContextTests.java +++ b/core/src/test/java/org/elasticsearch/script/ScriptContextTests.java @@ -40,16 +40,20 @@ public class ScriptContextTests extends ESTestCase { Settings settings = Settings.builder() .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir()) // no file watching, so we don't need a ResourceWatcherService - .put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING.getKey(), false) - .put("script." + PLUGIN_NAME + "_custom_globally_disabled_op", false) - .put("script.engine." + MockScriptEngine.NAME + ".inline." + PLUGIN_NAME + "_custom_exp_disabled_op", false) + .put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING.getKey(), "off") + .put("script." + PLUGIN_NAME + "_custom_globally_disabled_op", "off") + .put("script.engine." + MockScriptEngine.NAME + ".inline." + PLUGIN_NAME + "_custom_exp_disabled_op", "off") .build(); Set engines = new HashSet<>(Collections.singletonList(new MockScriptEngine())); + ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES))); List customContexts = Arrays.asList( new ScriptContext.Plugin(PLUGIN_NAME, "custom_op"), new ScriptContext.Plugin(PLUGIN_NAME, "custom_exp_disabled_op"), new ScriptContext.Plugin(PLUGIN_NAME, "custom_globally_disabled_op")); - return new ScriptService(settings, new Environment(settings), engines, null, new ScriptContextRegistry(customContexts)); + ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(customContexts); + ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); + + return new ScriptService(settings, new Environment(settings), engines, null, scriptEngineRegistry, scriptContextRegistry, scriptSettings); } public void testCustomGlobalScriptContextSettings() throws Exception { diff --git a/core/src/test/java/org/elasticsearch/script/ScriptModesTests.java b/core/src/test/java/org/elasticsearch/script/ScriptModesTests.java index 0f00c2dd58d..de5bdd15779 100644 --- a/core/src/test/java/org/elasticsearch/script/ScriptModesTests.java +++ b/core/src/test/java/org/elasticsearch/script/ScriptModesTests.java @@ -27,9 +27,11 @@ import org.elasticsearch.test.ESTestCase; import org.junit.After; import org.junit.Before; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -45,9 +47,10 @@ public class ScriptModesTests extends ESTestCase { private static final Set ALL_LANGS = unmodifiableSet( newHashSet("custom", "test")); - static final String[] ENABLE_VALUES = new String[]{"on", "true", "yes", "1"}; - static final String[] DISABLE_VALUES = new String[]{"off", "false", "no", "0"}; + static final String[] ENABLE_VALUES = new String[]{"on"}; + static final String[] DISABLE_VALUES = new String[]{"off"}; + ScriptSettings scriptSettings; ScriptContextRegistry scriptContextRegistry; private ScriptContext[] scriptContexts; private Map scriptEngines; @@ -74,6 +77,10 @@ public class ScriptModesTests extends ESTestCase { //add the native engine just to make sure it gets filtered out new NativeScriptEngineService(Settings.EMPTY, Collections.emptyMap()), new CustomScriptEngineService())); + ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Arrays.asList( + new ScriptEngineRegistry.ScriptEngineRegistration(NativeScriptEngineService.class, NativeScriptEngineService.TYPES), + new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.TYPES))); + scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); checkedSettings = new HashSet<>(); assertAllSettingsWereChecked = true; assertScriptModesNonNull = true; @@ -100,14 +107,14 @@ public class ScriptModesTests extends ESTestCase { } public void testDefaultSettings() { - this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, Settings.EMPTY); + this.scriptModes = new ScriptModes(scriptSettings, Settings.EMPTY); assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE); assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED, ScriptType.INLINE); } public void testMissingSetting() { assertAllSettingsWereChecked = false; - this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, Settings.EMPTY); + this.scriptModes = new ScriptModes(scriptSettings, Settings.EMPTY); try { scriptModes.getScriptMode("non_existing", randomFrom(ScriptType.values()), randomFrom(scriptContexts)); fail("Expected IllegalArgumentException"); @@ -130,9 +137,9 @@ public class ScriptModesTests extends ESTestCase { ScriptType[] randomScriptTypes = randomScriptTypesSet.toArray(new ScriptType[randomScriptTypesSet.size()]); Settings.Builder builder = Settings.builder(); for (int i = 0; i < randomInt; i++) { - builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + randomScriptTypes[i], randomScriptModes[i]); + builder.put("script" + "." + randomScriptTypes[i].getScriptType(), randomScriptModes[i]); } - this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build()); + this.scriptModes = new ScriptModes(scriptSettings, builder.build()); for (int i = 0; i < randomInt; i++) { assertScriptModesAllOps(randomScriptModes[i], ALL_LANGS, randomScriptTypes[i]); @@ -162,9 +169,9 @@ public class ScriptModesTests extends ESTestCase { ScriptContext[] randomScriptContexts = randomScriptContextsSet.toArray(new ScriptContext[randomScriptContextsSet.size()]); Settings.Builder builder = Settings.builder(); for (int i = 0; i < randomInt; i++) { - builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + randomScriptContexts[i].getKey(), randomScriptModes[i]); + builder.put("script" + "." + randomScriptContexts[i].getKey(), randomScriptModes[i]); } - this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build()); + this.scriptModes = new ScriptModes(scriptSettings, builder.build()); for (int i = 0; i < randomInt; i++) { assertScriptModesAllTypes(randomScriptModes[i], ALL_LANGS, randomScriptContexts[i]); @@ -177,10 +184,10 @@ public class ScriptModesTests extends ESTestCase { public void testConflictingScriptTypeAndOpGenericSettings() { ScriptContext scriptContext = randomFrom(scriptContexts); - Settings.Builder builder = Settings.builder().put(ScriptModes.SCRIPT_SETTINGS_PREFIX + scriptContext.getKey(), randomFrom(DISABLE_VALUES)) + Settings.Builder builder = Settings.builder().put("script" + "." + scriptContext.getKey(), randomFrom(DISABLE_VALUES)) .put("script.indexed", randomFrom(ENABLE_VALUES)).put("script.inline", ScriptMode.SANDBOX); //operations generic settings have precedence over script type generic settings - this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build()); + this.scriptModes = new ScriptModes(scriptSettings, builder.build()); assertScriptModesAllTypes(ScriptMode.OFF, ALL_LANGS, scriptContext); ScriptContext[] complementOf = complementOf(scriptContext); assertScriptModes(ScriptMode.ON, ALL_LANGS, new ScriptType[]{ScriptType.FILE, ScriptType.INDEXED}, complementOf); @@ -220,10 +227,6 @@ public class ScriptModesTests extends ESTestCase { return copy.values().toArray(new ScriptContext[copy.size()]); } - private static String specificEngineOpSettings(String lang, ScriptType scriptType, ScriptContext scriptContext) { - return ScriptModes.ENGINE_SETTINGS_PREFIX + "." + lang + "." + scriptType + "." + scriptContext.getKey(); - } - static Map buildScriptEnginesByLangMap(Set scriptEngines) { Map builder = new HashMap<>(); for (ScriptEngineService scriptEngine : scriptEngines) { @@ -235,14 +238,17 @@ public class ScriptModesTests extends ESTestCase { } private static class CustomScriptEngineService implements ScriptEngineService { + + public static final List TYPES = Collections.unmodifiableList(Arrays.asList("custom", "test")); + @Override - public String[] types() { - return new String[]{"custom", "test"}; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return new String[0]; + public List extensions() { + return Collections.singletonList(TYPES.get(0)); } @Override diff --git a/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java b/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java index 2028605d844..c67347cc156 100644 --- a/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java +++ b/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java @@ -33,10 +33,13 @@ import org.junit.Before; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; +import static org.elasticsearch.common.settings.Settings.builder; import static org.elasticsearch.common.settings.Settings.settingsBuilder; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -49,7 +52,9 @@ public class ScriptServiceTests extends ESTestCase { private ResourceWatcherService resourceWatcherService; private ScriptEngineService scriptEngineService; private Map scriptEnginesByLangMap; + private ScriptEngineRegistry scriptEngineRegistry; private ScriptContextRegistry scriptContextRegistry; + private ScriptSettings scriptSettings; private ScriptContext[] scriptContexts; private ScriptService scriptService; private Path scriptsFilePath; @@ -89,7 +94,9 @@ public class ScriptServiceTests extends ESTestCase { String context = plugin + "_" + operation; contexts.put(context, new ScriptContext.Plugin(plugin, operation)); } + scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(TestEngineService.class, TestEngineService.TYPES))); scriptContextRegistry = new ScriptContextRegistry(contexts.values()); + scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]); logger.info("--> setup script service"); scriptsFilePath = genericConfigFolder.resolve("scripts"); @@ -99,7 +106,7 @@ public class ScriptServiceTests extends ESTestCase { private void buildScriptService(Settings additionalSettings) throws IOException { Settings finalSettings = Settings.builder().put(baseSettings).put(additionalSettings).build(); Environment environment = new Environment(finalSettings); - scriptService = new ScriptService(finalSettings, environment, Collections.singleton(scriptEngineService), resourceWatcherService, scriptContextRegistry) { + scriptService = new ScriptService(finalSettings, environment, Collections.singleton(scriptEngineService), resourceWatcherService, scriptEngineRegistry, scriptContextRegistry, scriptSettings) { @Override String getScriptFromIndex(String scriptLang, String id, HasContextAndHeaders headersContext) { //mock the script that gets retrieved from an index @@ -216,11 +223,11 @@ public class ScriptServiceTests extends ESTestCase { scriptSourceSettings.put(scriptType, randomFrom(ScriptMode.values())); } int numScriptContextSettings = randomIntBetween(0, this.scriptContextRegistry.scriptContexts().size()); - Map scriptContextSettings = new HashMap<>(); + Map scriptContextSettings = new HashMap<>(); for (int i = 0; i < numScriptContextSettings; i++) { - String scriptContext; + ScriptContext scriptContext; do { - scriptContext = randomFrom(this.scriptContexts).getKey(); + scriptContext = randomFrom(this.scriptContexts); } while (scriptContextSettings.containsKey(scriptContext)); scriptContextSettings.put(scriptContext, randomFrom(ScriptMode.values())); } @@ -231,7 +238,7 @@ public class ScriptServiceTests extends ESTestCase { do { ScriptType scriptType = randomFrom(ScriptType.values()); ScriptContext scriptContext = randomFrom(this.scriptContexts); - settingKey = scriptEngineService.types()[0] + "." + scriptType + "." + scriptContext.getKey(); + settingKey = scriptEngineService.types().get(0) + "." + scriptType + "." + scriptContext.getKey(); } while (engineSettings.containsKey(settingKey)); engineSettings.put(settingKey, randomFrom(ScriptMode.values())); } @@ -240,26 +247,27 @@ public class ScriptServiceTests extends ESTestCase { for (Map.Entry entry : scriptSourceSettings.entrySet()) { switch (entry.getValue()) { case ON: - builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), randomFrom(ScriptModesTests.ENABLE_VALUES)); + builder.put("script" + "." + entry.getKey().getScriptType(), "on"); break; case OFF: - builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), randomFrom(ScriptModesTests.DISABLE_VALUES)); + builder.put("script" + "." + entry.getKey().getScriptType(), "off"); break; case SANDBOX: - builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), ScriptMode.SANDBOX); + builder.put("script" + "." + entry.getKey().getScriptType(), "sandbox"); break; } } - for (Map.Entry entry : scriptContextSettings.entrySet()) { + for (Map.Entry entry : scriptContextSettings.entrySet()) { switch (entry.getValue()) { case ON: - builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), randomFrom(ScriptModesTests.ENABLE_VALUES)); + builder.put("script" + "." + entry.getKey().getKey(), "on"); break; + case OFF: - builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), randomFrom(ScriptModesTests.DISABLE_VALUES)); + builder.put("script" + "." + entry.getKey().getKey(), "off"); break; case SANDBOX: - builder.put(ScriptModes.SCRIPT_SETTINGS_PREFIX + entry.getKey(), ScriptMode.SANDBOX); + builder.put("script" + "." + entry.getKey().getKey(), "sandbox"); break; } } @@ -271,13 +279,13 @@ public class ScriptServiceTests extends ESTestCase { String lang = randomFrom(scriptEnginesByLangMap.get(part1).types()); switch (entry.getValue()) { case ON: - builder.put(ScriptModes.ENGINE_SETTINGS_PREFIX + "." + lang + "." + part2, randomFrom(ScriptModesTests.ENABLE_VALUES)); + builder.put("script.engine" + "." + lang + "." + part2, "on"); break; case OFF: - builder.put(ScriptModes.ENGINE_SETTINGS_PREFIX + "." + lang + "." + part2, randomFrom(ScriptModesTests.DISABLE_VALUES)); + builder.put("script.engine" + "." + lang + "." + part2, "off"); break; case SANDBOX: - builder.put(ScriptModes.ENGINE_SETTINGS_PREFIX + "." + lang + "." + part2, ScriptMode.SANDBOX); + builder.put("script.engine" + "." + lang + "." + part2, "sandbox"); break; } } @@ -291,9 +299,9 @@ public class ScriptServiceTests extends ESTestCase { String script = scriptType == ScriptType.FILE ? "file_script" : "script"; for (ScriptContext scriptContext : this.scriptContexts) { //fallback mechanism: 1) engine specific settings 2) op based settings 3) source based settings - ScriptMode scriptMode = engineSettings.get(scriptEngineService.types()[0] + "." + scriptType + "." + scriptContext.getKey()); + ScriptMode scriptMode = engineSettings.get(scriptEngineService.types().get(0) + "." + scriptType + "." + scriptContext.getKey()); if (scriptMode == null) { - scriptMode = scriptContextSettings.get(scriptContext.getKey()); + scriptMode = scriptContextSettings.get(scriptContext); } if (scriptMode == null) { scriptMode = scriptSourceSettings.get(scriptType); @@ -305,16 +313,16 @@ public class ScriptServiceTests extends ESTestCase { for (String lang : scriptEngineService.types()) { switch (scriptMode) { case ON: - assertCompileAccepted(lang, script, scriptType, scriptContext, contextAndHeaders); + assertCompileAccepted(lang, script, scriptType, scriptContext, contextAndHeaders); break; case OFF: - assertCompileRejected(lang, script, scriptType, scriptContext, contextAndHeaders); + assertCompileRejected(lang, script, scriptType, scriptContext, contextAndHeaders); break; case SANDBOX: if (scriptEngineService.sandboxed()) { - assertCompileAccepted(lang, script, scriptType, scriptContext, contextAndHeaders); + assertCompileAccepted(lang, script, scriptType, scriptContext, contextAndHeaders); } else { - assertCompileRejected(lang, script, scriptType, scriptContext, contextAndHeaders); + assertCompileRejected(lang, script, scriptType, scriptContext, contextAndHeaders); } break; } @@ -411,6 +419,16 @@ public class ScriptServiceTests extends ESTestCase { assertEquals(1L, scriptService.stats().getCacheEvictions()); } + public void testDefaultLanguage() throws IOException { + ContextAndHeaderHolder contextAndHeaderHolder = new ContextAndHeaderHolder(); + Settings.Builder builder = Settings.builder(); + builder.put("script.default_lang", "test"); + buildScriptService(builder.build()); + CompiledScript script = + scriptService.compile(new Script("1 + 1", ScriptType.INLINE, null, null), randomFrom(scriptContexts), contextAndHeaderHolder, Collections.emptyMap()); + assertEquals(script.lang(), "test"); + } + private void createFileScripts(String... langs) throws IOException { for (String lang : langs) { Path scriptPath = scriptsFilePath.resolve("file_script." + lang); @@ -429,21 +447,24 @@ public class ScriptServiceTests extends ESTestCase { } } - private void assertCompileAccepted(String lang, String script, ScriptType scriptType, ScriptContext scriptContext, - HasContextAndHeaders contextAndHeaders) { + private void assertCompileAccepted(String lang, String script, ScriptType scriptType, ScriptContext scriptContext, HasContextAndHeaders contextAndHeaders) { assertThat(scriptService.compile(new Script(script, scriptType, lang, null), scriptContext, contextAndHeaders, Collections.emptyMap()), notNullValue()); } public static class TestEngineService implements ScriptEngineService { + public static final List TYPES = Collections.unmodifiableList(Arrays.asList("test", "test2")); + + public static final List EXTENSIONS = Collections.unmodifiableList(Arrays.asList("test", "tst")); + @Override - public String[] types() { - return new String[] {"test", "test2"}; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return new String[] {"test", "tst"}; + public List extensions() { + return EXTENSIONS; } @Override diff --git a/core/src/test/java/org/elasticsearch/script/ScriptSettingsTests.java b/core/src/test/java/org/elasticsearch/script/ScriptSettingsTests.java new file mode 100644 index 00000000000..a407aac63c5 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/script/ScriptSettingsTests.java @@ -0,0 +1,112 @@ +/* + * 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.Nullable; +import org.elasticsearch.common.settings.Setting; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.search.lookup.SearchLookup; +import org.elasticsearch.test.ESTestCase; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.anyOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; + +public class ScriptSettingsTests extends ESTestCase { + + public void testConflictingModesForLanguage() { + ScriptEngineRegistry scriptEngineRegistry = + new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(CustomScriptEngineService.class, CustomScriptEngineService.TYPES))); + ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); + ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); + ScriptService.ScriptType scriptType = randomFrom(ScriptService.ScriptType.values()); + ScriptContext scriptContext = randomFrom(ScriptContext.Standard.values()); + Settings settings = + Settings + .builder() + .put(ScriptModes.getKey("test1", scriptType, scriptContext), "off") + .put(ScriptModes.getKey("test2", scriptType, scriptContext), "on") + .build(); + boolean sawConflictingSettings = false; + for (Setting scriptModeSetting : scriptSettings.getScriptLanguageSettings()) { + if (scriptModeSetting.getKey().startsWith(ScriptModes.getKey("test3", scriptType, scriptContext))) { + try { + scriptModeSetting.get(settings); + fail("should have seen conflicting settings"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), anyOf(containsString("conflicting settings [{off=[test1], on=[test2]}] for language [test3]"), containsString("conflicting settings [{on=[test2], on=[test1]}] for language [test3]"))); + sawConflictingSettings = true; + } + } + } + assertTrue(sawConflictingSettings); + } + + private static class CustomScriptEngineService implements ScriptEngineService { + + public static final List TYPES = Collections.unmodifiableList(Arrays.asList("test1", "test2", "test3")); + + @Override + public List types() { + return TYPES; + } + + @Override + public List extensions() { + return Collections.singletonList(TYPES.get(0)); + } + + @Override + public boolean sandboxed() { + return false; + } + + @Override + public Object compile(String script, Map params) { + return null; + } + + @Override + public ExecutableScript executable(CompiledScript compiledScript, @Nullable Map vars) { + return null; + } + + @Override + public SearchScript search(CompiledScript compiledScript, SearchLookup lookup, @Nullable Map vars) { + return null; + } + + @Override + public void close() { + + } + + @Override + public void scriptRemoved(@Nullable CompiledScript script) { + + } + } + +} diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramIT.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramIT.java index ef784b6f812..f595aaaad3c 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramIT.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramIT.java @@ -33,6 +33,7 @@ import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.LeafSearchScript; import org.elasticsearch.script.Script; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineService; import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.ScriptService.ScriptType; @@ -55,6 +56,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -1397,7 +1399,7 @@ public class DateHistogramIT extends ESIntegTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(ExtractFieldScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractFieldScriptEngine.class, ExtractFieldScriptEngine.TYPES)); } } @@ -1409,18 +1411,20 @@ public class DateHistogramIT extends ESIntegTestCase { public static final String NAME = "extract_field"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override @@ -1517,7 +1521,7 @@ public class DateHistogramIT extends ESIntegTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(FieldValueScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES)); } } @@ -1529,18 +1533,20 @@ public class DateHistogramIT extends ESIntegTestCase { public static final String NAME = "field_value"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/AvgIT.java b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/AvgIT.java index cb819a7027b..eeb13679b8d 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/AvgIT.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/AvgIT.java @@ -26,6 +26,7 @@ import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.LeafSearchScript; import org.elasticsearch.script.Script; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineService; import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.ScriptService.ScriptType; @@ -332,7 +333,7 @@ public class AvgIT extends AbstractNumericTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(ExtractFieldScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractFieldScriptEngine.class, ExtractFieldScriptEngine.TYPES)); } } @@ -344,18 +345,20 @@ public class AvgIT extends AbstractNumericTestCase { public static final String NAME = "extract_field"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override @@ -462,7 +465,7 @@ public class AvgIT extends AbstractNumericTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(FieldValueScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES)); } } @@ -474,18 +477,20 @@ public class AvgIT extends AbstractNumericTestCase { public static final String NAME = "field_value"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/SumIT.java b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/SumIT.java index 39c865eae35..1b43d47a39d 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/SumIT.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/SumIT.java @@ -26,6 +26,7 @@ import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.LeafSearchScript; import org.elasticsearch.script.Script; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineService; import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.ScriptService.ScriptType; @@ -40,6 +41,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -326,7 +328,7 @@ public class SumIT extends AbstractNumericTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(ExtractFieldScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractFieldScriptEngine.class, ExtractFieldScriptEngine.TYPES)); } } @@ -339,18 +341,20 @@ public class SumIT extends AbstractNumericTestCase { public static final String NAME = "extract_field"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override @@ -458,7 +462,7 @@ public class SumIT extends AbstractNumericTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(FieldValueScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES)); } } @@ -471,18 +475,20 @@ public class SumIT extends AbstractNumericTestCase { public static final String NAME = "field_value"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/ValueCountIT.java b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/ValueCountIT.java index 903c1bab356..adc282e5b26 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/ValueCountIT.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/ValueCountIT.java @@ -26,6 +26,7 @@ import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.LeafSearchScript; import org.elasticsearch.script.Script; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineService; import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.ScriptService.ScriptType; @@ -40,6 +41,7 @@ import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; @@ -221,7 +223,7 @@ public class ValueCountIT extends ESIntegTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(FieldValueScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldValueScriptEngine.class, FieldValueScriptEngine.TYPES)); } } @@ -233,18 +235,20 @@ public class ValueCountIT extends ESIntegTestCase { public static final String NAME = "field_value"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override diff --git a/core/src/test/java/org/elasticsearch/update/UpdateIT.java b/core/src/test/java/org/elasticsearch/update/UpdateIT.java index 68d3f7d828a..7d9713c8271 100644 --- a/core/src/test/java/org/elasticsearch/update/UpdateIT.java +++ b/core/src/test/java/org/elasticsearch/update/UpdateIT.java @@ -41,6 +41,7 @@ import org.elasticsearch.plugins.Plugin; import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.Script; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptEngineService; import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.ScriptService; @@ -92,7 +93,7 @@ public class UpdateIT extends ESIntegTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(PutFieldValuesScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(PutFieldValuesScriptEngine.class, PutFieldValuesScriptEngine.TYPES)); } } @@ -101,18 +102,20 @@ public class UpdateIT extends ESIntegTestCase { public static final String NAME = "put_values"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override @@ -184,7 +187,7 @@ public class UpdateIT extends ESIntegTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(FieldIncrementScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(FieldIncrementScriptEngine.class, FieldIncrementScriptEngine.TYPES)); } } @@ -193,18 +196,20 @@ public class UpdateIT extends ESIntegTestCase { public static final String NAME = "field_inc"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override @@ -269,7 +274,7 @@ public class UpdateIT extends ESIntegTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(ScriptedUpsertScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ScriptedUpsertScriptEngine.class, ScriptedUpsertScriptEngine.TYPES)); } } @@ -278,18 +283,20 @@ public class UpdateIT extends ESIntegTestCase { public static final String NAME = "scripted_upsert"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override @@ -354,7 +361,7 @@ public class UpdateIT extends ESIntegTestCase { } public void onModule(ScriptModule module) { - module.addScriptEngine(ExtractContextInSourceScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExtractContextInSourceScriptEngine.class, ExtractContextInSourceScriptEngine.TYPES)); } } @@ -363,18 +370,20 @@ public class UpdateIT extends ESIntegTestCase { public static final String NAME = "extract_ctx"; + public static final List TYPES = Collections.singletonList(NAME); + @Override public void close() throws IOException { } @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override diff --git a/docs/reference/migration/migrate_3_0.asciidoc b/docs/reference/migration/migrate_3_0.asciidoc index db3ef9c98f6..c53f29947a5 100644 --- a/docs/reference/migration/migrate_3_0.asciidoc +++ b/docs/reference/migration/migrate_3_0.asciidoc @@ -17,6 +17,7 @@ your application to Elasticsearch 3.0. * <> * <> * <> +* <> [[breaking_30_search_changes]] === Warmers @@ -684,3 +685,15 @@ and these error messages would be lost to the nether. The default has changed to now route standard output to the journal and standard error to inherit this setting (these are the defaults for systemd). These settings can be modified by editing the elasticsearch.service file. + +[[breaking_30_scripting]] +=== Scripting + +==== Script mode settings + +Previously script mode settings (e.g., "script.inline: on", +"script.engine.groovy.inline.aggs: off", etc.) accepted the values +`on`, `true`, `1`, and `yes` for enabling a scripting mode, and the +values `off`, `false`, `0`, and `no` for disabling a scripting mode. +The variants `true`, `1`, and `yes ` for enabling and `false`, `0`, +and `no` for disabling are no longer supported. diff --git a/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionPlugin.java b/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionPlugin.java index c72428c4c4c..a987855bae3 100644 --- a/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionPlugin.java +++ b/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionPlugin.java @@ -20,10 +20,11 @@ package org.elasticsearch.script.expression; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptModule; public class ExpressionPlugin extends Plugin { - + @Override public String name() { return "lang-expression"; @@ -35,6 +36,6 @@ public class ExpressionPlugin extends Plugin { } public void onModule(ScriptModule module) { - module.addScriptEngine(ExpressionScriptEngineService.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(ExpressionScriptEngineService.class, ExpressionScriptEngineService.TYPES)); } } diff --git a/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngineService.java b/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngineService.java index 192f69884e8..5ff5536d2be 100644 --- a/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngineService.java +++ b/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngineService.java @@ -50,6 +50,8 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.text.ParseException; import java.util.Calendar; +import java.util.Collections; +import java.util.List; import java.util.Map; /** @@ -60,6 +62,8 @@ public class ExpressionScriptEngineService extends AbstractComponent implements public static final String NAME = "expression"; + public static final List TYPES = Collections.singletonList(NAME); + protected static final String GET_YEAR_METHOD = "getYear"; protected static final String GET_MONTH_METHOD = "getMonth"; protected static final String GET_DAY_OF_MONTH_METHOD = "getDayOfMonth"; @@ -80,13 +84,13 @@ public class ExpressionScriptEngineService extends AbstractComponent implements } @Override - public String[] types() { - return new String[]{NAME}; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return new String[]{NAME}; + public List extensions() { + return TYPES; } @Override diff --git a/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/IndexedExpressionTests.java b/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/IndexedExpressionTests.java index 65b47b92331..a4fdb7d8eca 100644 --- a/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/IndexedExpressionTests.java +++ b/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/IndexedExpressionTests.java @@ -41,7 +41,6 @@ public class IndexedExpressionTests extends ESIntegTestCase { Settings.Builder builder = Settings.builder().put(super.nodeSettings(nodeOrdinal)); builder.put("script.engine.expression.indexed.update", "off"); builder.put("script.engine.expression.indexed.search", "off"); - builder.put("script.engine.expression.indexed.aggs", "off"); builder.put("script.engine.expression.indexed.mapping", "off"); return builder.build(); } diff --git a/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyPlugin.java b/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyPlugin.java index 78f803a75ca..e7f81f58a78 100644 --- a/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyPlugin.java +++ b/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyPlugin.java @@ -20,6 +20,7 @@ package org.elasticsearch.script.groovy; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptModule; public class GroovyPlugin extends Plugin { @@ -35,6 +36,6 @@ public class GroovyPlugin extends Plugin { } public void onModule(ScriptModule module) { - module.addScriptEngine(GroovyScriptEngineService.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(GroovyScriptEngineService.class, GroovyScriptEngineService.TYPES)); } } diff --git a/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyScriptEngineService.java b/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyScriptEngineService.java index da7ff0f2eb2..6b8836e7b80 100644 --- a/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyScriptEngineService.java +++ b/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyScriptEngineService.java @@ -19,15 +19,10 @@ package org.elasticsearch.script.groovy; -import java.io.IOException; -import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.HashMap; -import java.util.Map; - +import groovy.lang.Binding; +import groovy.lang.GroovyClassLoader; +import groovy.lang.GroovyCodeSource; +import groovy.lang.Script; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.search.Scorer; import org.codehaus.groovy.ast.ClassCodeExpressionTransformer; @@ -60,10 +55,16 @@ import org.elasticsearch.script.SearchScript; import org.elasticsearch.search.lookup.LeafSearchLookup; import org.elasticsearch.search.lookup.SearchLookup; -import groovy.lang.Binding; -import groovy.lang.GroovyClassLoader; -import groovy.lang.GroovyCodeSource; -import groovy.lang.Script; +import java.io.IOException; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Provides the infrastructure for Groovy as a scripting language for Elasticsearch @@ -74,6 +75,8 @@ public class GroovyScriptEngineService extends AbstractComponent implements Scri * The name of the scripting engine/language. */ public static final String NAME = "groovy"; + + public static final List TYPES = Collections.singletonList(NAME); /** * The name of the Groovy compiler setting to use associated with activating invokedynamic support. */ @@ -158,13 +161,13 @@ public class GroovyScriptEngineService extends AbstractComponent implements Scri } @Override - public String[] types() { - return new String[]{NAME}; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return new String[]{NAME}; + public List extensions() { + return TYPES; } @Override diff --git a/modules/lang-groovy/src/test/java/org/elasticsearch/messy/tests/IndexedScriptTests.java b/modules/lang-groovy/src/test/java/org/elasticsearch/messy/tests/IndexedScriptTests.java index a3a786a140e..363193c6d6b 100644 --- a/modules/lang-groovy/src/test/java/org/elasticsearch/messy/tests/IndexedScriptTests.java +++ b/modules/lang-groovy/src/test/java/org/elasticsearch/messy/tests/IndexedScriptTests.java @@ -66,7 +66,6 @@ public class IndexedScriptTests extends ESIntegTestCase { builder.put("script.engine.groovy.inline.aggs", "off"); builder.put("script.engine.expression.indexed.update", "off"); builder.put("script.engine.expression.indexed.search", "off"); - builder.put("script.engine.expression.indexed.aggs", "off"); builder.put("script.engine.expression.indexed.mapping", "off"); return builder.build(); } diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustachePlugin.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustachePlugin.java index 3f6f6e00716..935dab7e439 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustachePlugin.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustachePlugin.java @@ -20,6 +20,7 @@ package org.elasticsearch.script.mustache; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptModule; public class MustachePlugin extends Plugin { @@ -35,6 +36,6 @@ public class MustachePlugin extends Plugin { } public void onModule(ScriptModule module) { - module.addScriptEngine(MustacheScriptEngineService.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(MustacheScriptEngineService.class, MustacheScriptEngineService.TYPES)); } } diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngineService.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngineService.java index 685ba6a4aae..c88eb1ca50b 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngineService.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngineService.java @@ -18,13 +18,8 @@ */ package org.elasticsearch.script.mustache; -import java.lang.ref.SoftReference; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Collections; -import java.io.Reader; -import java.util.Map; - +import com.github.mustachejava.DefaultMustacheFactory; +import com.github.mustachejava.Mustache; import org.elasticsearch.SpecialPermission; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.component.AbstractComponent; @@ -40,8 +35,13 @@ import org.elasticsearch.script.ScriptException; import org.elasticsearch.script.SearchScript; import org.elasticsearch.search.lookup.SearchLookup; -import com.github.mustachejava.Mustache; -import com.github.mustachejava.DefaultMustacheFactory; +import java.io.Reader; +import java.lang.ref.SoftReference; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.List; +import java.util.Map; /** * Main entry point handling template registration, compilation and @@ -54,6 +54,9 @@ import com.github.mustachejava.DefaultMustacheFactory; public final class MustacheScriptEngineService extends AbstractComponent implements ScriptEngineService { public static final String NAME = "mustache"; + + public static final List TYPES = Collections.singletonList(NAME); + static final String CONTENT_TYPE_PARAM = "content_type"; static final String JSON_CONTENT_TYPE = "application/json"; static final String PLAIN_TEXT_CONTENT_TYPE = "text/plain"; @@ -109,13 +112,13 @@ public final class MustacheScriptEngineService extends AbstractComponent impleme } @Override - public String[] types() { - return new String[] {NAME}; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return new String[] {NAME}; + public List extensions() { + return TYPES; } @Override diff --git a/modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/TemplateQueryParserTests.java b/modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/TemplateQueryParserTests.java index e005ca5b100..5ed8a7504d9 100644 --- a/modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/TemplateQueryParserTests.java +++ b/modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/TemplateQueryParserTests.java @@ -18,10 +18,6 @@ */ package org.elasticsearch.messy.tests; -import java.io.IOException; -import java.lang.reflect.Proxy; -import java.util.Collections; - import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.util.Accountable; @@ -62,6 +58,7 @@ import org.elasticsearch.indices.breaker.NoneCircuitBreakerService; import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCache; import org.elasticsearch.indices.mapper.MapperRegistry; import org.elasticsearch.indices.query.IndicesQueriesRegistry; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.mustache.MustacheScriptEngineService; @@ -74,6 +71,10 @@ import org.elasticsearch.threadpool.ThreadPoolModule; import org.junit.After; import org.junit.Before; +import java.io.IOException; +import java.lang.reflect.Proxy; +import java.util.Collections; + import static org.hamcrest.Matchers.containsString; /** @@ -100,10 +101,10 @@ public class TemplateQueryParserTests extends ESTestCase { }); Index index = new Index("test"); IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(index, settings); - ScriptModule scriptModule = new ScriptModule(settings); - // TODO: make this use a mock engine instead of mustache and it will no longer be messy! - scriptModule.addScriptEngine(MustacheScriptEngineService.class); SettingsModule settingsModule = new SettingsModule(settings, new SettingsFilter(settings)); + ScriptModule scriptModule = new ScriptModule(settingsModule); + // TODO: make this use a mock engine instead of mustache and it will no longer be messy! + scriptModule.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(MustacheScriptEngineService.class, MustacheScriptEngineService.TYPES)); settingsModule.registerSetting(InternalSettingsPlugin.VERSION_CREATED); injector = new ModulesBuilder().add( new EnvironmentModule(new Environment(settings)), diff --git a/plugins/lang-javascript/src/main/java/org/elasticsearch/plugin/javascript/JavaScriptPlugin.java b/plugins/lang-javascript/src/main/java/org/elasticsearch/plugin/javascript/JavaScriptPlugin.java index 9ca36bd9f86..d8c79e8d110 100644 --- a/plugins/lang-javascript/src/main/java/org/elasticsearch/plugin/javascript/JavaScriptPlugin.java +++ b/plugins/lang-javascript/src/main/java/org/elasticsearch/plugin/javascript/JavaScriptPlugin.java @@ -20,6 +20,7 @@ package org.elasticsearch.plugin.javascript; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.javascript.JavaScriptScriptEngineService; @@ -44,6 +45,6 @@ public class JavaScriptPlugin extends Plugin { } public void onModule(ScriptModule module) { - module.addScriptEngine(JavaScriptScriptEngineService.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(JavaScriptScriptEngineService.class, JavaScriptScriptEngineService.TYPES)); } } diff --git a/plugins/lang-javascript/src/main/java/org/elasticsearch/script/javascript/JavaScriptScriptEngineService.java b/plugins/lang-javascript/src/main/java/org/elasticsearch/script/javascript/JavaScriptScriptEngineService.java index 14124551e76..59f65add60a 100644 --- a/plugins/lang-javascript/src/main/java/org/elasticsearch/script/javascript/JavaScriptScriptEngineService.java +++ b/plugins/lang-javascript/src/main/java/org/elasticsearch/script/javascript/JavaScriptScriptEngineService.java @@ -19,18 +19,6 @@ package org.elasticsearch.script.javascript; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.CodeSource; -import java.security.PrivilegedAction; -import java.security.cert.Certificate; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.search.Scorer; import org.elasticsearch.SpecialPermission; @@ -61,11 +49,27 @@ import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.SecurityController; import org.mozilla.javascript.WrapFactory; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.CodeSource; +import java.security.PrivilegedAction; +import java.security.cert.Certificate; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + /** * */ public class JavaScriptScriptEngineService extends AbstractComponent implements ScriptEngineService { + public static final List TYPES = Collections.unmodifiableList(Arrays.asList("js", "javascript")); + private final AtomicLong counter = new AtomicLong(); private static WrapFactory wrapFactory = new CustomWrapFactory(); @@ -155,13 +159,13 @@ public class JavaScriptScriptEngineService extends AbstractComponent implements } @Override - public String[] types() { - return new String[]{"js", "javascript"}; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return new String[]{"js"}; + public List extensions() { + return Collections.unmodifiableList(Arrays.asList("js")); } @Override diff --git a/plugins/lang-plan-a/src/main/java/org/elasticsearch/plan/a/PlanAPlugin.java b/plugins/lang-plan-a/src/main/java/org/elasticsearch/plan/a/PlanAPlugin.java index d87c9a9e1c4..dbfda5ef57f 100644 --- a/plugins/lang-plan-a/src/main/java/org/elasticsearch/plan/a/PlanAPlugin.java +++ b/plugins/lang-plan-a/src/main/java/org/elasticsearch/plan/a/PlanAPlugin.java @@ -20,6 +20,7 @@ package org.elasticsearch.plan.a; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptModule; public final class PlanAPlugin extends Plugin { @@ -35,6 +36,6 @@ public final class PlanAPlugin extends Plugin { } public void onModule(final ScriptModule module) { - module.addScriptEngine(PlanAScriptEngineService.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(PlanAScriptEngineService.class, PlanAScriptEngineService.TYPES)); } } diff --git a/plugins/lang-plan-a/src/main/java/org/elasticsearch/plan/a/PlanAScriptEngineService.java b/plugins/lang-plan-a/src/main/java/org/elasticsearch/plan/a/PlanAScriptEngineService.java index 858bf21021c..17eb0c00d84 100644 --- a/plugins/lang-plan-a/src/main/java/org/elasticsearch/plan/a/PlanAScriptEngineService.java +++ b/plugins/lang-plan-a/src/main/java/org/elasticsearch/plan/a/PlanAScriptEngineService.java @@ -37,7 +37,9 @@ import java.security.AccessController; import java.security.Permissions; import java.security.PrivilegedAction; import java.security.ProtectionDomain; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -50,6 +52,8 @@ public class PlanAScriptEngineService extends AbstractComponent implements Scrip */ public static final String NAME = "plan-a"; + public static final List TYPES = Collections.singletonList(NAME); + /** * Default compiler settings to be used. */ @@ -97,8 +101,8 @@ public class PlanAScriptEngineService extends AbstractComponent implements Scrip * @return Always contains only the single name of the language. */ @Override - public String[] types() { - return new String[] { NAME }; + public List types() { + return TYPES; } /** @@ -106,8 +110,8 @@ public class PlanAScriptEngineService extends AbstractComponent implements Scrip * @return Always contains only the single extension of the language. */ @Override - public String[] extensions() { - return new String[] { NAME }; + public List extensions() { + return TYPES; } /** diff --git a/plugins/lang-python/src/main/java/org/elasticsearch/plugin/python/PythonPlugin.java b/plugins/lang-python/src/main/java/org/elasticsearch/plugin/python/PythonPlugin.java index 28dad5135ab..50dd3fd98b4 100644 --- a/plugins/lang-python/src/main/java/org/elasticsearch/plugin/python/PythonPlugin.java +++ b/plugins/lang-python/src/main/java/org/elasticsearch/plugin/python/PythonPlugin.java @@ -20,6 +20,7 @@ package org.elasticsearch.plugin.python; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.python.PythonScriptEngineService; @@ -39,6 +40,6 @@ public class PythonPlugin extends Plugin { } public void onModule(ScriptModule module) { - module.addScriptEngine(PythonScriptEngineService.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(PythonScriptEngineService.class, PythonScriptEngineService.TYPES)); } } diff --git a/plugins/lang-python/src/main/java/org/elasticsearch/script/python/PythonScriptEngineService.java b/plugins/lang-python/src/main/java/org/elasticsearch/script/python/PythonScriptEngineService.java index 3722709e420..36f1ec6c809 100644 --- a/plugins/lang-python/src/main/java/org/elasticsearch/script/python/PythonScriptEngineService.java +++ b/plugins/lang-python/src/main/java/org/elasticsearch/script/python/PythonScriptEngineService.java @@ -47,6 +47,9 @@ import java.security.AccessController; import java.security.Permissions; import java.security.PrivilegedAction; import java.security.ProtectionDomain; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Map; /** @@ -55,6 +58,8 @@ import java.util.Map; //TODO we can optimize the case for Map similar to PyStringMap public class PythonScriptEngineService extends AbstractComponent implements ScriptEngineService { + public static final List TYPES = Collections.unmodifiableList(Arrays.asList("py", "python")); + private final PythonInterpreter interp; @Inject @@ -91,13 +96,13 @@ public class PythonScriptEngineService extends AbstractComponent implements Scri } @Override - public String[] types() { - return new String[]{"python", "py"}; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return new String[]{"py"}; + public List extensions() { + return Collections.unmodifiableList(Arrays.asList("py")); } @Override diff --git a/qa/ingest-with-mustache/src/test/java/org/elasticsearch/ingest/AbstractMustacheTests.java b/qa/ingest-with-mustache/src/test/java/org/elasticsearch/ingest/AbstractMustacheTests.java index 57165e69fb6..49e9964427d 100644 --- a/qa/ingest-with-mustache/src/test/java/org/elasticsearch/ingest/AbstractMustacheTests.java +++ b/qa/ingest-with-mustache/src/test/java/org/elasticsearch/ingest/AbstractMustacheTests.java @@ -21,10 +21,11 @@ package org.elasticsearch.ingest; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; -import org.elasticsearch.ingest.InternalTemplateService; import org.elasticsearch.ingest.core.TemplateService; import org.elasticsearch.script.ScriptContextRegistry; +import org.elasticsearch.script.ScriptEngineRegistry; import org.elasticsearch.script.ScriptService; +import org.elasticsearch.script.ScriptSettings; import org.elasticsearch.script.mustache.MustacheScriptEngineService; import org.elasticsearch.test.ESTestCase; import org.junit.Before; @@ -39,13 +40,15 @@ public abstract class AbstractMustacheTests extends ESTestCase { public void init() throws Exception { Settings settings = Settings.builder() .put("path.home", createTempDir()) - .put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING, false) + .put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING.getKey(), false) .build(); MustacheScriptEngineService mustache = new MustacheScriptEngineService(settings); - ScriptContextRegistry registry = new ScriptContextRegistry(Collections.emptyList()); - ScriptService scriptService = new ScriptService( - settings, new Environment(settings), Collections.singleton(mustache), null, registry - ); + ScriptEngineRegistry scriptEngineRegistry = + new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry.ScriptEngineRegistration(MustacheScriptEngineService.class, MustacheScriptEngineService.TYPES))); + ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); + ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); + ScriptService scriptService = + new ScriptService(settings, new Environment(settings), Collections.singleton(mustache), null, scriptEngineRegistry, scriptContextRegistry, scriptSettings); templateService = new InternalTemplateService(scriptService); } diff --git a/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java b/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java index 0096fcf9b5f..9e0740c5cc3 100644 --- a/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java +++ b/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java @@ -26,14 +26,19 @@ import org.elasticsearch.plugins.Plugin; import org.elasticsearch.search.lookup.SearchLookup; import java.io.IOException; +import java.util.Collections; +import java.util.List; import java.util.Map; /** * A dummy script engine used for testing. Scripts must be a number. Running the script */ public class MockScriptEngine implements ScriptEngineService { + public static final String NAME = "mockscript"; + public static final List TYPES = Collections.singletonList(NAME); + public static class TestPlugin extends Plugin { public TestPlugin() { @@ -50,19 +55,19 @@ public class MockScriptEngine implements ScriptEngineService { } public void onModule(ScriptModule module) { - module.addScriptEngine(MockScriptEngine.class); + module.addScriptEngine(new ScriptEngineRegistry.ScriptEngineRegistration(MockScriptEngine.class, MockScriptEngine.TYPES)); } } @Override - public String[] types() { - return new String[]{ NAME }; + public List types() { + return TYPES; } @Override - public String[] extensions() { - return types(); + public List extensions() { + return TYPES; } @Override