Painless: Decouple PainlessLookupBuilder and Whitelists (#32346)
Implements a static function in PainlessLookupBuilder that contains all the logic related to Whitelist. PainlessLookupBuilder is available for use in loading from methods beyond Whitelist now.
This commit is contained in:
parent
8067250fbe
commit
853aa0afb4
|
@ -103,10 +103,10 @@ public final class PainlessScriptEngine extends AbstractComponent implements Scr
|
|||
ScriptContext<?> context = entry.getKey();
|
||||
if (context.instanceClazz.equals(SearchScript.class) || context.instanceClazz.equals(ExecutableScript.class)) {
|
||||
contextsToCompilers.put(context, new Compiler(GenericElasticsearchScript.class,
|
||||
new PainlessLookupBuilder(entry.getValue()).build()));
|
||||
PainlessLookupBuilder.buildFromWhitelists(entry.getValue())));
|
||||
} else {
|
||||
contextsToCompilers.put(context, new Compiler(context.instanceClazz,
|
||||
new PainlessLookupBuilder(entry.getValue()).build()));
|
||||
PainlessLookupBuilder.buildFromWhitelists(entry.getValue())));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -126,14 +126,55 @@ public class PainlessLookupBuilder {
|
|||
private static final Pattern METHOD_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][_a-zA-Z0-9]*$");
|
||||
private static final Pattern FIELD_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][_a-zA-Z0-9]*$");
|
||||
|
||||
private final List<Whitelist> whitelists;
|
||||
public static PainlessLookup buildFromWhitelists(List<Whitelist> whitelists) {
|
||||
PainlessLookupBuilder painlessLookupBuilder = new PainlessLookupBuilder();
|
||||
String origin = "internal error";
|
||||
|
||||
try {
|
||||
for (Whitelist whitelist : whitelists) {
|
||||
for (WhitelistClass whitelistClass : whitelist.whitelistStructs) {
|
||||
origin = whitelistClass.origin;
|
||||
painlessLookupBuilder.addPainlessClass(
|
||||
whitelist.javaClassLoader, whitelistClass.javaClassName, whitelistClass.onlyFQNJavaClassName == false);
|
||||
}
|
||||
}
|
||||
|
||||
for (Whitelist whitelist : whitelists) {
|
||||
for (WhitelistClass whitelistClass : whitelist.whitelistStructs) {
|
||||
String targetCanonicalClassName = whitelistClass.javaClassName.replace('$', '.');
|
||||
|
||||
for (WhitelistConstructor whitelistConstructor : whitelistClass.whitelistConstructors) {
|
||||
origin = whitelistConstructor.origin;
|
||||
painlessLookupBuilder.addPainlessConstructor(
|
||||
targetCanonicalClassName, whitelistConstructor.painlessParameterTypeNames);
|
||||
}
|
||||
|
||||
for (WhitelistMethod whitelistMethod : whitelistClass.whitelistMethods) {
|
||||
origin = whitelistMethod.origin;
|
||||
painlessLookupBuilder.addPainlessMethod(
|
||||
whitelist.javaClassLoader, targetCanonicalClassName, whitelistMethod.javaAugmentedClassName,
|
||||
whitelistMethod.javaMethodName, whitelistMethod.painlessReturnTypeName,
|
||||
whitelistMethod.painlessParameterTypeNames);
|
||||
}
|
||||
|
||||
for (WhitelistField whitelistField : whitelistClass.whitelistFields) {
|
||||
origin = whitelistField.origin;
|
||||
painlessLookupBuilder.addPainlessField(
|
||||
targetCanonicalClassName, whitelistField.javaFieldName, whitelistField.painlessFieldTypeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
throw new IllegalArgumentException("error loading whitelist(s) " + origin, exception);
|
||||
}
|
||||
|
||||
return painlessLookupBuilder.build();
|
||||
}
|
||||
|
||||
private final Map<String, Class<?>> canonicalClassNamesToClasses;
|
||||
private final Map<Class<?>, PainlessClassBuilder> classesToPainlessClassBuilders;
|
||||
|
||||
public PainlessLookupBuilder(List<Whitelist> whitelists) {
|
||||
this.whitelists = whitelists;
|
||||
|
||||
public PainlessLookupBuilder() {
|
||||
canonicalClassNamesToClasses = new HashMap<>();
|
||||
classesToPainlessClassBuilders = new HashMap<>();
|
||||
|
||||
|
@ -666,60 +707,6 @@ public class PainlessLookupBuilder {
|
|||
}
|
||||
|
||||
public PainlessLookup build() {
|
||||
String origin = "internal error";
|
||||
|
||||
try {
|
||||
// first iteration collects all the Painless type names that
|
||||
// are used for validation during the second iteration
|
||||
for (Whitelist whitelist : whitelists) {
|
||||
for (WhitelistClass whitelistStruct : whitelist.whitelistStructs) {
|
||||
String painlessTypeName = whitelistStruct.javaClassName.replace('$', '.');
|
||||
PainlessClassBuilder painlessStruct =
|
||||
classesToPainlessClassBuilders.get(canonicalClassNamesToClasses.get(painlessTypeName));
|
||||
|
||||
if (painlessStruct != null && painlessStruct.clazz.getName().equals(whitelistStruct.javaClassName) == false) {
|
||||
throw new IllegalArgumentException("struct [" + painlessStruct.name + "] cannot represent multiple classes " +
|
||||
"[" + painlessStruct.clazz.getName() + "] and [" + whitelistStruct.javaClassName + "]");
|
||||
}
|
||||
|
||||
origin = whitelistStruct.origin;
|
||||
addPainlessClass(
|
||||
whitelist.javaClassLoader, whitelistStruct.javaClassName, whitelistStruct.onlyFQNJavaClassName == false);
|
||||
|
||||
painlessStruct = classesToPainlessClassBuilders.get(canonicalClassNamesToClasses.get(painlessTypeName));
|
||||
classesToPainlessClassBuilders.put(painlessStruct.clazz, painlessStruct);
|
||||
}
|
||||
}
|
||||
|
||||
// second iteration adds all the constructors, methods, and fields that will
|
||||
// be available in Painless along with validating they exist and all their types have
|
||||
// been white-listed during the first iteration
|
||||
for (Whitelist whitelist : whitelists) {
|
||||
for (WhitelistClass whitelistStruct : whitelist.whitelistStructs) {
|
||||
String painlessTypeName = whitelistStruct.javaClassName.replace('$', '.');
|
||||
|
||||
for (WhitelistConstructor whitelistConstructor : whitelistStruct.whitelistConstructors) {
|
||||
origin = whitelistConstructor.origin;
|
||||
addPainlessConstructor(painlessTypeName, whitelistConstructor.painlessParameterTypeNames);
|
||||
}
|
||||
|
||||
for (WhitelistMethod whitelistMethod : whitelistStruct.whitelistMethods) {
|
||||
origin = whitelistMethod.origin;
|
||||
addPainlessMethod(whitelist.javaClassLoader, painlessTypeName, whitelistMethod.javaAugmentedClassName,
|
||||
whitelistMethod.javaMethodName, whitelistMethod.painlessReturnTypeName,
|
||||
whitelistMethod.painlessParameterTypeNames);
|
||||
}
|
||||
|
||||
for (WhitelistField whitelistField : whitelistStruct.whitelistFields) {
|
||||
origin = whitelistField.origin;
|
||||
addPainlessField(painlessTypeName, whitelistField.javaFieldName, whitelistField.painlessFieldTypeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
throw new IllegalArgumentException("error loading whitelist(s) " + origin, exception);
|
||||
}
|
||||
|
||||
copyPainlessClassMembers();
|
||||
cacheRuntimeHandles();
|
||||
setFunctionalInterfaceMethods();
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.elasticsearch.painless;
|
||||
|
||||
import org.elasticsearch.painless.lookup.PainlessCast;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
public class AnalyzerCasterTests extends ESTestCase {
|
||||
|
|
|
@ -19,14 +19,14 @@
|
|||
|
||||
package org.elasticsearch.painless;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.painless.lookup.PainlessLookup;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupBuilder;
|
||||
import org.elasticsearch.painless.spi.Whitelist;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -38,7 +38,7 @@ import static org.hamcrest.Matchers.startsWith;
|
|||
*/
|
||||
public class BaseClassTests extends ScriptTestCase {
|
||||
|
||||
private final PainlessLookup painlessLookup = new PainlessLookupBuilder(Whitelist.BASE_WHITELISTS).build();
|
||||
private final PainlessLookup painlessLookup = PainlessLookupBuilder.buildFromWhitelists(Whitelist.BASE_WHITELISTS);
|
||||
|
||||
public abstract static class Gets {
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@ package org.elasticsearch.painless;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
|
@ -22,10 +25,6 @@ import java.util.Collections;
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class BasicStatementTests extends ScriptTestCase {
|
||||
|
||||
public void testIfStatement() {
|
||||
|
|
|
@ -37,7 +37,7 @@ import static org.hamcrest.Matchers.hasKey;
|
|||
import static org.hamcrest.Matchers.not;
|
||||
|
||||
public class DebugTests extends ScriptTestCase {
|
||||
private final PainlessLookup painlessLookup = new PainlessLookupBuilder(Whitelist.BASE_WHITELISTS).build();
|
||||
private final PainlessLookup painlessLookup = PainlessLookupBuilder.buildFromWhitelists(Whitelist.BASE_WHITELISTS);
|
||||
|
||||
public void testExplain() {
|
||||
// Debug.explain can explain an object
|
||||
|
|
|
@ -40,7 +40,7 @@ final class Debugger {
|
|||
PrintWriter outputWriter = new PrintWriter(output);
|
||||
Textifier textifier = new Textifier();
|
||||
try {
|
||||
new Compiler(iface, new PainlessLookupBuilder(Whitelist.BASE_WHITELISTS).build())
|
||||
new Compiler(iface, PainlessLookupBuilder.buildFromWhitelists(Whitelist.BASE_WHITELISTS))
|
||||
.compile("<debugging>", source, settings, textifier);
|
||||
} catch (RuntimeException e) {
|
||||
textifier.print(outputWriter);
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
|
||||
package org.elasticsearch.painless;
|
||||
|
||||
import org.elasticsearch.painless.lookup.PainlessLookup;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupBuilder;
|
||||
import org.elasticsearch.painless.spi.Whitelist;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
@ -27,13 +32,8 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.elasticsearch.painless.lookup.PainlessLookup;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupBuilder;
|
||||
import org.elasticsearch.painless.spi.Whitelist;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
public class DefBootstrapTests extends ESTestCase {
|
||||
private final PainlessLookup painlessLookup = new PainlessLookupBuilder(Whitelist.BASE_WHITELISTS).build();
|
||||
private final PainlessLookup painlessLookup = PainlessLookupBuilder.buildFromWhitelists(Whitelist.BASE_WHITELISTS);
|
||||
|
||||
/** calls toString() on integers, twice */
|
||||
public void testOneType() throws Throwable {
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.elasticsearch.painless;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ import static java.util.stream.Collectors.toList;
|
|||
*/
|
||||
public class PainlessDocGenerator {
|
||||
|
||||
private static final PainlessLookup PAINLESS_LOOKUP = new PainlessLookupBuilder(Whitelist.BASE_WHITELISTS).build();
|
||||
private static final PainlessLookup PAINLESS_LOOKUP = PainlessLookupBuilder.buildFromWhitelists(Whitelist.BASE_WHITELISTS);
|
||||
private static final Logger logger = ESLoggerFactory.getLogger(PainlessDocGenerator.class);
|
||||
private static final Comparator<PainlessField> FIELD_NAME = comparing(f -> f.name);
|
||||
private static final Comparator<PainlessMethod> METHOD_NAME = comparing(m -> m.name);
|
||||
|
|
|
@ -92,7 +92,7 @@ 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) {
|
||||
PainlessLookup painlessLookup = new PainlessLookupBuilder(Whitelist.BASE_WHITELISTS).build();
|
||||
PainlessLookup painlessLookup = PainlessLookupBuilder.buildFromWhitelists(Whitelist.BASE_WHITELISTS);
|
||||
ScriptClassInfo scriptClassInfo = new ScriptClassInfo(painlessLookup, GenericElasticsearchScript.class);
|
||||
CompilerSettings pickySettings = new CompilerSettings();
|
||||
pickySettings.setPicky(true);
|
||||
|
|
|
@ -22,8 +22,8 @@ package org.elasticsearch.painless;
|
|||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
import org.apache.lucene.search.Scorer;
|
||||
import org.elasticsearch.painless.spi.Whitelist;
|
||||
import org.elasticsearch.script.ScriptedMetricAggContexts;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptedMetricAggContexts;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.elasticsearch.painless;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.elasticsearch.script.ScriptException;
|
||||
|
||||
|
|
|
@ -20,21 +20,21 @@
|
|||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.CompilerSettings;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookup;
|
||||
import org.elasticsearch.painless.lookup.PainlessCast;
|
||||
import org.elasticsearch.painless.lookup.PainlessField;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupBuilder;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
|
||||
import org.elasticsearch.painless.lookup.PainlessMethod;
|
||||
import org.elasticsearch.painless.lookup.PainlessClass;
|
||||
import org.elasticsearch.painless.FeatureTest;
|
||||
import org.elasticsearch.painless.GenericElasticsearchScript;
|
||||
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.spi.Whitelist;
|
||||
import org.elasticsearch.painless.antlr.Walker;
|
||||
import org.elasticsearch.painless.lookup.PainlessCast;
|
||||
import org.elasticsearch.painless.lookup.PainlessClass;
|
||||
import org.elasticsearch.painless.lookup.PainlessField;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookup;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupBuilder;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
|
||||
import org.elasticsearch.painless.lookup.PainlessMethod;
|
||||
import org.elasticsearch.painless.spi.Whitelist;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -49,7 +49,7 @@ 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 PainlessLookup painlessLookup = new PainlessLookupBuilder(Whitelist.BASE_WHITELISTS).build();
|
||||
private final PainlessLookup painlessLookup = PainlessLookupBuilder.buildFromWhitelists(Whitelist.BASE_WHITELISTS);
|
||||
|
||||
public void testEAssignment() {
|
||||
assertToString(
|
||||
|
|
Loading…
Reference in New Issue