Access simple bindings directly instead of accessing them via the Groovy engine

This commit is contained in:
Reinhard Pointner 2016-10-01 01:18:44 +08:00
parent 9209349f0c
commit 7afe232264
1 changed files with 74 additions and 38 deletions

View File

@ -13,7 +13,9 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.lang.model.SourceVersion;
import javax.script.Bindings; import javax.script.Bindings;
import javax.script.Compilable; import javax.script.Compilable;
import javax.script.CompiledScript; import javax.script.CompiledScript;
@ -33,38 +35,6 @@ import groovy.lang.MissingPropertyException;
public class ExpressionFormat extends Format { public class ExpressionFormat extends Format {
private static ScriptEngine engine;
private static Map<String, CompiledScript> scriptletCache = new HashMap<String, CompiledScript>();
protected static ScriptEngine createScriptEngine() {
CompilerConfiguration config = new CompilerConfiguration();
// include default functions
ImportCustomizer imports = new ImportCustomizer();
imports.addStaticStars(ExpressionFormatFunctions.class.getName());
config.addCompilationCustomizers(imports);
GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), config);
return new GroovyScriptEngineImpl(classLoader);
}
protected static synchronized ScriptEngine getGroovyScriptEngine() throws ScriptException {
if (engine == null) {
engine = createScriptEngine();
}
return engine;
}
protected static synchronized CompiledScript compileScriptlet(String expression) throws ScriptException {
Compilable engine = (Compilable) getGroovyScriptEngine();
CompiledScript scriptlet = scriptletCache.get(expression);
if (scriptlet == null) {
scriptlet = engine.compile(expression);
scriptletCache.put(expression, scriptlet);
}
return scriptlet;
}
private final String expression; private final String expression;
private final Object[] compilation; private final Object[] compilation;
@ -230,21 +200,87 @@ public class ExpressionFormat extends Format {
return lastException; return lastException;
} }
@Override
public Object parseObject(String source, ParsePosition pos) {
throw new UnsupportedOperationException();
}
private Object[] secure(Object[] compilation) { private Object[] secure(Object[] compilation) {
for (int i = 0; i < compilation.length; i++) { for (int i = 0; i < compilation.length; i++) {
Object snipped = compilation[i]; Object snippet = compilation[i];
if (snipped instanceof CompiledScript) { // simple expressions like {n} can't contain any malicious code
compilation[i] = new SecureCompiledScript((CompiledScript) snipped); if (snippet instanceof Variable) {
continue;
}
if (snippet instanceof CompiledScript) {
compilation[i] = new SecureCompiledScript((CompiledScript) snippet);
} }
} }
return compilation; return compilation;
} }
private static ScriptEngine engine;
private static Map<String, CompiledScript> scriptletCache = new HashMap<String, CompiledScript>();
protected static ScriptEngine createScriptEngine() {
CompilerConfiguration config = new CompilerConfiguration();
// include default functions
ImportCustomizer imports = new ImportCustomizer();
imports.addStaticStars(ExpressionFormatFunctions.class.getName());
config.addCompilationCustomizers(imports);
GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), config);
return new GroovyScriptEngineImpl(classLoader);
}
protected static synchronized ScriptEngine getGroovyScriptEngine() throws ScriptException {
if (engine == null) {
engine = createScriptEngine();
}
return engine;
}
protected static synchronized CompiledScript compileScriptlet(String expression) throws ScriptException {
// simple expressions like {n} don't need to be interpreted by the script engine
if (SourceVersion.isIdentifier(expression)) {
return new Variable(expression);
}
CompiledScript scriptlet = scriptletCache.get(expression);
if (scriptlet == null) {
Compilable engine = (Compilable) getGroovyScriptEngine();
scriptlet = engine.compile(expression);
scriptletCache.put(expression, scriptlet);
}
return scriptlet;
}
private static class Variable extends CompiledScript {
private String name;
public Variable(String name) {
this.name = name;
}
@Override @Override
public Object parseObject(String source, ParsePosition pos) { public Object eval(ScriptContext context) throws ScriptException {
throw new UnsupportedOperationException(); try {
return context.getAttribute(name);
} catch (Throwable t) {
throw new ScriptException(new ExecutionException(t));
}
}
@Override
public ScriptEngine getEngine() {
return null;
}
} }
} }