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 582ba6f4d5b06..ad5e80ba16edd 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 @@ -69,12 +69,28 @@ final class Compiler { */ static final class Loader extends SecureClassLoader { private final AtomicInteger lambdaCounter = new AtomicInteger(0); + private final Definition definition; /** * @param parent The parent ClassLoader. */ - Loader(ClassLoader parent) { + Loader(ClassLoader parent, Definition definition) { super(parent); + + this.definition = definition; + } + + /** + * Will check to see if the {@link Class} has already been loaded when + * the {@link Definition} was initially created. Allows for {@link Whitelist}ed + * classes to be loaded from other modules/plugins without a direct relationship + * to the module's/plugin's {@link ClassLoader}. + */ + @Override + public Class findClass(String name) throws ClassNotFoundException { + Class found = definition.getClassFromBinaryName(name); + + return found != null ? found : super.findClass(name); } /** @@ -116,6 +132,14 @@ int newLambdaIdentifier() { } } + /** + * Return a new {@link Loader} for a script using the + * {@link Compiler}'s specified {@link Definition}. + */ + public Loader createLoader(ClassLoader parent) { + return new Loader(parent, definition); + } + /** * The class/interface the script is guaranteed to derive/implement. */ 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 853c836f9cfca..34385dbf7acfc 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 @@ -43,7 +43,7 @@ public final class Definition { private static final Pattern TYPE_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][._a-zA-Z0-9]*$"); - private static final String[] DEFINITION_FILES = new String[] { + public static final String[] DEFINITION_FILES = new String[] { "org.elasticsearch.txt", "java.lang.txt", "java.math.txt", @@ -522,6 +522,12 @@ public RuntimeClass getRuntimeClass(Class clazz) { return runtimeMap.get(clazz); } + public Class getClassFromBinaryName(String name) { + Struct struct = structsMap.get(name.replace('$', '.')); + + return struct == null ? null : struct.clazz; + } + /** Collection of all simple types. Used by {@code PainlessDocGenerator} to generate an API reference. */ Collection allSimpleTypes() { return simpleTypesMap.values(); @@ -535,7 +541,7 @@ Collection allSimpleTypes() { public AnalyzerCaster caster; - private Definition(List whitelists) { + public Definition(List whitelists) { structsMap = new HashMap<>(); simpleTypesMap = new HashMap<>(); runtimeMap = new HashMap<>(); 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 28b860bb539ce..842af8717a34b 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 @@ -37,11 +37,6 @@ */ public final class PainlessPlugin extends Plugin implements ScriptPlugin, ExtensiblePlugin { - // force to parse our definition at startup (not on the user's first script) - static { - Definition.DEFINITION.hashCode(); - } - @Override public ScriptEngine getScriptEngine(Settings settings, Collection> contexts) { return new PainlessScriptEngine(settings, contexts); 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 5299adb1dc8dd..ac01f45a7fdd6 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 @@ -99,11 +99,16 @@ public PainlessScriptEngine(Settings settings, Collection> cont 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) { if (context.instanceClazz.equals(SearchScript.class) || context.instanceClazz.equals(ExecutableScript.class)) { - contextsToCompilers.put(context, new Compiler(GenericElasticsearchScript.class, Definition.DEFINITION)); + contextsToCompilers.put(context, new Compiler(GenericElasticsearchScript.class, definition)); } else { - contextsToCompilers.put(context, new Compiler(context.instanceClazz, Definition.DEFINITION)); + contextsToCompilers.put(context, new Compiler(context.instanceClazz, definition)); } } @@ -126,9 +131,11 @@ public String getType() { @Override public T compile(String scriptName, String scriptSource, ScriptContext context, Map params) { + Compiler compiler = contextsToCompilers.get(context); + if (context.instanceClazz.equals(SearchScript.class)) { GenericElasticsearchScript painlessScript = - (GenericElasticsearchScript)compile(contextsToCompilers.get(context), scriptName, scriptSource, params); + (GenericElasticsearchScript)compile(compiler, scriptName, scriptSource, params); SearchScript.Factory factory = (p, lookup) -> new SearchScript.LeafFactory() { @Override @@ -143,7 +150,7 @@ public boolean needs_score() { return context.factoryClazz.cast(factory); } else if (context.instanceClazz.equals(ExecutableScript.class)) { GenericElasticsearchScript painlessScript = - (GenericElasticsearchScript)compile(contextsToCompilers.get(context), scriptName, scriptSource, params); + (GenericElasticsearchScript)compile(compiler, scriptName, scriptSource, params); ExecutableScript.Factory factory = (p) -> new ScriptImpl(painlessScript, p, null, null); return context.factoryClazz.cast(factory); @@ -155,7 +162,7 @@ public boolean needs_score() { final Loader loader = AccessController.doPrivileged(new PrivilegedAction() { @Override public Loader run() { - return new Loader(getClass().getClassLoader()); + return compiler.createLoader(getClass().getClassLoader()); } }); @@ -414,7 +421,7 @@ Object compile(Compiler compiler, String scriptName, String source, Map() { @Override public Loader run() { - return new Loader(getClass().getClassLoader()); + return compiler.createLoader(getClass().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 249ce122b43e5..58ae31a45c93a 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,75 +23,82 @@ 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 void assertCast(Type actual, Type expected, boolean mustBeExplicit) { Location location = new Location("dummy", 0); if (actual.equals(expected)) { assertFalse(mustBeExplicit); - assertNull(Definition.DEFINITION.caster.getLegalCast(location, actual, expected, false, false)); - assertNull(Definition.DEFINITION.caster.getLegalCast(location, actual, expected, true, false)); + assertNull(definition.caster.getLegalCast(location, actual, expected, false, false)); + assertNull(definition.caster.getLegalCast(location, actual, expected, true, false)); return; } - Cast cast = Definition.DEFINITION.caster.getLegalCast(location, actual, expected, true, false); + Cast cast = definition.caster.getLegalCast(location, actual, expected, true, false); assertEquals(actual, cast.from); assertEquals(expected, cast.to); if (mustBeExplicit) { ClassCastException error = expectThrows(ClassCastException.class, - () -> Definition.DEFINITION.caster.getLegalCast(location, actual, expected, false, false)); + () -> definition.caster.getLegalCast(location, actual, expected, false, false)); assertTrue(error.getMessage().startsWith("Cannot cast")); } else { - cast = Definition.DEFINITION.caster.getLegalCast(location, actual, expected, false, false); + cast = definition.caster.getLegalCast(location, actual, expected, false, false); assertEquals(actual, cast.from); assertEquals(expected, cast.to); } } public void testNumericCasts() { - assertCast(Definition.DEFINITION.byteType, Definition.DEFINITION.byteType, false); - assertCast(Definition.DEFINITION.byteType, Definition.DEFINITION.shortType, false); - assertCast(Definition.DEFINITION.byteType, Definition.DEFINITION.intType, false); - assertCast(Definition.DEFINITION.byteType, Definition.DEFINITION.longType, false); - assertCast(Definition.DEFINITION.byteType, Definition.DEFINITION.floatType, false); - assertCast(Definition.DEFINITION.byteType, Definition.DEFINITION.doubleType, false); - - assertCast(Definition.DEFINITION.shortType, Definition.DEFINITION.byteType, true); - assertCast(Definition.DEFINITION.shortType, Definition.DEFINITION.shortType, false); - assertCast(Definition.DEFINITION.shortType, Definition.DEFINITION.intType, false); - assertCast(Definition.DEFINITION.shortType, Definition.DEFINITION.longType, false); - assertCast(Definition.DEFINITION.shortType, Definition.DEFINITION.floatType, false); - assertCast(Definition.DEFINITION.shortType, Definition.DEFINITION.doubleType, false); - - assertCast(Definition.DEFINITION.intType, Definition.DEFINITION.byteType, true); - assertCast(Definition.DEFINITION.intType, Definition.DEFINITION.shortType, true); - assertCast(Definition.DEFINITION.intType, Definition.DEFINITION.intType, false); - assertCast(Definition.DEFINITION.intType, Definition.DEFINITION.longType, false); - assertCast(Definition.DEFINITION.intType, Definition.DEFINITION.floatType, false); - assertCast(Definition.DEFINITION.intType, Definition.DEFINITION.doubleType, false); - - assertCast(Definition.DEFINITION.longType, Definition.DEFINITION.byteType, true); - assertCast(Definition.DEFINITION.longType, Definition.DEFINITION.shortType, true); - assertCast(Definition.DEFINITION.longType, Definition.DEFINITION.intType, true); - assertCast(Definition.DEFINITION.longType, Definition.DEFINITION.longType, false); - assertCast(Definition.DEFINITION.longType, Definition.DEFINITION.floatType, false); - assertCast(Definition.DEFINITION.longType, Definition.DEFINITION.doubleType, false); - - assertCast(Definition.DEFINITION.floatType, Definition.DEFINITION.byteType, true); - assertCast(Definition.DEFINITION.floatType, Definition.DEFINITION.shortType, true); - assertCast(Definition.DEFINITION.floatType, Definition.DEFINITION.intType, true); - assertCast(Definition.DEFINITION.floatType, Definition.DEFINITION.longType, true); - assertCast(Definition.DEFINITION.floatType, Definition.DEFINITION.floatType, false); - assertCast(Definition.DEFINITION.floatType, Definition.DEFINITION.doubleType, false); - - assertCast(Definition.DEFINITION.doubleType, Definition.DEFINITION.byteType, true); - assertCast(Definition.DEFINITION.doubleType, Definition.DEFINITION.shortType, true); - assertCast(Definition.DEFINITION.doubleType, Definition.DEFINITION.intType, true); - assertCast(Definition.DEFINITION.doubleType, Definition.DEFINITION.longType, true); - assertCast(Definition.DEFINITION.doubleType, Definition.DEFINITION.floatType, true); - assertCast(Definition.DEFINITION.doubleType, Definition.DEFINITION.doubleType, false); + assertCast(definition.byteType, definition.byteType, false); + assertCast(definition.byteType, definition.shortType, false); + assertCast(definition.byteType, definition.intType, false); + assertCast(definition.byteType, definition.longType, false); + assertCast(definition.byteType, definition.floatType, false); + assertCast(definition.byteType, definition.doubleType, false); + + assertCast(definition.shortType, definition.byteType, true); + assertCast(definition.shortType, definition.shortType, false); + assertCast(definition.shortType, definition.intType, false); + assertCast(definition.shortType, definition.longType, false); + assertCast(definition.shortType, definition.floatType, false); + assertCast(definition.shortType, definition.doubleType, false); + + assertCast(definition.intType, definition.byteType, true); + assertCast(definition.intType, definition.shortType, true); + assertCast(definition.intType, definition.intType, false); + assertCast(definition.intType, definition.longType, false); + assertCast(definition.intType, definition.floatType, false); + assertCast(definition.intType, definition.doubleType, false); + + assertCast(definition.longType, definition.byteType, true); + assertCast(definition.longType, definition.shortType, true); + assertCast(definition.longType, definition.intType, true); + assertCast(definition.longType, definition.longType, false); + assertCast(definition.longType, definition.floatType, false); + assertCast(definition.longType, definition.doubleType, false); + + assertCast(definition.floatType, definition.byteType, true); + assertCast(definition.floatType, definition.shortType, true); + assertCast(definition.floatType, definition.intType, true); + assertCast(definition.floatType, definition.longType, true); + assertCast(definition.floatType, definition.floatType, false); + assertCast(definition.floatType, definition.doubleType, false); + + assertCast(definition.doubleType, definition.byteType, true); + assertCast(definition.doubleType, definition.shortType, true); + assertCast(definition.doubleType, definition.intType, true); + assertCast(definition.doubleType, definition.longType, true); + assertCast(definition.doubleType, definition.floatType, true); + assertCast(definition.doubleType, definition.doubleType, false); } } 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 cdd51447bc149..2ba8692b8af59 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 @@ -37,6 +37,9 @@ */ public class BaseClassTests extends ScriptTestCase { + private final Definition definition = new Definition( + Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); + public abstract static class Gets { private final String testString; @@ -66,7 +69,7 @@ public Map getTestMap() { } public void testGets() { - Compiler compiler = new Compiler(Gets.class, Definition.DEFINITION); + Compiler compiler = new Compiler(Gets.class, definition); Map map = new HashMap<>(); map.put("s", 1); @@ -84,7 +87,7 @@ public abstract static class NoArgs { public abstract Object execute(); } public void testNoArgs() { - Compiler compiler = new Compiler(NoArgs.class, Definition.DEFINITION); + Compiler compiler = new Compiler(NoArgs.class, definition); assertEquals(1, ((NoArgs)scriptEngine.compile(compiler, null, "1", emptyMap())).execute()); assertEquals("foo", ((NoArgs)scriptEngine.compile(compiler, null, "'foo'", emptyMap())).execute()); @@ -108,13 +111,13 @@ public abstract static class OneArg { public abstract Object execute(Object arg); } public void testOneArg() { - Compiler compiler = new Compiler(OneArg.class, Definition.DEFINITION); + Compiler compiler = new Compiler(OneArg.class, definition); Object rando = randomInt(); assertEquals(rando, ((OneArg)scriptEngine.compile(compiler, null, "arg", emptyMap())).execute(rando)); rando = randomAlphaOfLength(5); assertEquals(rando, ((OneArg)scriptEngine.compile(compiler, null, "arg", emptyMap())).execute(rando)); - Compiler noargs = new Compiler(NoArgs.class, Definition.DEFINITION); + Compiler noargs = new Compiler(NoArgs.class, definition); Exception e = expectScriptThrows(IllegalArgumentException.class, () -> scriptEngine.compile(noargs, null, "doc", emptyMap())); assertEquals("Variable [doc] is not defined.", e.getMessage()); @@ -129,7 +132,7 @@ public abstract static class ArrayArg { public abstract Object execute(String[] arg); } public void testArrayArg() { - Compiler compiler = new Compiler(ArrayArg.class, Definition.DEFINITION); + Compiler compiler = new Compiler(ArrayArg.class, definition); String rando = randomAlphaOfLength(5); assertEquals(rando, ((ArrayArg)scriptEngine.compile(compiler, null, "arg[0]", emptyMap())).execute(new String[] {rando, "foo"})); } @@ -139,7 +142,7 @@ public abstract static class PrimitiveArrayArg { public abstract Object execute(int[] arg); } public void testPrimitiveArrayArg() { - Compiler compiler = new Compiler(PrimitiveArrayArg.class, Definition.DEFINITION); + Compiler compiler = new Compiler(PrimitiveArrayArg.class, definition); int rando = randomInt(); assertEquals(rando, ((PrimitiveArrayArg)scriptEngine.compile(compiler, null, "arg[0]", emptyMap())).execute(new int[] {rando, 10})); } @@ -149,7 +152,7 @@ public abstract static class DefArrayArg { public abstract Object execute(Object[] arg); } public void testDefArrayArg() { - Compiler compiler = new Compiler(DefArrayArg.class, Definition.DEFINITION); + Compiler compiler = new Compiler(DefArrayArg.class, definition); Object rando = randomInt(); assertEquals(rando, ((DefArrayArg)scriptEngine.compile(compiler, null, "arg[0]", emptyMap())).execute(new Object[] {rando, 10})); rando = randomAlphaOfLength(5); @@ -167,7 +170,7 @@ public abstract static class ManyArgs { public abstract boolean needsD(); } public void testManyArgs() { - Compiler compiler = new Compiler(ManyArgs.class, Definition.DEFINITION); + Compiler compiler = new Compiler(ManyArgs.class, definition); int rando = randomInt(); assertEquals(rando, ((ManyArgs)scriptEngine.compile(compiler, null, "a", emptyMap())).execute(rando, 0, 0, 0)); assertEquals(10, ((ManyArgs)scriptEngine.compile(compiler, null, "a + b + c + d", emptyMap())).execute(1, 2, 3, 4)); @@ -195,7 +198,7 @@ public abstract static class VarargTest { public abstract Object execute(String... arg); } public void testVararg() { - Compiler compiler = new Compiler(VarargTest.class, Definition.DEFINITION); + Compiler compiler = new Compiler(VarargTest.class, definition); assertEquals("foo bar baz", ((VarargTest)scriptEngine.compile(compiler, null, "String.join(' ', Arrays.asList(arg))", emptyMap())) .execute("foo", "bar", "baz")); } @@ -211,7 +214,7 @@ public Object executeWithASingleOne(int a, int b, int c) { } } public void testDefaultMethods() { - Compiler compiler = new Compiler(DefaultMethods.class, Definition.DEFINITION); + Compiler compiler = new Compiler(DefaultMethods.class, definition); int rando = randomInt(); assertEquals(rando, ((DefaultMethods)scriptEngine.compile(compiler, null, "a", emptyMap())).execute(rando, 0, 0, 0)); assertEquals(rando, ((DefaultMethods)scriptEngine.compile(compiler, null, "a", emptyMap())).executeWithASingleOne(rando, 0, 0)); @@ -225,7 +228,7 @@ public abstract static class ReturnsVoid { public abstract void execute(Map map); } public void testReturnsVoid() { - Compiler compiler = new Compiler(ReturnsVoid.class, Definition.DEFINITION); + Compiler compiler = new Compiler(ReturnsVoid.class, definition); Map map = new HashMap<>(); ((ReturnsVoid)scriptEngine.compile(compiler, null, "map.a = 'foo'", emptyMap())).execute(map); assertEquals(singletonMap("a", "foo"), map); @@ -244,7 +247,7 @@ public abstract static class ReturnsPrimitiveBoolean { public abstract boolean execute(); } public void testReturnsPrimitiveBoolean() { - Compiler compiler = new Compiler(ReturnsPrimitiveBoolean.class, Definition.DEFINITION); + Compiler compiler = new Compiler(ReturnsPrimitiveBoolean.class, definition); assertEquals(true, ((ReturnsPrimitiveBoolean)scriptEngine.compile(compiler, null, "true", emptyMap())).execute()); assertEquals(false, ((ReturnsPrimitiveBoolean)scriptEngine.compile(compiler, null, "false", emptyMap())).execute()); @@ -286,7 +289,7 @@ public abstract static class ReturnsPrimitiveInt { public abstract int execute(); } public void testReturnsPrimitiveInt() { - Compiler compiler = new Compiler(ReturnsPrimitiveInt.class, Definition.DEFINITION); + Compiler compiler = new Compiler(ReturnsPrimitiveInt.class, definition); assertEquals(1, ((ReturnsPrimitiveInt)scriptEngine.compile(compiler, null, "1", emptyMap())).execute()); assertEquals(1, ((ReturnsPrimitiveInt)scriptEngine.compile(compiler, null, "(int) 1L", emptyMap())).execute()); @@ -328,7 +331,7 @@ public abstract static class ReturnsPrimitiveFloat { public abstract float execute(); } public void testReturnsPrimitiveFloat() { - Compiler compiler = new Compiler(ReturnsPrimitiveFloat.class, Definition.DEFINITION); + Compiler compiler = new Compiler(ReturnsPrimitiveFloat.class, definition); assertEquals(1.1f, ((ReturnsPrimitiveFloat)scriptEngine.compile(compiler, null, "1.1f", emptyMap())).execute(), 0); assertEquals(1.1f, ((ReturnsPrimitiveFloat)scriptEngine.compile(compiler, null, "(float) 1.1d", emptyMap())).execute(), 0); @@ -359,7 +362,7 @@ public abstract static class ReturnsPrimitiveDouble { public abstract double execute(); } public void testReturnsPrimitiveDouble() { - Compiler compiler = new Compiler(ReturnsPrimitiveDouble.class, Definition.DEFINITION); + Compiler compiler = new Compiler(ReturnsPrimitiveDouble.class, definition); assertEquals(1.0, ((ReturnsPrimitiveDouble)scriptEngine.compile(compiler, null, "1", emptyMap())).execute(), 0); assertEquals(1.0, ((ReturnsPrimitiveDouble)scriptEngine.compile(compiler, null, "1L", emptyMap())).execute(), 0); @@ -393,7 +396,7 @@ public abstract static class NoArgumentsConstant { public abstract Object execute(String foo); } public void testNoArgumentsConstant() { - Compiler compiler = new Compiler(NoArgumentsConstant.class, Definition.DEFINITION); + Compiler compiler = new Compiler(NoArgumentsConstant.class, definition); Exception e = expectScriptThrows(IllegalArgumentException.class, false, () -> scriptEngine.compile(compiler, null, "1", emptyMap())); assertThat(e.getMessage(), startsWith( @@ -406,7 +409,7 @@ public abstract static class WrongArgumentsConstant { public abstract Object execute(String foo); } public void testWrongArgumentsConstant() { - Compiler compiler = new Compiler(WrongArgumentsConstant.class, Definition.DEFINITION); + Compiler compiler = new Compiler(WrongArgumentsConstant.class, definition); Exception e = expectScriptThrows(IllegalArgumentException.class, false, () -> scriptEngine.compile(compiler, null, "1", emptyMap())); assertThat(e.getMessage(), startsWith( @@ -419,7 +422,7 @@ public abstract static class WrongLengthOfArgumentConstant { public abstract Object execute(String foo); } public void testWrongLengthOfArgumentConstant() { - Compiler compiler = new Compiler(WrongLengthOfArgumentConstant.class, Definition.DEFINITION); + Compiler compiler = new Compiler(WrongLengthOfArgumentConstant.class, definition); Exception e = expectScriptThrows(IllegalArgumentException.class, false, () -> scriptEngine.compile(compiler, null, "1", emptyMap())); assertThat(e.getMessage(), startsWith("[" + WrongLengthOfArgumentConstant.class.getName() + "#ARGUMENTS] has length [2] but [" @@ -431,7 +434,7 @@ public abstract static class UnknownArgType { public abstract Object execute(UnknownArgType foo); } public void testUnknownArgType() { - Compiler compiler = new Compiler(UnknownArgType.class, Definition.DEFINITION); + Compiler compiler = new Compiler(UnknownArgType.class, definition); Exception e = expectScriptThrows(IllegalArgumentException.class, false, () -> scriptEngine.compile(compiler, null, "1", emptyMap())); assertEquals("[foo] is of unknown type [" + UnknownArgType.class.getName() + ". Painless interfaces can only accept arguments " @@ -443,7 +446,7 @@ public abstract static class UnknownReturnType { public abstract UnknownReturnType execute(String foo); } public void testUnknownReturnType() { - Compiler compiler = new Compiler(UnknownReturnType.class, Definition.DEFINITION); + Compiler compiler = new Compiler(UnknownReturnType.class, definition); Exception e = expectScriptThrows(IllegalArgumentException.class, false, () -> scriptEngine.compile(compiler, null, "1", emptyMap())); assertEquals("Painless can only implement execute methods returning a whitelisted type but [" + UnknownReturnType.class.getName() @@ -455,7 +458,7 @@ public abstract static class UnknownArgTypeInArray { public abstract Object execute(UnknownArgTypeInArray[] foo); } public void testUnknownArgTypeInArray() { - Compiler compiler = new Compiler(UnknownArgTypeInArray.class, Definition.DEFINITION); + Compiler compiler = new Compiler(UnknownArgTypeInArray.class, definition); Exception e = expectScriptThrows(IllegalArgumentException.class, false, () -> scriptEngine.compile(compiler, null, "1", emptyMap())); assertEquals("[foo] is of unknown type [" + UnknownArgTypeInArray.class.getName() + ". Painless interfaces can only accept " @@ -467,7 +470,7 @@ public abstract static class TwoExecuteMethods { public abstract Object execute(boolean foo); } public void testTwoExecuteMethods() { - Compiler compiler = new Compiler(TwoExecuteMethods.class, Definition.DEFINITION); + Compiler compiler = new Compiler(TwoExecuteMethods.class, definition); Exception e = expectScriptThrows(IllegalArgumentException.class, false, () -> scriptEngine.compile(compiler, null, "null", emptyMap())); assertEquals("Painless can only implement interfaces that have a single method named [execute] but [" 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 ba31ea48d92d9..a55b48f0189b3 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,6 +25,7 @@ import org.elasticsearch.script.ScriptException; import java.io.IOException; +import java.util.Collections; import java.util.Map; import static java.util.Collections.singletonList; @@ -34,7 +35,8 @@ import static org.hamcrest.Matchers.not; public class DebugTests extends ScriptTestCase { - private final Definition definition = Definition.DEFINITION; + private final Definition definition = new Definition( + Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); 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 2b4a896fb5e66..52ec783db4ef4 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,6 +24,7 @@ import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Collections; /** quick and dirty tools for debugging */ final class Debugger { @@ -39,7 +40,9 @@ static String toString(Class iface, String source, CompilerSettings settings) PrintWriter outputWriter = new PrintWriter(output); Textifier textifier = new Textifier(); try { - new Compiler(iface, Definition.DEFINITION).compile("", source, settings, textifier); + new Compiler(iface, new Definition( + Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES)))) + .compile("", source, settings, textifier); } catch (Exception e) { textifier.print(outputWriter); e.addSuppressed(new Exception("current bytecode: \n" + output)); 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 7188caf425197..dccc9c0aeb505 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,7 +30,8 @@ import org.elasticsearch.test.ESTestCase; public class DefBootstrapTests extends ESTestCase { - private final Definition definition = Definition.DEFINITION; + private final Definition definition = new Definition( + Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); /** calls toString() on integers, twice */ public void testOneType() throws Throwable { 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 74e0f90cc1b9f..edd600c5664f2 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 @@ -36,6 +36,7 @@ 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; @@ -44,7 +45,6 @@ import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toList; -import static org.elasticsearch.painless.Definition.DEFINITION; /** * Generates an API reference from the method and type whitelists in {@link Definition}. @@ -68,7 +68,9 @@ 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 = DEFINITION.allSimpleTypes().stream().sorted(comparing(t -> t.name)).collect(toList()); + List types = new Definition(Collections.singletonList( + WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))). + allSimpleTypes().stream().sorted(comparing(t -> t.name)).collect(toList()); for (Type type : types) { if (type.clazz.isPrimitive()) { // Primitives don't have methods to reference 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 89159c5364798..730dd298f8a54 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 @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -91,7 +92,8 @@ 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 = Definition.DEFINITION; + Definition definition = new Definition( + Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); 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/node/NodeToStringTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java index 2bd9753ea26a6..9e3477b1cfe02 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,10 +33,12 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.Operation; import org.elasticsearch.painless.ScriptClassInfo; +import org.elasticsearch.painless.WhitelistLoader; 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; @@ -48,7 +50,8 @@ * Tests {@link Object#toString} implementations on all extensions of {@link ANode}. */ public class NodeToStringTests extends ESTestCase { - private final Definition definition = Definition.DEFINITION; + private final Definition definition = new Definition( + Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))); public void testEAssignment() { assertToString( @@ -161,12 +164,12 @@ public void testECapturingFunctionRef() { public void testECast() { Location l = new Location(getTestName(), 0); AExpression child = new EConstant(l, "test"); - Cast cast = Cast.standard(Definition.DEFINITION.StringType, Definition.DEFINITION.IntegerType, true); + Cast cast = Cast.standard(definition.StringType, definition.IntegerType, true); assertEquals("(ECast java.lang.Integer (EConstant String 'test'))", new ECast(l, child, cast).toString()); l = new Location(getTestName(), 1); child = new EBinary(l, Operation.ADD, new EConstant(l, "test"), new EConstant(l, 12)); - cast = Cast.standard(Definition.DEFINITION.IntegerType, Definition.DEFINITION.BooleanType, true); + cast = Cast.standard(definition.IntegerType, definition.BooleanType, true); assertEquals("(ECast java.lang.Boolean (EBinary (EConstant String 'test') + (EConstant Integer 12)))", new ECast(l, child, cast).toString()); } @@ -396,7 +399,7 @@ public void testPSubArrayLength() { public void testPSubBrace() { Location l = new Location(getTestName(), 0); - PSubBrace node = new PSubBrace(l, Definition.DEFINITION.intType, new ENumeric(l, "1", 10)); + PSubBrace node = new PSubBrace(l, definition.intType, new ENumeric(l, "1", 10)); node.prefix = new EVariable(l, "a"); assertEquals("(PSubBrace (EVariable a) (ENumeric 1))", node.toString()); } @@ -762,7 +765,7 @@ public void testSIfElse() { public void testSSubEachArray() { Location l = new Location(getTestName(), 0); - Variable v = new Variable(l, "test", Definition.DEFINITION.intType, 5, false); + Variable v = new Variable(l, "test", definition.intType, 5, false); AExpression e = new ENewArray(l, "int", Arrays.asList(new EConstant(l, 1), new EConstant(l, 2), new EConstant(l, 3)), true); SBlock b = new SBlock(l, singletonList(new SReturn(l, new EConstant(l, 5)))); SSubEachArray node = new SSubEachArray(l, v, e, b); @@ -774,7 +777,7 @@ public void testSSubEachArray() { public void testSSubEachIterable() { Location l = new Location(getTestName(), 0); - Variable v = new Variable(l, "test", Definition.DEFINITION.intType, 5, false); + Variable v = new Variable(l, "test", definition.intType, 5, false); AExpression e = new EListInit(l, Arrays.asList(new EConstant(l, 1), new EConstant(l, 2), new EConstant(l, 3))); SBlock b = new SBlock(l, singletonList(new SReturn(l, new EConstant(l, 5)))); SSubEachIterable node = new SSubEachIterable(l, v, e, b);