From 60e44d12ac418d65136aa732d819f04c84d39cf4 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Tue, 9 Jan 2018 15:34:03 -0800 Subject: [PATCH 1/3] Painless: Add whitelist extensions This commit adds a PainlessExtension which may be plugged in via SPI to add additional classes, methods and members to the painless whitelist on a per context basis. An example plugin adding and using a whitelist is also added. --- .../elasticsearch/painless/Definition.java | 23 -------- .../painless/PainlessExtension.java | 30 ++++++++++ .../painless/PainlessPlugin.java | 30 +++++++++- .../painless/PainlessScriptEngine.java | 16 ++---- .../org/elasticsearch/painless/Whitelist.java | 20 +++++++ .../painless/WhitelistLoader.java | 5 +- .../plugin-metadata/plugin-security.policy | 3 + .../painless/AnalyzerCasterTests.java | 7 +-- .../painless/BaseClassTests.java | 6 +- .../elasticsearch/painless/DebugTests.java | 4 +- .../org/elasticsearch/painless/Debugger.java | 4 +- .../painless/DefBootstrapTests.java | 3 +- .../elasticsearch/painless/FactoryTests.java | 14 +++-- .../painless/NeedsScoreTests.java | 10 +++- .../painless/PainlessDocGenerator.java | 5 +- .../painless/ScriptTestCase.java | 13 ++--- .../painless/SimilarityScriptTests.java | 12 +++- .../painless/node/NodeToStringTests.java | 6 +- .../examples/painless-whitelist/build.gradle | 4 ++ .../ExampleWhitelistExtension.java | 42 ++++++++++++++ .../ExampleWhitelistedClass.java | 57 +++++++++++++++++++ .../painlesswhitelist/MyWhitelistPlugin.java | 1 + ...g.elasticsearch.painless.PainlessExtension | 1 + .../painlesswhitelist/example_whitelist.txt | 42 ++++++++++++++ .../test/painless_whitelist/20_whitelist.yml | 26 +++++++++ 25 files changed, 305 insertions(+), 79 deletions(-) create mode 100644 modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessExtension.java create mode 100644 plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java create mode 100644 plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistedClass.java create mode 100644 plugins/examples/painless-whitelist/src/main/resources/META-INF/services/org.elasticsearch.painless.PainlessExtension create mode 100644 plugins/examples/painless-whitelist/src/main/resources/org/elasticsearch/example/painlesswhitelist/example_whitelist.txt create mode 100644 plugins/examples/painless-whitelist/src/test/resources/rest-api-spec/test/painless_whitelist/20_whitelist.yml diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java index 7d8b4ff4e614e..fb00030b10421 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java @@ -46,29 +46,6 @@ public final class Definition { private static final Pattern TYPE_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][._a-zA-Z0-9]*$"); - public static final String[] DEFINITION_FILES = new String[] { - "org.elasticsearch.txt", - "java.lang.txt", - "java.math.txt", - "java.text.txt", - "java.time.txt", - "java.time.chrono.txt", - "java.time.format.txt", - "java.time.temporal.txt", - "java.time.zone.txt", - "java.util.txt", - "java.util.function.txt", - "java.util.regex.txt", - "java.util.stream.txt", - "joda.time.txt" - }; - - /** - * Whitelist that is "built in" to Painless and required by all scripts. - */ - public static final Definition DEFINITION = new Definition( - Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, DEFINITION_FILES))); - /** Some native types as constants: */ public final Type voidType; public final Type booleanType; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessExtension.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessExtension.java new file mode 100644 index 0000000000000..204136eb3372a --- /dev/null +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessExtension.java @@ -0,0 +1,30 @@ +/* + * 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.painless; + +import java.util.List; +import java.util.Map; + +import org.elasticsearch.script.ScriptContext; + +public interface PainlessExtension { + + Map, List> getContextWhitelists(); +} diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java index 842af8717a34b..6aa98ed36ce40 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java @@ -20,6 +20,7 @@ package org.elasticsearch.painless; +import org.apache.lucene.util.SetOnce; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.ExtensiblePlugin; @@ -28,22 +29,49 @@ import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptEngine; +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; +import java.util.ServiceLoader; /** * Registers Painless as a plugin. */ public final class PainlessPlugin extends Plugin implements ScriptPlugin, ExtensiblePlugin { + private final Map, List> extendedWhitelists = new HashMap<>(); + @Override public ScriptEngine getScriptEngine(Settings settings, Collection> contexts) { - return new PainlessScriptEngine(settings, contexts); + Map, List> contextsWithWhitelists = new HashMap<>(); + for (ScriptContext context : contexts) { + // we might have a context that only uses the base whitelists, so would not have been filled in by reloadSPI + List whitelists = extendedWhitelists.get(context); + if (whitelists == null) { + whitelists = new ArrayList<>(Whitelist.BASE_WHITELISTS); + } + contextsWithWhitelists.put(context, whitelists); + } + return new PainlessScriptEngine(settings, contextsWithWhitelists); } @Override public List> getSettings() { return Arrays.asList(CompilerSettings.REGEX_ENABLED); } + + @Override + public void reloadSPI(ClassLoader loader) { + for (PainlessExtension extension : ServiceLoader.load(PainlessExtension.class, loader)) { + for (Map.Entry, List> entry : extension.getContextWhitelists().entrySet()) { + List existing = extendedWhitelists.computeIfAbsent(entry.getKey(), + c -> new ArrayList<>(Whitelist.BASE_WHITELISTS)); + existing.addAll(entry.getValue()); + } + } + } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java index ac01f45a7fdd6..c2671a643da55 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java @@ -82,7 +82,7 @@ public final class PainlessScriptEngine extends AbstractComponent implements Scr /** * Default compiler settings to be used. Note that {@link CompilerSettings} is mutable but this instance shouldn't be mutated outside - * of {@link PainlessScriptEngine#PainlessScriptEngine(Settings, Collection)}. + * of {@link PainlessScriptEngine#PainlessScriptEngine(Settings, Map)}. */ private final CompilerSettings defaultCompilerSettings = new CompilerSettings(); @@ -92,23 +92,19 @@ public final class PainlessScriptEngine extends AbstractComponent implements Scr * Constructor. * @param settings The settings to initialize the engine with. */ - public PainlessScriptEngine(Settings settings, Collection> contexts) { + public PainlessScriptEngine(Settings settings, Map, List> contexts) { super(settings); defaultCompilerSettings.setRegexesEnabled(CompilerSettings.REGEX_ENABLED.get(settings)); Map, Compiler> contextsToCompilers = new HashMap<>(); - // Placeholder definition used for all contexts until SPI is fully integrated. Reduces memory foot print - // by re-using the same definition since caching isn't implemented at this time. - Definition definition = new Definition( - Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); - - for (ScriptContext context : contexts) { + for (Map.Entry, List> entry : contexts.entrySet()) { + ScriptContext context = entry.getKey(); if (context.instanceClazz.equals(SearchScript.class) || context.instanceClazz.equals(ExecutableScript.class)) { - contextsToCompilers.put(context, new Compiler(GenericElasticsearchScript.class, definition)); + contextsToCompilers.put(context, new Compiler(GenericElasticsearchScript.class, new Definition(entry.getValue()))); } else { - contextsToCompilers.put(context, new Compiler(context.instanceClazz, definition)); + contextsToCompilers.put(context, new Compiler(context.instanceClazz, new Definition(entry.getValue()))); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Whitelist.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Whitelist.java index 678b8a4c1ae38..52964276483c9 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Whitelist.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Whitelist.java @@ -34,6 +34,26 @@ */ public final class Whitelist { + private static final String[] BASE_WHITELIST_FILES = new String[] { + "org.elasticsearch.txt", + "java.lang.txt", + "java.math.txt", + "java.text.txt", + "java.time.txt", + "java.time.chrono.txt", + "java.time.format.txt", + "java.time.temporal.txt", + "java.time.zone.txt", + "java.util.txt", + "java.util.function.txt", + "java.util.regex.txt", + "java.util.stream.txt", + "joda.time.txt" + }; + + public static final List BASE_WHITELISTS = + Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Whitelist.class, BASE_WHITELIST_FILES)); + /** * Struct represents the equivalent of a Java class in Painless complete with super classes, * constructors, methods, and fields. In Painless a class is known as a struct primarily to avoid diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WhitelistLoader.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/WhitelistLoader.java index 93ea951f453aa..56b80b4f35711 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WhitelistLoader.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/WhitelistLoader.java @@ -25,6 +25,8 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -296,8 +298,9 @@ public static Whitelist loadFromResourceFiles(Class resource, String... filep throw new RuntimeException("error in [" + filepath + "] at line [" + number + "]", exception); } } + ClassLoader loader = AccessController.doPrivileged((PrivilegedAction)resource::getClassLoader); - return new Whitelist(resource.getClassLoader(), whitelistStructs); + return new Whitelist(loader, whitelistStructs); } private WhitelistLoader() {} diff --git a/modules/lang-painless/src/main/plugin-metadata/plugin-security.policy b/modules/lang-painless/src/main/plugin-metadata/plugin-security.policy index e45c1b86ceb2c..b383c6da3f12c 100644 --- a/modules/lang-painless/src/main/plugin-metadata/plugin-security.policy +++ b/modules/lang-painless/src/main/plugin-metadata/plugin-security.policy @@ -20,4 +20,7 @@ grant { // needed to generate runtime classes permission java.lang.RuntimePermission "createClassLoader"; + + // needed to find the classloader to load whitelisted classes from + permission java.lang.RuntimePermission "getClassLoader"; }; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java index 58ae31a45c93a..5284f577f8ca3 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java @@ -23,14 +23,9 @@ import org.elasticsearch.painless.Definition.Type; import org.elasticsearch.test.ESTestCase; -import java.util.Collections; - -import static org.elasticsearch.painless.Definition.DEFINITION_FILES; - public class AnalyzerCasterTests extends ESTestCase { - private static final Definition definition = new Definition( - Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, DEFINITION_FILES))); + private static final Definition definition = new Definition(Whitelist.BASE_WHITELISTS); private static void assertCast(Type actual, Type expected, boolean mustBeExplicit) { Location location = new Location("dummy", 0); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java index 2ba8692b8af59..0ab524a715220 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java @@ -19,9 +19,6 @@ package org.elasticsearch.painless; -import org.elasticsearch.script.ScriptContext; - -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -37,8 +34,7 @@ */ public class BaseClassTests extends ScriptTestCase { - private final Definition definition = new Definition( - Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); + private final Definition definition = new Definition(Whitelist.BASE_WHITELISTS); public abstract static class Gets { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DebugTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DebugTests.java index a55b48f0189b3..66c38bf608744 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DebugTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DebugTests.java @@ -25,7 +25,6 @@ import org.elasticsearch.script.ScriptException; import java.io.IOException; -import java.util.Collections; import java.util.Map; import static java.util.Collections.singletonList; @@ -35,8 +34,7 @@ import static org.hamcrest.Matchers.not; public class DebugTests extends ScriptTestCase { - private final Definition definition = new Definition( - Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); + private final Definition definition = new Definition(Whitelist.BASE_WHITELISTS); public void testExplain() { // Debug.explain can explain an object diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java index 52ec783db4ef4..2059601fda6d8 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java @@ -24,7 +24,6 @@ import java.io.PrintWriter; import java.io.StringWriter; -import java.util.Collections; /** quick and dirty tools for debugging */ final class Debugger { @@ -40,8 +39,7 @@ static String toString(Class iface, String source, CompilerSettings settings) PrintWriter outputWriter = new PrintWriter(output); Textifier textifier = new Textifier(); try { - new Compiler(iface, new Definition( - Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES)))) + new Compiler(iface, new Definition(Whitelist.BASE_WHITELISTS)) .compile("", source, settings, textifier); } catch (Exception e) { textifier.print(outputWriter); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefBootstrapTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefBootstrapTests.java index dccc9c0aeb505..dbfb79d9d4459 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefBootstrapTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefBootstrapTests.java @@ -30,8 +30,7 @@ import org.elasticsearch.test.ESTestCase; public class DefBootstrapTests extends ESTestCase { - private final Definition definition = new Definition( - Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); + private final Definition definition = new Definition(Whitelist.BASE_WHITELISTS); /** calls toString() on integers, twice */ public void testOneType() throws Throwable { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java index b15a2747bd088..020ee3ff9d14a 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java @@ -24,16 +24,18 @@ import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Map; public class FactoryTests extends ScriptTestCase { - protected Collection> scriptContexts() { - Collection> contexts = super.scriptContexts(); - contexts.add(StatefulFactoryTestScript.CONTEXT); - contexts.add(FactoryTestScript.CONTEXT); - contexts.add(EmptyTestScript.CONTEXT); - contexts.add(TemplateScript.CONTEXT); + @Override + protected Map, List> scriptContexts() { + Map, List> contexts = super.scriptContexts(); + contexts.put(StatefulFactoryTestScript.CONTEXT, Whitelist.BASE_WHITELISTS); + contexts.put(FactoryTestScript.CONTEXT, Whitelist.BASE_WHITELISTS); + contexts.put(EmptyTestScript.CONTEXT, Whitelist.BASE_WHITELISTS); + contexts.put(TemplateScript.CONTEXT, Whitelist.BASE_WHITELISTS); return contexts; } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java index db254b734a81a..4c150ecf5f6f2 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java @@ -24,12 +24,16 @@ import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.script.ExecutableScript; +import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.SearchScript; import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.test.ESSingleNodeTestCase; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Test that needsScores() is reported correctly depending on whether _score is used @@ -40,8 +44,10 @@ public class NeedsScoreTests extends ESSingleNodeTestCase { public void testNeedsScores() { IndexService index = createIndex("test", Settings.EMPTY, "type", "d", "type=double"); - PainlessScriptEngine service = new PainlessScriptEngine(Settings.EMPTY, - Arrays.asList(SearchScript.CONTEXT, ExecutableScript.CONTEXT)); + Map, List> contexts = new HashMap<>(); + contexts.put(SearchScript.CONTEXT, Whitelist.BASE_WHITELISTS); + contexts.put(ExecutableScript.CONTEXT, Whitelist.BASE_WHITELISTS); + PainlessScriptEngine service = new PainlessScriptEngine(Settings.EMPTY, contexts); QueryShardContext shardContext = index.newQueryShardContext(0, null, () -> 0, null); SearchLookup lookup = new SearchLookup(index.mapperService(), shardContext::getForField, null); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/PainlessDocGenerator.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/PainlessDocGenerator.java index edd600c5664f2..91e5d3e1468be 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/PainlessDocGenerator.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/PainlessDocGenerator.java @@ -27,7 +27,6 @@ import org.elasticsearch.painless.Definition.Method; import org.elasticsearch.painless.Definition.Struct; import org.elasticsearch.painless.Definition.Type; -import org.elasticsearch.painless.api.Augmentation; import java.io.IOException; import java.io.PrintStream; @@ -36,7 +35,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; @@ -68,8 +66,7 @@ public static void main(String[] args) throws IOException { Files.newOutputStream(indexPath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE), false, StandardCharsets.UTF_8.name())) { emitGeneratedWarning(indexStream); - List types = new Definition(Collections.singletonList( - WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))). + List types = new Definition(Whitelist.BASE_WHITELISTS). allSimpleTypes().stream().sorted(comparing(t -> t.name)).collect(toList()); for (Type type : types) { if (type.clazz.isPrimitive()) { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java index 730dd298f8a54..4ec26b827b8c8 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java @@ -35,6 +35,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.elasticsearch.painless.node.SSource.MainMethodReserved; @@ -63,11 +64,10 @@ protected Settings scriptEngineSettings() { /** * Script contexts used to build the script engine. Override to customize which script contexts are available. */ - protected Collection> scriptContexts() { - Collection> contexts = new ArrayList<>(); - contexts.add(SearchScript.CONTEXT); - contexts.add(ExecutableScript.CONTEXT); - + protected Map, List> scriptContexts() { + Map, List> contexts = new HashMap<>(); + contexts.put(SearchScript.CONTEXT, Whitelist.BASE_WHITELISTS); + contexts.put(ExecutableScript.CONTEXT, Whitelist.BASE_WHITELISTS); return contexts; } @@ -92,8 +92,7 @@ public Object exec(String script, Map vars, boolean picky) { public Object exec(String script, Map vars, Map compileParams, Scorer scorer, boolean picky) { // test for ambiguity errors before running the actual script if picky is true if (picky) { - Definition definition = new Definition( - Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); + Definition definition = new Definition(Whitelist.BASE_WHITELISTS); ScriptClassInfo scriptClassInfo = new ScriptClassInfo(definition, GenericElasticsearchScript.class); CompilerSettings pickySettings = new CompilerSettings(); pickySettings.setPicky(true); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/SimilarityScriptTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/SimilarityScriptTests.java index d8f43fb066867..76c66fa3ee201 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/SimilarityScriptTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/SimilarityScriptTests.java @@ -37,7 +37,9 @@ import org.apache.lucene.store.Directory; import org.apache.lucene.store.RAMDirectory; import org.elasticsearch.index.similarity.ScriptedSimilarity; +import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.SearchScript; import org.elasticsearch.script.SimilarityScript; import org.elasticsearch.script.SimilarityWeightScript; @@ -45,12 +47,18 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class SimilarityScriptTests extends ScriptTestCase { @Override - protected Collection> scriptContexts() { - return Arrays.asList(SimilarityScript.CONTEXT, SimilarityWeightScript.CONTEXT); + protected Map, List> scriptContexts() { + Map, List> contexts = new HashMap<>(); + contexts.put(SimilarityScript.CONTEXT, Whitelist.BASE_WHITELISTS); + contexts.put(SimilarityWeightScript.CONTEXT, Whitelist.BASE_WHITELISTS); + return contexts; } public void testBasics() throws IOException { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java index 9e3477b1cfe02..a6493fa304aed 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java @@ -33,12 +33,11 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.Operation; import org.elasticsearch.painless.ScriptClassInfo; -import org.elasticsearch.painless.WhitelistLoader; +import org.elasticsearch.painless.Whitelist; import org.elasticsearch.painless.antlr.Walker; import org.elasticsearch.test.ESTestCase; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -50,8 +49,7 @@ * Tests {@link Object#toString} implementations on all extensions of {@link ANode}. */ public class NodeToStringTests extends ESTestCase { - private final Definition definition = new Definition( - Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); + private final Definition definition = new Definition(Whitelist.BASE_WHITELISTS); public void testEAssignment() { assertToString( diff --git a/plugins/examples/painless-whitelist/build.gradle b/plugins/examples/painless-whitelist/build.gradle index 2213aea16f6cd..12bbff8b0419e 100644 --- a/plugins/examples/painless-whitelist/build.gradle +++ b/plugins/examples/painless-whitelist/build.gradle @@ -26,6 +26,10 @@ esplugin { extendedPlugins = ['lang-painless'] } +dependencies { + compileOnly project(':modules:lang-painless') +} + integTestCluster { distribution = 'zip' } diff --git a/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java b/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java new file mode 100644 index 0000000000000..ed945633c1e42 --- /dev/null +++ b/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java @@ -0,0 +1,42 @@ +/* + * 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.example.painlesswhitelist; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.elasticsearch.painless.PainlessExtension; +import org.elasticsearch.painless.Whitelist; +import org.elasticsearch.painless.WhitelistLoader; +import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.SearchScript; + +/** An extension of painless which adds a whitelist. */ +public class ExampleWhitelistExtension implements PainlessExtension { + + private static final Whitelist WHITELIST = + WhitelistLoader.loadFromResourceFiles(ExampleWhitelistExtension.class, "example_whitelist.txt"); + + @Override + public Map, List> getContextWhitelists() { + return Collections.singletonMap(SearchScript.CONTEXT, Collections.singletonList(WHITELIST)); + } +} diff --git a/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistedClass.java b/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistedClass.java new file mode 100644 index 0000000000000..14f15b383d0c8 --- /dev/null +++ b/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistedClass.java @@ -0,0 +1,57 @@ +/* + * 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.example.painlesswhitelist; + +/** + * An example of a class to be whitelisted for use by painless scripts + * + * Each of the members and methods below are whitelisted for use in search scripts. + * See example_whitelist.txt. + */ +public class ExampleWhitelistedClass { + + public static final int CONSTANT = 42; + + public int publicMember; + + private int privateMember; + + public ExampleWhitelistedClass(int publicMember, int privateMember) { + this.publicMember = publicMember; + this.privateMember = privateMember; + } + + public int getPrivateMemberAccessor() { + return this.privateMember; + } + + public void setPrivateMemberAccessor(int privateMember) { + this.privateMember = privateMember; + } + + public static void staticMethod() { + // electricity + } + + // example augmentation method + public static int toInt(String x) { + return Integer.parseInt(x); + } +} diff --git a/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/MyWhitelistPlugin.java b/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/MyWhitelistPlugin.java index 877a05391ac77..a4ef5f6f000e1 100644 --- a/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/MyWhitelistPlugin.java +++ b/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/MyWhitelistPlugin.java @@ -22,4 +22,5 @@ import org.elasticsearch.plugins.Plugin; public class MyWhitelistPlugin extends Plugin { + // we don't actually need anything here, since whitelists are extended through SPI } diff --git a/plugins/examples/painless-whitelist/src/main/resources/META-INF/services/org.elasticsearch.painless.PainlessExtension b/plugins/examples/painless-whitelist/src/main/resources/META-INF/services/org.elasticsearch.painless.PainlessExtension new file mode 100644 index 0000000000000..9babd702c8083 --- /dev/null +++ b/plugins/examples/painless-whitelist/src/main/resources/META-INF/services/org.elasticsearch.painless.PainlessExtension @@ -0,0 +1 @@ +org.elasticsearch.example.painlesswhitelist.ExampleWhitelistExtension \ No newline at end of file diff --git a/plugins/examples/painless-whitelist/src/main/resources/org/elasticsearch/example/painlesswhitelist/example_whitelist.txt b/plugins/examples/painless-whitelist/src/main/resources/org/elasticsearch/example/painlesswhitelist/example_whitelist.txt new file mode 100644 index 0000000000000..7908d35417511 --- /dev/null +++ b/plugins/examples/painless-whitelist/src/main/resources/org/elasticsearch/example/painlesswhitelist/example_whitelist.txt @@ -0,0 +1,42 @@ +# +# 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. +# + +# This file contains a whitelist for an example class which may be access from painless + +class org.elasticsearch.example.painlesswhitelist.ExampleWhitelistedClass { + # constructor + (int, int) + + # static constants and methods look the same as instance members and methods + int CONSTANT + void staticMethod() + + # members lack parenthesis that methods have + int publicMember + + # getter and setter for private member + int getPrivateMemberAccessor() + void setPrivateMemberAccessor(int) +} + +class java.lang.String { + # existing classes can be "augmented" to have additional methods, which take the object + # to operate on as the first argument to a static method + int org.elasticsearch.example.painlesswhitelist.ExampleWhitelistedClass toInt() +} \ No newline at end of file diff --git a/plugins/examples/painless-whitelist/src/test/resources/rest-api-spec/test/painless_whitelist/20_whitelist.yml b/plugins/examples/painless-whitelist/src/test/resources/rest-api-spec/test/painless_whitelist/20_whitelist.yml new file mode 100644 index 0000000000000..bbb0b44ef1d45 --- /dev/null +++ b/plugins/examples/painless-whitelist/src/test/resources/rest-api-spec/test/painless_whitelist/20_whitelist.yml @@ -0,0 +1,26 @@ +# Example test using whitelisted members and methods + +"Whitelisted custom class": + - do: + index: + index: test + type: test + id: 1 + body: { "num1": 1.0 } + - do: + indices.refresh: {} + + - do: + index: test + search: + body: + query: + match_all: {} + script_fields: + sNum1: + script: + source: "def e = new ExampleWhitelistedClass(6, 42); ExampleWhitelistedClass.staticMethod(); return e.publicMember + e.privateMemberAccessor + ExampleWhitelistedClass.CONSTANT + '2'.toInt()" + lang: painless + + - match: { hits.total: 1 } + - match: { hits.hits.0.fields.sNum1.0: 92 } From 869657fbc844ac229763c0c9c421e619e9900f31 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Tue, 9 Jan 2018 16:08:33 -0800 Subject: [PATCH 2/3] move spi related classes to spi package --- .../src/main/java/org/elasticsearch/painless/Compiler.java | 1 + .../main/java/org/elasticsearch/painless/Definition.java | 1 + .../java/org/elasticsearch/painless/PainlessPlugin.java | 4 ++-- .../org/elasticsearch/painless/PainlessScriptEngine.java | 3 +-- .../elasticsearch/painless/{ => spi}/PainlessExtension.java | 2 +- .../org/elasticsearch/painless/{ => spi}/Whitelist.java | 2 +- .../elasticsearch/painless/{ => spi}/WhitelistLoader.java | 2 +- .../org/elasticsearch/painless/AnalyzerCasterTests.java | 1 + .../java/org/elasticsearch/painless/BaseClassTests.java | 2 ++ .../test/java/org/elasticsearch/painless/DebugTests.java | 1 + .../src/test/java/org/elasticsearch/painless/Debugger.java | 1 + .../java/org/elasticsearch/painless/DefBootstrapTests.java | 1 + .../test/java/org/elasticsearch/painless/FactoryTests.java | 2 +- .../java/org/elasticsearch/painless/NeedsScoreTests.java | 3 +-- .../org/elasticsearch/painless/PainlessDocGenerator.java | 1 + .../java/org/elasticsearch/painless/ScriptTestCase.java | 4 +--- .../org/elasticsearch/painless/SimilarityScriptTests.java | 5 +---- .../org/elasticsearch/painless/node/NodeToStringTests.java | 2 +- .../painlesswhitelist/ExampleWhitelistExtension.java | 6 +++--- ...ion => org.elasticsearch.painless.spi.PainlessExtension} | 0 20 files changed, 23 insertions(+), 21 deletions(-) rename modules/lang-painless/src/main/java/org/elasticsearch/painless/{ => spi}/PainlessExtension.java (96%) rename modules/lang-painless/src/main/java/org/elasticsearch/painless/{ => spi}/Whitelist.java (99%) rename modules/lang-painless/src/main/java/org/elasticsearch/painless/{ => spi}/WhitelistLoader.java (99%) rename plugins/examples/painless-whitelist/src/main/resources/META-INF/services/{org.elasticsearch.painless.PainlessExtension => org.elasticsearch.painless.spi.PainlessExtension} (100%) diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java index ad5e80ba16edd..8102016828c30 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java @@ -22,6 +22,7 @@ import org.elasticsearch.bootstrap.BootstrapInfo; import org.elasticsearch.painless.antlr.Walker; import org.elasticsearch.painless.node.SSource; +import org.elasticsearch.painless.spi.Whitelist; import org.objectweb.asm.util.Printer; import java.lang.reflect.Constructor; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java index fb00030b10421..7729c5319ea81 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java @@ -20,6 +20,7 @@ package org.elasticsearch.painless; import org.apache.lucene.util.SetOnce; +import org.elasticsearch.painless.spi.Whitelist; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java index 6aa98ed36ce40..795d81bb6e058 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java @@ -20,9 +20,10 @@ package org.elasticsearch.painless; -import org.apache.lucene.util.SetOnce; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.painless.spi.PainlessExtension; +import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.plugins.ExtensiblePlugin; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.ScriptPlugin; @@ -32,7 +33,6 @@ 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; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java index c2671a643da55..95a38bf22c653 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java @@ -19,12 +19,12 @@ package org.elasticsearch.painless; -import org.apache.logging.log4j.core.tools.Generate; import org.apache.lucene.index.LeafReaderContext; import org.elasticsearch.SpecialPermission; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.painless.Compiler.Loader; +import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptEngine; @@ -45,7 +45,6 @@ import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessExtension.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/spi/PainlessExtension.java similarity index 96% rename from modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessExtension.java rename to modules/lang-painless/src/main/java/org/elasticsearch/painless/spi/PainlessExtension.java index 204136eb3372a..9434e6986c0a3 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessExtension.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/spi/PainlessExtension.java @@ -17,7 +17,7 @@ * under the License. */ -package org.elasticsearch.painless; +package org.elasticsearch.painless.spi; import java.util.List; import java.util.Map; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Whitelist.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/spi/Whitelist.java similarity index 99% rename from modules/lang-painless/src/main/java/org/elasticsearch/painless/Whitelist.java rename to modules/lang-painless/src/main/java/org/elasticsearch/painless/spi/Whitelist.java index 52964276483c9..e715eb0090c7f 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Whitelist.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/spi/Whitelist.java @@ -17,7 +17,7 @@ * under the License. */ -package org.elasticsearch.painless; +package org.elasticsearch.painless.spi; import java.util.Collections; import java.util.List; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WhitelistLoader.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java similarity index 99% rename from modules/lang-painless/src/main/java/org/elasticsearch/painless/WhitelistLoader.java rename to modules/lang-painless/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java index 56b80b4f35711..8817bfa274c60 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WhitelistLoader.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java @@ -17,7 +17,7 @@ * under the License. */ -package org.elasticsearch.painless; +package org.elasticsearch.painless.spi; import java.io.InputStreamReader; import java.io.LineNumberReader; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java index 5284f577f8ca3..919b0881c0794 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AnalyzerCasterTests.java @@ -21,6 +21,7 @@ import org.elasticsearch.painless.Definition.Cast; import org.elasticsearch.painless.Definition.Type; +import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.test.ESTestCase; public class AnalyzerCasterTests extends ESTestCase { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java index 0ab524a715220..59cafa96ddcb9 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java @@ -23,6 +23,8 @@ import java.util.HashMap; import java.util.Map; +import org.elasticsearch.painless.spi.Whitelist; + import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; import static org.hamcrest.Matchers.containsString; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DebugTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DebugTests.java index 66c38bf608744..279438e74a7c3 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DebugTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DebugTests.java @@ -22,6 +22,7 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.script.ScriptException; import java.io.IOException; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java index 2059601fda6d8..e29986a3c87de 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java @@ -20,6 +20,7 @@ package org.elasticsearch.painless; import org.apache.lucene.util.IOUtils; +import org.elasticsearch.painless.spi.Whitelist; import org.objectweb.asm.util.Textifier; import java.io.PrintWriter; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefBootstrapTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefBootstrapTests.java index dbfb79d9d4459..8fd96d67d5b53 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefBootstrapTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefBootstrapTests.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.HashMap; +import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.test.ESTestCase; public class DefBootstrapTests extends ESTestCase { diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java index 020ee3ff9d14a..556ef8dd3c6d3 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java @@ -19,10 +19,10 @@ package org.elasticsearch.painless; +import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.TemplateScript; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java index 4c150ecf5f6f2..50a377b881878 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java @@ -22,14 +22,13 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.query.QueryShardContext; -import org.elasticsearch.index.shard.IndexShard; +import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.SearchScript; import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.test.ESSingleNodeTestCase; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/PainlessDocGenerator.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/PainlessDocGenerator.java index 91e5d3e1468be..87b1677102635 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/PainlessDocGenerator.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/PainlessDocGenerator.java @@ -27,6 +27,7 @@ import org.elasticsearch.painless.Definition.Method; import org.elasticsearch.painless.Definition.Struct; import org.elasticsearch.painless.Definition.Type; +import org.elasticsearch.painless.spi.Whitelist; import java.io.IOException; import java.io.PrintStream; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java index 4ec26b827b8c8..ea1d2275b3e8d 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java @@ -24,6 +24,7 @@ import org.elasticsearch.common.lucene.ScorerAware; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.painless.antlr.Walker; +import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptException; @@ -31,9 +32,6 @@ import org.elasticsearch.test.ESTestCase; import org.junit.Before; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/SimilarityScriptTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/SimilarityScriptTests.java index 76c66fa3ee201..0795ab7777526 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/SimilarityScriptTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/SimilarityScriptTests.java @@ -37,15 +37,12 @@ import org.apache.lucene.store.Directory; import org.apache.lucene.store.RAMDirectory; import org.elasticsearch.index.similarity.ScriptedSimilarity; -import org.elasticsearch.script.ExecutableScript; +import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.script.ScriptContext; -import org.elasticsearch.script.SearchScript; import org.elasticsearch.script.SimilarityScript; import org.elasticsearch.script.SimilarityWeightScript; import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java index a6493fa304aed..424b0c286ecff 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java @@ -33,7 +33,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.Operation; import org.elasticsearch.painless.ScriptClassInfo; -import org.elasticsearch.painless.Whitelist; +import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.painless.antlr.Walker; import org.elasticsearch.test.ESTestCase; diff --git a/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java b/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java index ed945633c1e42..9e3bc66e7d58d 100644 --- a/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java +++ b/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java @@ -23,9 +23,9 @@ import java.util.List; import java.util.Map; -import org.elasticsearch.painless.PainlessExtension; -import org.elasticsearch.painless.Whitelist; -import org.elasticsearch.painless.WhitelistLoader; +import org.elasticsearch.painless.spi.PainlessExtension; +import org.elasticsearch.painless.spi.Whitelist; +import org.elasticsearch.painless.spi.WhitelistLoader; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.SearchScript; diff --git a/plugins/examples/painless-whitelist/src/main/resources/META-INF/services/org.elasticsearch.painless.PainlessExtension b/plugins/examples/painless-whitelist/src/main/resources/META-INF/services/org.elasticsearch.painless.spi.PainlessExtension similarity index 100% rename from plugins/examples/painless-whitelist/src/main/resources/META-INF/services/org.elasticsearch.painless.PainlessExtension rename to plugins/examples/painless-whitelist/src/main/resources/META-INF/services/org.elasticsearch.painless.spi.PainlessExtension From 8e5ffac57336acfc070818fc4b59ac50971f3e9b Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 10 Jan 2018 09:37:38 -0800 Subject: [PATCH 3/3] Move resource files to same package as whitelist classes for SPI. --- .../resources/org/elasticsearch/painless/{ => spi}/java.lang.txt | 0 .../resources/org/elasticsearch/painless/{ => spi}/java.math.txt | 0 .../resources/org/elasticsearch/painless/{ => spi}/java.text.txt | 0 .../org/elasticsearch/painless/{ => spi}/java.time.chrono.txt | 0 .../org/elasticsearch/painless/{ => spi}/java.time.format.txt | 0 .../org/elasticsearch/painless/{ => spi}/java.time.temporal.txt | 0 .../resources/org/elasticsearch/painless/{ => spi}/java.time.txt | 0 .../org/elasticsearch/painless/{ => spi}/java.time.zone.txt | 0 .../org/elasticsearch/painless/{ => spi}/java.util.function.txt | 0 .../org/elasticsearch/painless/{ => spi}/java.util.regex.txt | 0 .../org/elasticsearch/painless/{ => spi}/java.util.stream.txt | 0 .../resources/org/elasticsearch/painless/{ => spi}/java.util.txt | 0 .../resources/org/elasticsearch/painless/{ => spi}/joda.time.txt | 0 .../org/elasticsearch/painless/{ => spi}/org.elasticsearch.txt | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.lang.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.math.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.text.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.time.chrono.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.time.format.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.time.temporal.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.time.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.time.zone.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.util.function.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.util.regex.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.util.stream.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/java.util.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/joda.time.txt (100%) rename modules/lang-painless/src/main/resources/org/elasticsearch/painless/{ => spi}/org.elasticsearch.txt (100%) diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.lang.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.lang.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.lang.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.lang.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.math.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.math.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.math.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.math.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.text.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.text.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.text.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.text.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.time.chrono.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.time.chrono.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.time.chrono.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.time.chrono.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.time.format.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.time.format.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.time.format.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.time.format.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.time.temporal.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.time.temporal.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.time.temporal.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.time.temporal.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.time.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.time.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.time.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.time.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.time.zone.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.time.zone.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.time.zone.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.time.zone.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.util.function.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.util.function.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.util.function.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.util.function.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.util.regex.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.util.regex.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.util.regex.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.util.regex.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.util.stream.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.util.stream.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.util.stream.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.util.stream.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.util.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.util.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/java.util.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/java.util.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/joda.time.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/joda.time.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/joda.time.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/joda.time.txt diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/org.elasticsearch.txt similarity index 100% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.txt rename to modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/org.elasticsearch.txt