feat(plugins): 实现插件系统并优化加载过程
- 新增 BoxClassLoader、IClassTransformer、LoadingCorePlugin 等核心类 - 重构 Main 类,采用多线程和 ProgressBarManager 优化加载过程 - 完善 PluginLoader 类,支持核心插件和字节码转换器的加载- 重定向系统输出到 Log4j2,提高日志管理的灵活性
This commit is contained in:
14
build.gradle
14
build.gradle
@@ -24,11 +24,8 @@ repositories {
|
||||
dependencies {
|
||||
testImplementation platform('org.junit:junit-bom:5.10.0')
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||
// https://mvnrepository.com/artifact/org.commonmark/commonmark
|
||||
implementation 'org.commonmark:commonmark:0.24.0'
|
||||
// https://mvnrepository.com/artifact/org.commonjava.googlecode.markdown4j/markdown4j
|
||||
implementation 'org.commonjava.googlecode.markdown4j:markdown4j:2.2-cj-1.1'
|
||||
// https://mvnrepository.com/artifact/com.google.code.gson/gson
|
||||
implementation 'com.google.code.gson:gson:2.8.9'
|
||||
|
||||
implementation 'org.apache.logging.log4j:log4j-api:2.20.0'
|
||||
@@ -42,16 +39,19 @@ dependencies {
|
||||
implementation 'org.ow2.asm:asm-tree:7.1'
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass = 'com.axis.innovators.box.Main'
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes 'Main-Class': 'com.axis.innovators.box.Main'
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass = 'com.axis.innovators.box.Main'
|
||||
applicationDefaultJvmArgs = [
|
||||
"-Djava.system.class.loader=com.axis.innovators.box.plugins.BoxClassLoader"
|
||||
]
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.axis.innovators.box;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* 将输出传递给 Log4j2 的日志记录器
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class Log4j2OutputStream extends OutputStream {
|
||||
private static final Logger logger = LogManager.getLogger(Log4j2OutputStream.class);
|
||||
|
||||
@Override
|
||||
public void write(int b) {
|
||||
logger.info(String.valueOf((char) b));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) {
|
||||
logger.info(new String(b, off, len));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重定向 System.out 和 System.err 到 Log4j2
|
||||
*/
|
||||
public static void redirectSystemStreams() {
|
||||
System.setOut(new PrintStream(new Log4j2OutputStream()));
|
||||
System.setErr(new PrintStream(new Log4j2OutputStream()));
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,7 @@ package com.axis.innovators.box;
|
||||
import com.axis.innovators.box.events.GlobalEventBus;
|
||||
import com.axis.innovators.box.events.SettingsLoadEvents;
|
||||
import com.axis.innovators.box.events.SubscribeEvent;
|
||||
import com.axis.innovators.box.gui.FridaWindow;
|
||||
import com.axis.innovators.box.gui.LocalWindow;
|
||||
import com.axis.innovators.box.gui.MainWindow;
|
||||
import com.axis.innovators.box.gui.LoadIcon;
|
||||
import com.axis.innovators.box.gui.*;
|
||||
import com.axis.innovators.box.plugins.PluginLoader;
|
||||
import com.axis.innovators.box.tools.LibraryLoad;
|
||||
import com.axis.innovators.box.tools.SystemInfoUtil;
|
||||
@@ -29,9 +26,10 @@ public class Main {
|
||||
"tzdwindows 7"
|
||||
};
|
||||
/** 我是总任务数 **/
|
||||
public static int totalTasks = 1;
|
||||
public static int totalTasks = 0;
|
||||
/** 我是当前任务数 **/
|
||||
public static int completedTasks = 0;
|
||||
public static ProgressBarManager progressBarManager = new ProgressBarManager("加载中...", totalTasks);
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -52,6 +50,7 @@ public class Main {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Log4j2OutputStream.redirectSystemStreams();
|
||||
// 输出版本和作者信息
|
||||
logger.info("Application Version: {}", VERSIONS);
|
||||
logger.info("Authors: {}", String.join(", ", AUTHOR));
|
||||
@@ -61,6 +60,11 @@ public class Main {
|
||||
logger.info("OS Architecture: {}", SystemInfoUtil.getOSArch());
|
||||
logger.info("CPU: {}", SystemInfoUtil.getCPUInfo());
|
||||
logger.info("GPU: {}", SystemInfoUtil.getGPUInfo());
|
||||
logger.info("Java Version: {}", System.getProperty("java.version"));
|
||||
logger.info("Java Vendor: {}", System.getProperty("java.vendor"));
|
||||
logger.info("Java Home: {}", System.getProperty("java.home"));
|
||||
logger.info("Java Class Path: {}", System.getProperty("java.class.path"));
|
||||
logger.info("ClassLoader.getSystemClassLoader(): {}", ClassLoader.getSystemClassLoader());
|
||||
|
||||
// 注册事件
|
||||
GlobalEventBus.EVENT_BUS.register(new Main());
|
||||
@@ -71,109 +75,66 @@ public class Main {
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to load the system facade class", e);
|
||||
}
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
// 主任务1:加载插件
|
||||
progressBarManager.updateMainProgress(++completedTasks);
|
||||
PluginLoader.loadPlugins();
|
||||
logger.info("Loaded plugins");
|
||||
|
||||
JFrame loadingFrame = new JFrame("加载中...");
|
||||
loadingFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
loadingFrame.setSize(400, 200);
|
||||
loadingFrame.setLocationRelativeTo(null);
|
||||
loadingFrame.setIconImage(LoadIcon.loadIcon("logo.png", 64).getImage());
|
||||
progressBarManager.close();
|
||||
|
||||
JPanel loadingPanel = new JPanel(new BorderLayout());
|
||||
JProgressBar progressBar = new JProgressBar(0, 100);
|
||||
progressBar.setStringPainted(true);
|
||||
JLabel statusLabel = new JLabel("Initializing...", SwingConstants.CENTER);
|
||||
JLabel timeLabel = new JLabel("Time elapsed: 0s", SwingConstants.CENTER);
|
||||
JLabel logoLabel = new JLabel(LoadIcon.loadIcon("logo.png", 64));
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
MainWindow ex = new MainWindow();
|
||||
int id = 0;
|
||||
MainWindow.ToolCategory debugCategory = new MainWindow.ToolCategory("调试工具",
|
||||
"debug/debug.png",
|
||||
"用于调试指定Windows工具的一个分类");
|
||||
|
||||
loadingPanel.add(logoLabel, BorderLayout.NORTH);
|
||||
loadingPanel.add(progressBar, BorderLayout.CENTER);
|
||||
loadingPanel.add(statusLabel, BorderLayout.SOUTH);
|
||||
loadingPanel.add(timeLabel, BorderLayout.SOUTH);
|
||||
debugCategory.addTool(new MainWindow.ToolItem("Frida注入工具", "debug/frida/frida_main.png",
|
||||
"使用frida注入目标进程的脚本程序 " +
|
||||
"\n作者:tzdwindows 7", ++id, new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Window owner = SwingUtilities.windowForComponent((Component) e.getSource());
|
||||
FridaWindow fridaWindow = new FridaWindow(owner);
|
||||
fridaWindow.setVisible(true);
|
||||
}
|
||||
}));
|
||||
|
||||
loadingFrame.add(loadingPanel);
|
||||
loadingFrame.setVisible(true);
|
||||
ex.addToolCategory(debugCategory);
|
||||
|
||||
new Thread(() -> {
|
||||
long startTime = System.currentTimeMillis();
|
||||
int classifyTask = 0;
|
||||
MainWindow.ToolCategory aICategory = new MainWindow.ToolCategory("AI工具",
|
||||
"ai/ai.png",
|
||||
"人工智能/大语言模型");
|
||||
|
||||
new Thread(() -> {
|
||||
while (completedTasks < totalTasks) {
|
||||
completedTasks++;
|
||||
final int progress = (int) ((completedTasks / (double) totalTasks) * 100);
|
||||
aICategory.addTool(new MainWindow.ToolItem("本地AI执行工具", "ai/local/local_main.png",
|
||||
"在本机对开源大语言模型进行推理" +
|
||||
"\n作者:tzdwindows 7", ++id, new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Window owner = SwingUtilities.windowForComponent((Component) e.getSource());
|
||||
LocalWindow dialog = new LocalWindow(owner);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
}));
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
progressBar.setValue(progress);
|
||||
statusLabel.setText("Loading: " + progress + "%");
|
||||
long elapsedTime = (System.currentTimeMillis() - startTime) / 1000;
|
||||
timeLabel.setText("Time elapsed: " + elapsedTime + "s");
|
||||
});
|
||||
}
|
||||
});
|
||||
while (completedTasks < totalTasks) {
|
||||
try {
|
||||
if (classifyTask == 0){
|
||||
PluginLoader.loadPlugins();
|
||||
logger.info("Loaded plugins");
|
||||
classifyTask++;
|
||||
ex.addToolCategory(aICategory);
|
||||
|
||||
ex.initUI();
|
||||
ex.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
logger.error("There was a problem starting the main thread", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
// 非显示任务请添加在这添加
|
||||
// ....
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to load plugins", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load plugins", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
loadingFrame.dispose();
|
||||
try {
|
||||
MainWindow ex = new MainWindow();
|
||||
int id = 0;
|
||||
MainWindow.ToolCategory debugCategory = new MainWindow.ToolCategory("调试工具",
|
||||
"debug/debug.png",
|
||||
"用于调试指定Windows工具的一个分类");
|
||||
|
||||
debugCategory.addTool(new MainWindow.ToolItem("Frida注入工具", "debug/frida/frida_main.png",
|
||||
"使用frida注入目标进程的脚本程序 " +
|
||||
"\n作者:tzdwindows 7", ++id, new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Window owner = SwingUtilities.windowForComponent((Component) e.getSource());
|
||||
FridaWindow fridaWindow = new FridaWindow(owner);
|
||||
fridaWindow.setVisible(true);
|
||||
}
|
||||
}));
|
||||
|
||||
// 在后面注册你自己的项或是添加你自己的分类
|
||||
// ....
|
||||
|
||||
ex.addToolCategory(debugCategory);
|
||||
|
||||
MainWindow.ToolCategory aICategory = new MainWindow.ToolCategory("AI工具",
|
||||
"ai/ai.png",
|
||||
"人工智能/大语言模型");
|
||||
|
||||
aICategory.addTool(new MainWindow.ToolItem("本地AI执行工具", "ai/local/local_main.png",
|
||||
"在本机对开源大语言模型进行推理" +
|
||||
"\n作者:tzdwindows 7", ++id, new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Window owner = SwingUtilities.windowForComponent((Component) e.getSource());
|
||||
LocalWindow dialog = new LocalWindow(owner);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
}));
|
||||
|
||||
ex.addToolCategory(aICategory);
|
||||
|
||||
ex.initUI();
|
||||
ex.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
logger.error("There was a problem starting the main thread", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}).start();
|
||||
});
|
||||
thread.setName("Main Thread");
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.axis.innovators.box.gui;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 启动窗口的任务系统
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class ProgressBarManager {
|
||||
private JFrame loadingFrame;
|
||||
private JProgressBar mainProgressBar;
|
||||
private JProgressBar subProgressBar;
|
||||
private JLabel statusLabel;
|
||||
private JLabel timeLabel;
|
||||
private long startTime;
|
||||
|
||||
private int totalTasks;
|
||||
private int completedTasks;
|
||||
private Map<String, Integer> subTasks = new HashMap<>();
|
||||
|
||||
public ProgressBarManager(String title, int totalTasks) {
|
||||
this.totalTasks = totalTasks;
|
||||
this.completedTasks = 0;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
|
||||
loadingFrame = new JFrame(title);
|
||||
loadingFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
loadingFrame.setSize(400, 250);
|
||||
loadingFrame.setLocationRelativeTo(null);
|
||||
loadingFrame.setIconImage(LoadIcon.loadIcon("logo.png", 64).getImage());
|
||||
|
||||
JPanel loadingPanel = new JPanel(new BorderLayout());
|
||||
|
||||
mainProgressBar = new JProgressBar(0, 100);
|
||||
mainProgressBar.setStringPainted(true);
|
||||
|
||||
subProgressBar = new JProgressBar(0, 100);
|
||||
subProgressBar.setStringPainted(true);
|
||||
subProgressBar.setString("Subtask Progress");
|
||||
|
||||
statusLabel = new JLabel("Initializing...", SwingConstants.CENTER);
|
||||
timeLabel = new JLabel("Time elapsed: 0s", SwingConstants.CENTER);
|
||||
|
||||
JLabel logoLabel = new JLabel(LoadIcon.loadIcon("logo.png", 64));
|
||||
|
||||
JPanel progressPanel = new JPanel(new GridLayout(2, 1));
|
||||
progressPanel.add(mainProgressBar);
|
||||
progressPanel.add(subProgressBar);
|
||||
|
||||
loadingPanel.add(logoLabel, BorderLayout.NORTH);
|
||||
loadingPanel.add(progressPanel, BorderLayout.CENTER);
|
||||
loadingPanel.add(statusLabel, BorderLayout.SOUTH);
|
||||
loadingPanel.add(timeLabel, BorderLayout.SOUTH);
|
||||
|
||||
loadingFrame.add(loadingPanel);
|
||||
loadingFrame.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新主任务进度
|
||||
* @param completedTasks 已完成的主任务数量
|
||||
*/
|
||||
public void updateMainProgress(int completedTasks) {
|
||||
this.completedTasks = completedTasks;
|
||||
int progress = (int) ((completedTasks / (double) totalTasks) * 100);
|
||||
mainProgressBar.setValue(progress);
|
||||
statusLabel.setText("Main Progress: " + progress + "%");
|
||||
updateTimeLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新子任务进度
|
||||
* @param subTaskName 子任务名称
|
||||
* @param subTaskCompleted 已完成的子任务数量
|
||||
* @param subTaskTotal 子任务总数
|
||||
*/
|
||||
public void updateSubProgress(String subTaskName, int subTaskCompleted, int subTaskTotal) {
|
||||
subTasks.put(subTaskName, subTaskCompleted);
|
||||
int progress = (int) ((subTaskCompleted / (double) subTaskTotal) * 100);
|
||||
subProgressBar.setValue(progress);
|
||||
subProgressBar.setString(subTaskName + ": " + progress + "%");
|
||||
updateTimeLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新总任务数
|
||||
*/
|
||||
public void setTotalTasks(int totalTasks) {
|
||||
this.totalTasks = totalTasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭加载窗口
|
||||
*/
|
||||
public void close() {
|
||||
loadingFrame.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新时间标签
|
||||
*/
|
||||
private void updateTimeLabel() {
|
||||
long elapsedTime = (System.currentTimeMillis() - startTime) / 1000;
|
||||
timeLabel.setText("Time elapsed: " + elapsedTime + "s");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.axis.innovators.box.plugins;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* 自定义加载器
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class BoxClassLoader extends URLClassLoader {
|
||||
|
||||
public BoxClassLoader(ClassLoader parent) {
|
||||
super(new URL[0], parent);
|
||||
}
|
||||
|
||||
public BoxClassLoader(URL[] sources) {
|
||||
super(sources);
|
||||
}
|
||||
|
||||
public BoxClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super(urls, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
byte[] classBytes;
|
||||
try {
|
||||
classBytes = getClassBytes(name);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
byte[] transformedClass = transformClass(name, null, classBytes);
|
||||
return defineClass(name, transformedClass, 0, transformedClass.length);
|
||||
}
|
||||
|
||||
public byte[] getClassBytes(String className) throws IOException, ClassNotFoundException {
|
||||
String path = className.replace('.', '/') + ".class";
|
||||
URL classUrl = getResource(path);
|
||||
if (classUrl == null) {
|
||||
throw new ClassNotFoundException("Class not found: " + className);
|
||||
}
|
||||
try (InputStream is = classUrl.openStream()) {
|
||||
return is.readAllBytes();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] transformClass(String className, String transformedName, byte[] basicClass) {
|
||||
return PluginLoader.transformClass(className, transformedName, basicClass);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.axis.innovators.box.plugins;
|
||||
|
||||
/**
|
||||
* 字节码操作接口
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public interface IClassTransformer {
|
||||
/**
|
||||
* 字节码操作
|
||||
* @param name 类名
|
||||
* @param transformedName 当前core插件名
|
||||
* @param bytes 字节码
|
||||
* @return 修改后的字节码
|
||||
*/
|
||||
byte[] transform(String name, String transformedName, byte[] bytes);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.axis.innovators.box.plugins;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Core插件接口
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public interface LoadingCorePlugin {
|
||||
String[] getLibraryRequestClass();
|
||||
String[] getASMTransformerClass();
|
||||
String getSetupClass();
|
||||
void injectData(Map<String, Object> data);
|
||||
}
|
||||
@@ -11,18 +11,15 @@ import java.util.*;
|
||||
import java.util.jar.*;
|
||||
|
||||
/**
|
||||
* 加载插件的系统
|
||||
* 插件加载器
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class PluginLoader {
|
||||
private static final Logger logger = LogManager.getLogger(PluginLoader.class);
|
||||
public static final String PLUGIN_PATH = FolderCreator.getPluginFolder();
|
||||
private static final List<PluginDescriptor> loadedPlugins = new ArrayList<>();
|
||||
private static final List<IClassTransformer> transformers = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 加载插件
|
||||
* @throws IOException 插件加载失败
|
||||
*/
|
||||
public static void loadPlugins() throws IOException {
|
||||
File pluginDir = new File(PLUGIN_PATH);
|
||||
File[] jars = pluginDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".jar"));
|
||||
@@ -30,10 +27,12 @@ public class PluginLoader {
|
||||
if (jars == null) {
|
||||
return;
|
||||
}
|
||||
Main.totalTasks = jars.length;
|
||||
for (int i = 0; i < jars.length; i++) {
|
||||
processJarFile(jars[i]);
|
||||
Main.completedTasks = i;
|
||||
Main.progressBarManager.updateSubProgress(
|
||||
"Loading Plugin " + i,
|
||||
i,
|
||||
jars.length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +44,45 @@ public class PluginLoader {
|
||||
} else {
|
||||
processWithAnnotations(jar, jarFile);
|
||||
}
|
||||
|
||||
// Check for CorePlugin in MANIFEST.MF
|
||||
Attributes attributes = jar.getManifest().getMainAttributes();
|
||||
String corePluginClass = attributes.getValue("CorePlugin");
|
||||
if (corePluginClass != null) {
|
||||
processCorePlugin(jarFile, corePluginClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processCorePlugin(File jarFile, String corePluginClass) {
|
||||
try (URLClassLoader classLoader = new URLClassLoader(
|
||||
new URL[]{jarFile.toURI().toURL()},
|
||||
PluginLoader.class.getClassLoader())
|
||||
) {
|
||||
Class<?> coreClass = classLoader.loadClass(corePluginClass);
|
||||
if (LoadingCorePlugin.class.isAssignableFrom(coreClass)) {
|
||||
LoadingCorePlugin corePlugin = (LoadingCorePlugin) coreClass.getDeclaredConstructor().newInstance();
|
||||
registerTransformers(corePlugin);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load core plugin: {}", corePluginClass, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerTransformers(LoadingCorePlugin corePlugin) {
|
||||
String[] transformerClasses = corePlugin.getASMTransformerClass();
|
||||
if (transformerClasses != null) {
|
||||
for (String transformerClass : transformerClasses) {
|
||||
try {
|
||||
Class<?> transformerClazz = Class.forName(transformerClass);
|
||||
if (IClassTransformer.class.isAssignableFrom(transformerClazz)) {
|
||||
IClassTransformer transformer = (IClassTransformer) transformerClazz.getDeclaredConstructor().newInstance();
|
||||
transformers.add(transformer);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to register transformer: {}", transformerClass, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,4 +183,11 @@ public class PluginLoader {
|
||||
public static List<PluginDescriptor> getLoadedPlugins() {
|
||||
return Collections.unmodifiableList(loadedPlugins);
|
||||
}
|
||||
|
||||
public static byte[] transformClass(String name, String transformedName, byte[] basicClass) {
|
||||
for (IClassTransformer transformer : transformers) {
|
||||
basicClass = transformer.transform(name, transformedName, basicClass);
|
||||
}
|
||||
return basicClass;
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
<Appenders>
|
||||
<!-- 固定日志文件(按时间和大小滚动) -->
|
||||
<RollingFile name="MainFileAppender"
|
||||
fileName="logs/app.log"
|
||||
filePattern="logs/app-%d{yyyy-MM-dd}-%i.log">
|
||||
fileName="logs/box.log"
|
||||
filePattern="logs/box-%d{yyyy-MM-dd}-%i.log">
|
||||
<PatternLayout>
|
||||
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Pattern>
|
||||
</PatternLayout>
|
||||
@@ -15,10 +15,10 @@
|
||||
<DefaultRolloverStrategy max="7"/>
|
||||
</RollingFile>
|
||||
|
||||
<!-- 每次运行独立的日志文件(带时间和PID) -->
|
||||
<!-- 每次运行独立的日志文件(带时间) -->
|
||||
<RollingFile name="SessionFileAppender"
|
||||
fileName="logs/app-${date:yyyy-MM-dd_HH-mm-ss}.log"
|
||||
filePattern="logs/app-%d{yyyy-MM-dd}-%i.log"
|
||||
fileName="logs/box-${date:yyyy-MM-dd_HH-mm-ss}.log"
|
||||
filePattern="logs/box-%d{yyyy-MM-dd}-%i.log"
|
||||
immediateFlush="true"
|
||||
createOnDemand="false">
|
||||
<PatternLayout>
|
||||
|
||||
Reference in New Issue
Block a user