mirror of
https://github.com/LamGC/Oracle-Sentry.git
synced 2025-04-29 14:17:34 +00:00
feat: 添加 ScriptComponentFactory 以允许通过该接口实例动态生成脚本组件.
通过 ScriptComponentFactory 接口, 可以根据脚本信息动态得构造一些特定于脚本的组件, 例如日志. 本次提交同时调整了 Groovy 脚本的初始化过程, 让 ScriptInfo 的初始化能够更先于脚本 Trigger 的运行.
This commit is contained in:
parent
c2aa02cae3
commit
2f225d27fe
@ -0,0 +1,22 @@
|
||||
package net.lamgc.oracle.sentry.script;
|
||||
|
||||
/**
|
||||
* 脚本组件工厂.
|
||||
* @author LamGC
|
||||
*/
|
||||
public interface ScriptComponentFactory<T> {
|
||||
|
||||
/**
|
||||
* 创建并获取实例.
|
||||
* @param info 脚本信息.
|
||||
* @return 返回对象.
|
||||
*/
|
||||
T getInstance(ScriptInfo info);
|
||||
|
||||
/**
|
||||
* 对象属性名.
|
||||
* @return 返回建议的对象属性名, {@link ScriptLoader} 并不一定遵守.
|
||||
*/
|
||||
String getPropertyName();
|
||||
|
||||
}
|
@ -2,12 +2,15 @@ package net.lamgc.oracle.sentry.script.groovy;
|
||||
|
||||
import groovy.lang.Closure;
|
||||
import groovy.lang.DelegatesTo;
|
||||
import net.lamgc.oracle.sentry.ComputeInstanceManager;
|
||||
import net.lamgc.oracle.sentry.script.Script;
|
||||
import net.lamgc.oracle.sentry.script.ScriptInfo;
|
||||
import net.lamgc.oracle.sentry.script.tools.http.ScriptHttpClient;
|
||||
import net.lamgc.oracle.sentry.script.groovy.trigger.GroovyTrigger;
|
||||
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Groovy DSL 脚本的父类.
|
||||
* @author LamGC
|
||||
@ -16,11 +19,14 @@ import org.codehaus.groovy.runtime.DefaultGroovyMethods;
|
||||
public class GroovyDslDelegate implements Script {
|
||||
|
||||
private final GroovyScriptInfo scriptInfo = new GroovyScriptInfo();
|
||||
private final GroovyScriptLoader scriptLoader;
|
||||
|
||||
/**
|
||||
* 构建一个 DSL Delegate, 并传入可操作对象.
|
||||
* @param scriptLoader 该脚本所属的加载器.
|
||||
*/
|
||||
public GroovyDslDelegate() {
|
||||
public GroovyDslDelegate(GroovyScriptLoader scriptLoader) {
|
||||
this.scriptLoader = scriptLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -29,7 +35,11 @@ public class GroovyDslDelegate implements Script {
|
||||
* @param closure 待执行闭包.
|
||||
*/
|
||||
private void trigger(String triggerName, Closure<?> closure){
|
||||
DefaultGroovyMethods.with(GroovyTriggerProvider.INSTANCE.getTriggerByName(triggerName), closure);
|
||||
if (!scriptLoader.isInitialed(this)) {
|
||||
return;
|
||||
}
|
||||
GroovyTrigger trigger = GroovyTriggerProvider.INSTANCE.getTriggerByName(triggerName);
|
||||
DefaultGroovyMethods.with(trigger, closure);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.lamgc.oracle.sentry.script.groovy;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Throwables;
|
||||
import groovy.lang.Binding;
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
@ -8,6 +9,7 @@ import net.lamgc.oracle.sentry.script.Script;
|
||||
import net.lamgc.oracle.sentry.script.ScriptComponents;
|
||||
import net.lamgc.oracle.sentry.script.ScriptInfo;
|
||||
import net.lamgc.oracle.sentry.script.ScriptLoader;
|
||||
import net.lamgc.oracle.sentry.script.ScriptComponentFactory;
|
||||
import org.codehaus.groovy.control.CompilerConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -17,7 +19,9 @@ import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
@ -30,8 +34,8 @@ public class GroovyScriptLoader implements ScriptLoader {
|
||||
private final static Logger log = LoggerFactory.getLogger(GroovyScriptLoader.class);
|
||||
|
||||
private final GroovyClassLoader scriptClassLoader;
|
||||
|
||||
private final Map<Script, ScriptInfo> scriptInfoMap = new ConcurrentHashMap<>();
|
||||
private final Set<Script> initialedScript = new HashSet<>();
|
||||
|
||||
/**
|
||||
* 构造一个新的脚本加载器.
|
||||
@ -58,11 +62,17 @@ public class GroovyScriptLoader implements ScriptLoader {
|
||||
Constructor<? extends DelegatingScript> constructor =
|
||||
scriptClass.asSubclass(DelegatingScript.class).getConstructor();
|
||||
DelegatingScript newScriptObject = constructor.newInstance();
|
||||
GroovyDslDelegate dslDelegate = new GroovyDslDelegate();
|
||||
GroovyDslDelegate dslDelegate = new GroovyDslDelegate(this);
|
||||
newScriptObject.setDelegate(dslDelegate);
|
||||
newScriptObject.setBinding(createBinding(context));
|
||||
newScriptObject.run();
|
||||
scriptInfoMap.put(dslDelegate, dslDelegate.getScriptInfo());
|
||||
ScriptInfo scriptInfo = dslDelegate.getScriptInfo();
|
||||
if (!checkScriptInfo(scriptInfo)) {
|
||||
return null;
|
||||
}
|
||||
initialedScript.add(dslDelegate);
|
||||
newScriptObject.setBinding(createBinding(context, scriptInfo));
|
||||
newScriptObject.run();
|
||||
scriptInfoMap.put(dslDelegate, scriptInfo);
|
||||
return dslDelegate;
|
||||
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
log.error("加载脚本时发生异常.(ScriptPath: {})\n{}", scriptFile.getAbsolutePath(), Throwables.getStackTraceAsString(e));
|
||||
@ -75,18 +85,48 @@ public class GroovyScriptLoader implements ScriptLoader {
|
||||
return scriptInfoMap.get(script);
|
||||
}
|
||||
|
||||
private static Binding createBinding(ScriptComponents components) {
|
||||
/**
|
||||
* 检查脚本是否已经初始化完毕.
|
||||
* @param script 脚本对象.
|
||||
* @return 如果已初始化完毕, 返回 {@code true}.
|
||||
*/
|
||||
public boolean isInitialed(GroovyDslDelegate script) {
|
||||
return initialedScript.contains(script);
|
||||
}
|
||||
|
||||
private static Binding createBinding(ScriptComponents components, ScriptInfo info) {
|
||||
Binding binding = new Binding();
|
||||
for (Field field : components.getClass().getDeclaredFields()) {
|
||||
try {
|
||||
String name = field.getName();
|
||||
field.setAccessible(true);
|
||||
Object o = field.get(components);
|
||||
binding.setProperty(name, o);
|
||||
if (o instanceof ScriptComponentFactory factory) {
|
||||
binding.setProperty(factory.getPropertyName(), factory.getInstance(info));
|
||||
} else {
|
||||
binding.setProperty(name, o);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return binding;
|
||||
}
|
||||
|
||||
private static boolean checkScriptInfo(ScriptInfo info) {
|
||||
if (Strings.isNullOrEmpty(info.getGroup())) {
|
||||
log.warn("脚本信息缺少 {}, 跳过加载.", "Group");
|
||||
return false;
|
||||
}
|
||||
if (Strings.isNullOrEmpty(info.getName())) {
|
||||
log.warn("脚本信息缺少 {}, 跳过加载.", "Name");
|
||||
return false;
|
||||
}
|
||||
if (Strings.isNullOrEmpty(info.getVersion())) {
|
||||
log.warn("脚本信息缺少 {}, 跳过加载.", "Version");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user