Painless: Modify Loader to Load Classes Directly from Definition (#28088)
This commit is contained in:
parent
27bbec0c19
commit
b5377d294f
|
@ -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 @@ final class Compiler {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
|
|
@ -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 final class Definition {
|
|||
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<Type> allSimpleTypes() {
|
||||
return simpleTypesMap.values();
|
||||
|
@ -535,7 +541,7 @@ public final class Definition {
|
|||
|
||||
public AnalyzerCaster caster;
|
||||
|
||||
private Definition(List<Whitelist> whitelists) {
|
||||
public Definition(List<Whitelist> whitelists) {
|
||||
structsMap = new HashMap<>();
|
||||
simpleTypesMap = new HashMap<>();
|
||||
runtimeMap = new HashMap<>();
|
||||
|
|
|
@ -37,11 +37,6 @@ import java.util.List;
|
|||
*/
|
||||
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<ScriptContext<?>> contexts) {
|
||||
return new PainlessScriptEngine(settings, contexts);
|
||||
|
|
|
@ -99,11 +99,16 @@ public final class PainlessScriptEngine extends AbstractComponent implements Scr
|
|||
|
||||
Map<ScriptContext<?>, 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 final class PainlessScriptEngine extends AbstractComponent implements Scr
|
|||
|
||||
@Override
|
||||
public <T> T compile(String scriptName, String scriptSource, ScriptContext<T> context, Map<String, String> 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 final class PainlessScriptEngine extends AbstractComponent implements Scr
|
|||
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 final class PainlessScriptEngine extends AbstractComponent implements Scr
|
|||
final Loader loader = AccessController.doPrivileged(new PrivilegedAction<Loader>() {
|
||||
@Override
|
||||
public Loader run() {
|
||||
return new Loader(getClass().getClassLoader());
|
||||
return compiler.createLoader(getClass().getClassLoader());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -414,7 +421,7 @@ public final class PainlessScriptEngine extends AbstractComponent implements Scr
|
|||
final Loader loader = AccessController.doPrivileged(new PrivilegedAction<Loader>() {
|
||||
@Override
|
||||
public Loader run() {
|
||||
return new Loader(getClass().getClassLoader());
|
||||
return compiler.createLoader(getClass().getClassLoader());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -23,75 +23,82 @@ import org.elasticsearch.painless.Definition.Cast;
|
|||
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.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.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.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.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.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.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.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.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.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.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.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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@ import static org.hamcrest.Matchers.startsWith;
|
|||
*/
|
||||
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 class BaseClassTests extends ScriptTestCase {
|
|||
}
|
||||
|
||||
public void testGets() {
|
||||
Compiler compiler = new Compiler(Gets.class, Definition.DEFINITION);
|
||||
Compiler compiler = new Compiler(Gets.class, definition);
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("s", 1);
|
||||
|
||||
|
@ -84,7 +87,7 @@ public class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
}
|
||||
}
|
||||
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 class BaseClassTests extends ScriptTestCase {
|
|||
public abstract void execute(Map<String, Object> map);
|
||||
}
|
||||
public void testReturnsVoid() {
|
||||
Compiler compiler = new Compiler(ReturnsVoid.class, Definition.DEFINITION);
|
||||
Compiler compiler = new Compiler(ReturnsVoid.class, definition);
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
((ReturnsVoid)scriptEngine.compile(compiler, null, "map.a = 'foo'", emptyMap())).execute(map);
|
||||
assertEquals(singletonMap("a", "foo"), map);
|
||||
|
@ -244,7 +247,7 @@ public class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 class BaseClassTests extends ScriptTestCase {
|
|||
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 ["
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
|
|||
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.hasKey;
|
|||
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
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.objectweb.asm.util.Textifier;
|
|||
|
||||
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 @@ final class Debugger {
|
|||
PrintWriter outputWriter = new PrintWriter(output);
|
||||
Textifier textifier = new Textifier();
|
||||
try {
|
||||
new Compiler(iface, Definition.DEFINITION).compile("<debugging>", source, settings, textifier);
|
||||
new Compiler(iface, new Definition(
|
||||
Collections.singletonList(WhitelistLoader.loadFromResourceFiles(Definition.class, Definition.DEFINITION_FILES))))
|
||||
.compile("<debugging>", source, settings, textifier);
|
||||
} catch (Exception e) {
|
||||
textifier.print(outputWriter);
|
||||
e.addSuppressed(new Exception("current bytecode: \n" + output));
|
||||
|
|
|
@ -30,7 +30,8 @@ import java.util.HashMap;
|
|||
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 {
|
||||
|
|
|
@ -36,6 +36,7 @@ import java.nio.charset.StandardCharsets;
|
|||
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 java.util.function.Consumer;
|
|||
|
||||
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 class PainlessDocGenerator {
|
|||
Files.newOutputStream(indexPath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE),
|
||||
false, StandardCharsets.UTF_8.name())) {
|
||||
emitGeneratedWarning(indexStream);
|
||||
List<Type> types = DEFINITION.allSimpleTypes().stream().sorted(comparing(t -> t.name)).collect(toList());
|
||||
List<Type> 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
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.junit.Before;
|
|||
|
||||
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 abstract class ScriptTestCase extends ESTestCase {
|
|||
public Object exec(String script, Map<String, Object> vars, Map<String,String> 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);
|
||||
|
|
|
@ -33,10 +33,12 @@ import org.elasticsearch.painless.Locals.Variable;
|
|||
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 @@ import static org.elasticsearch.painless.node.SSource.MainMethodReserved;
|
|||
* 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 class NodeToStringTests extends ESTestCase {
|
|||
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 class NodeToStringTests extends ESTestCase {
|
|||
|
||||
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 class NodeToStringTests extends ESTestCase {
|
|||
|
||||
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 class NodeToStringTests extends ESTestCase {
|
|||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue