From ad73d3a71cc0887ba983c551e43e5c6a1af90eb3 Mon Sep 17 00:00:00 2001 From: gewuyou <1063891901@qq.com> Date: Thu, 5 Oct 2023 15:28:33 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A9=20=E5=AE=8C=E5=96=84=20=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E6=96=87=E4=BB=B6=E6=A0=B9=E8=B7=AF=E5=BE=84=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/jcnc/jnotepad/LunchApp.java | 2 +- .../config/BaseConfigController.java | 4 +- .../jcnc/jnotepad/app/config/AppConfig.java | 48 +++++++++++- .../app/manager/ApplicationManager.java | 55 ++++++++++++-- .../common/constants/AppConstants.java | 4 + .../module/interfaces/ControllerAble.java | 6 +- .../component/stage/setting/SetStage.java | 3 + .../controller/ResourceController.java | 50 +------------ .../config/AppConfigController.java | 5 +- .../config/PluginConfigController.java | 6 +- .../config/UserConfigController.java | 3 +- .../controller/manager/Controller.java | 2 +- .../jcnc/jnotepad/plugin/PluginLoader.java | 38 ++++++++++ .../java/org/jcnc/jnotepad/util/FileUtil.java | 73 ++++++++++++++++++- 14 files changed, 231 insertions(+), 68 deletions(-) diff --git a/src/main/java/org/jcnc/jnotepad/LunchApp.java b/src/main/java/org/jcnc/jnotepad/LunchApp.java index 7d6efea..4fd23bb 100644 --- a/src/main/java/org/jcnc/jnotepad/LunchApp.java +++ b/src/main/java/org/jcnc/jnotepad/LunchApp.java @@ -47,6 +47,6 @@ public class LunchApp extends Application { @Override public void stop() { - APPLICATION_MANAGER.stopApp(); + APPLICATION_MANAGER.operationBeforeStopping(); } } diff --git a/src/main/java/org/jcnc/jnotepad/api/core/controller/config/BaseConfigController.java b/src/main/java/org/jcnc/jnotepad/api/core/controller/config/BaseConfigController.java index d3561fa..b5bc79e 100644 --- a/src/main/java/org/jcnc/jnotepad/api/core/controller/config/BaseConfigController.java +++ b/src/main/java/org/jcnc/jnotepad/api/core/controller/config/BaseConfigController.java @@ -22,7 +22,9 @@ import java.nio.file.Paths; */ public abstract class BaseConfigController implements ConfigController { - public static final String ROOT_CONFIG_DIR = "config"; + protected final String rootConfigDir = "config"; + + protected final String systemConfigDir = "system"; protected T config; Logger logger = LogUtil.getLogger(this.getClass()); diff --git a/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java b/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java index 8423b5e..c2488af 100644 --- a/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java +++ b/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java @@ -1,8 +1,15 @@ package org.jcnc.jnotepad.app.config; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.io.File; +import java.nio.file.Paths; +import java.util.Collections; import java.util.Optional; +import java.util.Set; import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY; +import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY; /** * 应用程序配置文件 @@ -14,12 +21,51 @@ public class AppConfig { * 程序根路径 */ private String rootPath; + /** + * 排除的文件夹 + */ + @JsonIgnore + private final Set ignoreFolder; + /** + * 排除的文件 + */ + @JsonIgnore + private final Set ignoreFile; + /** + * 上次的程序根路径 + */ + @JsonIgnore + private String lastRootPath; + + public AppConfig() { + ignoreFolder = Set.of( + new File(Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY, "system").toString()), + new File(Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY, "logs").toString()) + ); + ignoreFile = Collections.emptySet(); + } public String getRootPath() { - return Optional.of(rootPath).orElse(System.getProperty(DEFAULT_PROPERTY)); + return Optional.ofNullable(rootPath).orElse(System.getProperty(DEFAULT_PROPERTY)); } public void setRootPath(String rootPath) { this.rootPath = rootPath; } + + public String getLastRootPath() { + return lastRootPath; + } + + public void setLastRootPath(String lastRootPath) { + this.lastRootPath = lastRootPath; + } + + public Set getIgnoreFolder() { + return ignoreFolder; + } + + public Set getIgnoreFile() { + return ignoreFile; + } } diff --git a/src/main/java/org/jcnc/jnotepad/app/manager/ApplicationManager.java b/src/main/java/org/jcnc/jnotepad/app/manager/ApplicationManager.java index 4808e31..7809837 100644 --- a/src/main/java/org/jcnc/jnotepad/app/manager/ApplicationManager.java +++ b/src/main/java/org/jcnc/jnotepad/app/manager/ApplicationManager.java @@ -8,24 +8,35 @@ import javafx.scene.layout.Pane; import javafx.stage.Stage; import javafx.stage.Window; import org.jcnc.jnotepad.LunchApp; +import org.jcnc.jnotepad.app.config.AppConfig; import org.jcnc.jnotepad.app.i18n.UiResourceBundle; import org.jcnc.jnotepad.common.constants.AppConstants; import org.jcnc.jnotepad.common.constants.TextConstants; import org.jcnc.jnotepad.common.manager.ThreadPoolManager; import org.jcnc.jnotepad.controller.ResourceController; import org.jcnc.jnotepad.controller.cache.CacheController; +import org.jcnc.jnotepad.controller.config.AppConfigController; import org.jcnc.jnotepad.controller.config.PluginConfigController; +import org.jcnc.jnotepad.controller.exception.AppException; import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.plugin.manager.PluginManager; +import org.jcnc.jnotepad.util.FileUtil; import org.jcnc.jnotepad.util.LogUtil; import org.jcnc.jnotepad.util.UiUtil; import org.jcnc.jnotepad.views.manager.*; +import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.concurrent.ExecutorService; +import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY; +import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY; + /** * 应用程序管理类
@@ -130,11 +141,42 @@ public class ApplicationManager { } /** - * 停止程序 + * 迁移程序根文件夹 + */ + public void migrateFileRootFolder() { + AppConfig config = AppConfigController.getInstance().getConfig(); + String lastRootPath = config.getLastRootPath(); + if (lastRootPath == null) { + return; + } + // 获取源文件夹 + File sourceFolder = new File(lastRootPath, PROGRAM_FILE_DIRECTORY); + // 获取目标文件夹 + File targetFolder = new File(config.getRootPath(), PROGRAM_FILE_DIRECTORY); + // 设置忽略文件夹 + Set ignoredFolders = config.getIgnoreFolder(); + // 设置忽略文件 + Set ignoredFiles = config.getIgnoreFile(); + // 移动文件夹 + FileUtil.migrateFolder(sourceFolder, targetFolder, ignoredFolders, ignoredFiles); + // 删除.jnotepad + if (!sourceFolder.equals(new File(Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY).toString()))) { + try { + Files.delete(sourceFolder.toPath()); + } catch (IOException e) { + throw new AppException(e); + } + } + // 保存新配置 + AppConfigController.getInstance().writeConfig(); + } + + /** + * 停止前操作 * * @apiNote 在停止程序之前会执行此操作 */ - public void stopApp() { + public void operationBeforeStopping() { PluginConfigController pluginConfigController = PluginConfigController.getInstance(); // 刷新插件配置文件 pluginConfigController.getConfig().setPlugins(PluginManager.getInstance().getPluginDescriptors()); @@ -146,6 +188,8 @@ public class ApplicationManager { CenterTabPaneManager.getInstance().saveOpenFileTabs(); // 将缓存写入本地 CacheController.getInstance().writeCaches(); + // 迁移文件夹 + migrateFileRootFolder(); // 关闭线程池 threadPool.shutdownNow(); } @@ -205,12 +249,11 @@ public class ApplicationManager { // 构建新进程来重新启动应用程序 ProcessBuilder builder = new ProcessBuilder(javaCommand, "-cp", System.getProperty("java.class.path"), mainClass); builder.start(); - // 关闭当前应用程序 - System.exit(0); + // fixme 使用这个System.exit(0);,在开发环境,点击重启程序,停止前操作不生效 + stop(); } catch (IOException e) { LogUtil.getLogger("正在重启当前应用程序".getClass()); - } } @@ -239,7 +282,7 @@ public class ApplicationManager { this.primaryStage = primaryStage; } - public void stopApplication() { + public void stop() { Platform.exit(); } } diff --git a/src/main/java/org/jcnc/jnotepad/common/constants/AppConstants.java b/src/main/java/org/jcnc/jnotepad/common/constants/AppConstants.java index f318e86..d61e7a2 100644 --- a/src/main/java/org/jcnc/jnotepad/common/constants/AppConstants.java +++ b/src/main/java/org/jcnc/jnotepad/common/constants/AppConstants.java @@ -44,6 +44,10 @@ public class AppConstants { * 默认属性 */ public static final String DEFAULT_PROPERTY = "user.home"; + /** + * 程序文件目录 + */ + public static final String PROGRAM_FILE_DIRECTORY = ".jnotepad"; /** diff --git a/src/main/java/org/jcnc/jnotepad/component/module/interfaces/ControllerAble.java b/src/main/java/org/jcnc/jnotepad/component/module/interfaces/ControllerAble.java index 72de36f..eaaf6c2 100644 --- a/src/main/java/org/jcnc/jnotepad/component/module/interfaces/ControllerAble.java +++ b/src/main/java/org/jcnc/jnotepad/component/module/interfaces/ControllerAble.java @@ -1,7 +1,5 @@ package org.jcnc.jnotepad.component.module.interfaces; -import java.util.List; - /** * 控制器接口类 * @@ -9,14 +7,14 @@ import java.util.List; * * @author 许轲 */ -public interface ControllerAble { +public interface ControllerAble { /** * 打开关联文件并创建 TextArea。 * * @param rawParameters 原始参数列表 */ - void openAssociatedFileAndCreateTextArea(List rawParameters); + void openAssociatedFileAndCreateTextArea(T rawParameters); /** * 打开关联文件。 diff --git a/src/main/java/org/jcnc/jnotepad/component/stage/setting/SetStage.java b/src/main/java/org/jcnc/jnotepad/component/stage/setting/SetStage.java index e9b2825..077290b 100644 --- a/src/main/java/org/jcnc/jnotepad/component/stage/setting/SetStage.java +++ b/src/main/java/org/jcnc/jnotepad/component/stage/setting/SetStage.java @@ -266,6 +266,9 @@ public class SetStage extends Stage { cache.setCacheData(file.getParent()); cacheManager.addCache(cache); } + // 设置上次的根路径 + config.setLastRootPath(config.getRootPath()); + // 设置当前根路径 config.setRootPath(file.getAbsolutePath()); PopUpUtil.questionAlert("更改", "设置程序文件根路径", "设置成功,请重启程序以应用路径更改!", appDialog -> { appDialog.close(); diff --git a/src/main/java/org/jcnc/jnotepad/controller/ResourceController.java b/src/main/java/org/jcnc/jnotepad/controller/ResourceController.java index b7dada8..8ac7794 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/ResourceController.java +++ b/src/main/java/org/jcnc/jnotepad/controller/ResourceController.java @@ -1,25 +1,15 @@ package org.jcnc.jnotepad.controller; -import org.jcnc.jnotepad.controller.config.PluginConfigController; -import org.jcnc.jnotepad.controller.exception.AppException; import org.jcnc.jnotepad.controller.i18n.LocalizationController; import org.jcnc.jnotepad.plugin.PluginLoader; -import org.jcnc.jnotepad.util.LogUtil; -import org.slf4j.Logger; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.stream.Stream; /** - * 资源控制器:用于加载程序所需的资源 + * 资源控制器 * * @author gewuyou */ public class ResourceController { private static final ResourceController INSTANCE = new ResourceController(); - Logger logger = LogUtil.getLogger(this.getClass()); private ResourceController() { } @@ -33,42 +23,6 @@ public class ResourceController { // 1. 加载语言 LocalizationController.initLocal(); // 2. 加载插件 - loadPlugins(); - } - - /** - * 装载插件 - * - * @since 2023/9/15 21:39 - */ - public void loadPlugins() { - // 扫描并装载插件 - scanLoadPlugins(PluginConfigController.getInstance().getPlungsPath()); - } - - - /** - * 扫描插件 - * - * @param pluginsPath 插件路径 - * @apiNote 扫描所有插件,更新配置文件中的插件信息 - * @since 2023/9/16 0:21 - */ - - private void scanLoadPlugins(Path pluginsPath) { - if (!Files.isDirectory(pluginsPath)) { - try { - Files.createDirectory(pluginsPath); - } catch (IOException e) { - throw new AppException("这不是一个有效的路径!"); - } - } - // 获取插件加载器 - PluginLoader pluginLoader = PluginLoader.getInstance(); - try (Stream pathStream = Files.walk(pluginsPath)) { - pathStream.filter(path -> path.toString().endsWith(".jar")).forEach(path -> pluginLoader.loadPluginByPath(path.toString())); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } + PluginLoader.getInstance().loadPlugins(); } } diff --git a/src/main/java/org/jcnc/jnotepad/controller/config/AppConfigController.java b/src/main/java/org/jcnc/jnotepad/controller/config/AppConfigController.java index 5e67393..da06385 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/config/AppConfigController.java +++ b/src/main/java/org/jcnc/jnotepad/controller/config/AppConfigController.java @@ -6,6 +6,7 @@ import org.jcnc.jnotepad.app.config.AppConfig; import java.nio.file.Paths; import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY; +import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY; /** * 应用程序配置文件控制器 @@ -23,12 +24,12 @@ public class AppConfigController extends BaseConfigController { /** * 配置文件名 */ - public static final String CONFIG_NAME = "appConfig.json"; + public static final String CONFIG_NAME = "JNotepadConfig.json"; private final String configDir; public AppConfigController() { - configDir = Paths.get(System.getProperty(DEFAULT_PROPERTY), ".jnotepad", ROOT_CONFIG_DIR).toString(); + configDir = Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY, systemConfigDir).toString(); loadConfig(); } diff --git a/src/main/java/org/jcnc/jnotepad/controller/config/PluginConfigController.java b/src/main/java/org/jcnc/jnotepad/controller/config/PluginConfigController.java index 085c56b..3568c32 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/config/PluginConfigController.java +++ b/src/main/java/org/jcnc/jnotepad/controller/config/PluginConfigController.java @@ -7,6 +7,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY; + /** * 插件控制器 * @@ -24,8 +26,8 @@ public class PluginConfigController extends BaseConfigController { private PluginConfigController() { String rootPath = AppConfigController.getInstance().getConfig().getRootPath(); - configDir = Paths.get(rootPath, ".jnotepad", ROOT_CONFIG_DIR).toString(); - setPluginsDir(Paths.get(rootPath, ".jnotepad", "plugins").toString()); + configDir = Paths.get(rootPath, PROGRAM_FILE_DIRECTORY, rootConfigDir).toString(); + setPluginsDir(Paths.get(rootPath, PROGRAM_FILE_DIRECTORY, "plugins").toString()); loadConfig(); } diff --git a/src/main/java/org/jcnc/jnotepad/controller/config/UserConfigController.java b/src/main/java/org/jcnc/jnotepad/controller/config/UserConfigController.java index c0c88ce..3db3c65 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/config/UserConfigController.java +++ b/src/main/java/org/jcnc/jnotepad/controller/config/UserConfigController.java @@ -8,6 +8,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY; import static org.jcnc.jnotepad.common.constants.TextConstants.CHINESE; /** @@ -31,7 +32,7 @@ public class UserConfigController extends BaseConfigController { private String configDir; private UserConfigController() { - configDir = Paths.get(AppConfigController.getInstance().getConfig().getRootPath(), ".jnotepad", ROOT_CONFIG_DIR).toString(); + configDir = Paths.get(AppConfigController.getInstance().getConfig().getRootPath(), PROGRAM_FILE_DIRECTORY, rootConfigDir).toString(); loadConfig(); } diff --git a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java index c299b2f..9b6b851 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java +++ b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java @@ -15,7 +15,7 @@ import java.util.Optional; * * @author 许轲 */ -public class Controller implements ControllerAble { +public class Controller implements ControllerAble> { private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance(); private static final Controller INSTANCE = new Controller(); diff --git a/src/main/java/org/jcnc/jnotepad/plugin/PluginLoader.java b/src/main/java/org/jcnc/jnotepad/plugin/PluginLoader.java index 09aa933..865d271 100644 --- a/src/main/java/org/jcnc/jnotepad/plugin/PluginLoader.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/PluginLoader.java @@ -14,10 +14,13 @@ import java.io.*; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.stream.Stream; import java.util.zip.ZipEntry; /** @@ -244,4 +247,39 @@ public class PluginLoader { logger.info("已加载插件:{}", pluginDescriptor.getName()); return pluginClass; } + + /** + * 装载插件 + * + * @since 2023/9/15 21:39 + */ + public void loadPlugins() { + // 扫描并装载插件 + scanLoadPlugins(PluginConfigController.getInstance().getPlungsPath()); + } + + /** + * 扫描插件 + * + * @param pluginsPath 插件路径 + * @apiNote 扫描所有插件,更新配置文件中的插件信息 + * @since 2023/9/16 0:21 + */ + + private void scanLoadPlugins(Path pluginsPath) { + if (!Files.isDirectory(pluginsPath)) { + try { + Files.createDirectory(pluginsPath); + } catch (IOException e) { + throw new AppException("这不是一个有效的路径!"); + } + } + // 获取插件加载器 + PluginLoader pluginLoader = PluginLoader.getInstance(); + try (Stream pathStream = Files.walk(pluginsPath)) { + pathStream.filter(path -> path.toString().endsWith(".jar")).forEach(path -> pluginLoader.loadPluginByPath(path.toString())); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } } diff --git a/src/main/java/org/jcnc/jnotepad/util/FileUtil.java b/src/main/java/org/jcnc/jnotepad/util/FileUtil.java index aefab59..f2a0560 100644 --- a/src/main/java/org/jcnc/jnotepad/util/FileUtil.java +++ b/src/main/java/org/jcnc/jnotepad/util/FileUtil.java @@ -15,6 +15,7 @@ import java.nio.file.StandardCopyOption; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Set; import static org.kordamp.ikonli.antdesignicons.AntDesignIconsFilled.*; @@ -170,7 +171,7 @@ public class FileUtil { * @since 2023/10/5 12:18 */ - private static void migrateFolder(File sourceFolder, File targetFolder) { + public static void migrateFolder(File sourceFolder, File targetFolder) { // 创建目标文件夹 targetFolder.mkdirs(); @@ -197,4 +198,74 @@ public class FileUtil { } } + /** + * 迁移文件夹 + * + * @param sourceFolder 源文件夹 + * @param targetFolder 目标文件夹 + * @param ignoredFolders 忽略的文件夹集合 + * @param ignoredFiles 忽略的文件集合 + * @since 2023/10/5 13:58 + */ + public static void migrateFolder(File sourceFolder, File targetFolder, Set ignoredFolders, Set ignoredFiles) { + // 创建目标文件夹 + targetFolder.mkdir(); + // 获取源文件夹中的所有文件和文件夹 + File[] files = sourceFolder.listFiles(); + if (files != null) { + // 遍历源文件夹中的每个文件和文件夹 + for (File file : files) { + // 如果是文件夹且不是忽略的文件夹,递归调用自身进行迁移 + if (file.isDirectory() && !ignoredFolders.contains(file)) { + migrateFolder(targetFolder, ignoredFolders, ignoredFiles, file); + continue; + } + // 如果是文件且不是忽略的文件,将文件复制到目标文件夹中 + if (!file.isDirectory() && !ignoredFiles.contains(file)) { + migrateFile(targetFolder, file); + } + } + } + } + + /** + * 迁移文件 + * + * @param targetFolder 目标文件夹 + * @param file 文件 + */ + public static void migrateFile(File targetFolder, File file) { + Path sourceFilePath = file.toPath(); + Path targetFilePath = new File(targetFolder, file.getName()).toPath(); + try { + Files.copy(sourceFilePath, targetFilePath, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new AppException(e); + } + // 删除源文件 + try { + Files.delete(file.toPath()); + } catch (IOException e) { + throw new AppException(e); + } + } + + /** + * 迁移文件夹 + * + * @param targetFolder 目标文件夹 + * @param ignoredFolders 忽略的文件夹集合 + * @param ignoredFiles 忽略的文件集合 + * @param file 文件 + */ + private static void migrateFolder(File targetFolder, Set ignoredFolders, Set ignoredFiles, File file) { + migrateFolder(file, new File(targetFolder, file.getName()), ignoredFolders, ignoredFiles); + // 调用完毕删除当前目录 + try { + Files.deleteIfExists(file.toPath()); + } catch (IOException e) { + throw new AppException(e); + } + } } +