org.zodiac.script.engine.common.CommonScriptEngine Maven / Gradle / Ivy
package org.zodiac.script.engine.common;
import org.zodiac.script.engine.ExecuteResult;
import org.zodiac.script.engine.ListenerSupportEngine;
import org.zodiac.script.engine.ScriptListener;
import org.zodiac.sdk.toolkit.crypto.Md5;
import org.zodiac.sdk.toolkit.util.SystemClock;
import org.zodiac.sdk.toolkit.util.collection.CollUtil;
import org.zodiac.sdk.toolkit.util.lang.ArrayUtil;
import org.zodiac.sdk.toolkit.util.lang.ObjUtil;
import java.util.List;
import java.util.Map;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;
public abstract class CommonScriptEngine extends ListenerSupportEngine {
/*编译器。*/
protected Compilable compilable;
/*脚本库。*/
protected Map scriptBase = CollUtil.concurrentMap();
protected Bindings utilBindings;
protected List scriptListeners;
protected CommonScriptEngine() {
try {
init();
} catch (Exception e) {
logger.warn("Init {} error", getScriptEngineName());
}
}
@Override
public boolean compiled(String id) {
return scriptBase.containsKey(id);
}
@Override
public boolean remove(String id) {
return scriptBase.remove(id) != null;
}
@Override
public void init(String... contents) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName(getScriptEngineName());
compilable = (Compilable)engine;
utilBindings = engine.createBindings();
CompiledScript script;
if (ArrayUtil.isNotEmptyArray(contents)) {
for (String content : contents) {
script = compilable.compile(content);
script.eval(utilBindings);
}
}
// scriptBase.clear();
}
@Override
public org.zodiac.script.engine.ScriptContext getContext(String id) {
return scriptBase.get(id);
}
@Override
public boolean compile(String id, String code) throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("Compile {} {} : {}", getScriptEngineName(), id, code);
}
if (compilable == null)
init();
CompiledScript compiledScript = compilable.compile(code);
CommonScriptContext scriptContext = new CommonScriptContext(id, Md5.md5Hex(code), compiledScript);
scriptBase.put(id, scriptContext);
return true;
}
@Override
public void addListener(ScriptListener scriptListener) {
scriptListeners = ObjUtil.defaultIfNull(scriptListeners, CollUtil.linkedList());
scriptListeners.add(scriptListener);
}
@Override
public ExecuteResult execute(String id) {
return execute(id, CollUtil.map());
}
@Override
public ExecuteResult execute(String id, Map param) {
long startTime = SystemClock.nowTimeMillis();
if (logger.isDebugEnabled()) {
logger.debug("Execute {} {} : {}", getScriptEngineName(), id);
}
ExecuteResult result = new ExecuteResult();
CommonScriptContext scriptContext = scriptBase.get(id);
try {
if (scriptContext != null) {
doListenerBefore(scriptContext);
ScriptContext context = new SimpleScriptContext();
context.setBindings(utilBindings, ScriptContext.GLOBAL_SCOPE);
for (Map.Entry entry : param.entrySet()) {
context.setAttribute(entry.getKey(), entry.getValue(), ScriptContext.ENGINE_SCOPE);
}
result.setResult(scriptContext.getScript().eval(context)).setSuccess(true);
} else {
result.setSuccess(false).setMessage(String.format("script(%s): %s not found!", getScriptEngineName(), id));
}
} catch (ScriptException e) {
result.setException(e);
}
result.setUseTime(SystemClock.nowTimeMillis() - startTime);
doListenerAfter(scriptContext, result);
return result;
}
@Override
public void addGlobalVariable(Map vars) {
utilBindings.putAll(vars);
}
protected class CommonScriptContext extends org.zodiac.script.engine.ScriptContext {
private CompiledScript script;
public CommonScriptContext(String id, String md5, CompiledScript script) {
super(id, md5);
this.script = script;
}
public CompiledScript getScript() {
return script;
}
}
public Bindings getUtilBindings() {
return utilBindings;
}
public void setUtilBindings(Bindings utilBindings) {
this.utilBindings = utilBindings;
}
}