diff --git a/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/Whitelist.java b/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/Whitelist.java index d6fe9c6870ace..c36625ad145be 100644 --- a/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/Whitelist.java +++ b/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/Whitelist.java @@ -63,16 +63,16 @@ public final class Whitelist { /** The {@link List} of all the whitelisted static Painless methods. */ public final List whitelistImportedMethods; - /** The {@link List} of all the whitelisted Painless bindings. */ - public final List whitelistBindings; + /** The {@link List} of all the whitelisted Painless class bindings. */ + public final List whitelistClassBindings; /** Standard constructor. All values must be not {@code null}. */ public Whitelist(ClassLoader classLoader, List whitelistClasses, - List whitelistImportedMethods, List whitelistBindings) { + List whitelistImportedMethods, List whitelistClassBindings) { this.classLoader = Objects.requireNonNull(classLoader); this.whitelistClasses = Collections.unmodifiableList(Objects.requireNonNull(whitelistClasses)); this.whitelistImportedMethods = Collections.unmodifiableList(Objects.requireNonNull(whitelistImportedMethods)); - this.whitelistBindings = Collections.unmodifiableList(Objects.requireNonNull(whitelistBindings)); + this.whitelistClassBindings = Collections.unmodifiableList(Objects.requireNonNull(whitelistClassBindings)); } } diff --git a/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistBinding.java b/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistClassBinding.java similarity index 69% rename from modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistBinding.java rename to modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistClassBinding.java index 364dbbb09ca9b..f1e762b37c02f 100644 --- a/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistBinding.java +++ b/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistClassBinding.java @@ -23,23 +23,23 @@ import java.util.Objects; /** - * A binding represents a method call that stores state. Each binding class must have exactly one - * public constructor and one public method excluding those inherited directly from {@link Object}. - * The canonical type name parameters provided must match those of the constructor and method combined. - * The constructor for a binding class will be called when the binding method is called for the first - * time at which point state may be stored for the arguments passed into the constructor. The method - * for a binding class will be called each time the binding method is called and may use the previously - * stored state. + * A class binding represents a method call that stores state. Each class binding's Java class must + * have exactly one public constructor and one public method excluding those inherited directly + * from {@link Object}. The canonical type name parameters provided must match those of the + * constructor and method combined. The constructor for a class binding's Java class will be called + * when the binding method is called for the first time at which point state may be stored for the + * arguments passed into the constructor. The method for a binding class will be called each time + * the binding method is called and may use the previously stored state. */ -public class WhitelistBinding { +public class WhitelistClassBinding { /** Information about where this constructor was whitelisted from. */ public final String origin; - /** The Java class name this binding represents. */ + /** The Java class name this class binding targets. */ public final String targetJavaClassName; - /** The method name for this binding. */ + /** The method name for this class binding. */ public final String methodName; /** @@ -54,7 +54,7 @@ public class WhitelistBinding { public final List canonicalTypeNameParameters; /** Standard constructor. All values must be not {@code null}. */ - public WhitelistBinding(String origin, String targetJavaClassName, + public WhitelistClassBinding(String origin, String targetJavaClassName, String methodName, String returnCanonicalTypeName, List canonicalTypeNameParameters) { this.origin = Objects.requireNonNull(origin); diff --git a/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java b/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java index 2f5dec769fc2f..560010a35e9be 100644 --- a/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java +++ b/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java @@ -134,7 +134,7 @@ public final class WhitelistLoader { public static Whitelist loadFromResourceFiles(Class resource, String... filepaths) { List whitelistClasses = new ArrayList<>(); List whitelistStatics = new ArrayList<>(); - List whitelistBindings = new ArrayList<>(); + List whitelistClassBindings = new ArrayList<>(); // Execute a single pass through the whitelist text files. This will gather all the // constructors, methods, augmented methods, and fields for each whitelisted class. @@ -292,7 +292,7 @@ public static Whitelist loadFromResourceFiles(Class resource, String... filep whitelistStatics.add(new WhitelistMethod(origin, targetJavaClassName, methodName, returnCanonicalTypeName, Arrays.asList(canonicalTypeNameParameters))); } else if ("bound_to".equals(staticImportType)) { - whitelistBindings.add(new WhitelistBinding(origin, targetJavaClassName, + whitelistClassBindings.add(new WhitelistClassBinding(origin, targetJavaClassName, methodName, returnCanonicalTypeName, Arrays.asList(canonicalTypeNameParameters))); } else { throw new IllegalArgumentException("invalid static import definition: " + @@ -392,7 +392,7 @@ public static Whitelist loadFromResourceFiles(Class resource, String... filep ClassLoader loader = AccessController.doPrivileged((PrivilegedAction)resource::getClassLoader); - return new Whitelist(loader, whitelistClasses, whitelistStatics, whitelistBindings); + return new Whitelist(loader, whitelistClasses, whitelistStatics, whitelistClassBindings); } private WhitelistLoader() {} diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessBinding.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessClassBinding.java similarity index 88% rename from modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessBinding.java rename to modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessClassBinding.java index 41178dd5d7506..3418b2d82446c 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessBinding.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessClassBinding.java @@ -23,7 +23,7 @@ import java.lang.reflect.Method; import java.util.List; -public class PainlessBinding { +public class PainlessClassBinding { public final Constructor javaConstructor; public final Method javaMethod; @@ -31,7 +31,7 @@ public class PainlessBinding { public final Class returnType; public final List> typeParameters; - PainlessBinding(Constructor javaConstructor, Method javaMethod, Class returnType, List> typeParameters) { + PainlessClassBinding(Constructor javaConstructor, Method javaMethod, Class returnType, List> typeParameters) { this.javaConstructor = javaConstructor; this.javaMethod = javaMethod; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookup.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookup.java index 7be659d11a124..ed9e76683368a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookup.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookup.java @@ -38,23 +38,23 @@ public final class PainlessLookup { private final Map, PainlessClass> classesToPainlessClasses; private final Map painlessMethodKeysToImportedPainlessMethods; - private final Map painlessMethodKeysToPainlessBindings; + private final Map painlessMethodKeysToPainlessClassBindings; PainlessLookup(Map> canonicalClassNamesToClasses, Map, PainlessClass> classesToPainlessClasses, Map painlessMethodKeysToImportedPainlessMethods, - Map painlessMethodKeysToPainlessBindings) { + Map painlessMethodKeysToPainlessClassBindings) { Objects.requireNonNull(canonicalClassNamesToClasses); Objects.requireNonNull(classesToPainlessClasses); Objects.requireNonNull(painlessMethodKeysToImportedPainlessMethods); - Objects.requireNonNull(painlessMethodKeysToPainlessBindings); + Objects.requireNonNull(painlessMethodKeysToPainlessClassBindings); this.canonicalClassNamesToClasses = Collections.unmodifiableMap(canonicalClassNamesToClasses); this.classesToPainlessClasses = Collections.unmodifiableMap(classesToPainlessClasses); this.painlessMethodKeysToImportedPainlessMethods = Collections.unmodifiableMap(painlessMethodKeysToImportedPainlessMethods); - this.painlessMethodKeysToPainlessBindings = Collections.unmodifiableMap(painlessMethodKeysToPainlessBindings); + this.painlessMethodKeysToPainlessClassBindings = Collections.unmodifiableMap(painlessMethodKeysToPainlessClassBindings); } public boolean isValidCanonicalClassName(String canonicalClassName) { @@ -182,12 +182,12 @@ public PainlessMethod lookupImportedPainlessMethod(String methodName, int arity) return painlessMethodKeysToImportedPainlessMethods.get(painlessMethodKey); } - public PainlessBinding lookupPainlessBinding(String methodName, int arity) { + public PainlessClassBinding lookupPainlessClassBinding(String methodName, int arity) { Objects.requireNonNull(methodName); String painlessMethodKey = buildPainlessMethodKey(methodName, arity); - return painlessMethodKeysToPainlessBindings.get(painlessMethodKey); + return painlessMethodKeysToPainlessClassBindings.get(painlessMethodKey); } public PainlessMethod lookupFunctionalInterfacePainlessMethod(Class targetClass) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookupBuilder.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookupBuilder.java index b822bd47c7a48..ce451f3dca893 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookupBuilder.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookupBuilder.java @@ -20,7 +20,7 @@ package org.elasticsearch.painless.lookup; import org.elasticsearch.painless.spi.Whitelist; -import org.elasticsearch.painless.spi.WhitelistBinding; +import org.elasticsearch.painless.spi.WhitelistClassBinding; import org.elasticsearch.painless.spi.WhitelistClass; import org.elasticsearch.painless.spi.WhitelistConstructor; import org.elasticsearch.painless.spi.WhitelistField; @@ -156,14 +156,14 @@ public int hashCode() { } } - private static class PainlessBindingCacheKey { + private static class PainlessClassBindingCacheKey { private final Class targetClass; private final String methodName; private final Class methodReturnType; private final List> methodTypeParameters; - private PainlessBindingCacheKey(Class targetClass, + private PainlessClassBindingCacheKey(Class targetClass, String methodName, Class returnType, List> typeParameters) { this.targetClass = targetClass; @@ -182,7 +182,7 @@ public boolean equals(Object object) { return false; } - PainlessBindingCacheKey that = (PainlessBindingCacheKey)object; + PainlessClassBindingCacheKey that = (PainlessClassBindingCacheKey)object; return Objects.equals(targetClass, that.targetClass) && Objects.equals(methodName, that.methodName) && @@ -196,10 +196,10 @@ public int hashCode() { } } - private static final Map painlessConstructorCache = new HashMap<>(); - private static final Map painlessMethodCache = new HashMap<>(); - private static final Map painlessFieldCache = new HashMap<>(); - private static final Map painlessBindingCache = new HashMap<>(); + private static final Map painlessConstructorCache = new HashMap<>(); + private static final Map painlessMethodCache = new HashMap<>(); + private static final Map painlessFieldCache = new HashMap<>(); + private static final Map painlessClassBindingCache = new HashMap<>(); private static final Pattern CLASS_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][._a-zA-Z0-9]*$"); private static final Pattern METHOD_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][_a-zA-Z0-9]*$"); @@ -251,12 +251,12 @@ public static PainlessLookup buildFromWhitelists(List whitelists) { whitelistStatic.canonicalTypeNameParameters); } - for (WhitelistBinding whitelistBinding : whitelist.whitelistBindings) { - origin = whitelistBinding.origin; - painlessLookupBuilder.addPainlessBinding( - whitelist.classLoader, whitelistBinding.targetJavaClassName, - whitelistBinding.methodName, whitelistBinding.returnCanonicalTypeName, - whitelistBinding.canonicalTypeNameParameters); + for (WhitelistClassBinding whitelistClassBinding : whitelist.whitelistClassBindings) { + origin = whitelistClassBinding.origin; + painlessLookupBuilder.addPainlessClassBinding( + whitelist.classLoader, whitelistClassBinding.targetJavaClassName, + whitelistClassBinding.methodName, whitelistClassBinding.returnCanonicalTypeName, + whitelistClassBinding.canonicalTypeNameParameters); } } } catch (Exception exception) { @@ -270,14 +270,14 @@ public static PainlessLookup buildFromWhitelists(List whitelists) { private final Map, PainlessClassBuilder> classesToPainlessClassBuilders; private final Map painlessMethodKeysToImportedPainlessMethods; - private final Map painlessMethodKeysToPainlessBindings; + private final Map painlessMethodKeysToPainlessClassBindings; public PainlessLookupBuilder() { canonicalClassNamesToClasses = new HashMap<>(); classesToPainlessClassBuilders = new HashMap<>(); painlessMethodKeysToImportedPainlessMethods = new HashMap<>(); - painlessMethodKeysToPainlessBindings = new HashMap<>(); + painlessMethodKeysToPainlessClassBindings = new HashMap<>(); } private Class canonicalTypeNameToType(String canonicalTypeName) { @@ -909,8 +909,8 @@ public void addImportedPainlessMethod(Class targetClass, String methodName, C String painlessMethodKey = buildPainlessMethodKey(methodName, typeParametersSize); - if (painlessMethodKeysToPainlessBindings.containsKey(painlessMethodKey)) { - throw new IllegalArgumentException("imported method and binding cannot have the same name [" + methodName + "]"); + if (painlessMethodKeysToPainlessClassBindings.containsKey(painlessMethodKey)) { + throw new IllegalArgumentException("imported method and class binding cannot have the same name [" + methodName + "]"); } PainlessMethod importedPainlessMethod = painlessMethodKeysToImportedPainlessMethods.get(painlessMethodKey); @@ -945,7 +945,7 @@ public void addImportedPainlessMethod(Class targetClass, String methodName, C } } - public void addPainlessBinding(ClassLoader classLoader, String targetJavaClassName, + public void addPainlessClassBinding(ClassLoader classLoader, String targetJavaClassName, String methodName, String returnCanonicalTypeName, List canonicalTypeNameParameters) { Objects.requireNonNull(classLoader); @@ -969,7 +969,7 @@ public void addPainlessBinding(ClassLoader classLoader, String targetJavaClassNa Class typeParameter = canonicalTypeNameToType(canonicalTypeNameParameter); if (typeParameter == null) { - throw new IllegalArgumentException("type parameter [" + canonicalTypeNameParameter + "] not found for binding " + + throw new IllegalArgumentException("type parameter [" + canonicalTypeNameParameter + "] not found for class binding " + "[[" + targetCanonicalClassName + "], [" + methodName + "], " + canonicalTypeNameParameters + "]"); } @@ -979,14 +979,14 @@ public void addPainlessBinding(ClassLoader classLoader, String targetJavaClassNa Class returnType = canonicalTypeNameToType(returnCanonicalTypeName); if (returnType == null) { - throw new IllegalArgumentException("return type [" + returnCanonicalTypeName + "] not found for binding " + + throw new IllegalArgumentException("return type [" + returnCanonicalTypeName + "] not found for class binding " + "[[" + targetCanonicalClassName + "], [" + methodName + "], " + canonicalTypeNameParameters + "]"); } - addPainlessBinding(targetClass, methodName, returnType, typeParameters); + addPainlessClassBinding(targetClass, methodName, returnType, typeParameters); } - public void addPainlessBinding(Class targetClass, String methodName, Class returnType, List> typeParameters) { + public void addPainlessClassBinding(Class targetClass, String methodName, Class returnType, List> typeParameters) { Objects.requireNonNull(targetClass); Objects.requireNonNull(methodName); @@ -994,7 +994,7 @@ public void addPainlessBinding(Class targetClass, String methodName, Class Objects.requireNonNull(typeParameters); if (targetClass == def.class) { - throw new IllegalArgumentException("cannot add binding as reserved class [" + DEF_CLASS_NAME + "]"); + throw new IllegalArgumentException("cannot add class binding as reserved class [" + DEF_CLASS_NAME + "]"); } String targetCanonicalClassName = typeToCanonicalTypeName(targetClass); @@ -1005,7 +1005,8 @@ public void addPainlessBinding(Class targetClass, String methodName, Class for (Constructor eachJavaConstructor : javaConstructors) { if (eachJavaConstructor.getDeclaringClass() == targetClass) { if (javaConstructor != null) { - throw new IllegalArgumentException("binding [" + targetCanonicalClassName + "] cannot have multiple constructors"); + throw new IllegalArgumentException( + "class binding [" + targetCanonicalClassName + "] cannot have multiple constructors"); } javaConstructor = eachJavaConstructor; @@ -1013,7 +1014,7 @@ public void addPainlessBinding(Class targetClass, String methodName, Class } if (javaConstructor == null) { - throw new IllegalArgumentException("binding [" + targetCanonicalClassName + "] must have exactly one constructor"); + throw new IllegalArgumentException("class binding [" + targetCanonicalClassName + "] must have exactly one constructor"); } int constructorTypeParametersSize = javaConstructor.getParameterCount(); @@ -1023,26 +1024,26 @@ public void addPainlessBinding(Class targetClass, String methodName, Class if (isValidType(typeParameter) == false) { throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(typeParameter) + "] not found " + - "for binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); + "for class binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); } Class javaTypeParameter = javaConstructor.getParameterTypes()[typeParameterIndex]; if (isValidType(javaTypeParameter) == false) { throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(typeParameter) + "] not found " + - "for binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); + "for class binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); } if (javaTypeParameter != typeToJavaType(typeParameter)) { throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(javaTypeParameter) + "] " + "does not match the specified type parameter [" + typeToCanonicalTypeName(typeParameter) + "] " + - "for binding [[" + targetClass.getCanonicalName() + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); + "for class binding [[" + targetClass.getCanonicalName() + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); } } if (METHOD_NAME_PATTERN.matcher(methodName).matches() == false) { throw new IllegalArgumentException( - "invalid method name [" + methodName + "] for binding [" + targetCanonicalClassName + "]."); + "invalid method name [" + methodName + "] for class binding [" + targetCanonicalClassName + "]."); } Method[] javaMethods = targetClass.getMethods(); @@ -1051,7 +1052,7 @@ public void addPainlessBinding(Class targetClass, String methodName, Class for (Method eachJavaMethod : javaMethods) { if (eachJavaMethod.getDeclaringClass() == targetClass) { if (javaMethod != null) { - throw new IllegalArgumentException("binding [" + targetCanonicalClassName + "] cannot have multiple methods"); + throw new IllegalArgumentException("class binding [" + targetCanonicalClassName + "] cannot have multiple methods"); } javaMethod = eachJavaMethod; @@ -1059,7 +1060,7 @@ public void addPainlessBinding(Class targetClass, String methodName, Class } if (javaMethod == null) { - throw new IllegalArgumentException("binding [" + targetCanonicalClassName + "] must have exactly one method"); + throw new IllegalArgumentException("class binding [" + targetCanonicalClassName + "] must have exactly one method"); } int methodTypeParametersSize = javaMethod.getParameterCount(); @@ -1069,60 +1070,60 @@ public void addPainlessBinding(Class targetClass, String methodName, Class if (isValidType(typeParameter) == false) { throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(typeParameter) + "] not found " + - "for binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); + "for class binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); } Class javaTypeParameter = javaMethod.getParameterTypes()[typeParameterIndex]; if (isValidType(javaTypeParameter) == false) { throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(typeParameter) + "] not found " + - "for binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); + "for class binding [[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); } if (javaTypeParameter != typeToJavaType(typeParameter)) { throw new IllegalArgumentException("type parameter [" + typeToCanonicalTypeName(javaTypeParameter) + "] " + "does not match the specified type parameter [" + typeToCanonicalTypeName(typeParameter) + "] " + - "for binding [[" + targetClass.getCanonicalName() + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); + "for class binding [[" + targetClass.getCanonicalName() + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); } } if (javaMethod.getReturnType() != typeToJavaType(returnType)) { throw new IllegalArgumentException("return type [" + typeToCanonicalTypeName(javaMethod.getReturnType()) + "] " + "does not match the specified returned type [" + typeToCanonicalTypeName(returnType) + "] " + - "for binding [[" + targetClass.getCanonicalName() + "], [" + methodName + "], " + + "for class binding [[" + targetClass.getCanonicalName() + "], [" + methodName + "], " + typesToCanonicalTypeNames(typeParameters) + "]"); } String painlessMethodKey = buildPainlessMethodKey(methodName, constructorTypeParametersSize + methodTypeParametersSize); if (painlessMethodKeysToImportedPainlessMethods.containsKey(painlessMethodKey)) { - throw new IllegalArgumentException("binding and imported method cannot have the same name [" + methodName + "]"); + throw new IllegalArgumentException("class binding and imported method cannot have the same name [" + methodName + "]"); } - PainlessBinding painlessBinding = painlessMethodKeysToPainlessBindings.get(painlessMethodKey); + PainlessClassBinding painlessClassBinding = painlessMethodKeysToPainlessClassBindings.get(painlessMethodKey); - if (painlessBinding == null) { + if (painlessClassBinding == null) { Constructor finalJavaConstructor = javaConstructor; Method finalJavaMethod = javaMethod; - painlessBinding = painlessBindingCache.computeIfAbsent( - new PainlessBindingCacheKey(targetClass, methodName, returnType, typeParameters), - key -> new PainlessBinding(finalJavaConstructor, finalJavaMethod, returnType, typeParameters)); + painlessClassBinding = painlessClassBindingCache.computeIfAbsent( + new PainlessClassBindingCacheKey(targetClass, methodName, returnType, typeParameters), + key -> new PainlessClassBinding(finalJavaConstructor, finalJavaMethod, returnType, typeParameters)); - painlessMethodKeysToPainlessBindings.put(painlessMethodKey, painlessBinding); - } else if (painlessBinding.javaConstructor.equals(javaConstructor) == false || - painlessBinding.javaMethod.equals(javaMethod) == false || - painlessBinding.returnType != returnType || - painlessBinding.typeParameters.equals(typeParameters) == false) { - throw new IllegalArgumentException("cannot have bindings " + + painlessMethodKeysToPainlessClassBindings.put(painlessMethodKey, painlessClassBinding); + } else if (painlessClassBinding.javaConstructor.equals(javaConstructor) == false || + painlessClassBinding.javaMethod.equals(javaMethod) == false || + painlessClassBinding.returnType != returnType || + painlessClassBinding.typeParameters.equals(typeParameters) == false) { + throw new IllegalArgumentException("cannot have class bindings " + "[[" + targetCanonicalClassName + "], " + "[" + methodName + "], " + "[" + typeToCanonicalTypeName(returnType) + "], " + typesToCanonicalTypeNames(typeParameters) + "] and " + "[[" + targetCanonicalClassName + "], " + "[" + methodName + "], " + - "[" + typeToCanonicalTypeName(painlessBinding.returnType) + "], " + - typesToCanonicalTypeNames(painlessBinding.typeParameters) + "] and " + + "[" + typeToCanonicalTypeName(painlessClassBinding.returnType) + "], " + + typesToCanonicalTypeNames(painlessClassBinding.typeParameters) + "] and " + "with the same name and arity but different constructors or methods"); } } @@ -1139,7 +1140,7 @@ public PainlessLookup build() { } return new PainlessLookup(canonicalClassNamesToClasses, classesToPainlessClasses, - painlessMethodKeysToImportedPainlessMethods, painlessMethodKeysToPainlessBindings); + painlessMethodKeysToImportedPainlessMethods, painlessMethodKeysToPainlessClassBindings); } private void copyPainlessClassMembers() { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java index d161296d90a56..e613018dbc54c 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java @@ -24,7 +24,7 @@ import org.elasticsearch.painless.Locals.LocalMethod; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.lookup.PainlessBinding; +import org.elasticsearch.painless.lookup.PainlessClassBinding; import org.elasticsearch.painless.lookup.PainlessMethod; import org.objectweb.asm.Label; import org.objectweb.asm.Type; @@ -45,9 +45,9 @@ public final class ECallLocal extends AExpression { private final String name; private final List arguments; - private LocalMethod method = null; - private PainlessMethod imported = null; - private PainlessBinding binding = null; + private LocalMethod localMethod = null; + private PainlessMethod importedMethod = null; + private PainlessClassBinding classBinding = null; public ECallLocal(Location location, String name, List arguments) { super(location); @@ -65,15 +65,15 @@ void extractVariables(Set variables) { @Override void analyze(Locals locals) { - method = locals.getMethod(name, arguments.size()); + localMethod = locals.getMethod(name, arguments.size()); - if (method == null) { - imported = locals.getPainlessLookup().lookupImportedPainlessMethod(name, arguments.size()); + if (localMethod == null) { + importedMethod = locals.getPainlessLookup().lookupImportedPainlessMethod(name, arguments.size()); - if (imported == null) { - binding = locals.getPainlessLookup().lookupPainlessBinding(name, arguments.size()); + if (importedMethod == null) { + classBinding = locals.getPainlessLookup().lookupPainlessClassBinding(name, arguments.size()); - if (binding == null) { + if (classBinding == null) { throw createError( new IllegalArgumentException("Unknown call [" + name + "] with [" + arguments.size() + "] arguments.")); } @@ -82,15 +82,15 @@ void analyze(Locals locals) { List> typeParameters; - if (method != null) { - typeParameters = new ArrayList<>(method.typeParameters); - actual = method.returnType; - } else if (imported != null) { - typeParameters = new ArrayList<>(imported.typeParameters); - actual = imported.returnType; - } else if (binding != null) { - typeParameters = new ArrayList<>(binding.typeParameters); - actual = binding.returnType; + if (localMethod != null) { + typeParameters = new ArrayList<>(localMethod.typeParameters); + actual = localMethod.returnType; + } else if (importedMethod != null) { + typeParameters = new ArrayList<>(importedMethod.typeParameters); + actual = importedMethod.returnType; + } else if (classBinding != null) { + typeParameters = new ArrayList<>(classBinding.typeParameters); + actual = classBinding.returnType; } else { throw new IllegalStateException("Illegal tree structure."); } @@ -111,23 +111,23 @@ void analyze(Locals locals) { void write(MethodWriter writer, Globals globals) { writer.writeDebugInfo(location); - if (method != null) { + if (localMethod != null) { for (AExpression argument : arguments) { argument.write(writer, globals); } - writer.invokeStatic(CLASS_TYPE, new Method(method.name, method.methodType.toMethodDescriptorString())); - } else if (imported != null) { + writer.invokeStatic(CLASS_TYPE, new Method(localMethod.name, localMethod.methodType.toMethodDescriptorString())); + } else if (importedMethod != null) { for (AExpression argument : arguments) { argument.write(writer, globals); } - writer.invokeStatic(Type.getType(imported.targetClass), - new Method(imported.javaMethod.getName(), imported.methodType.toMethodDescriptorString())); - } else if (binding != null) { - String name = globals.addBinding(binding.javaConstructor.getDeclaringClass()); - Type type = Type.getType(binding.javaConstructor.getDeclaringClass()); - int javaConstructorParameterCount = binding.javaConstructor.getParameterCount(); + writer.invokeStatic(Type.getType(importedMethod.targetClass), + new Method(importedMethod.javaMethod.getName(), importedMethod.methodType.toMethodDescriptorString())); + } else if (classBinding != null) { + String name = globals.addBinding(classBinding.javaConstructor.getDeclaringClass()); + Type type = Type.getType(classBinding.javaConstructor.getDeclaringClass()); + int javaConstructorParameterCount = classBinding.javaConstructor.getParameterCount(); Label nonNull = new Label(); @@ -142,18 +142,18 @@ void write(MethodWriter writer, Globals globals) { arguments.get(argument).write(writer, globals); } - writer.invokeConstructor(type, Method.getMethod(binding.javaConstructor)); + writer.invokeConstructor(type, Method.getMethod(classBinding.javaConstructor)); writer.putField(CLASS_TYPE, name, type); writer.mark(nonNull); writer.loadThis(); writer.getField(CLASS_TYPE, name, type); - for (int argument = 0; argument < binding.javaMethod.getParameterCount(); ++argument) { + for (int argument = 0; argument < classBinding.javaMethod.getParameterCount(); ++argument) { arguments.get(argument + javaConstructorParameterCount).write(writer, globals); } - writer.invokeVirtual(type, Method.getMethod(binding.javaMethod)); + writer.invokeVirtual(type, Method.getMethod(classBinding.javaMethod)); } else { throw new IllegalStateException("Illegal tree structure."); }