feat(box): 添加命令行文件解析功能并优化主题和语言管理- 新增 ArgsParser 类用于解析命令行参数中的文件路径
- 添加 OpenFileEvents 事件类用于处理打开文件请求 - 更新 AxisInnovatorsBox 类,支持命令行文件解析 - 重构 LanguageManager 类,优化语言合并和加载逻辑 - 更新 MainWindow 类,改进界面样式和滚动条UI - 修改 PluginDescriptor 类,增加注册名字段
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.axis.innovators.box;
|
||||
|
||||
import com.axis.innovators.box.events.GlobalEventBus;
|
||||
import com.axis.innovators.box.events.OpenFileEvents;
|
||||
import com.axis.innovators.box.events.StartupEvent;
|
||||
import com.axis.innovators.box.gui.*;
|
||||
import com.axis.innovators.box.plugins.PluginDescriptor;
|
||||
@@ -9,6 +10,7 @@ import com.axis.innovators.box.register.RegistrationSettingsItem;
|
||||
import com.axis.innovators.box.register.RegistrationTool;
|
||||
import com.axis.innovators.box.register.RegistrationTopic;
|
||||
import com.axis.innovators.box.register.LanguageManager;
|
||||
import com.axis.innovators.box.tools.ArgsParser;
|
||||
import com.axis.innovators.box.tools.LibraryLoad;
|
||||
import com.axis.innovators.box.tools.StateManager;
|
||||
import com.axis.innovators.box.tools.SystemInfoUtil;
|
||||
@@ -22,7 +24,9 @@ import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 主类
|
||||
@@ -52,13 +56,14 @@ public class AxisInnovatorsBox {
|
||||
private final List<WindowsJDialog> windowsJDialogList = new ArrayList<>();
|
||||
private final StateManager stateManager = new StateManager();
|
||||
|
||||
public AxisInnovatorsBox(String[] args){
|
||||
public AxisInnovatorsBox(String[] args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
LibraryLoad.loadLibrary("FridaNative");
|
||||
LibraryLoad.loadLibrary("ThrowSafely");
|
||||
LM.loadLibrary(LM.CUDA);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load the 'FridaNative' library", e);
|
||||
@@ -218,6 +223,9 @@ public class AxisInnovatorsBox {
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Log4j2
|
||||
*/
|
||||
public void initLog4j2() {
|
||||
Log4j2OutputStream.redirectSystemStreams();
|
||||
|
||||
@@ -235,9 +243,11 @@ public class AxisInnovatorsBox {
|
||||
logger.info("ClassLoader.getSystemClassLoader(): {}", ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置主题
|
||||
*/
|
||||
private void setTopic() {
|
||||
try {
|
||||
|
||||
main.registrationTopic.addTopic(UIManager.getSystemLookAndFeelClassName(),
|
||||
LanguageManager.getLoadedLanguages().getText("default_theme.system.topicName"),
|
||||
LanguageManager.getLoadedLanguages().getText("default_theme.default.tip"),
|
||||
@@ -317,43 +327,59 @@ public class AxisInnovatorsBox {
|
||||
isWindow = true;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void run(String[] args) {
|
||||
main = new AxisInnovatorsBox(args);
|
||||
main.initLog4j2();
|
||||
main.setTopic();
|
||||
try {
|
||||
main.initLog4j2();
|
||||
main.setTopic();
|
||||
|
||||
main.thread = new Thread(() -> {
|
||||
try {
|
||||
// 主任务1:加载插件
|
||||
logger.info("Loaded plugins Started");
|
||||
main.progressBarManager.updateMainProgress(++main.completedTasks);
|
||||
PluginLoader.loadPlugins();
|
||||
logger.info("Loaded plugins End");
|
||||
List<Map<String, String>> validFiles = ArgsParser.parseArgs(args);
|
||||
|
||||
main.progressBarManager.close();
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
main.ex = new MainWindow();
|
||||
GlobalEventBus.EVENT_BUS.post(new StartupEvent(main));
|
||||
main.runWindow();
|
||||
} catch (Exception e) {
|
||||
logger.error("There was a problem starting the main thread", e);
|
||||
main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
main.organizingCrashReports(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load plugins", e);
|
||||
main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
main.organizingCrashReports(e);
|
||||
throw new RuntimeException(e);
|
||||
for (Map<String, String> fileInfo : validFiles) {
|
||||
OpenFileEvents openFileEvents = new OpenFileEvents(fileInfo.get("path"), fileInfo.get("extension"));
|
||||
GlobalEventBus.EVENT_BUS.post(openFileEvents);
|
||||
if (!openFileEvents.isContinue()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
main.thread.setName("Main Thread");
|
||||
main.thread.start();
|
||||
|
||||
main.thread = new Thread(() -> {
|
||||
try {
|
||||
// 主任务1:加载插件
|
||||
logger.info("Loaded plugins Started");
|
||||
main.progressBarManager.updateMainProgress(++main.completedTasks);
|
||||
PluginLoader.loadPlugins();
|
||||
logger.info("Loaded plugins End");
|
||||
|
||||
main.progressBarManager.close();
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
main.ex = new MainWindow();
|
||||
GlobalEventBus.EVENT_BUS.post(new StartupEvent(main));
|
||||
main.runWindow();
|
||||
} catch (Exception e) {
|
||||
logger.error("There was a problem starting the main thread", e);
|
||||
main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
main.organizingCrashReports(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load plugins", e);
|
||||
main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
main.organizingCrashReports(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
main.thread.setName("Main Thread");
|
||||
main.thread.start();
|
||||
} catch (Exception e) {
|
||||
logger.error("In unexpected errors", e);
|
||||
main.ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
main.organizingCrashReports(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void runWindow() {
|
||||
|
||||
@@ -10,7 +10,12 @@ import com.axis.innovators.box.register.LanguageManager;
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
FolderCleaner.cleanFolder(FolderCreator.getLogsFolder(), 10);
|
||||
|
||||
LanguageManager.loadSavedLanguage();
|
||||
AxisInnovatorsBox.main(args);
|
||||
if (LanguageManager.getLoadedLanguages() == null){
|
||||
LanguageManager.loadLanguage("system:zh_CN");
|
||||
}
|
||||
|
||||
AxisInnovatorsBox.run(args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.axis.innovators.box.events;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 当程序接受到了文件时触发
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class OpenFileEvents {
|
||||
private final File filePath;
|
||||
private final String extension;
|
||||
private boolean isContinue;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param filePath 文件路径
|
||||
* @param extension 文件后缀
|
||||
*/
|
||||
public OpenFileEvents(String filePath, String extension) {
|
||||
this.filePath = new File(filePath);
|
||||
this.extension = extension;
|
||||
isContinue = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件路径
|
||||
* @return 文件路径
|
||||
*/
|
||||
public File getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件后缀
|
||||
* @return 文件后缀
|
||||
*/
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
public boolean isContinue() {
|
||||
return isContinue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 希望程序继续执行后面的操作
|
||||
* @param isContinue 是否继续
|
||||
*/
|
||||
public void setContinue(boolean isContinue) {
|
||||
this.isContinue = isContinue;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import com.axis.innovators.box.AxisInnovatorsBox;
|
||||
import com.axis.innovators.box.events.*;
|
||||
import com.axis.innovators.box.register.RegistrationSettingsItem;
|
||||
import com.axis.innovators.box.register.LanguageManager;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -13,9 +15,7 @@ import javax.swing.plaf.PanelUI;
|
||||
import javax.swing.plaf.basic.BasicScrollBarUI;
|
||||
import javax.swing.plaf.basic.BasicTabbedPaneUI;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ConvolveOp;
|
||||
import java.awt.image.Kernel;
|
||||
@@ -30,16 +30,22 @@ public class MainWindow extends JFrame {
|
||||
private static final Logger logger = LogManager.getLogger(MainWindow.class);
|
||||
private final Map<JComponent, Float> cardScales = new HashMap<>();
|
||||
private final Map<JComponent, Integer> cardElevations = new HashMap<>();
|
||||
// 选项卡颜色
|
||||
private final Color CARD_COLOR = Color.WHITE;
|
||||
private final List<ToolCategory> categories = new ArrayList<>();
|
||||
// 是否启用背景图片
|
||||
private final boolean isBackground = true;
|
||||
// 启动背景图片后是否启动背景模糊
|
||||
private final boolean isBlur = true;
|
||||
|
||||
public MainWindow() {
|
||||
setIconImage(LoadIcon.loadIcon("logo.png", 32).getImage());
|
||||
addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
for (JComponent card : cardScales.keySet()) {
|
||||
cardScales.put(card, 1.0f);
|
||||
card.repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,18 +58,13 @@ public class MainWindow extends JFrame {
|
||||
|
||||
|
||||
public void initUI() {
|
||||
// 设置窗口属性
|
||||
|
||||
setTitle(LanguageManager.getLoadedLanguages().getText("mainWindow.title"));
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
setSize(1200, 800);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
// 设置窗口和内容面板透明
|
||||
//setBackground(new Color(0, 0, 0, 0));
|
||||
getContentPane().setBackground(new Color(0, 0, 0, 0));
|
||||
|
||||
// 自定义面板
|
||||
JPanel mainPanel = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
@@ -96,24 +97,18 @@ public class MainWindow extends JFrame {
|
||||
logger.error("Failed to load background image", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// 强制面板不透明
|
||||
mainPanel.setOpaque(true);
|
||||
mainPanel.putClientProperty("FlatLaf.style", "background: null;");
|
||||
|
||||
// 设置布局和边距
|
||||
mainPanel.setLayout(new BorderLayout(20, 20));
|
||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
|
||||
|
||||
// 添加其他组件
|
||||
mainPanel.add(createHeader(), BorderLayout.NORTH);
|
||||
mainPanel.add(createCategoryTabs(), BorderLayout.CENTER);
|
||||
|
||||
// 添加主面板到窗口
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
@@ -208,6 +203,10 @@ public class MainWindow extends JFrame {
|
||||
private JComponent createCategoryTabs() {
|
||||
JTabbedPane tabbedPane = new JTabbedPane();
|
||||
|
||||
//tabbedPane.putClientProperty(FlatClientProperties.TABBED_PANE_TAB_AREA_ALIGN, Component.LEFT_ALIGNMENT);
|
||||
tabbedPane.putClientProperty(FlatClientProperties.TABBED_PANE_TAB_HEIGHT, 40);
|
||||
tabbedPane.putClientProperty(FlatClientProperties.TABBED_PANE_TAB_ICON_PLACEMENT, SwingConstants.TOP);
|
||||
|
||||
tabbedPane.setOpaque(false);
|
||||
tabbedPane.setBackground(new Color(0, 0, 0, 0));
|
||||
tabbedPane.setBorder(null);
|
||||
@@ -236,7 +235,7 @@ public class MainWindow extends JFrame {
|
||||
}
|
||||
tabbedPane.addTab(
|
||||
category.getName(),
|
||||
LoadIcon.loadIcon(category.getIcon(), 24),
|
||||
LoadIcon.loadIcon(category.getIcon(), 12),
|
||||
scrollPane
|
||||
);
|
||||
}
|
||||
@@ -246,7 +245,7 @@ public class MainWindow extends JFrame {
|
||||
|
||||
private JPanel createToolsPanel(ToolCategory category) {
|
||||
JPanel panel = new JPanel(new GridLayout(0, 3, 20, 20));
|
||||
for (ToolItem tool : category.getTools()) {
|
||||
for (ToolItem tool : category.getTools()) {
|
||||
panel.add(createToolCard(tool));
|
||||
}
|
||||
panel.setOpaque(false);
|
||||
@@ -264,16 +263,14 @@ public class MainWindow extends JFrame {
|
||||
title.setFont(new Font("微软雅黑", Font.BOLD, 28));
|
||||
title.setForeground(new Color(44, 62, 80));
|
||||
|
||||
//JLabel iconLabel = new JLabel(LoadIcon.loadIcon("logo.png", 28));
|
||||
//iconLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
|
||||
|
||||
JButton settings = new JButton(LoadIcon.loadIcon("settings.png", 32));
|
||||
settings.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_BORDERLESS);
|
||||
settings.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
settings.setContentAreaFilled(false);
|
||||
settings.addActionListener(e -> showSettings());
|
||||
|
||||
JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
|
||||
titlePanel.setOpaque(false);
|
||||
//titlePanel.add(iconLabel);
|
||||
titlePanel.add(title);
|
||||
|
||||
header.add(titlePanel, BorderLayout.WEST);
|
||||
@@ -323,7 +320,6 @@ public class MainWindow extends JFrame {
|
||||
JPanel card = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
|
||||
Graphics2D g2d = (Graphics2D) g.create();
|
||||
|
||||
// 毛玻璃效果
|
||||
@@ -350,7 +346,8 @@ public class MainWindow extends JFrame {
|
||||
g2d.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
card.setPreferredSize(new Dimension(200, 150));
|
||||
card.setMinimumSize(new Dimension(100, 75));
|
||||
card.setLayout(new BorderLayout(15, 15));
|
||||
card.setBackground(CARD_COLOR);
|
||||
card.setBorder(BorderFactory.createCompoundBorder(
|
||||
@@ -395,7 +392,6 @@ public class MainWindow extends JFrame {
|
||||
card.add(iconLabel, BorderLayout.NORTH);
|
||||
card.add(textPanel, BorderLayout.CENTER);
|
||||
|
||||
// 鼠标悬停动画
|
||||
card.addMouseListener(new CardMouseAdapter(card, tool));
|
||||
card.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
@@ -418,6 +414,19 @@ public class MainWindow extends JFrame {
|
||||
super.update(g, c);
|
||||
}
|
||||
});
|
||||
|
||||
card.addMouseListener(new CardMouseAdapter(card, tool) {
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
cardElevations.put(card, 8);
|
||||
animateCardElevation(card, 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
animateCardElevation(card, 2);
|
||||
}
|
||||
});
|
||||
return card;
|
||||
}
|
||||
|
||||
@@ -429,7 +438,25 @@ public class MainWindow extends JFrame {
|
||||
"</body></html>";
|
||||
}
|
||||
|
||||
// 工具类别内部类
|
||||
private void animateCardElevation(JComponent card, int targetElevation) {
|
||||
new Timer(10, new AbstractAction() {
|
||||
private int currentElevation = cardElevations.getOrDefault(card, 2);
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (currentElevation < targetElevation) currentElevation++;
|
||||
else if (currentElevation > targetElevation) currentElevation--;
|
||||
|
||||
cardElevations.put(card, currentElevation);
|
||||
card.repaint();
|
||||
|
||||
if (currentElevation == targetElevation) {
|
||||
((Timer)e.getSource()).stop();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public static class ToolCategory {
|
||||
private final String name;
|
||||
private final String icon;
|
||||
@@ -687,52 +714,41 @@ public class MainWindow extends JFrame {
|
||||
|
||||
public static class CustomScrollBarUI extends BasicScrollBarUI {
|
||||
@Override
|
||||
protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
protected void configureScrollBarColors() {
|
||||
this.thumbColor = new Color(90, 90, 120);
|
||||
this.trackColor = new Color(50, 50, 70);
|
||||
}
|
||||
|
||||
// 设置轨道背景颜色
|
||||
Color trackColor = new Color(240, 240, 240);
|
||||
g2d.setColor(trackColor);
|
||||
g2d.fillRoundRect(
|
||||
trackBounds.x,
|
||||
trackBounds.y,
|
||||
trackBounds.width - 1,
|
||||
trackBounds.height - 1,
|
||||
5, 5 // 圆角半径
|
||||
);
|
||||
@Override
|
||||
protected JButton createDecreaseButton(int orientation) {
|
||||
return createInvisibleButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JButton createIncreaseButton(int orientation) {
|
||||
return createInvisibleButton();
|
||||
}
|
||||
|
||||
private JButton createInvisibleButton() {
|
||||
JButton btn = new JButton();
|
||||
btn.setPreferredSize(new Dimension(0, 0));
|
||||
btn.setMinimumSize(new Dimension(0, 0));
|
||||
btn.setMaximumSize(new Dimension(0, 0));
|
||||
return btn;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
Color thumbColor = new Color(180, 180, 180);
|
||||
g2d.setColor(thumbColor);
|
||||
g2d.fillRoundRect(
|
||||
thumbBounds.x,
|
||||
thumbBounds.y,
|
||||
thumbBounds.width - 1,
|
||||
thumbBounds.height - 1,
|
||||
5, 5
|
||||
);
|
||||
|
||||
Color borderColor = new Color(160, 160, 160);
|
||||
g2d.setColor(borderColor);
|
||||
g2d.drawRoundRect(
|
||||
thumbBounds.x,
|
||||
thumbBounds.y,
|
||||
thumbBounds.width - 1,
|
||||
thumbBounds.height - 1,
|
||||
5, 5
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2.setColor(thumbColor);
|
||||
g2.fillRoundRect(
|
||||
thumbBounds.x + 2,
|
||||
thumbBounds.y + 2,
|
||||
thumbBounds.width - 4,
|
||||
thumbBounds.height - 4,
|
||||
8, 8
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintDecreaseHighlight(Graphics g) {}
|
||||
|
||||
@Override
|
||||
protected void paintIncreaseHighlight(Graphics g) {}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ public class PluginDescriptor {
|
||||
private String description;
|
||||
private Object instance;
|
||||
private String transformers;
|
||||
private String registrationName;
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() { return id; }
|
||||
@@ -29,4 +30,6 @@ public class PluginDescriptor {
|
||||
public void setInstance(Object instance) { this.instance = instance; }
|
||||
public String getTransformers() {return transformers;}
|
||||
public void setTransformers(String transformers) {this.transformers = transformers;}
|
||||
public String getRegistrationName() {return registrationName;}
|
||||
public void setRegistrationName(String registrationName) {this.registrationName = registrationName;}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package com.axis.innovators.box.plugins;
|
||||
|
||||
import com.axis.innovators.box.AxisInnovatorsBox;
|
||||
import com.axis.innovators.box.register.LanguageManager;
|
||||
import com.axis.innovators.box.register.RegistrationTool;
|
||||
import com.axis.innovators.box.tools.FolderCreator;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.jar.*;
|
||||
|
||||
@@ -20,7 +24,8 @@ public class PluginLoader {
|
||||
private static final List<PluginDescriptor> loadedPlugins = new ArrayList<>();
|
||||
private static final List<IClassTransformer> transformers = new ArrayList<>();
|
||||
private static final List<String> corePluginMainClass = new ArrayList<>();
|
||||
public static void loadPlugins() throws IOException {
|
||||
private static final List<String> pluginRegisteredName = new ArrayList<>();
|
||||
public static void loadPlugins() throws IOException, PluginLoadingError {
|
||||
logger = LogManager.getLogger(PluginLoader.class);
|
||||
File pluginDir = null;
|
||||
if (PLUGIN_PATH != null) {
|
||||
@@ -43,7 +48,7 @@ public class PluginLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private static void processJarFile(File jarFile, boolean isCorePlugin) throws IOException {
|
||||
private static void processJarFile(File jarFile, boolean isCorePlugin) throws IOException, PluginLoadingError {
|
||||
try (JarFile jar = new JarFile(jarFile)) {
|
||||
// Check for CorePlugin in MANIFEST.MF
|
||||
if (isCorePlugin) {
|
||||
@@ -80,7 +85,11 @@ public class PluginLoader {
|
||||
return;
|
||||
}
|
||||
for (File jar : jars) {
|
||||
processJarFile(jar, true);
|
||||
try {
|
||||
processJarFile(jar, true);
|
||||
} catch (PluginLoadingError e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +131,8 @@ public class PluginLoader {
|
||||
//}
|
||||
}
|
||||
|
||||
private static void processWithManifest(JarFile jar, JarEntry entry, File jarFile) throws IOException {
|
||||
private static void processWithManifest(JarFile jar, JarEntry entry, File jarFile)
|
||||
throws IOException, PluginLoadingError {
|
||||
Properties props = new Properties();
|
||||
try (InputStream is = jar.getInputStream(entry)) {
|
||||
props.load(is);
|
||||
@@ -139,27 +149,92 @@ public class PluginLoader {
|
||||
descriptor.setSupportedVersions(
|
||||
Arrays.asList(props.getProperty("supportedVersions").split(","))
|
||||
);
|
||||
String registrationName = props.getProperty("registrationName");
|
||||
verifyRegisteredNameValid(descriptor, registrationName);
|
||||
|
||||
logger.info("Loaded plugin: {}", descriptor.getName());
|
||||
loadMainClass(props.getProperty("mainClass"), jarFile, descriptor);
|
||||
|
||||
Attributes attributes = jar.getManifest().getMainAttributes();
|
||||
String corePluginClass = attributes.getValue("CorePlugin");
|
||||
descriptor.setTransformers(corePluginClass);
|
||||
loadPluginLanguages(jarFile, descriptor);
|
||||
}
|
||||
|
||||
private static void processWithAnnotations(JarFile jar, File jarFile) {
|
||||
private static void verifyRegisteredNameValid(PluginDescriptor descriptor, String registrationName) throws PluginLoadingError {
|
||||
if (registrationName != null && !registrationName.isEmpty()
|
||||
&& !pluginRegisteredName.contains(registrationName)) {
|
||||
pluginRegisteredName.add(registrationName);
|
||||
} else {
|
||||
if (registrationName == null || registrationName.isEmpty()) {
|
||||
throw new PluginLoadingError("Invalid registration name");
|
||||
}
|
||||
throw new PluginLoadingError("When the \" "
|
||||
+ descriptor.getName()
|
||||
+ "\" plugin is loaded, this plugin contains the same registered name as the previously loaded plugin");
|
||||
}
|
||||
|
||||
descriptor.setRegistrationName(registrationName);
|
||||
}
|
||||
|
||||
private static void processWithAnnotations(JarFile jar, File jarFile) throws PluginLoadingError {
|
||||
URLClassLoader classLoader = createClassLoader(jarFile);
|
||||
Enumeration<JarEntry> entries = jar.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
if (entry.getName().endsWith(".class")) {
|
||||
if (classLoader != null) {
|
||||
processClassEntry(entry, jar,classLoader);
|
||||
processClassEntry(entry, jar,classLoader,jarFile);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadPluginLanguages(File jarFile, PluginDescriptor plugin) {
|
||||
try (JarFile jar = new JarFile(jarFile)) {
|
||||
Enumeration<JarEntry> entries = jar.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
if (entry.getName().startsWith("lang/") &&
|
||||
entry.getName().endsWith(".properties")) {
|
||||
processLanguageFile(jar, entry, plugin);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to load language files for plugin: {}", plugin.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void processLanguageFile(JarFile jar, JarEntry entry, PluginDescriptor plugin) {
|
||||
String fileName = entry.getName().substring(entry.getName().lastIndexOf("/") + 1);
|
||||
String[] parts = fileName.split("[_.]");
|
||||
if (parts.length < 3) {
|
||||
return;
|
||||
}
|
||||
String langCode = parts[parts.length-1].replace(".properties", "");
|
||||
String langName = plugin.getName() + " " + langCode.toUpperCase();
|
||||
String registeredName = plugin.getRegistrationName() + "_" + langCode;
|
||||
try (InputStream is = jar.getInputStream(entry)) {
|
||||
Properties properties2 = new Properties();
|
||||
properties2.load(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
LanguageManager.Language language = new LanguageManager.Language(
|
||||
langName,
|
||||
registeredName,
|
||||
null
|
||||
) {
|
||||
@Override
|
||||
public void loadLanguageFile(String languageFile) {
|
||||
this.properties.putAll(properties2);
|
||||
}
|
||||
};
|
||||
LanguageManager.addLanguage(language);
|
||||
logger.info("Loaded plugin language: {} ({})", langName, registeredName);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to load language file: {}", entry.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static URLClassLoader createClassLoader(File jarFile) {
|
||||
try {
|
||||
return new URLClassLoader(
|
||||
@@ -172,7 +247,9 @@ public class PluginLoader {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void processClassEntry(JarEntry entry,JarFile jar, URLClassLoader classLoader) {
|
||||
private static void processClassEntry(JarEntry entry,JarFile jar,
|
||||
URLClassLoader classLoader,
|
||||
File jarFile) throws PluginLoadingError {
|
||||
String className = entry.getName()
|
||||
.replace("/", ".")
|
||||
.replace(".class", "");
|
||||
@@ -188,14 +265,27 @@ public class PluginLoader {
|
||||
descriptor.setIcon(meta.icon());
|
||||
descriptor.setSupportedVersions(Arrays.asList(meta.supportedVersions()));
|
||||
|
||||
String registrationName = meta.registeredName();
|
||||
verifyRegisteredNameValid(descriptor, registrationName);
|
||||
|
||||
try {
|
||||
Object instance = clazz.getDeclaredConstructor().newInstance();
|
||||
descriptor.setInstance(instance);
|
||||
loadedPlugins.add(descriptor);
|
||||
|
||||
try {
|
||||
Field pluginInstance = instance.getClass().getDeclaredField("INSTANCE");
|
||||
pluginInstance.setAccessible(true);
|
||||
pluginInstance.set(null, descriptor);
|
||||
} catch (NoSuchFieldException | IllegalArgumentException
|
||||
| SecurityException | IllegalAccessException e) {
|
||||
logger.warn("Failed to set plugin instance: {}", instance.getClass(), e);
|
||||
}
|
||||
|
||||
loadedPlugins.add(descriptor);
|
||||
Attributes attributes = jar.getManifest().getMainAttributes();
|
||||
String corePluginClass = attributes.getValue("CorePlugin");
|
||||
descriptor.setTransformers(corePluginClass);
|
||||
loadPluginLanguages(jarFile, descriptor);
|
||||
logger.info("Loaded plugin: {}", descriptor.getName());
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to instantiate plugin class: {}", className, e);
|
||||
@@ -208,6 +298,7 @@ public class PluginLoader {
|
||||
|
||||
private static void loadMainClass(String mainClassName, File jarFile, PluginDescriptor descriptor) {
|
||||
if (mainClassName == null || mainClassName.isEmpty()) {
|
||||
logger.error("Invalid main class name: {}", mainClassName);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -218,6 +309,15 @@ public class PluginLoader {
|
||||
Class<?> mainClass = classLoader.loadClass(mainClassName);
|
||||
Object instance = mainClass.getDeclaredConstructor().newInstance();
|
||||
descriptor.setInstance(instance);
|
||||
|
||||
try {
|
||||
Field pluginInstance = mainClass.getDeclaredField("INSTANCE");
|
||||
pluginInstance.setAccessible(true);
|
||||
pluginInstance.set(null, descriptor);
|
||||
} catch (NoSuchFieldException | IllegalArgumentException
|
||||
| SecurityException | IllegalAccessException e) {
|
||||
logger.warn("Failed to set plugin instance: {}", mainClassName, e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to load main class: {}", mainClassName, e);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.axis.innovators.box.plugins;
|
||||
|
||||
/**
|
||||
* 当加载插件时发生的错误
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class PluginLoadingError extends Exception{
|
||||
public PluginLoadingError(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public PluginLoadingError(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -6,15 +6,34 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* 这是创建基础参数的注解
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface PluginMeta {
|
||||
/**
|
||||
* 插件ID
|
||||
*/
|
||||
String id();
|
||||
/**
|
||||
* 创建显示名称
|
||||
*/
|
||||
String name();
|
||||
/**
|
||||
* 支持的版本
|
||||
*/
|
||||
String[] supportedVersions();
|
||||
/**
|
||||
* 插件描述
|
||||
*/
|
||||
String description();
|
||||
/**
|
||||
* 插件图标
|
||||
*/
|
||||
String icon() default "";
|
||||
/**
|
||||
* 插件注册名称(确保其唯一性)
|
||||
*/
|
||||
String registeredName() default "no_registration";
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
package com.axis.innovators.box.register;
|
||||
|
||||
import com.axis.innovators.box.plugins.PluginLoader;
|
||||
import com.axis.innovators.box.tools.FolderCreator;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 语言管理器
|
||||
@@ -18,27 +19,106 @@ public class LanguageManager {
|
||||
private static final String LANGUAGE_PATH = FolderCreator.getLanguageFolder();
|
||||
private static final List<Language> LANGUAGES = new ArrayList<>();
|
||||
private static final String SAVED_LANGUAGE_FILE = LANGUAGE_PATH + "\\saved_language.properties";
|
||||
private static final Logger logger = LogManager.getLogger(PluginLoader.class);
|
||||
|
||||
static {
|
||||
LANGUAGES.add(new Language("简体中文", "Zh","SimplifiedChineseLanguage"));
|
||||
LANGUAGES.add(new Language("繁體中文", "TC","TraditionalChineseLanguage"));
|
||||
LANGUAGES.add(new Language("English", "En","EnglishLanguage"));
|
||||
LANGUAGES.add(new Language("简体中文", "system:zh_CN", "sys_zh_CN"));
|
||||
LANGUAGES.add(new Language("繁體中文(台灣)", "system:zh_TW", "sys_zh_TW"));
|
||||
LANGUAGES.add(new Language("English (International)", "system:en_US", "sys_en_US"));
|
||||
LANGUAGES.add(new Language("日本語", "system:ja_JP", "sys_ja_JP"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加语言
|
||||
* @param language 语言
|
||||
* 添加/合并语言资源
|
||||
* @param language 要添加的语言对象
|
||||
* 处理规则:
|
||||
* 1. 注册名相同时保留原有基础信息
|
||||
* 2. 相同键值的新内容覆盖旧内容
|
||||
* 3. 详细记录新增、更新的键值数量
|
||||
* 4. 提供关键示例用于调试
|
||||
*/
|
||||
public static void addLanguage(Language language) {
|
||||
for (int i = 0; i < LANGUAGES.size(); i++) {
|
||||
Language language1 = LANGUAGES.get(i);
|
||||
if (Objects.equals(language1.getRegisteredName(), language.getRegisteredName())){
|
||||
LANGUAGES.set(i, language);
|
||||
for (Language existing : LANGUAGES) {
|
||||
if (existing.getRegisteredName().equals(language.getRegisteredName())) {
|
||||
try {
|
||||
int added = 0;
|
||||
int updated = 0;
|
||||
Set<String> sampleAddedKeys = new LinkedHashSet<>();
|
||||
Set<String> sampleUpdatedKeys = new LinkedHashSet<>();
|
||||
for (String key : language.properties.stringPropertyNames()) {
|
||||
String newValue = language.properties.getProperty(key);
|
||||
|
||||
if (existing.properties.containsKey(key)) {
|
||||
updated++;
|
||||
if (sampleUpdatedKeys.size() < 5) {
|
||||
sampleUpdatedKeys.add(key);
|
||||
}
|
||||
} else {
|
||||
added++;
|
||||
if (sampleAddedKeys.size() < 5) {
|
||||
sampleAddedKeys.add(key);
|
||||
}
|
||||
}
|
||||
existing.properties.setProperty(key, newValue);
|
||||
}
|
||||
|
||||
String logDetail = buildMergeLogDetails(added, updated, sampleAddedKeys, sampleUpdatedKeys);
|
||||
|
||||
logger.info("【语言合并报告】\n" +
|
||||
"▌合并目标:{} ({})\n" +
|
||||
"▌变更统计:新增 {} 条 / 更新 {} 条\n" +
|
||||
"▌当前总量:{} 条\n" +
|
||||
"▌关键示例:\n{}",
|
||||
existing.getLanguageName(),
|
||||
existing.getRegisteredName(),
|
||||
added,
|
||||
updated,
|
||||
existing.properties.size(),
|
||||
logDetail);
|
||||
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
logger.error("语言合并异常!注册名:{} - {}",
|
||||
existing.getRegisteredName(),
|
||||
e.getClass().getSimpleName(),
|
||||
e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LANGUAGES.add(language);
|
||||
logger.info("【新增语言】{} ({}) 初始加载 {} 条",
|
||||
language.getLanguageName(),
|
||||
language.getRegisteredName(),
|
||||
language.properties.size());
|
||||
}
|
||||
|
||||
private static String buildMergeLogDetails(int added, int updated,
|
||||
Set<String> sampleAdded, Set<String> sampleUpdated) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (added > 0) {
|
||||
sb.append("✦ 新增条目:\n");
|
||||
sampleAdded.forEach(k -> sb.append(" ▸ ").append(k).append("\n"));
|
||||
if (added > 5) {
|
||||
sb.append(" ...(共").append(added).append("条)\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (updated > 0) {
|
||||
sb.append("✦ 更新条目:\n");
|
||||
sampleUpdated.forEach(k -> sb.append(" ▸ ").append(k).append("\n"));
|
||||
if (updated > 5) {
|
||||
sb.append(" ...(共").append(updated).append("条)\n");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString().isEmpty() ? "无内容变更" : sb.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 加载语言
|
||||
* @param languageName 语言注册名
|
||||
@@ -120,7 +200,7 @@ public class LanguageManager {
|
||||
private final String languageName;
|
||||
private final String registeredName;
|
||||
private final String languageFile;
|
||||
private final Properties properties;
|
||||
protected final Properties properties;
|
||||
|
||||
public Language(String languageName,
|
||||
String registeredName,
|
||||
@@ -133,14 +213,14 @@ public class LanguageManager {
|
||||
this.languageFile = LANGUAGE_PATH + "\\" + languageFileName + ".properties";
|
||||
}
|
||||
this.properties = new Properties();
|
||||
loadLanguageFile();
|
||||
loadLanguageFile(languageFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载语言文件
|
||||
*/
|
||||
private void loadLanguageFile() {
|
||||
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(this.languageFile),
|
||||
public void loadLanguageFile(String languageFile) {
|
||||
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(languageFile),
|
||||
StandardCharsets.UTF_8)) {
|
||||
properties.load(reader);
|
||||
} catch (IOException e) {
|
||||
@@ -161,6 +241,13 @@ public class LanguageManager {
|
||||
return properties.getProperty(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加文本
|
||||
*/
|
||||
public void addText(String key, String value) {
|
||||
properties.setProperty(key, value);
|
||||
}
|
||||
|
||||
public String getLanguageName() {
|
||||
return languageName;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 用于注册设置项的类
|
||||
@@ -563,7 +564,7 @@ public class RegistrationSettingsItem extends WindowsJDialog {
|
||||
* @param tip 描述
|
||||
* @param registeredName 注册名(必须是唯一的)
|
||||
*/
|
||||
public void addSettings(JPanel tabbedPanesSettings,
|
||||
private void addSettings(JPanel tabbedPanesSettings,
|
||||
String title,
|
||||
Icon icon,
|
||||
String tip,
|
||||
@@ -579,6 +580,49 @@ public class RegistrationSettingsItem extends WindowsJDialog {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册设置项
|
||||
* @param tabbedPanesSettings 设置页面
|
||||
* @param title 标题
|
||||
* @param icon 显示图标(可为null)
|
||||
* @param tip 描述
|
||||
* @param plugin 插件
|
||||
* @param registeredName 注册名(必须是唯一的)
|
||||
*/
|
||||
public void addSettings(JPanel tabbedPanesSettings,
|
||||
String title,
|
||||
Icon icon,
|
||||
String tip,
|
||||
PluginDescriptor plugin,
|
||||
String registeredName) {
|
||||
if (mainWindow != null) {
|
||||
if (!mainWindow.isWindow()) {
|
||||
registrationItem(tabbedPanesSettings, title, icon, tip,plugin.getRegistrationName()
|
||||
+ ":" +
|
||||
registeredName);
|
||||
} else {
|
||||
logger.warn("Wrong time to add tools");
|
||||
}
|
||||
} else {
|
||||
registrationItem(tabbedPanesSettings, title, icon, tip, registeredName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 PluginDescriptor 查询整个插件装载的注册项
|
||||
* @param plugin 插件描述符
|
||||
* @return List<RegistrationSettingsItem> 与指定插件相关的注册设置项列表
|
||||
*/
|
||||
public static List<RegistrationSettingsItem> getRegistrationsByPlugin(PluginDescriptor plugin) {
|
||||
return registrationSettingsItemList.stream()
|
||||
.filter(item ->
|
||||
item.getRegisteredNameList().stream()
|
||||
.anyMatch(name ->
|
||||
name.startsWith(plugin.getRegistrationName() + ":"))
|
||||
)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void registrationItem(JPanel tabbedPanesSettings, String title, Icon icon, String tip, String registeredName) {
|
||||
if (registeredNameList.contains(registeredName)) {
|
||||
throw new RegistrationError(registeredName + " duplicate registered names");
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.axis.innovators.box.AxisInnovatorsBox;
|
||||
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.plugins.PluginDescriptor;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -24,6 +25,7 @@ public class RegistrationTool {
|
||||
private final AxisInnovatorsBox main;
|
||||
private final List<UUID> uuidList = new ArrayList<>();
|
||||
private final List<String> registeredNameList = new ArrayList<>();
|
||||
private final List<PluginDescriptor> pluginDescriptors = new ArrayList<>();
|
||||
|
||||
public RegistrationTool(AxisInnovatorsBox main) {
|
||||
this.main = main;
|
||||
@@ -66,7 +68,7 @@ public class RegistrationTool {
|
||||
* 注册ToolCategory
|
||||
* @param toolCategory ToolCategory
|
||||
*/
|
||||
public void addToolCategory(MainWindow.ToolCategory toolCategory,
|
||||
private boolean addToolCategory(MainWindow.ToolCategory toolCategory,
|
||||
String registeredName) {
|
||||
if (!main.isWindow()) {
|
||||
if (registeredNameList.contains(registeredName)) {
|
||||
@@ -75,8 +77,24 @@ public class RegistrationTool {
|
||||
uuidList.add(toolCategory.getId());
|
||||
registeredNameList.add(registeredName);
|
||||
toolCategories.add(toolCategory);
|
||||
return true;
|
||||
} else {
|
||||
logger.warn("Wrong time to add tools");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册ToolCategory
|
||||
* @param toolCategory ToolCategory
|
||||
*/
|
||||
public void addToolCategory(MainWindow.ToolCategory toolCategory,
|
||||
PluginDescriptor pluginDescriptor,
|
||||
String registeredName) {
|
||||
if (addToolCategory(toolCategory,
|
||||
pluginDescriptor.getRegistrationName() + ":" +
|
||||
registeredName)) {
|
||||
pluginDescriptors.add(pluginDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
83
src/main/java/com/axis/innovators/box/tools/ArgsParser.java
Normal file
83
src/main/java/com/axis/innovators/box/tools/ArgsParser.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package com.axis.innovators.box.tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ArgsParser 类用于解析命令行参数,并返回包含合法文件信息的列表。
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class ArgsParser {
|
||||
|
||||
/**
|
||||
* 判断路径是否合法(存在且是文件)
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @return 是否合法
|
||||
*/
|
||||
private static boolean isValidPath(String path) {
|
||||
File file = new File(path);
|
||||
return file.exists() && file.isFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件的后缀名
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @return 文件后缀名(如 ".txt")
|
||||
*/
|
||||
private static String getFileExtension(String path) {
|
||||
int lastDotIndex = path.lastIndexOf('.');
|
||||
if (lastDotIndex == -1) {
|
||||
return ""; // 没有后缀名
|
||||
}
|
||||
return path.substring(lastDotIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 args 参数并保存合法的文件路径
|
||||
*
|
||||
* @param args main 方法的参数
|
||||
* @return 包含合法文件信息的列表,每个元素是一个 Map,包含 "extension" 和 "path"
|
||||
*/
|
||||
public static List<Map<String, String>> parseArgs(String[] args) {
|
||||
List<Map<String, String>> validFiles = new ArrayList<>();
|
||||
|
||||
for (String arg : args) {
|
||||
if (isValidPath(arg)) {
|
||||
String extension = getFileExtension(arg);
|
||||
|
||||
Map<String, String> fileInfo = new HashMap<>();
|
||||
fileInfo.put("extension", extension);
|
||||
fileInfo.put("path", arg);
|
||||
|
||||
validFiles.add(fileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return validFiles;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 模拟 main 方法的 args 参数
|
||||
String[] testArgs = {
|
||||
"C:\\Program Files\\test.txt", // 合法文件
|
||||
"C:\\invalid_file.exe", // 不存在的文件
|
||||
"D:\\Documents\\report.pdf", // 合法文件
|
||||
"not_a_path", // 无效路径
|
||||
"C:\\Windows\\system32" // 目录,不是文件
|
||||
};
|
||||
|
||||
// 解析 args 参数
|
||||
List<Map<String, String>> validFiles = parseArgs(testArgs);
|
||||
|
||||
// 输出结果
|
||||
System.out.println("Valid files:");
|
||||
for (Map<String, String> fileInfo : validFiles) {
|
||||
System.out.println("Extension: " + fileInfo.get("extension") + ", Path: " + fileInfo.get("path"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ public class StateManager {
|
||||
* @param statusName 状态文件名
|
||||
*/
|
||||
public StateManager(String statusName) {
|
||||
statusFile = FolderCreator.getConfigurationFolder() + statusName + ".properties";
|
||||
statusFile = FolderCreator.getConfigurationFolder() + "\\" + statusName + ".properties";
|
||||
configMap = new HashMap<>();
|
||||
properties = new Properties();
|
||||
loadConfiguration();
|
||||
@@ -32,7 +32,7 @@ public class StateManager {
|
||||
* 默认构造函数
|
||||
*/
|
||||
public StateManager() {
|
||||
statusFile = FolderCreator.getConfigurationFolder() + "state_management.properties";
|
||||
statusFile = FolderCreator.getConfigurationFolder() + "\\toolbox.properties";
|
||||
configMap = new HashMap<>();
|
||||
properties = new Properties();
|
||||
loadConfiguration();
|
||||
|
||||
Reference in New Issue
Block a user