keycloak-scim/services/src/main/java/org/keycloak/scripting/AbstractEvaluatableScriptAdapter.java
Jay Anslow 7614ff8c6f Extract EvaluatebleScriptAdapter
Precursor for InvocableScriptAdapter, which compiles/evaluates a script without affecting the engine's bindings. This allows the same script to be compiled once and then evaluated multiple times (with the same ScriptEngine).
2017-06-19 15:32:14 +01:00

76 lines
2.5 KiB
Java

package org.keycloak.scripting;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import org.keycloak.models.ScriptModel;
/**
* Abstract class for wrapping a {@link ScriptModel} to make it evaluatable.
*
* @author <a href="mailto:jay@anslow.me.uk">Jay Anslow</a>
*/
abstract class AbstractEvaluatableScriptAdapter implements EvaluatableScriptAdapter {
/**
* Holds the {@link ScriptModel}.
*/
private final ScriptModel scriptModel;
AbstractEvaluatableScriptAdapter(final ScriptModel scriptModel) {
if (scriptModel == null) {
throw new IllegalArgumentException("scriptModel must not be null");
}
this.scriptModel = scriptModel;
}
@Override
public Object eval(final ScriptBindingsConfigurer bindingsConfigurer) throws ScriptExecutionException {
return evalUnchecked(createBindings(bindingsConfigurer));
}
@Override
public ScriptModel getScriptModel() {
return scriptModel;
}
/**
* Note, calling this method modifies the underlying {@link ScriptEngine},
* preventing concurrent use of the ScriptEngine (Nashorn's {@link ScriptEngine} and
* {@link javax.script.CompiledScript} is thread-safe, but {@link Bindings} isn't).
*/
InvocableScriptAdapter prepareInvokableScript(final ScriptBindingsConfigurer bindingsConfigurer) {
final Bindings bindings = createBindings(bindingsConfigurer);
evalUnchecked(bindings);
final ScriptEngine engine = getEngine();
engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
return new InvocableScriptAdapter(scriptModel, engine);
}
protected String getCode() {
return scriptModel.getCode();
}
protected abstract ScriptEngine getEngine();
protected abstract Object eval(Bindings bindings) throws ScriptException;
private Object evalUnchecked(final Bindings bindings) {
try {
return eval(bindings);
}
catch (ScriptException e) {
throw new ScriptExecutionException(scriptModel, e);
}
}
private Bindings createBindings(final ScriptBindingsConfigurer bindingsConfigurer) {
if (bindingsConfigurer == null) {
throw new IllegalArgumentException("bindingsConfigurer must not be null");
}
final Bindings bindings = getEngine().createBindings();
bindingsConfigurer.configureBindings(bindings);
return bindings;
}
}