parent
f2cc8486af
commit
2028691e66
|
@ -59,12 +59,12 @@ public class NativeScriptEngineService extends AbstractComponent implements Scri
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
NativeScriptFactory scriptFactory = scripts.get(script);
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
NativeScriptFactory scriptFactory = scripts.get(scriptSource);
|
||||
if (scriptFactory != null) {
|
||||
return scriptFactory;
|
||||
}
|
||||
throw new IllegalArgumentException("Native script [" + script + "] not found");
|
||||
throw new IllegalArgumentException("Native script [" + scriptSource + "] not found");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -35,7 +35,15 @@ public interface ScriptEngineService extends Closeable {
|
|||
|
||||
String getExtension();
|
||||
|
||||
Object compile(String script, Map<String, String> params);
|
||||
/**
|
||||
* Compiles a script.
|
||||
* @param scriptName name of the script. {@code null} if it is anonymous (inline).
|
||||
* For a file script, its the file name (with extension).
|
||||
* For a stored script, its the identifier.
|
||||
* @param scriptSource actual source of the script
|
||||
* @param params compile-time parameters (such as flags to the compiler)
|
||||
*/
|
||||
Object compile(String scriptName, String scriptSource, Map<String, String> params);
|
||||
|
||||
ExecutableScript executable(CompiledScript compiledScript, @Nullable Map<String, Object> vars);
|
||||
|
||||
|
|
|
@ -302,7 +302,10 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
//Either an un-cached inline script or indexed script
|
||||
//If the script type is inline the name will be the same as the code for identification in exceptions
|
||||
try {
|
||||
compiledScript = new CompiledScript(type, name, lang, scriptEngineService.compile(code, params));
|
||||
// but give the script engine the chance to be better, give it separate name + source code
|
||||
// for the inline case, then its anonymous: null.
|
||||
String actualName = (type == ScriptType.INLINE) ? null : name;
|
||||
compiledScript = new CompiledScript(type, name, lang, scriptEngineService.compile(actualName, code, params));
|
||||
} catch (Exception exception) {
|
||||
throw new ScriptException("Failed to compile " + type + " script [" + name + "] using lang [" + lang + "]", exception);
|
||||
}
|
||||
|
@ -351,7 +354,7 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
//we don't know yet what the script will be used for, but if all of the operations for this lang with
|
||||
//indexed scripts are disabled, it makes no sense to even compile it.
|
||||
if (isAnyScriptContextEnabled(scriptLang, scriptEngineService, ScriptType.STORED)) {
|
||||
Object compiled = scriptEngineService.compile(template.getScript(), Collections.emptyMap());
|
||||
Object compiled = scriptEngineService.compile(id, template.getScript(), Collections.emptyMap());
|
||||
if (compiled == null) {
|
||||
throw new IllegalArgumentException("Unable to parse [" + template.getScript() +
|
||||
"] lang [" + scriptLang + "] (ScriptService.compile returned null)");
|
||||
|
@ -559,8 +562,12 @@ public class ScriptService extends AbstractComponent implements Closeable {
|
|||
logger.info("compiling script file [{}]", file.toAbsolutePath());
|
||||
try (InputStreamReader reader = new InputStreamReader(Files.newInputStream(file), StandardCharsets.UTF_8)) {
|
||||
String script = Streams.copyToString(reader);
|
||||
CacheKey cacheKey = new CacheKey(engineService, scriptNameExt.v1(), null, Collections.emptyMap());
|
||||
staticCache.put(cacheKey, new CompiledScript(ScriptType.FILE, scriptNameExt.v1(), engineService.getType(), engineService.compile(script, Collections.emptyMap())));
|
||||
String name = scriptNameExt.v1();
|
||||
CacheKey cacheKey = new CacheKey(engineService, name, null, Collections.emptyMap());
|
||||
// pass the actual file name to the compiler (for script engines that care about this)
|
||||
Object executable = engineService.compile(file.getFileName().toString(), script, Collections.emptyMap());
|
||||
CompiledScript compiledScript = new CompiledScript(ScriptType.FILE, name, engineService.getType(), executable);
|
||||
staticCache.put(cacheKey, compiledScript);
|
||||
scriptMetrics.onCompilation();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.elasticsearch.script;
|
|||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.script.MockScriptEngine.MockCompiledScript;
|
||||
import org.elasticsearch.script.ScriptMode;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
|
@ -56,7 +57,10 @@ public class FileScriptTests extends ESTestCase {
|
|||
.put("script.engine." + MockScriptEngine.NAME + ".file.aggs", "false").build();
|
||||
ScriptService scriptService = makeScriptService(settings);
|
||||
Script script = new Script("script1", ScriptService.ScriptType.FILE, MockScriptEngine.NAME, null);
|
||||
assertNotNull(scriptService.compile(script, ScriptContext.Standard.SEARCH, Collections.emptyMap(), null));
|
||||
CompiledScript compiledScript = scriptService.compile(script, ScriptContext.Standard.SEARCH, Collections.emptyMap(), null);
|
||||
assertNotNull(compiledScript);
|
||||
MockCompiledScript executable = (MockCompiledScript) compiledScript.compiled();
|
||||
assertEquals("script1.mockscript", executable.name);
|
||||
}
|
||||
|
||||
public void testAllOpsDisabled() throws Exception {
|
||||
|
|
|
@ -246,7 +246,7 @@ public class ScriptModesTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -521,8 +521,8 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
return "compiled_" + script;
|
||||
public Object compile(String scriptName, String scriptText, Map<String, String> params) {
|
||||
return "compiled_" + scriptText;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -563,8 +563,8 @@ public class ScriptServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
return "compiled_" + script;
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return "compiled_" + scriptSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -84,7 +84,7 @@ public class ScriptSettingsTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -397,8 +397,8 @@ public class AvgIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
return script;
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return scriptSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -522,8 +522,8 @@ public class AvgIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
return script;
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return scriptSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -393,8 +393,8 @@ public class SumIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
return script;
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return scriptSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -520,8 +520,8 @@ public class SumIT extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
return script;
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return scriptSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -251,8 +251,8 @@ public class ValueCountIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
return script;
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return scriptSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.elasticsearch.search.innerhits;
|
|||
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
|
||||
import org.elasticsearch.action.index.IndexRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.cluster.health.ClusterHealthStatus;
|
||||
|
|
|
@ -118,7 +118,7 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return new Object(); // unused
|
||||
}
|
||||
|
||||
|
@ -205,8 +205,8 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
return script;
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return scriptSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -285,7 +285,7 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return new Object(); // unused
|
||||
}
|
||||
|
||||
|
@ -365,7 +365,7 @@ public class UpdateIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return new Object(); // unused
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ public class ExpressionScriptEngineService extends AbstractComponent implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
// classloader created here
|
||||
final SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
|
@ -105,9 +105,9 @@ public class ExpressionScriptEngineService extends AbstractComponent implements
|
|||
};
|
||||
}
|
||||
// NOTE: validation is delayed to allow runtime vars, and we don't have access to per index stuff here
|
||||
return JavascriptCompiler.compile(script, JavascriptCompiler.DEFAULT_FUNCTIONS, loader);
|
||||
return JavascriptCompiler.compile(scriptSource, JavascriptCompiler.DEFAULT_FUNCTIONS, loader);
|
||||
} catch (ParseException e) {
|
||||
throw new ScriptException("Failed to parse expression: " + script, e);
|
||||
throw new ScriptException("Failed to parse expression: " + scriptSource, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -37,19 +37,19 @@ public class ExpressionTests extends ESSingleNodeTestCase {
|
|||
ExpressionScriptEngineService service = new ExpressionScriptEngineService(Settings.EMPTY);
|
||||
SearchLookup lookup = new SearchLookup(index.mapperService(), index.fieldData(), null);
|
||||
|
||||
Object compiled = service.compile("1.2", Collections.emptyMap());
|
||||
Object compiled = service.compile(null, "1.2", Collections.emptyMap());
|
||||
SearchScript ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "expression", compiled), lookup, Collections.<String, Object>emptyMap());
|
||||
assertFalse(ss.needsScores());
|
||||
|
||||
compiled = service.compile("doc['d'].value", Collections.emptyMap());
|
||||
compiled = service.compile(null, "doc['d'].value", Collections.emptyMap());
|
||||
ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "expression", compiled), lookup, Collections.<String, Object>emptyMap());
|
||||
assertFalse(ss.needsScores());
|
||||
|
||||
compiled = service.compile("1/_score", Collections.emptyMap());
|
||||
compiled = service.compile(null, "1/_score", Collections.emptyMap());
|
||||
ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "expression", compiled), lookup, Collections.<String, Object>emptyMap());
|
||||
assertTrue(ss.needsScores());
|
||||
|
||||
compiled = service.compile("doc['d'].value * _score", Collections.emptyMap());
|
||||
compiled = service.compile(null, "doc['d'].value * _score", Collections.emptyMap());
|
||||
ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "expression", compiled), lookup, Collections.<String, Object>emptyMap());
|
||||
assertTrue(ss.needsScores());
|
||||
}
|
||||
|
|
|
@ -170,19 +170,19 @@ public class GroovyScriptEngineService extends AbstractComponent implements Scri
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
try {
|
||||
// we reuse classloader, so do a security check just in case.
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new SpecialPermission());
|
||||
}
|
||||
String fake = MessageDigests.toHexString(MessageDigests.sha1().digest(script.getBytes(StandardCharsets.UTF_8)));
|
||||
String fake = MessageDigests.toHexString(MessageDigests.sha1().digest(scriptSource.getBytes(StandardCharsets.UTF_8)));
|
||||
// same logic as GroovyClassLoader.parseClass() but with a different codesource string:
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
@Override
|
||||
public Class<?> run() {
|
||||
GroovyCodeSource gcs = new GroovyCodeSource(script, fake, BootstrapInfo.UNTRUSTED_CODEBASE);
|
||||
GroovyCodeSource gcs = new GroovyCodeSource(scriptSource, fake, BootstrapInfo.UNTRUSTED_CODEBASE);
|
||||
gcs.setCachable(false);
|
||||
// TODO: we could be more complicated and paranoid, and move this to separate block, to
|
||||
// sandbox the compilation process itself better.
|
||||
|
|
|
@ -138,7 +138,7 @@ public class GroovySecurityTests extends ESTestCase {
|
|||
vars.put("myarray", Arrays.asList("foo"));
|
||||
vars.put("myobject", new MyObject());
|
||||
|
||||
se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "test", "js", se.compile(script, Collections.emptyMap())), vars).run();
|
||||
se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "test", "js", se.compile(null, script, Collections.emptyMap())), vars).run();
|
||||
}
|
||||
|
||||
public static class MyObject {
|
||||
|
|
|
@ -86,12 +86,12 @@ public final class MustacheScriptEngineService extends AbstractComponent impleme
|
|||
* Compile a template string to (in this case) a Mustache object than can
|
||||
* later be re-used for execution to fill in missing parameter values.
|
||||
*
|
||||
* @param template
|
||||
* @param templateSource
|
||||
* a string representing the template to compile.
|
||||
* @return a compiled template object for later execution.
|
||||
* */
|
||||
@Override
|
||||
public Object compile(String template, Map<String, String> params) {
|
||||
public Object compile(String templateName, String templateSource, Map<String, String> params) {
|
||||
String contentType = params.getOrDefault(CONTENT_TYPE_PARAM, JSON_CONTENT_TYPE);
|
||||
final DefaultMustacheFactory mustacheFactory;
|
||||
switch (contentType){
|
||||
|
@ -105,7 +105,7 @@ public final class MustacheScriptEngineService extends AbstractComponent impleme
|
|||
break;
|
||||
}
|
||||
mustacheFactory.setObjectHandler(new CustomReflectionObjectHandler());
|
||||
Reader reader = new FastStringReader(template);
|
||||
Reader reader = new FastStringReader(templateSource);
|
||||
return mustacheFactory.compile(reader, "query-template");
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ public class MustacheScriptEngineTests extends ESTestCase {
|
|||
+ "\"negative\": {\"term\": {\"body\": {\"value\": \"solr\"}" + "}}, \"negative_boost\": {{boost_val}} } }}";
|
||||
Map<String, Object> vars = new HashMap<>();
|
||||
vars.put("boost_val", "0.3");
|
||||
BytesReference o = (BytesReference) qe.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "", "mustache", qe.compile(template, compileParams)), vars).run();
|
||||
BytesReference o = (BytesReference) qe.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "", "mustache", qe.compile(null, template, compileParams)), vars).run();
|
||||
assertEquals("GET _search {\"query\": {\"boosting\": {\"positive\": {\"match\": {\"body\": \"gift\"}},"
|
||||
+ "\"negative\": {\"term\": {\"body\": {\"value\": \"solr\"}}}, \"negative_boost\": 0.3 } }}",
|
||||
new String(o.toBytes(), Charset.forName("UTF-8")));
|
||||
|
@ -65,7 +65,7 @@ public class MustacheScriptEngineTests extends ESTestCase {
|
|||
Map<String, Object> vars = new HashMap<>();
|
||||
vars.put("boost_val", "0.3");
|
||||
vars.put("body_val", "\"quick brown\"");
|
||||
BytesReference o = (BytesReference) qe.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "", "mustache", qe.compile(template, compileParams)), vars).run();
|
||||
BytesReference o = (BytesReference) qe.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "", "mustache", qe.compile(null, template, compileParams)), vars).run();
|
||||
assertEquals("GET _search {\"query\": {\"boosting\": {\"positive\": {\"match\": {\"body\": \"gift\"}},"
|
||||
+ "\"negative\": {\"term\": {\"body\": {\"value\": \"\\\"quick brown\\\"\"}}}, \"negative_boost\": 0.3 } }}",
|
||||
new String(o.toBytes(), Charset.forName("UTF-8")));
|
||||
|
|
|
@ -58,7 +58,7 @@ public class MustacheTests extends ESTestCase {
|
|||
+ "}}, \"negative_boost\": {{boost_val}} } }}";
|
||||
Map<String, Object> params = Collections.singletonMap("boost_val", "0.2");
|
||||
|
||||
Mustache mustache = (Mustache) engine.compile(template, Collections.emptyMap());
|
||||
Mustache mustache = (Mustache) engine.compile(null, template, Collections.emptyMap());
|
||||
CompiledScript compiledScript = new CompiledScript(ScriptService.ScriptType.INLINE, "my-name", "mustache", mustache);
|
||||
ExecutableScript result = engine.executable(compiledScript, params);
|
||||
assertEquals(
|
||||
|
@ -71,7 +71,7 @@ public class MustacheTests extends ESTestCase {
|
|||
|
||||
public void testArrayAccess() throws Exception {
|
||||
String template = "{{data.0}} {{data.1}}";
|
||||
CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(template, Collections.emptyMap()));
|
||||
CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(null, template, Collections.emptyMap()));
|
||||
Map<String, Object> vars = new HashMap<>();
|
||||
Object data = randomFrom(
|
||||
new String[] { "foo", "bar" },
|
||||
|
@ -97,7 +97,7 @@ public class MustacheTests extends ESTestCase {
|
|||
|
||||
public void testArrayInArrayAccess() throws Exception {
|
||||
String template = "{{data.0.0}} {{data.0.1}}";
|
||||
CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(template, Collections.emptyMap()));
|
||||
CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(null, template, Collections.emptyMap()));
|
||||
Map<String, Object> vars = new HashMap<>();
|
||||
Object data = randomFrom(
|
||||
new String[][] { new String[] { "foo", "bar" }},
|
||||
|
@ -114,7 +114,7 @@ public class MustacheTests extends ESTestCase {
|
|||
|
||||
public void testMapInArrayAccess() throws Exception {
|
||||
String template = "{{data.0.key}} {{data.1.key}}";
|
||||
CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(template, Collections.emptyMap()));
|
||||
CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(null, template, Collections.emptyMap()));
|
||||
Map<String, Object> vars = new HashMap<>();
|
||||
Object data = randomFrom(
|
||||
new Object[] { singletonMap("key", "foo"), singletonMap("key", "bar") },
|
||||
|
@ -141,7 +141,7 @@ public class MustacheTests extends ESTestCase {
|
|||
public void testEscaping() {
|
||||
// json string escaping enabled:
|
||||
Map<String, String> params = randomBoolean() ? Collections.emptyMap() : Collections.singletonMap(CONTENT_TYPE_PARAM, JSON_CONTENT_TYPE);
|
||||
Mustache mustache = (Mustache) engine.compile("{ \"field1\": \"{{value}}\"}", Collections.emptyMap());
|
||||
Mustache mustache = (Mustache) engine.compile(null, "{ \"field1\": \"{{value}}\"}", Collections.emptyMap());
|
||||
CompiledScript compiledScript = new CompiledScript(ScriptService.ScriptType.INLINE, "name", "mustache", mustache);
|
||||
ExecutableScript executableScript = engine.executable(compiledScript, Collections.singletonMap("value", "a \"value\""));
|
||||
BytesReference rawResult = (BytesReference) executableScript.run();
|
||||
|
@ -149,7 +149,7 @@ public class MustacheTests extends ESTestCase {
|
|||
assertThat(result, equalTo("{ \"field1\": \"a \\\"value\\\"\"}"));
|
||||
|
||||
// json string escaping disabled:
|
||||
mustache = (Mustache) engine.compile("{ \"field1\": \"{{value}}\"}", Collections.singletonMap(CONTENT_TYPE_PARAM, PLAIN_TEXT_CONTENT_TYPE));
|
||||
mustache = (Mustache) engine.compile(null, "{ \"field1\": \"{{value}}\"}", Collections.singletonMap(CONTENT_TYPE_PARAM, PLAIN_TEXT_CONTENT_TYPE));
|
||||
compiledScript = new CompiledScript(ScriptService.ScriptType.INLINE, "name", "mustache", mustache);
|
||||
executableScript = engine.executable(compiledScript, Collections.singletonMap("value", "a \"value\""));
|
||||
rawResult = (BytesReference) executableScript.run();
|
||||
|
@ -162,7 +162,7 @@ public class MustacheTests extends ESTestCase {
|
|||
List<String> randomList = Arrays.asList(generateRandomStringArray(10, 20, false));
|
||||
|
||||
String template = "{{data.array.size}} {{data.list.size}}";
|
||||
CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(template, Collections.emptyMap()));
|
||||
CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(null, template, Collections.emptyMap()));
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("array", randomArrayValues);
|
||||
data.put("list", randomList);
|
||||
|
|
|
@ -93,7 +93,7 @@ final class Compiler {
|
|||
* @return An {@link Executable} Painless script.
|
||||
*/
|
||||
static Executable compile(final Loader loader, final String name, final String source, final CompilerSettings settings) {
|
||||
byte[] bytes = compile(source, settings);
|
||||
byte[] bytes = compile(name, source, settings);
|
||||
|
||||
return createExecutable(loader, name, source, bytes);
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ final class Compiler {
|
|||
* @param settings The CompilerSettings to be used during the compilation.
|
||||
* @return The bytes for compilation.
|
||||
*/
|
||||
static byte[] compile(final String source, final CompilerSettings settings) {
|
||||
static byte[] compile(String name, String source, CompilerSettings settings) {
|
||||
if (source.length() > MAXIMUM_SOURCE_LENGTH) {
|
||||
throw new IllegalArgumentException("Scripts may be no longer than " + MAXIMUM_SOURCE_LENGTH +
|
||||
" characters. The passed in script is " + source.length() + " characters. Consider using a" +
|
||||
|
@ -115,7 +115,7 @@ final class Compiler {
|
|||
final SSource root = Walker.buildPainlessTree(source, reserved);
|
||||
final Variables variables = Analyzer.analyze(settings, Definition.INSTANCE, reserved, root);
|
||||
|
||||
return Writer.write(settings, Definition.INSTANCE, source, variables, root);
|
||||
return Writer.write(settings, Definition.INSTANCE, name, source, variables, root);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -100,15 +100,14 @@ public final class PainlessScriptEngineService extends AbstractComponent impleme
|
|||
public String getExtension() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compiles a Painless script with the specified parameters.
|
||||
* @param script The code to be compiled.
|
||||
* @param params The params used to modify the compiler settings on a per script basis.
|
||||
* @return Compiled script object represented by an {@link Executable}.
|
||||
* When a script is anonymous (inline), we give it this name.
|
||||
*/
|
||||
static final String INLINE_NAME = "<inline>";
|
||||
|
||||
@Override
|
||||
public Object compile(final String script, final Map<String, String> params) {
|
||||
public Object compile(String scriptName, final String scriptSource, final Map<String, String> params) {
|
||||
final CompilerSettings compilerSettings;
|
||||
|
||||
if (params.isEmpty()) {
|
||||
|
@ -154,7 +153,7 @@ public final class PainlessScriptEngineService extends AbstractComponent impleme
|
|||
return AccessController.doPrivileged(new PrivilegedAction<Executable>() {
|
||||
@Override
|
||||
public Executable run() {
|
||||
return Compiler.compile(loader, "unknown", script, compilerSettings);
|
||||
return Compiler.compile(loader, scriptName == null ? INLINE_NAME : scriptName, scriptSource, compilerSettings);
|
||||
}
|
||||
}, COMPILATION_CONTEXT);
|
||||
}
|
||||
|
|
|
@ -39,14 +39,15 @@ import static org.elasticsearch.painless.WriterConstants.MAP_TYPE;
|
|||
final class Writer {
|
||||
|
||||
static byte[] write(final CompilerSettings settings, final Definition definition,
|
||||
final String source, final Variables variables, final SSource root) {
|
||||
final Writer writer = new Writer(settings, definition, source, variables, root);
|
||||
String name, final String source, final Variables variables, final SSource root) {
|
||||
final Writer writer = new Writer(settings, definition, name, source, variables, root);
|
||||
|
||||
return writer.getBytes();
|
||||
}
|
||||
|
||||
private final CompilerSettings settings;
|
||||
private final Definition definition;
|
||||
private final String scriptName;
|
||||
private final String source;
|
||||
private final Variables variables;
|
||||
private final SSource root;
|
||||
|
@ -55,9 +56,10 @@ final class Writer {
|
|||
private final GeneratorAdapter adapter;
|
||||
|
||||
private Writer(final CompilerSettings settings, final Definition definition,
|
||||
final String source, final Variables variables, final SSource root) {
|
||||
String name, final String source, final Variables variables, final SSource root) {
|
||||
this.settings = settings;
|
||||
this.definition = definition;
|
||||
this.scriptName = name;
|
||||
this.source = source;
|
||||
this.variables = variables;
|
||||
this.root = root;
|
||||
|
@ -73,8 +75,11 @@ final class Writer {
|
|||
writeEnd();
|
||||
}
|
||||
|
||||
// This maximum length is theoretically 65535 bytes, but as it's CESU-8 encoded we dont know how large it is in bytes, so be safe
|
||||
private static final int MAX_NAME_LENGTH = 256;
|
||||
|
||||
private void writeBegin() {
|
||||
final int version = Opcodes.V1_7;
|
||||
final int version = Opcodes.V1_8;
|
||||
final int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL;
|
||||
final String base = BASE_CLASS_TYPE.getInternalName();
|
||||
final String name = CLASS_TYPE.getInternalName();
|
||||
|
@ -84,7 +89,47 @@ final class Writer {
|
|||
new String[] { WriterConstants.NEEDS_SCORE_TYPE.getInternalName() } : null;
|
||||
|
||||
writer.visit(version, access, name, null, base, interfaces);
|
||||
writer.visitSource(source, null);
|
||||
writer.visitSource(computeSourceName(), null);
|
||||
}
|
||||
|
||||
/** Computes the file name (mostly important for stacktraces) */
|
||||
private String computeSourceName() {
|
||||
StringBuilder fileName = new StringBuilder();
|
||||
if (scriptName.equals(PainlessScriptEngineService.INLINE_NAME)) {
|
||||
// its an anonymous script, include at least a portion of the source to help identify which one it is
|
||||
// but don't create stacktraces with filenames that contain newlines or huge names.
|
||||
|
||||
// truncate to the first newline
|
||||
int limit = source.indexOf('\n');
|
||||
if (limit >= 0) {
|
||||
int limit2 = source.indexOf('\r');
|
||||
if (limit2 >= 0) {
|
||||
limit = Math.min(limit, limit2);
|
||||
}
|
||||
} else {
|
||||
limit = source.length();
|
||||
}
|
||||
|
||||
// truncate to our limit
|
||||
limit = Math.min(limit, MAX_NAME_LENGTH);
|
||||
fileName.append(source, 0, limit);
|
||||
|
||||
// if we truncated, make it obvious
|
||||
if (limit != source.length()) {
|
||||
fileName.append(" ...");
|
||||
}
|
||||
fileName.append(" @ <inline script>");
|
||||
} else {
|
||||
// its a named script, just use the name
|
||||
// but don't trust this has a reasonable length!
|
||||
if (scriptName.length() > MAX_NAME_LENGTH) {
|
||||
fileName.append(scriptName, 0, MAX_NAME_LENGTH);
|
||||
fileName.append(" ...");
|
||||
} else {
|
||||
fileName.append(scriptName);
|
||||
}
|
||||
}
|
||||
return fileName.toString();
|
||||
}
|
||||
|
||||
private void writeConstructor() {
|
||||
|
|
|
@ -37,7 +37,7 @@ import java.util.Map;
|
|||
public final class WriterConstants {
|
||||
|
||||
public final static String BASE_CLASS_NAME = Executable.class.getName();
|
||||
public final static String CLASS_NAME = BASE_CLASS_NAME + "$CompiledPainlessExecutable";
|
||||
public final static String CLASS_NAME = BASE_CLASS_NAME + "$Script";
|
||||
public final static Type BASE_CLASS_TYPE = Type.getType(Executable.class);
|
||||
public final static Type CLASS_TYPE = Type.getType("L" + CLASS_NAME.replace(".", "/") + ";");
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.commons.GeneratorAdapter;
|
||||
|
||||
/**
|
||||
* The superclass for all other nodes.
|
||||
*/
|
||||
|
@ -42,4 +45,15 @@ public abstract class ANode {
|
|||
public String error(final String message) {
|
||||
return "Error " + location + ": " + message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes line number information
|
||||
* <p>
|
||||
* Currently we emit line number data for for leaf S-nodes
|
||||
*/
|
||||
void writeDebugInfo(GeneratorAdapter adapter) {
|
||||
Label label = new Label();
|
||||
adapter.visitLabel(label);
|
||||
adapter.visitLineNumber(line, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public final class SBreak extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
adapter.goTo(brake);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ public final class SContinue extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
adapter.goTo(continu);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ public final class SDeclaration extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
final org.objectweb.asm.Type type = variable.type.type;
|
||||
final Sort sort = variable.type.sort;
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ public final class SDo extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
final Label start = new Label();
|
||||
final Label begin = new Label();
|
||||
final Label end = new Label();
|
||||
|
|
|
@ -61,6 +61,7 @@ public final class SExpression extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
expression.write(settings, definition, adapter);
|
||||
|
||||
if (methodEscape) {
|
||||
|
|
|
@ -130,6 +130,7 @@ public final class SFor extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
final Label start = new Label();
|
||||
final Label begin = afterthought == null ? start : new Label();
|
||||
final Label end = new Label();
|
||||
|
|
|
@ -85,6 +85,7 @@ public final class SIfElse extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
final Label end = new Label();
|
||||
final Label fals = elseblock != null ? new Label() : end;
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ public final class SReturn extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
expression.write(settings, definition, adapter);
|
||||
adapter.returnValue();
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ public final class SThrow extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
expression.write(settings, definition, adapter);
|
||||
adapter.throwException();
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ public final class STrap extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
final Label jump = new Label();
|
||||
|
||||
adapter.mark(jump);
|
||||
|
|
|
@ -84,6 +84,7 @@ public final class STry extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
final Label begin = new Label();
|
||||
final Label end = new Label();
|
||||
final Label exception = new Label();
|
||||
|
|
|
@ -94,6 +94,7 @@ public final class SWhile extends AStatement {
|
|||
|
||||
@Override
|
||||
void write(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
writeDebugInfo(adapter);
|
||||
final Label begin = new Label();
|
||||
final Label end = new Label();
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@ final class Debugger {
|
|||
}
|
||||
|
||||
/** compiles to bytecode, and returns debugging output */
|
||||
static String toString(final String source, final CompilerSettings settings) {
|
||||
final byte[] bytes = Compiler.compile(source, settings);
|
||||
static String toString(String source, CompilerSettings settings) {
|
||||
final byte[] bytes = Compiler.compile("<debugging>", source, settings);
|
||||
final ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
final PrintWriter outputWriter = new PrintWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
|
||||
final ClassReader reader = new ClassReader(bytes);
|
||||
|
|
|
@ -41,22 +41,22 @@ public class NeedsScoreTests extends ESSingleNodeTestCase {
|
|||
PainlessScriptEngineService service = new PainlessScriptEngineService(Settings.EMPTY);
|
||||
SearchLookup lookup = new SearchLookup(index.mapperService(), index.fieldData(), null);
|
||||
|
||||
Object compiled = service.compile("1.2", Collections.emptyMap());
|
||||
Object compiled = service.compile(null, "1.2", Collections.emptyMap());
|
||||
SearchScript ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled),
|
||||
lookup, Collections.<String, Object>emptyMap());
|
||||
assertFalse(ss.needsScores());
|
||||
|
||||
compiled = service.compile("doc['d'].value", Collections.emptyMap());
|
||||
compiled = service.compile(null, "doc['d'].value", Collections.emptyMap());
|
||||
ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled),
|
||||
lookup, Collections.<String, Object>emptyMap());
|
||||
assertFalse(ss.needsScores());
|
||||
|
||||
compiled = service.compile("1/_score", Collections.emptyMap());
|
||||
compiled = service.compile(null, "1/_score", Collections.emptyMap());
|
||||
ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled),
|
||||
lookup, Collections.<String, Object>emptyMap());
|
||||
assertTrue(ss.needsScores());
|
||||
|
||||
compiled = service.compile("doc['d'].value * _score", Collections.emptyMap());
|
||||
compiled = service.compile(null, "doc['d'].value * _score", Collections.emptyMap());
|
||||
ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled),
|
||||
lookup, Collections.<String, Object>emptyMap());
|
||||
assertTrue(ss.needsScores());
|
||||
|
|
|
@ -81,7 +81,7 @@ public class ScriptEngineTests extends ScriptTestCase {
|
|||
Map<String, Object> ctx = new HashMap<>();
|
||||
vars.put("ctx", ctx);
|
||||
|
||||
Object compiledScript = scriptEngine.compile(
|
||||
Object compiledScript = scriptEngine.compile(null,
|
||||
"return ctx.value;", Collections.emptyMap());
|
||||
ExecutableScript script = scriptEngine.executable(new CompiledScript(ScriptService.ScriptType.INLINE,
|
||||
"testChangingVarsCrossExecution1", "painless", compiledScript), vars);
|
||||
|
@ -97,7 +97,7 @@ public class ScriptEngineTests extends ScriptTestCase {
|
|||
|
||||
public void testChangingVarsCrossExecution2() {
|
||||
Map<String, Object> vars = new HashMap<>();
|
||||
Object compiledScript = scriptEngine.compile("return params['value'];", Collections.emptyMap());
|
||||
Object compiledScript = scriptEngine.compile(null, "return params['value'];", Collections.emptyMap());
|
||||
|
||||
ExecutableScript script = scriptEngine.executable(new CompiledScript(ScriptService.ScriptType.INLINE,
|
||||
"testChangingVarsCrossExecution2", "painless", compiledScript), vars);
|
||||
|
|
|
@ -53,7 +53,7 @@ public abstract class ScriptTestCase extends ESTestCase {
|
|||
|
||||
/** Compiles and returns the result of {@code script} with access to {@code vars} and compile-time parameters */
|
||||
public Object exec(String script, Map<String, Object> vars, Map<String,String> compileParams) {
|
||||
Object object = scriptEngine.compile(script, compileParams);
|
||||
Object object = scriptEngine.compile(null, script, compileParams);
|
||||
CompiledScript compiled = new CompiledScript(ScriptService.ScriptType.INLINE, getTestName(), "painless", object);
|
||||
return scriptEngine.executable(compiled, vars).run();
|
||||
}
|
||||
|
|
|
@ -30,6 +30,41 @@ public class WhenThingsGoWrongTests extends ScriptTestCase {
|
|||
});
|
||||
}
|
||||
|
||||
public void testLineNumbers() {
|
||||
// trigger NPE at line 1 of the script
|
||||
NullPointerException exception = expectThrows(NullPointerException.class, () -> {
|
||||
exec("String x = null; boolean y = x.isEmpty();\n" +
|
||||
"return y;");
|
||||
});
|
||||
assertEquals(1, exception.getStackTrace()[0].getLineNumber());
|
||||
|
||||
// trigger NPE at line 2 of the script
|
||||
exception = expectThrows(NullPointerException.class, () -> {
|
||||
exec("String x = null;\n" +
|
||||
"return x.isEmpty();");
|
||||
});
|
||||
assertEquals(2, exception.getStackTrace()[0].getLineNumber());
|
||||
|
||||
// trigger NPE at line 3 of the script
|
||||
exception = expectThrows(NullPointerException.class, () -> {
|
||||
exec("String x = null;\n" +
|
||||
"String y = x;\n" +
|
||||
"return y.isEmpty();");
|
||||
});
|
||||
assertEquals(3, exception.getStackTrace()[0].getLineNumber());
|
||||
|
||||
// trigger NPE at line 4 in script (inside conditional)
|
||||
exception = expectThrows(NullPointerException.class, () -> {
|
||||
exec("String x = null;\n" +
|
||||
"boolean y = false;\n" +
|
||||
"if (!y) {\n" +
|
||||
" y = x.isEmpty();\n" +
|
||||
"}\n" +
|
||||
"return y;");
|
||||
});
|
||||
assertEquals(4, exception.getStackTrace()[0].getLineNumber());
|
||||
}
|
||||
|
||||
public void testInvalidShift() {
|
||||
expectThrows(ClassCastException.class, () -> {
|
||||
exec("float x = 15F; x <<= 2; return x;");
|
||||
|
|
|
@ -171,10 +171,10 @@ public class JavaScriptScriptEngineService extends AbstractComponent implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
Context ctx = Context.enter();
|
||||
try {
|
||||
return ctx.compileString(script, generateScriptName(), 1, DOMAIN);
|
||||
return ctx.compileString(scriptSource, generateScriptName(), 1, DOMAIN);
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public class JavaScriptScriptEngineTests extends ESTestCase {
|
|||
|
||||
public void testSimpleEquation() {
|
||||
Map<String, Object> vars = new HashMap<String, Object>();
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testSimpleEquation", "js", se.compile("1 + 2", Collections.emptyMap())), vars).run();
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testSimpleEquation", "js", se.compile(null, "1 + 2", Collections.emptyMap())), vars).run();
|
||||
assertThat(((Number) o).intValue(), equalTo(3));
|
||||
}
|
||||
|
||||
|
@ -66,13 +66,13 @@ public class JavaScriptScriptEngineTests extends ESTestCase {
|
|||
Map<String, Object> obj2 = MapBuilder.<String, Object>newMapBuilder().put("prop2", "value2").map();
|
||||
Map<String, Object> obj1 = MapBuilder.<String, Object>newMapBuilder().put("prop1", "value1").put("obj2", obj2).put("l", Arrays.asList("2", "1")).map();
|
||||
vars.put("obj1", obj1);
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testMapAccess", "js", se.compile("obj1", Collections.emptyMap())), vars).run();
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testMapAccess", "js", se.compile(null, "obj1", Collections.emptyMap())), vars).run();
|
||||
assertThat(o, instanceOf(Map.class));
|
||||
obj1 = (Map<String, Object>) o;
|
||||
assertThat((String) obj1.get("prop1"), equalTo("value1"));
|
||||
assertThat((String) ((Map<String, Object>) obj1.get("obj2")).get("prop2"), equalTo("value2"));
|
||||
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testMapAccess", "js", se.compile("obj1.l[0]", Collections.emptyMap())), vars).run();
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testMapAccess", "js", se.compile(null, "obj1.l[0]", Collections.emptyMap())), vars).run();
|
||||
assertThat(((String) o), equalTo("2"));
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ public class JavaScriptScriptEngineTests extends ESTestCase {
|
|||
public void testJavaScriptObjectToMap() {
|
||||
Map<String, Object> vars = new HashMap<String, Object>();
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testJavaScriptObjectToMap", "js",
|
||||
se.compile("var obj1 = {}; obj1.prop1 = 'value1'; obj1.obj2 = {}; obj1.obj2.prop2 = 'value2'; obj1", Collections.emptyMap())), vars).run();
|
||||
se.compile(null, "var obj1 = {}; obj1.prop1 = 'value1'; obj1.obj2 = {}; obj1.obj2.prop2 = 'value2'; obj1", Collections.emptyMap())), vars).run();
|
||||
Map<String, Object> obj1 = (Map<String, Object>) o;
|
||||
assertThat((String) obj1.get("prop1"), equalTo("value1"));
|
||||
assertThat((String) ((Map<String, Object>) obj1.get("obj2")).get("prop2"), equalTo("value2"));
|
||||
|
@ -96,7 +96,7 @@ public class JavaScriptScriptEngineTests extends ESTestCase {
|
|||
vars.put("ctx", ctx);
|
||||
|
||||
ExecutableScript executable = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testJavaScriptObjectMapInter", "js",
|
||||
se.compile("ctx.obj2 = {}; ctx.obj2.prop2 = 'value2'; ctx.obj1.prop1 = 'uvalue1'", Collections.emptyMap())), vars);
|
||||
se.compile(null, "ctx.obj2 = {}; ctx.obj2.prop2 = 'value2'; ctx.obj1.prop1 = 'uvalue1'", Collections.emptyMap())), vars);
|
||||
executable.run();
|
||||
ctx = (Map<String, Object>) executable.unwrap(vars.get("ctx"));
|
||||
assertThat(ctx.containsKey("obj1"), equalTo(true));
|
||||
|
@ -111,7 +111,7 @@ public class JavaScriptScriptEngineTests extends ESTestCase {
|
|||
Map<String, Object> doc = new HashMap<String, Object>();
|
||||
ctx.put("doc", doc);
|
||||
|
||||
Object compiled = se.compile("ctx.doc.field1 = ['value1', 'value2']", Collections.emptyMap());
|
||||
Object compiled = se.compile(null, "ctx.doc.field1 = ['value1', 'value2']", Collections.emptyMap());
|
||||
ExecutableScript script = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testJavaScriptInnerArrayCreation", "js",
|
||||
compiled), new HashMap<String, Object>());
|
||||
script.setNextVar("ctx", ctx);
|
||||
|
@ -130,21 +130,21 @@ public class JavaScriptScriptEngineTests extends ESTestCase {
|
|||
vars.put("l", Arrays.asList("1", "2", "3", obj1));
|
||||
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testAccessInScript", "js",
|
||||
se.compile("l.length", Collections.emptyMap())), vars).run();
|
||||
se.compile(null, "l.length", Collections.emptyMap())), vars).run();
|
||||
assertThat(((Number) o).intValue(), equalTo(4));
|
||||
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testAccessInScript", "js",
|
||||
se.compile("l[0]", Collections.emptyMap())), vars).run();
|
||||
se.compile(null, "l[0]", Collections.emptyMap())), vars).run();
|
||||
assertThat(((String) o), equalTo("1"));
|
||||
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testAccessInScript", "js",
|
||||
se.compile("l[3]", Collections.emptyMap())), vars).run();
|
||||
se.compile(null, "l[3]", Collections.emptyMap())), vars).run();
|
||||
obj1 = (Map<String, Object>) o;
|
||||
assertThat((String) obj1.get("prop1"), equalTo("value1"));
|
||||
assertThat((String) ((Map<String, Object>) obj1.get("obj2")).get("prop2"), equalTo("value2"));
|
||||
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testAccessInScript", "js",
|
||||
se.compile("l[3].prop1", Collections.emptyMap())), vars).run();
|
||||
se.compile(null, "l[3].prop1", Collections.emptyMap())), vars).run();
|
||||
assertThat(((String) o), equalTo("value1"));
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ public class JavaScriptScriptEngineTests extends ESTestCase {
|
|||
Map<String, Object> vars = new HashMap<String, Object>();
|
||||
Map<String, Object> ctx = new HashMap<String, Object>();
|
||||
vars.put("ctx", ctx);
|
||||
Object compiledScript = se.compile("ctx.value", Collections.emptyMap());
|
||||
Object compiledScript = se.compile(null, "ctx.value", Collections.emptyMap());
|
||||
|
||||
ExecutableScript script = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testChangingVarsCrossExecution1", "js",
|
||||
compiledScript), vars);
|
||||
|
@ -167,7 +167,7 @@ public class JavaScriptScriptEngineTests extends ESTestCase {
|
|||
|
||||
public void testChangingVarsCrossExecution2() {
|
||||
Map<String, Object> vars = new HashMap<String, Object>();
|
||||
Object compiledScript = se.compile("value", Collections.emptyMap());
|
||||
Object compiledScript = se.compile(null, "value", Collections.emptyMap());
|
||||
|
||||
ExecutableScript script = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testChangingVarsCrossExecution2", "js",
|
||||
compiledScript), vars);
|
||||
|
|
|
@ -41,7 +41,7 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
public class JavaScriptScriptMultiThreadedTests extends ESTestCase {
|
||||
public void testExecutableNoRuntimeParams() throws Exception {
|
||||
final JavaScriptScriptEngineService se = new JavaScriptScriptEngineService(Settings.Builder.EMPTY_SETTINGS);
|
||||
final Object compiled = se.compile("x + y", Collections.emptyMap());
|
||||
final Object compiled = se.compile(null, "x + y", Collections.emptyMap());
|
||||
final AtomicBoolean failed = new AtomicBoolean();
|
||||
|
||||
Thread[] threads = new Thread[50];
|
||||
|
@ -83,7 +83,7 @@ public class JavaScriptScriptMultiThreadedTests extends ESTestCase {
|
|||
|
||||
public void testExecutableWithRuntimeParams() throws Exception {
|
||||
final JavaScriptScriptEngineService se = new JavaScriptScriptEngineService(Settings.Builder.EMPTY_SETTINGS);
|
||||
final Object compiled = se.compile("x + y", Collections.emptyMap());
|
||||
final Object compiled = se.compile(null, "x + y", Collections.emptyMap());
|
||||
final AtomicBoolean failed = new AtomicBoolean();
|
||||
|
||||
Thread[] threads = new Thread[50];
|
||||
|
@ -125,7 +125,7 @@ public class JavaScriptScriptMultiThreadedTests extends ESTestCase {
|
|||
|
||||
public void testExecute() throws Exception {
|
||||
final JavaScriptScriptEngineService se = new JavaScriptScriptEngineService(Settings.Builder.EMPTY_SETTINGS);
|
||||
final Object compiled = se.compile("x + y", Collections.emptyMap());
|
||||
final Object compiled = se.compile(null, "x + y", Collections.emptyMap());
|
||||
final AtomicBoolean failed = new AtomicBoolean();
|
||||
|
||||
Thread[] threads = new Thread[50];
|
||||
|
|
|
@ -54,7 +54,7 @@ public class JavaScriptSecurityTests extends ESTestCase {
|
|||
/** runs a script */
|
||||
private void doTest(String script) {
|
||||
Map<String, Object> vars = new HashMap<String, Object>();
|
||||
se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "test", "js", se.compile(script, Collections.emptyMap())), vars).run();
|
||||
se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "test", "js", se.compile(null, script, Collections.emptyMap())), vars).run();
|
||||
}
|
||||
|
||||
/** asserts that a script runs without exception */
|
||||
|
|
|
@ -107,7 +107,7 @@ public class PythonScriptEngineService extends AbstractComponent implements Scri
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
// classloader created here
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
|
@ -116,7 +116,7 @@ public class PythonScriptEngineService extends AbstractComponent implements Scri
|
|||
return AccessController.doPrivileged(new PrivilegedAction<PyCode>() {
|
||||
@Override
|
||||
public PyCode run() {
|
||||
return interp.compile(script);
|
||||
return interp.compile(scriptSource);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public class PythonScriptEngineTests extends ESTestCase {
|
|||
|
||||
public void testSimpleEquation() {
|
||||
Map<String, Object> vars = new HashMap<String, Object>();
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testSimpleEquation", "python", se.compile("1 + 2", Collections.emptyMap())), vars).run();
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testSimpleEquation", "python", se.compile(null, "1 + 2", Collections.emptyMap())), vars).run();
|
||||
assertThat(((Number) o).intValue(), equalTo(3));
|
||||
}
|
||||
|
||||
|
@ -65,13 +65,13 @@ public class PythonScriptEngineTests extends ESTestCase {
|
|||
Map<String, Object> obj2 = MapBuilder.<String, Object>newMapBuilder().put("prop2", "value2").map();
|
||||
Map<String, Object> obj1 = MapBuilder.<String, Object>newMapBuilder().put("prop1", "value1").put("obj2", obj2).put("l", Arrays.asList("2", "1")).map();
|
||||
vars.put("obj1", obj1);
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testMapAccess", "python", se.compile("obj1", Collections.emptyMap())), vars).run();
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testMapAccess", "python", se.compile(null, "obj1", Collections.emptyMap())), vars).run();
|
||||
assertThat(o, instanceOf(Map.class));
|
||||
obj1 = (Map<String, Object>) o;
|
||||
assertThat((String) obj1.get("prop1"), equalTo("value1"));
|
||||
assertThat((String) ((Map<String, Object>) obj1.get("obj2")).get("prop2"), equalTo("value2"));
|
||||
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testMapAccess", "python", se.compile("obj1['l'][0]", Collections.emptyMap())), vars).run();
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testMapAccess", "python", se.compile(null, "obj1['l'][0]", Collections.emptyMap())), vars).run();
|
||||
assertThat(((String) o), equalTo("2"));
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ public class PythonScriptEngineTests extends ESTestCase {
|
|||
vars.put("ctx", ctx);
|
||||
|
||||
ExecutableScript executable = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testObjectInterMap", "python",
|
||||
se.compile("ctx['obj2'] = { 'prop2' : 'value2' }; ctx['obj1']['prop1'] = 'uvalue1'", Collections.emptyMap())), vars);
|
||||
se.compile(null, "ctx['obj2'] = { 'prop2' : 'value2' }; ctx['obj1']['prop1'] = 'uvalue1'", Collections.emptyMap())), vars);
|
||||
executable.run();
|
||||
ctx = (Map<String, Object>) executable.unwrap(vars.get("ctx"));
|
||||
assertThat(ctx.containsKey("obj1"), equalTo(true));
|
||||
|
@ -104,15 +104,15 @@ public class PythonScriptEngineTests extends ESTestCase {
|
|||
// Object o = se.execute(se.compile("l.length"), vars);
|
||||
// assertThat(((Number) o).intValue(), equalTo(4));
|
||||
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testAccessListInScript", "python", se.compile("l[0]", Collections.emptyMap())), vars).run();
|
||||
Object o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testAccessListInScript", "python", se.compile(null, "l[0]", Collections.emptyMap())), vars).run();
|
||||
assertThat(((String) o), equalTo("1"));
|
||||
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testAccessListInScript", "python", se.compile("l[3]", Collections.emptyMap())), vars).run();
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testAccessListInScript", "python", se.compile(null, "l[3]", Collections.emptyMap())), vars).run();
|
||||
obj1 = (Map<String, Object>) o;
|
||||
assertThat((String) obj1.get("prop1"), equalTo("value1"));
|
||||
assertThat((String) ((Map<String, Object>) obj1.get("obj2")).get("prop2"), equalTo("value2"));
|
||||
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testAccessListInScript", "python", se.compile("l[3]['prop1']", Collections.emptyMap())), vars).run();
|
||||
o = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testAccessListInScript", "python", se.compile(null, "l[3]['prop1']", Collections.emptyMap())), vars).run();
|
||||
assertThat(((String) o), equalTo("value1"));
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ public class PythonScriptEngineTests extends ESTestCase {
|
|||
Map<String, Object> vars = new HashMap<String, Object>();
|
||||
Map<String, Object> ctx = new HashMap<String, Object>();
|
||||
vars.put("ctx", ctx);
|
||||
Object compiledScript = se.compile("ctx['value']", Collections.emptyMap());
|
||||
Object compiledScript = se.compile(null, "ctx['value']", Collections.emptyMap());
|
||||
|
||||
ExecutableScript script = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testChangingVarsCrossExecution1", "python", compiledScript), vars);
|
||||
ctx.put("value", 1);
|
||||
|
@ -135,7 +135,7 @@ public class PythonScriptEngineTests extends ESTestCase {
|
|||
public void testChangingVarsCrossExecution2() {
|
||||
Map<String, Object> vars = new HashMap<String, Object>();
|
||||
Map<String, Object> ctx = new HashMap<String, Object>();
|
||||
Object compiledScript = se.compile("value", Collections.emptyMap());
|
||||
Object compiledScript = se.compile(null, "value", Collections.emptyMap());
|
||||
|
||||
ExecutableScript script = se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "testChangingVarsCrossExecution2", "python", compiledScript), vars);
|
||||
script.setNextVar("value", 1);
|
||||
|
|
|
@ -42,7 +42,7 @@ public class PythonScriptMultiThreadedTests extends ESTestCase {
|
|||
|
||||
public void testExecutableNoRuntimeParams() throws Exception {
|
||||
final PythonScriptEngineService se = new PythonScriptEngineService(Settings.Builder.EMPTY_SETTINGS);
|
||||
final Object compiled = se.compile("x + y", Collections.emptyMap());
|
||||
final Object compiled = se.compile(null, "x + y", Collections.emptyMap());
|
||||
final CompiledScript compiledScript = new CompiledScript(ScriptService.ScriptType.INLINE, "testExecutableNoRuntimeParams", "python", compiled);
|
||||
final AtomicBoolean failed = new AtomicBoolean();
|
||||
|
||||
|
@ -128,7 +128,7 @@ public class PythonScriptMultiThreadedTests extends ESTestCase {
|
|||
|
||||
public void testExecute() throws Exception {
|
||||
final PythonScriptEngineService se = new PythonScriptEngineService(Settings.Builder.EMPTY_SETTINGS);
|
||||
final Object compiled = se.compile("x + y", Collections.emptyMap());
|
||||
final Object compiled = se.compile(null, "x + y", Collections.emptyMap());
|
||||
final CompiledScript compiledScript = new CompiledScript(ScriptService.ScriptType.INLINE, "testExecute", "python", compiled);
|
||||
final AtomicBoolean failed = new AtomicBoolean();
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ public class PythonSecurityTests extends ESTestCase {
|
|||
/** runs a script */
|
||||
private void doTest(String script) {
|
||||
Map<String, Object> vars = new HashMap<String, Object>();
|
||||
se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "test", "python", se.compile(script, Collections.emptyMap())), vars).run();
|
||||
se.executable(new CompiledScript(ScriptService.ScriptType.INLINE, "test", "python", se.compile(null, script, Collections.emptyMap())), vars).run();
|
||||
}
|
||||
|
||||
/** asserts that a script runs without exception */
|
||||
|
|
|
@ -32,12 +32,27 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A dummy script engine used for testing. Scripts must be a number. Running the script
|
||||
* A dummy script engine used for testing. Scripts must be a number. Many
|
||||
* tests rely on the fact this thing returns a String as its compiled form.
|
||||
* they even try to serialize it over the network!
|
||||
*/
|
||||
public class MockScriptEngine implements ScriptEngineService {
|
||||
|
||||
public static final String NAME = "mockscript";
|
||||
|
||||
/** A compiled script, just holds the scripts name, source, and params that were passed in */
|
||||
public static class MockCompiledScript {
|
||||
public final String name;
|
||||
public final String source;
|
||||
public final Map<String,String> params;
|
||||
|
||||
MockCompiledScript(String name, String source, Map<String,String> params) {
|
||||
this.name = name;
|
||||
this.source = source;
|
||||
this.params = params;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestPlugin extends Plugin {
|
||||
|
||||
public TestPlugin() {
|
||||
|
@ -71,16 +86,18 @@ public class MockScriptEngine implements ScriptEngineService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object compile(String script, Map<String, String> params) {
|
||||
return script;
|
||||
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
|
||||
return new MockCompiledScript(scriptName, scriptSource, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableScript executable(CompiledScript compiledScript, @Nullable Map<String, Object> vars) {
|
||||
assert compiledScript.compiled() instanceof MockCompiledScript
|
||||
: "do NOT pass compiled scripts from other engines to me, I will fail your test, got: " + compiledScript;
|
||||
return new AbstractExecutableScript() {
|
||||
@Override
|
||||
public Object run() {
|
||||
return new BytesArray((String)compiledScript.compiled());
|
||||
return new BytesArray(((MockCompiledScript)compiledScript.compiled()).source);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -94,7 +111,7 @@ public class MockScriptEngine implements ScriptEngineService {
|
|||
|
||||
@Override
|
||||
public Object run() {
|
||||
return compiledScript.compiled();
|
||||
return ((MockCompiledScript)compiledScript.compiled()).source;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue