ch.obermuhlner.scriptengine.java.JavaCompiledScript Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-scriptengine Show documentation
Show all versions of java-scriptengine Show documentation
Java script engine for Java as a scripting language.
package ch.obermuhlner.scriptengine.java;
import ch.obermuhlner.scriptengine.java.execution.ExecutionStrategy;
import javax.script.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* The compiled Java script created by a {@link JavaScriptEngine}.
*/
public class JavaCompiledScript extends CompiledScript {
private final JavaScriptEngine engine;
private final Class> compiledClass;
private final Object compiledInstance;
private ExecutionStrategy executionStrategy;
/**
* Construct a {@link JavaCompiledScript}.
*
* @param engine the {@link JavaScriptEngine} that compiled this script
* @param compiledClass the compiled {@link Class}
* @param compiledInstance the instance of the compiled {@link Class} or {@code null}
* if no instance was created and only static methods will be called
* by the the {@link ExecutionStrategy}.
* @param executionStrategy the {@link ExecutionStrategy}
*/
JavaCompiledScript(JavaScriptEngine engine, Class> compiledClass, Object compiledInstance, ExecutionStrategy executionStrategy) {
this.engine = engine;
this.compiledClass = compiledClass;
this.compiledInstance = compiledInstance;
this.executionStrategy = executionStrategy;
}
/**
* Returns the compiled {@link Class}.
*
* @return the compiled {@link Class}.
*/
public Class> getCompiledClass() {
return compiledClass;
}
/**
* Returns the instance of the compiled {@link Class}.
*
* @return the instance of the compiled {@link Class} or {@code null}
* if no instance was created and only static methods will be called
* by the the {@link ExecutionStrategy}.
*/
public Object getCompiledInstance() {
return compiledInstance;
}
/**
* Returns the compiled {@link Class}.
*
* @return the compiled {@link Class}.
* @deprecated in release 1.1.0 this method was deprecated,
* use {@link #getCompiledClass()} instead.
*/
@Deprecated(since = "1.1.0", forRemoval = true)
public Class> getInstanceClass() {
return getCompiledClass();
}
/**
* Returns the instance of the compiled {@link Class}.
*
* @return the instance of the compiled {@link Class} or {@code null}
* if no instance was created and only static methods will be called
* by the the {@link ExecutionStrategy}.
* @deprecated in release 1.1.0 this method was deprecated,
* use {@link #getCompiledInstance()} instead.
*/
@Deprecated(since = "1.1.0", forRemoval = true)
public Object getInstance() {
return getCompiledInstance();
}
/**
* Sets the {@link ExecutionStrategy} to be used when evaluating the compiled class instance.
*
* @param executionStrategy the {@link ExecutionStrategy}
*/
public void setExecutionStrategy(ExecutionStrategy executionStrategy) {
this.executionStrategy = executionStrategy;
}
@Override
public ScriptEngine getEngine() {
return engine;
}
@Override
public Object eval(ScriptContext context) throws ScriptException {
Bindings globalBindings = context.getBindings(ScriptContext.GLOBAL_SCOPE);
Bindings engineBindings = context.getBindings(ScriptContext.ENGINE_SCOPE);
pushVariables(globalBindings, engineBindings);
Object result = executionStrategy.execute(compiledInstance);
pullVariables(globalBindings, engineBindings);
return result;
}
private void pushVariables(Bindings globalBindings, Bindings engineBindings) throws ScriptException {
Map mergedBindings = mergeBindings(globalBindings, engineBindings);
for (Map.Entry entry : mergedBindings.entrySet()) {
String name = entry.getKey();
Object value = entry.getValue();
try {
Field field = compiledClass.getField(name);
field.set(compiledInstance, value);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new ScriptException(e);
}
}
}
private void pullVariables(Bindings globalBindings, Bindings engineBindings) throws ScriptException {
for (Field field : compiledClass.getFields()) {
try {
String name = field.getName();
Object value = field.get(compiledInstance);
setBindingsValue(globalBindings, engineBindings, name, value);
} catch (IllegalAccessException e) {
throw new ScriptException(e);
}
}
}
private void setBindingsValue(Bindings globalBindings, Bindings engineBindings, String name, Object value) {
if (!engineBindings.containsKey(name) && globalBindings.containsKey(name)) {
globalBindings.put(name, value);
} else {
engineBindings.put(name, value);
}
}
private Map mergeBindings(Bindings... bindingsToMerge) {
Map variables = new HashMap<>();
for (Bindings bindings : bindingsToMerge) {
if (bindings != null) {
for (Map.Entry globalEntry : bindings.entrySet()) {
variables.put(globalEntry.getKey(), globalEntry.getValue());
}
}
}
return variables;
}
}