This is an automated email from the ASF dual-hosted git repository. zhaoqingran pushed a commit to branch script in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
commit 4904b7f615596151b5b1afd47e6822dc3066e2d7 Author: zqr10159 <[email protected]> AuthorDate: Sat Aug 31 11:26:18 2024 +0800 init --- .../hertzbeat/common/constants/ScriptTypeEnum.java | 78 +++++++++++++++++ .../impl => plugin}/DefaultPluginRunner.java | 13 ++- .../manager/plugin/ScriptBeanManager.java | 20 +++++ .../manager/plugin/ScriptExecuteWrap.java | 97 ++++++++++++++++++++++ .../hertzbeat/manager/plugin/ScriptExecutor.java | 39 +++++++++ .../manager/plugin/ScriptExecutorFactory.java | 72 ++++++++++++++++ .../plugin/executor/JSR223ScriptExecutor.java | 84 +++++++++++++++++++ .../plugin/executor/JavaScriptExecutor.java | 38 +++++++++ .../manager/plugin/validator/ScriptValidator.java | 95 +++++++++++++++++++++ .../support/exception/ScriptLoadException.java | 30 +++++++ .../support/exception/ScriptSpiException.java | 29 +++++++ .../hertzbeat/manager/plugin/PluginScriptTest.java | 73 ++++++++++++++++ .../hertzbeat/plugin/runner/PluginRunner.java | 8 ++ 13 files changed, 675 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/apache/hertzbeat/common/constants/ScriptTypeEnum.java b/common/src/main/java/org/apache/hertzbeat/common/constants/ScriptTypeEnum.java new file mode 100644 index 000000000..1e1c14467 --- /dev/null +++ b/common/src/main/java/org/apache/hertzbeat/common/constants/ScriptTypeEnum.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.common.constants; + +import lombok.Getter; + +/** + * This code references dromara/liteflow, thanks to the author Bryan. + */ +@Getter +public enum ScriptTypeEnum { + + CUSTOM("custom", "custom"), + GROOVY("groovy", "groovy"), + QLEXPRESS("qlexpress", "qlexpress"), + JS("javascript", "js"), + PYTHON("python", "python"), + LUA("luaj", "lua"), + AVIATOR("AviatorScript", "aviator"), + JAVA("java", "java"), + KOTLIN("kotlin", "kotlin"); + + private String engineName; + + private String displayName; + + ScriptTypeEnum(String engineName, String displayName) { + this.engineName = engineName; + this.displayName = displayName; + } + + public void setEngineName(String engineName) { + this.engineName = engineName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public static ScriptTypeEnum getEnumByDisplayName(String displayName) { + for (ScriptTypeEnum e : ScriptTypeEnum.values()) { + if (e.getDisplayName().equals(displayName)) { + return e; + } + } + return null; + } + + /** + * 校验脚本类型是否合法 + * @param scriptType 脚本类型 + * @return true:合法,false:不合法 + */ + public static boolean checkScriptType(String scriptType) { + for (ScriptTypeEnum e : ScriptTypeEnum.values()) { + if (e.getDisplayName().equals(scriptType)) { + return true; + } + } + return false; + } + +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/DefaultPluginRunner.java b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/DefaultPluginRunner.java similarity index 87% rename from manager/src/main/java/org/apache/hertzbeat/manager/service/impl/DefaultPluginRunner.java rename to manager/src/main/java/org/apache/hertzbeat/manager/plugin/DefaultPluginRunner.java index 7add67d56..895de327d 100644 --- a/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/DefaultPluginRunner.java +++ b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/DefaultPluginRunner.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.hertzbeat.manager.service.impl; +package org.apache.hertzbeat.manager.plugin; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -54,4 +54,15 @@ public class DefaultPluginRunner implements PluginRunner { log.error("plugin execute failed", e); } } + + /** + * execute script + * + * @param clazz plugin class + * @param execute script execution logic + */ + @Override + public <T> void scriptExecute(Class<T> clazz, Consumer<T> execute) { + + } } diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptBeanManager.java b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptBeanManager.java new file mode 100644 index 000000000..c16e96594 --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptBeanManager.java @@ -0,0 +1,20 @@ +package org.apache.hertzbeat.manager.plugin; + +import java.util.HashMap; +import java.util.Map; +import lombok.Getter; + +/** + * The Script Bean Manager + * This code references dromara/liteflow, thanks to the author Bryan. + */ +public class ScriptBeanManager { + + @Getter + private static final Map<String, Object> scriptBeanMap = new HashMap<>(); + + public static void addScriptBean(String key, Object bean) { + scriptBeanMap.put(key, bean); + } + +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptExecuteWrap.java b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptExecuteWrap.java new file mode 100644 index 000000000..eaff72429 --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptExecuteWrap.java @@ -0,0 +1,97 @@ +package org.apache.hertzbeat.manager.plugin; + + +/** + * the wrapper meta parameters before script execution + * This code references dromara/liteflow, thanks to the author Bryan. + */ +public class ScriptExecuteWrap { + + public int slotIndex; + + public String currChainId; + + public String nodeId; + + public String tag; + + public Object cmpData; + + public Integer loopIndex; + + public Object loopObject; + + + public int getSlotIndex() { + return slotIndex; + } + + public void setSlotIndex(int slotIndex) { + this.slotIndex = slotIndex; + } + + /** + * @deprecated 请使用 {@link #getCurrChainId()} + * @return String + */ + @Deprecated + public String getCurrChainName() { + return currChainId; + } + + /** + * @deprecated 请使用{@link #setCurrChainId(String)} + */ + public void setCurrChainName(String currChainName) { + this.currChainId = currChainName; + } + + public String getCurrChainId() { + return currChainId; + } + + public void setCurrChainId(String currChainId) { + this.currChainId = currChainId; + } + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public Object getCmpData() { + return cmpData; + } + + public void setCmpData(Object cmpData) { + this.cmpData = cmpData; + } + + public Integer getLoopIndex() { + return loopIndex; + } + + public void setLoopIndex(Integer loopIndex) { + this.loopIndex = loopIndex; + } + + public Object getLoopObject() { + return loopObject; + } + + public void setLoopObject(Object loopObject) { + this.loopObject = loopObject; + } + +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptExecutor.java b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptExecutor.java new file mode 100644 index 000000000..43752adba --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptExecutor.java @@ -0,0 +1,39 @@ +package org.apache.hertzbeat.manager.plugin; + +import org.apache.hertzbeat.common.constants.ScriptTypeEnum; + +/** + * script executor interface + * This code references dromara/liteflow, thanks to the author Bryan. + */ +public abstract class ScriptExecutor { + + public ScriptExecutor init(){ + return this; + } + + public abstract void load(String nodeId, String script); + + public abstract void unLoad(String nodeId); + + + public Object execute(ScriptExecuteWrap wrap) throws Exception{ + return executeScript(wrap); + } + + public abstract Object executeScript(ScriptExecuteWrap wrap) throws Exception; + + public abstract void cleanCache(); + + public abstract ScriptTypeEnum scriptType(); + + + /** + * compile script + * + * @param script script content + * @return boolean + * @throws Exception if compile failed + */ + public abstract Object compile(String script) throws Exception; +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptExecutorFactory.java b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptExecutorFactory.java new file mode 100644 index 000000000..ea824f10e --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/ScriptExecutorFactory.java @@ -0,0 +1,72 @@ +package org.apache.hertzbeat.manager.plugin; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.ServiceLoader; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.hertzbeat.common.constants.ScriptTypeEnum; +import org.apache.hertzbeat.manager.support.exception.ScriptSpiException; + +/** + * Script executor factory class + * This code references dromara/liteflow, thanks to the author Bryan. + */ +public class ScriptExecutorFactory { + + private static ScriptExecutorFactory scriptExecutorFactory; + + private final Map<String, ScriptExecutor> scriptExecutorMap = new HashMap<>(); + + private final String NONE_LANGUAGE = "none"; + + public static ScriptExecutorFactory loadInstance() { + if (ObjectUtils.anyNull(scriptExecutorFactory)) { + scriptExecutorFactory = new ScriptExecutorFactory(); + } + return scriptExecutorFactory; + } + + public ScriptExecutor getScriptExecutor(String language) { + if (StringUtils.isBlank(language)) { + language = NONE_LANGUAGE; + } + + if (!scriptExecutorMap.containsKey(language)) { + ServiceLoader<ScriptExecutor> loader = ServiceLoader.load(ScriptExecutor.class); + + ScriptExecutor scriptExecutor; + Iterator<ScriptExecutor> it = loader.iterator(); + while (it.hasNext()) { + scriptExecutor = it.next().init(); + if (language.equals(NONE_LANGUAGE)) { + scriptExecutorMap.put(language, scriptExecutor); + break; + } + else { + ScriptTypeEnum scriptType = ScriptTypeEnum.getEnumByDisplayName(language); + if (ObjectUtils.anyNull(scriptType)) { + throw new ScriptSpiException("script language config error"); + } + if (scriptType != null && scriptType.equals(scriptExecutor.scriptType())) { + scriptExecutorMap.put(language, scriptExecutor); + break; + } + } + } + } + + if (scriptExecutorMap.containsKey(language)) { + return scriptExecutorMap.get(language); + } + else { + throw new ScriptSpiException("script spi component failed to load"); + } + } + + public void cleanScriptCache() { + this.scriptExecutorMap.forEach((key, value) -> value.cleanCache()); + } + +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/plugin/executor/JSR223ScriptExecutor.java b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/executor/JSR223ScriptExecutor.java new file mode 100644 index 000000000..57314916f --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/executor/JSR223ScriptExecutor.java @@ -0,0 +1,84 @@ +package org.apache.hertzbeat.manager.plugin.executor; + + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import javax.script.Bindings; +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.script.SimpleBindings; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.manager.plugin.ScriptExecuteWrap; +import org.apache.hertzbeat.manager.plugin.ScriptExecutor; +import org.apache.hertzbeat.manager.support.exception.ScriptLoadException; + +/** + * JSR223 script engine + * This code references dromara/liteflow, thanks to the author Bryan. + */ +@Slf4j +public abstract class JSR223ScriptExecutor extends ScriptExecutor { + + + private ScriptEngine scriptEngine; + + private final Map<String, CompiledScript> compiledScriptMap = new ConcurrentHashMap<>(); + + @Override + public ScriptExecutor init() { + ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); + scriptEngine = scriptEngineManager.getEngineByName(this.scriptType().getEngineName()); + return this; + } + + protected String convertScript(String script) { + return script; + } + + @Override + public void load(String nodeId, String script) { + try { + compiledScriptMap.put(nodeId, (CompiledScript) compile(script)); + } + catch (Exception e) { + String errorMsg = String.format("script loading error for node[%s], error msg:%s", nodeId, e.getMessage()); + throw new ScriptLoadException(errorMsg); + } + } + + @Override + public void unLoad(String nodeId) { + compiledScriptMap.remove(nodeId); + } + + + @Override + public Object executeScript(ScriptExecuteWrap wrap) throws Exception { + if (!compiledScriptMap.containsKey(wrap.getNodeId())) { + String errorMsg = String.format("script for node[%s] is not loaded", wrap.getNodeId()); + throw new ScriptLoadException(errorMsg); + } + + CompiledScript compiledScript = compiledScriptMap.get(wrap.getNodeId()); + Bindings bindings = new SimpleBindings(); + + return compiledScript.eval(bindings); + } + + @Override + public void cleanCache() { + compiledScriptMap.clear(); + } + + @Override + public Object compile(String script) throws ScriptException { + if(scriptEngine == null) { + log.error("script engine has not init"); + } + return ((Compilable) scriptEngine).compile(convertScript(script)); + } + +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/plugin/executor/JavaScriptExecutor.java b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/executor/JavaScriptExecutor.java new file mode 100644 index 000000000..08d98f650 --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/executor/JavaScriptExecutor.java @@ -0,0 +1,38 @@ +/* + * + * * Licensed to the Apache Software Foundation (ASF) under one or more + * * contributor license agreements. See the NOTICE file distributed with + * * this work for additional information regarding copyright ownership. + * * The ASF licenses this file to You under the Apache License, Version 2.0 + * * (the "License"); you may not use this file except in compliance with + * * the License. You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package org.apache.hertzbeat.manager.plugin.executor; + +import org.apache.hertzbeat.common.constants.ScriptTypeEnum; + +/** + * This class is used to execute JavaScript code in the plugin. + * This code references liteflow, thanks to the author Bryan. + */ +public class JavaScriptExecutor extends JSR223ScriptExecutor { + @Override + protected String convertScript(String script) { + return String.format("function process(){%s} process();", script); + } + + @Override + public ScriptTypeEnum scriptType() { + return ScriptTypeEnum.JS; + } +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/plugin/validator/ScriptValidator.java b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/validator/ScriptValidator.java new file mode 100644 index 000000000..8dbce562f --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/plugin/validator/ScriptValidator.java @@ -0,0 +1,95 @@ +package org.apache.hertzbeat.manager.plugin.validator; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.common.constants.ScriptTypeEnum; +import org.apache.hertzbeat.manager.plugin.ScriptExecutor; + +/** + * Script validator class + * This code references dromara/liteflow, thanks to the author Ge_Zuao. + */ +@Slf4j +public class ScriptValidator { + + private static final Map<ScriptTypeEnum, ScriptExecutor> scriptExecutors; + + static { + List<ScriptExecutor> scriptExecutorList = new ArrayList<>(); + scriptExecutors = new HashMap<>(); + ServiceLoader.load(ScriptExecutor.class).forEach(scriptExecutorList::add); + scriptExecutorList.stream() + .peek(ScriptExecutor::init) + .forEach(scriptExecutor -> scriptExecutors.put(scriptExecutor.scriptType(), scriptExecutor)); + } + + /** + * 验证脚本逻辑的公共部分 + * + * @param script 脚本 + * @param scriptType 脚本类型 + * @return boolean + */ + private static boolean validateScript(String script, ScriptTypeEnum scriptType){ + + if(scriptExecutors.isEmpty()){ + log.error("The loaded script modules not found."); + return false; + } + + if (scriptType != null && !scriptExecutors.containsKey(scriptType)) { + log.error(String.format("Specified script language %s was not found.", scriptType)); + return false; + } + + if (scriptExecutors.size() > 1 && scriptType == null) { + log.error("The loaded script modules more than 1. Please specify the script language."); + return false; + } + + ScriptExecutor scriptExecutor = (scriptType != null) ? scriptExecutors.get(scriptType) : scriptExecutors.values().iterator().next(); + try { + scriptExecutor.compile(script); + } catch (Exception e) { + log.error(String.format("%s Script component validate failure. ", scriptExecutor.scriptType()) + e.getMessage()); + return false; + } + return true; + } + + /** + * @param script script + * @return boolean + */ + public static boolean validate(String script){ + return validateScript(script, null); + } + + /** + * + * @param script script + * @param scriptType scriptType + * @return boolean + */ + public static boolean validate(String script, ScriptTypeEnum scriptType){ + return validateScript(script, scriptType); + } + + /** + * + * @param scripts scripts + * @return boolean + */ + public static boolean validate(Map<ScriptTypeEnum, String> scripts){ + for(Map.Entry<ScriptTypeEnum, String> script : scripts.entrySet()){ + if(!validate(script.getValue(), script.getKey())){ + return false; + } + } + return true; + } +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/support/exception/ScriptLoadException.java b/manager/src/main/java/org/apache/hertzbeat/manager/support/exception/ScriptLoadException.java new file mode 100644 index 000000000..d4094805d --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/support/exception/ScriptLoadException.java @@ -0,0 +1,30 @@ + +package org.apache.hertzbeat.manager.support.exception; + +import java.io.Serial; + +/** + * scrip load exception + * This code references dromara/liteflow, thanks to the author Bryan. + */ +public class ScriptLoadException extends RuntimeException { + + @Serial + private static final long serialVersionUID = 1L; + + private String message; + + public ScriptLoadException(String message) { + this.message = message; + } + + @Override + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + +} diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/support/exception/ScriptSpiException.java b/manager/src/main/java/org/apache/hertzbeat/manager/support/exception/ScriptSpiException.java new file mode 100644 index 000000000..f9232a46e --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/support/exception/ScriptSpiException.java @@ -0,0 +1,29 @@ + +package org.apache.hertzbeat.manager.support.exception; + +import java.io.Serial; + +/** + * Script SPI plugin loading exception + * This code references dromara/liteflow, thanks to the author Bryan. + */ +public class ScriptSpiException extends RuntimeException { + + @Serial + private static final long serialVersionUID = 1L; + + private String message; + + public ScriptSpiException(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + +} diff --git a/manager/src/test/java/org/apache/hertzbeat/manager/plugin/PluginScriptTest.java b/manager/src/test/java/org/apache/hertzbeat/manager/plugin/PluginScriptTest.java new file mode 100644 index 000000000..7d4a81013 --- /dev/null +++ b/manager/src/test/java/org/apache/hertzbeat/manager/plugin/PluginScriptTest.java @@ -0,0 +1,73 @@ +/* + * + * * Licensed to the Apache Software Foundation (ASF) under one or more + * * contributor license agreements. See the NOTICE file distributed with + * * this work for additional information regarding copyright ownership. + * * The ASF licenses this file to You under the Apache License, Version 2.0 + * * (the "License"); you may not use this file except in compliance with + * * the License. You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package org.apache.hertzbeat.manager.plugin; + +import org.apache.hertzbeat.common.constants.ScriptTypeEnum; +import org.apache.hertzbeat.manager.plugin.validator.ScriptValidator; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * Test case for {@link ScriptExecutor} + */ + +public class PluginScriptTest { + @Test + public void testJavaScriptScriptComponentValidateFunction(){ + String correctScript = "var a=3;\n" + + " var b=2;\n" + + " var c=1;\n" + + " var d=5;\n" + + "\n" + + " function addByArray(values) {\n" + + " var sum = 0;\n" + + " for (var i = 0; i < values.length; i++) {\n" + + " sum += values[i];\n" + + " }\n" + + " return sum;\n" + + " }\n" + + "\n" + + " var result = addByArray([a,b,c,d]);\n" + + "\n" + + " defaultContext.setData(\"s1\",parseInt(result));"; + + String wrongScript = "var a=3;\n" + + " var b=2;\n" + + " var c=1;\n" + + " var d=5;\n" + + "\n" + + " fon addByArray(values) {\n" + + " var sum = 0;\n" + + " for (var i = 0; i < values.length; i++) {\n" + + " sum += values[i];\n" + + " }\n" + + " return sum;\n" + + " }\n" + + "\n" + + " var result = addByArray([a,b,c,d]);\n" + + "\n" + + " defaultContext.setData(\"s1\",parseInt(result));"; + Assertions.assertTrue(ScriptValidator.validate(correctScript)); + Assertions.assertFalse(ScriptValidator.validate(wrongScript)); + + Assertions.assertTrue(ScriptValidator.validate(correctScript, ScriptTypeEnum.JS)); + Assertions.assertFalse(ScriptValidator.validate(correctScript, ScriptTypeEnum.JAVA)); + } +} diff --git a/plugin/src/main/java/org/apache/hertzbeat/plugin/runner/PluginRunner.java b/plugin/src/main/java/org/apache/hertzbeat/plugin/runner/PluginRunner.java index 7f3e00930..df25ff3b1 100644 --- a/plugin/src/main/java/org/apache/hertzbeat/plugin/runner/PluginRunner.java +++ b/plugin/src/main/java/org/apache/hertzbeat/plugin/runner/PluginRunner.java @@ -43,4 +43,12 @@ public interface PluginRunner { */ <T> void pluginExecute(Class<T> clazz, BiConsumer<T, PluginContext> execute); + /** + * execute script + * @param clazz plugin class + * @param execute script execution logic + * @param <T> script type + */ + <T> void scriptExecute(Class<T> clazz, Consumer<T> execute); + } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
