From da0db4c6db77ee7754021efe74f952c5b68c3123 Mon Sep 17 00:00:00 2001 From: zhuhuawu Date: Tue, 13 Dec 2022 11:20:07 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E4=BB=A3=E7=90=86=E7=9A=84Extra=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../starblues/spring/extract/DefaultOpExtractFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-brick/src/main/java/com/gitee/starblues/spring/extract/DefaultOpExtractFactory.java b/spring-brick/src/main/java/com/gitee/starblues/spring/extract/DefaultOpExtractFactory.java index 0aacb0c..a2a9436 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/spring/extract/DefaultOpExtractFactory.java +++ b/spring-brick/src/main/java/com/gitee/starblues/spring/extract/DefaultOpExtractFactory.java @@ -19,6 +19,7 @@ package com.gitee.starblues.spring.extract; import com.gitee.starblues.annotation.Extract; import com.gitee.starblues.utils.ObjectUtils; import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.ClassUtils; import java.util.*; @@ -184,7 +185,7 @@ public class DefaultOpExtractFactory implements OpExtractFactory { } private Extract getExtract(Object extractObject){ - return extractObject.getClass().getAnnotation(Extract.class); + return AnnotationUtils.findAnnotation(extractObject.getClass(),Extract.class); } -- Gitee From b91f9b254f021ef79ebfaadd85136cd85b75b906 Mon Sep 17 00:00:00 2001 From: StarBlues Date: Sun, 21 May 2023 19:56:31 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=88=B03.1.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- spring-brick-bootstrap/pom.xml | 2 +- spring-brick-common/pom.xml | 2 +- .../gitee/starblues/common/ManifestKey.java | 5 --- spring-brick-loader/pom.xml | 2 +- .../starblues/loader/LoaderConstant.java | 1 - .../loader/BaseURLResourceLoader.java | 36 +++++++++++++++++++ .../classpath/JarOutClasspathResource.java | 31 +++------------- .../coexist/CoexistJarOuterLauncher.java | 12 +++++-- .../isolation/IsolationJarOuterLauncher.java | 9 +++-- spring-brick-maven-packager/pom.xml | 2 +- .../plugin-help.xml | 2 +- .../main/resources/META-INF/maven/plugin.xml | 2 +- spring-brick/pom.xml | 2 +- .../NestedPluginJarResourceLoader.java | 2 ++ .../operator/DefaultPluginOperator.java | 3 +- update.md | 11 +++--- 17 files changed, 74 insertions(+), 52 deletions(-) create mode 100644 spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/loader/BaseURLResourceLoader.java diff --git a/pom.xml b/pom.xml index 9a9e053..def3519 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ com.gitee.starblues spring-brick-parent pom - 3.1.1 + 3.1.2 spring-brick-common diff --git a/spring-brick-bootstrap/pom.xml b/spring-brick-bootstrap/pom.xml index bb30410..0bf2be4 100644 --- a/spring-brick-bootstrap/pom.xml +++ b/spring-brick-bootstrap/pom.xml @@ -7,7 +7,7 @@ spring-brick-parent com.gitee.starblues - 3.1.1 + 3.1.2 spring-brick-bootstrap diff --git a/spring-brick-common/pom.xml b/spring-brick-common/pom.xml index e3b63b2..28acc18 100644 --- a/spring-brick-common/pom.xml +++ b/spring-brick-common/pom.xml @@ -7,7 +7,7 @@ spring-brick-parent com.gitee.starblues - 3.1.1 + 3.1.2 spring-brick-common diff --git a/spring-brick-common/src/main/java/com/gitee/starblues/common/ManifestKey.java b/spring-brick-common/src/main/java/com/gitee/starblues/common/ManifestKey.java index 0a33924..74b6267 100644 --- a/spring-brick-common/src/main/java/com/gitee/starblues/common/ManifestKey.java +++ b/spring-brick-common/src/main/java/com/gitee/starblues/common/ManifestKey.java @@ -78,11 +78,6 @@ public class ManifestKey { */ public static final String MAIN_LIB_DIR = "Lib-Dir"; - /** - * jar main lib indexes - */ - public static final String MAIN_LIB_INDEXES = "Lib-Indexes"; - /** * main package type diff --git a/spring-brick-loader/pom.xml b/spring-brick-loader/pom.xml index 2eee617..34b1da2 100644 --- a/spring-brick-loader/pom.xml +++ b/spring-brick-loader/pom.xml @@ -5,7 +5,7 @@ spring-brick-parent com.gitee.starblues - 3.1.1 + 3.1.2 4.0.0 diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/LoaderConstant.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/LoaderConstant.java index cf9da2c..bb7853e 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/LoaderConstant.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/LoaderConstant.java @@ -39,7 +39,6 @@ public class LoaderConstant { * ================= Manifest Key ===================== */ public static final String MAIN_LIB_DIR = "Lib-Dir"; - public static final String MAIN_LIB_INDEXES = "Lib-Indexes"; public static final String MAIN_LIB_INDEXES_SPLIT = " "; public static final String START_CLASS = "Start-Class"; diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/loader/BaseURLResourceLoader.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/loader/BaseURLResourceLoader.java new file mode 100644 index 0000000..5468cb8 --- /dev/null +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/loader/BaseURLResourceLoader.java @@ -0,0 +1,36 @@ +package com.gitee.starblues.loader.classloader.resource.loader; + +import com.gitee.starblues.loader.classloader.resource.storage.ResourceStorage; + +import java.net.URL; + +/** + * 基本 URL 资源加载 + * + * @author starBlues + * @since 3.1.2 + * @version 3.1.2 + */ +public class BaseURLResourceLoader implements ResourceLoader{ + + private final URL baseUrl; + + public BaseURLResourceLoader(URL baseUrl) { + this.baseUrl = baseUrl; + } + + @Override + public URL getBaseUrl() { + return baseUrl; + } + + @Override + public void load(ResourceStorage resourceStorage) throws Exception { + + } + + @Override + public void close() throws Exception { + + } +} diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/classpath/JarOutClasspathResource.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/classpath/JarOutClasspathResource.java index 3d382a3..31f0efe 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/classpath/JarOutClasspathResource.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/classpath/JarOutClasspathResource.java @@ -20,7 +20,7 @@ import com.gitee.starblues.loader.archive.Archive; import com.gitee.starblues.loader.archive.ExplodedArchive; import com.gitee.starblues.loader.archive.JarFileArchive; import com.gitee.starblues.loader.utils.FilesUtils; -import com.gitee.starblues.loader.utils.ObjectUtils; +import com.gitee.starblues.loader.utils.ResourceUtils; import lombok.AllArgsConstructor; import java.io.File; @@ -36,8 +36,8 @@ import static com.gitee.starblues.loader.LoaderConstant.*; * jar out 类型的 classpath 获取者 * * @author starBlues - * @version 3.1.0 * @since 3.0.4 + * @version 3.1.2 */ @AllArgsConstructor public class JarOutClasspathResource implements ClasspathResource{ @@ -93,8 +93,7 @@ public class JarOutClasspathResource implements ClasspathResource{ if(!libJarDir.exists()){ throw new IllegalStateException("主程序依赖目录不存在: " + libDir); } - List libIndexes = getLibIndexes(manifest); - File[] libJarFile = getLibJarFile(libJarDir, libIndexes); + File[] libJarFile = getLibJarFile(libJarDir); List urls = new ArrayList<>(libJarFile.length); for (File file : libJarFile) { urls.add(file.toPath().toUri().toURL()); @@ -102,31 +101,11 @@ public class JarOutClasspathResource implements ClasspathResource{ return urls; } - private List getLibIndexes(Manifest manifest){ - String libIndexes = manifest.getMainAttributes().getValue(MAIN_LIB_INDEXES); - if(ObjectUtils.isEmpty(libIndexes)){ - return Collections.emptyList(); - } - String[] indexSplit = libIndexes.split(MAIN_LIB_INDEXES_SPLIT); - List indexes = new ArrayList<>(indexSplit.length); - for (String index : indexSplit) { - if(ObjectUtils.isEmpty(index)){ - continue; - } - indexes.add(index); - } - if(indexes.isEmpty()){ - throw new IllegalStateException("主程序依赖包未发现!"); - } - return indexes; - } - - private File[] getLibJarFile(File rootFile, List libIndexes) { - Set linIndexes = new HashSet<>(libIndexes); + private File[] getLibJarFile(File rootFile) { File[] listFiles = rootFile.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { - return linIndexes.contains(pathname.getName()); + return ResourceUtils.isJarFile(pathname); } }); if(listFiles == null || listFiles.length == 0){ diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/coexist/CoexistJarOuterLauncher.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/coexist/CoexistJarOuterLauncher.java index 5adca6d..9ceb5ab 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/coexist/CoexistJarOuterLauncher.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/coexist/CoexistJarOuterLauncher.java @@ -17,6 +17,7 @@ package com.gitee.starblues.loader.launcher.coexist; import com.gitee.starblues.loader.classloader.GeneralUrlClassLoader; +import com.gitee.starblues.loader.classloader.resource.loader.MainJarResourceLoader; import com.gitee.starblues.loader.launcher.classpath.ClasspathResource; import com.gitee.starblues.loader.launcher.classpath.JarOutClasspathResource; import com.gitee.starblues.loader.launcher.runner.MethodRunner; @@ -26,12 +27,14 @@ import java.net.URL; import java.util.List; import java.util.Objects; +import static com.gitee.starblues.loader.LoaderConstant.PROD_CLASSES_URL_SIGN; + /** * 主程序jar-outer 模式启动者 * * @author starBlues - * @since 3.0.2 + * @since 3.1.2 * @version 3.0.2 */ public class CoexistJarOuterLauncher extends CoexistBaseLauncher { @@ -54,7 +57,12 @@ public class CoexistJarOuterLauncher extends CoexistBaseLauncher { super.addResource(classLoader); List classpath = classpathResource.getClasspath(); for (URL url : classpath) { - classLoader.addResource(url); + String path = url.getPath(); + if(path.contains(PROD_CLASSES_URL_SIGN)){ + classLoader.addResource(new MainJarResourceLoader(url)); + } else { + classLoader.addResource(url); + } } } diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/isolation/IsolationJarOuterLauncher.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/isolation/IsolationJarOuterLauncher.java index 3519c76..8b5553f 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/isolation/IsolationJarOuterLauncher.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/launcher/isolation/IsolationJarOuterLauncher.java @@ -37,7 +37,7 @@ import static com.gitee.starblues.loader.LoaderConstant.PROD_CLASSES_URL_SIGN; * * @author starBlues * @since 3.0.2 - * @version 3.0.2 + * @version 3.1.2 */ public class IsolationJarOuterLauncher extends IsolationBaseLauncher { @@ -68,7 +68,12 @@ public class IsolationJarOuterLauncher extends IsolationBaseLauncher { baseResource.addAll(classpath); } for (URL url : baseResource) { - classLoader.addResource(url); + String path = url.getPath(); + if(path.contains(PROD_CLASSES_URL_SIGN)){ + classLoader.addResource(new MainJarResourceLoader(url)); + } else { + classLoader.addResource(url); + } } } diff --git a/spring-brick-maven-packager/pom.xml b/spring-brick-maven-packager/pom.xml index 8756df0..232833c 100644 --- a/spring-brick-maven-packager/pom.xml +++ b/spring-brick-maven-packager/pom.xml @@ -7,7 +7,7 @@ spring-brick-parent com.gitee.starblues - 3.1.1 + 3.1.2 spring-brick-maven-packager diff --git a/spring-brick-maven-packager/src/main/resources/META-INF/maven/com.gitee.starblues.springboot-plugin-maven-packager/plugin-help.xml b/spring-brick-maven-packager/src/main/resources/META-INF/maven/com.gitee.starblues.springboot-plugin-maven-packager/plugin-help.xml index 7579b25..d4f52ad 100644 --- a/spring-brick-maven-packager/src/main/resources/META-INF/maven/com.gitee.starblues.springboot-plugin-maven-packager/plugin-help.xml +++ b/spring-brick-maven-packager/src/main/resources/META-INF/maven/com.gitee.starblues.springboot-plugin-maven-packager/plugin-help.xml @@ -4,7 +4,7 @@ Spring Boot Plugin Maven Packager com.gitee.starblues spring-brick-maven-packager - 3.1.1 + 3.1.2 spring-brick-packager false true diff --git a/spring-brick-maven-packager/src/main/resources/META-INF/maven/plugin.xml b/spring-brick-maven-packager/src/main/resources/META-INF/maven/plugin.xml index 7579b25..d4f52ad 100644 --- a/spring-brick-maven-packager/src/main/resources/META-INF/maven/plugin.xml +++ b/spring-brick-maven-packager/src/main/resources/META-INF/maven/plugin.xml @@ -4,7 +4,7 @@ Spring Boot Plugin Maven Packager com.gitee.starblues spring-brick-maven-packager - 3.1.1 + 3.1.2 spring-brick-packager false true diff --git a/spring-brick/pom.xml b/spring-brick/pom.xml index 312573d..fa3ea42 100644 --- a/spring-brick/pom.xml +++ b/spring-brick/pom.xml @@ -7,7 +7,7 @@ spring-brick-parent com.gitee.starblues - 3.1.1 + 3.1.2 spring-brick diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/NestedPluginJarResourceLoader.java b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/NestedPluginJarResourceLoader.java index cce11fc..d7c770b 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/NestedPluginJarResourceLoader.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/NestedPluginJarResourceLoader.java @@ -76,6 +76,8 @@ public class NestedPluginJarResourceLoader extends AbstractResourceLoader { private void addClassPath(ResourceStorage resourceStorage, JarFile jarFile) throws Exception{ String classesPath = pluginDescriptor.getPluginClassPath(); Enumeration entries = jarFile.entries(); + resourceLoaderFactory.addResource(new BaseURLResourceLoader(baseUrl)); + resourceLoaderFactory.addResource(new BaseURLResourceLoader(new URL(baseUrl, "classes/"))); while (entries.hasMoreElements()){ JarEntry jarEntry = entries.nextElement(); if(!jarEntry.getName().startsWith(classesPath)){ diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java b/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java index a82bb51..77709d6 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java @@ -285,6 +285,8 @@ public class DefaultPluginOperator implements PluginOperator { // 将上传的插件拷贝到临时目录 try (FileOutputStream outputStream = new FileOutputStream(tempFile)){ IOUtils.copy(inputStream, outputStream); + } finally { + IOUtils.closeQuietly(inputStream); } try { // 解析该插件包 @@ -317,7 +319,6 @@ public class DefaultPluginOperator implements PluginOperator { verifyFailureDelete(tempFilePath, e); throw e; } finally { - IOUtils.closeQuietly(inputStream); // 删除临时文件 tempFile.deleteOnExit(); } diff --git a/update.md b/update.md index 34a5d56..de7cb66 100644 --- a/update.md +++ b/update.md @@ -1,7 +1,4 @@ -1. 【新增】主程序可通过`pluginInfo`对象获取插件的`ClassLoader`。 -2. 【新增】新增配置`plugin.pluginSwaggerScan`可禁用扫描插件的 `swagger` 接口。 -3. 【新增】插件配置文件`spring.profiles.active`的值可跟随主程序配置切换。 -4. 【新增】插件的日志可配置为跟随主程序日志配置打印。 -5. 【新增】补充常见打包的 `META-INF\MANIFEST.MF` 文件内容。 -6. 【优化】优化插件隔离模式下,内存占用过大的问题。 -7. 【修复[#I61INH](https://gitee.com/starblues/springboot-plugin-framework-parent/issues/I61INH)】修复`PluginUser#getBean(String name, boolean includeMainBeans)`返回的`Bean`错误 \ No newline at end of file +1. 【修复】修复主程序打成`jar-out`类型包时,无法加载主类的问题 +2. 【修复】修复插件包打成`jar-out`时无法加载依赖的问题 +3. 【修复】修复插件在运行状态无法加载类的问题 +4. 【修复】修复对同一个插件包重复安装时,源插件包被系统占用的问题 \ No newline at end of file -- Gitee From b0463bb4de651a94d7dbdb4603bdd21752ccfd9f Mon Sep 17 00:00:00 2001 From: StarBlues Date: Sun, 28 May 2023 16:32:21 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8D=B8=E8=BD=BD?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=8D=A0=E7=94=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gitee/starblues/utils/FilesUtils.java | 61 +++++++- .../gitee/starblues/utils/ObjectUtils.java | 14 +- .../loader/PluginResourceStorage.java | 47 +++++-- .../resource/loader/JarResourceLoader.java | 5 +- .../storage/AbstractResourceStorage.java | 23 +-- .../storage/CacheFastResourceStorage.java | 10 +- .../gitee/starblues/loader/jar/Handler.java | 24 +--- .../starblues/loader/jar/JarFileWrapper.java | 6 +- .../starblues/loader/utils/ResourceUtils.java | 43 ++++-- .../starblues/core/DefaultPluginManager.java | 25 ++-- .../starblues/core/PluginLauncherManager.java | 6 +- .../gitee/starblues/core/PluginManager.java | 6 +- .../descriptor/ComposeDescriptorLoader.java | 14 +- .../plugin/SpringPluginHookWrapper.java | 17 ++- .../involved/DefaultPluginLaunchInvolved.java | 13 +- .../operator/DefaultPluginOperator.java | 133 +++++++++++------- .../com/gitee/starblues/utils/LogUtils.java | 6 +- update.md | 4 +- 18 files changed, 307 insertions(+), 150 deletions(-) diff --git a/spring-brick-common/src/main/java/com/gitee/starblues/utils/FilesUtils.java b/spring-brick-common/src/main/java/com/gitee/starblues/utils/FilesUtils.java index 50c481d..34fa6ce 100644 --- a/spring-brick-common/src/main/java/com/gitee/starblues/utils/FilesUtils.java +++ b/spring-brick-common/src/main/java/com/gitee/starblues/utils/FilesUtils.java @@ -21,13 +21,15 @@ import com.gitee.starblues.common.PackageStructure; import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.util.List; /** * 文件工具类 * * @author starBlues * @since 3.0.0 - * @version 3.1.0 + * @version 3.1.2 */ public class FilesUtils { @@ -232,5 +234,62 @@ public class FilesUtils { return path.startsWith(Constants.RELATIVE_SIGN); } + /** + * 判断两文件是否在同一个目录下 + * @param file1 文件1 + * @param file2 文件2 + * @return 所属目录 + */ + public static File sameParent(File file1, File file2){ + if(file1 == null || file2 == null){ + return null; + } + File parentFile = file1.getParentFile(); + if(parentFile.equals(file2.getParentFile())){ + return parentFile; + } + return null; + } + + /** + * 判断某个目录是否存在于根目录下 + * @param rootPath 根目录 + * @param comparePath 比较的目录 + * @return boolean + */ + public static boolean includePath(Path rootPath, Path comparePath){ + if(rootPath == null || comparePath == null){ + return false; + } + return comparePath.toString().startsWith(rootPath.toString()); + } + + /** + * 是否为子文件 + * @param rootFile rootFile + * @param childFile 子文件 + * @return boolean + */ + public static boolean isChildFile(List rootFile, File childFile){ + if(ObjectUtils.isEmpty(rootFile) || childFile == null || !childFile.exists()){ + return false; + } + for (String fileStr : rootFile) { + File file = new File(fileStr); + if(!file.exists()){ + continue; + } + File[] files = file.listFiles(); + if(files == null){ + continue; + } + for (File f : files) { + if(f.equals(childFile)){ + return true; + } + } + } + return false; + } } diff --git a/spring-brick-common/src/main/java/com/gitee/starblues/utils/ObjectUtils.java b/spring-brick-common/src/main/java/com/gitee/starblues/utils/ObjectUtils.java index fede520..7e0172c 100644 --- a/spring-brick-common/src/main/java/com/gitee/starblues/utils/ObjectUtils.java +++ b/spring-brick-common/src/main/java/com/gitee/starblues/utils/ObjectUtils.java @@ -25,7 +25,7 @@ import java.util.*; * * @author starBlues * @since 3.0.0 - * @version 3.0.0 + * @version 3.1.2 */ public class ObjectUtils { @@ -270,6 +270,18 @@ public class ObjectUtils { return false; } + public static boolean equalsElement(Object element, Object... objects) { + if (element == null || objects == null) { + return false; + } + for (Object obj : objects) { + if (Objects.equals(element, obj)) { + return true; + } + } + return false; + } + public static boolean nullSafeEquals(Object o1, Object o2) { if (o1 == o2) { return true; diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/PluginResourceStorage.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/PluginResourceStorage.java index 7af081c..67ec8ec 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/PluginResourceStorage.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/PluginResourceStorage.java @@ -25,6 +25,7 @@ import java.io.Closeable; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -34,7 +35,7 @@ import java.util.concurrent.ConcurrentHashMap; * * @author starBlues * @since 3.0.0 - * @version 3.0.0 + * @version 3.1.2 */ public class PluginResourceStorage { @@ -45,11 +46,11 @@ public class PluginResourceStorage { * @param pluginId 插件id * @param pluginFileName 插件文件名称 */ - public static void addPlugin(String pluginId, String pluginFileName){ + public static void addPlugin(String pluginId, String pluginFileName, List libPath){ if(STORAGE_MAP.containsKey(pluginId)){ return; } - STORAGE_MAP.put(pluginId, new Storage(pluginFileName)); + STORAGE_MAP.put(pluginId, new Storage(pluginFileName, libPath)); } /** @@ -80,7 +81,7 @@ public class PluginResourceStorage { * @param file 插件文件 * @param jarFile 插件jar文件 */ - public static void addRootJarFile(File file, JarFile jarFile){ + public static void addRootJarFile(File file, JarFileWrapper jarFile){ STORAGE_MAP.forEach((k,v)->{ v.addRootJarFile(file, jarFile); }); @@ -91,9 +92,9 @@ public class PluginResourceStorage { * @param file 插件文件 * @return 插件jar文件 */ - public static JarFile getRootJarFile(File file){ + public static JarFileWrapper getRootJarFile(File file){ for (Storage value : STORAGE_MAP.values()) { - JarFile jarFile = value.getRootJarFile(file); + JarFileWrapper jarFile = value.getRootJarFile(file); if(jarFile != null){ return jarFile; } @@ -104,31 +105,37 @@ public class PluginResourceStorage { private static class Storage implements Closeable { private final String pluginFileName; - private final Map rootJarFileMap = new ConcurrentHashMap<>(); + private final List libPath; + private final Map rootJarFileMap = new ConcurrentHashMap<>(); private final Map> jarFileMap = new ConcurrentHashMap<>(); - public Storage(String pluginFileName) { + public Storage(String pluginFileName, List libPath) { this.pluginFileName = pluginFileName; + if(libPath == null){ + this.libPath = Collections.emptyList(); + } else { + this.libPath = libPath; + } } public void addJarFile(String name, AbstractJarFile jarFile){ if(name == null || jarFile == null){ return; } - if(name.contains(pluginFileName)){ + if(isAddFile(name)){ List jarFiles = jarFileMap.computeIfAbsent(name, k -> new ArrayList<>()); jarFiles.add(jarFile); } } - public void addRootJarFile(File file, JarFile jarFile){ + public void addRootJarFile(File file, JarFileWrapper jarFile){ String absolutePath = file.getAbsolutePath(); - if(absolutePath.contains(pluginFileName)){ + if(isAddFile(absolutePath)){ rootJarFileMap.put(file, jarFile); } } - public JarFile getRootJarFile(File file){ + public JarFileWrapper getRootJarFile(File file){ return rootJarFileMap.get(file); } @@ -145,15 +152,29 @@ public class PluginResourceStorage { IOUtils.closeQuietly(jarFile); } } - for (JarFile jarFile : rootJarFileMap.values()) { + for (JarFileWrapper jarFile : rootJarFileMap.values()) { if(jarFile == null){ continue; } + jarFile.canClosed(); IOUtils.closeQuietly(jarFile); } jarFileMap.clear(); rootJarFileMap.clear(); } + + private boolean isAddFile(String path){ + if(path.contains(pluginFileName)){ + return true; + } + for (String libPath : libPath) { + if(path.contains(libPath)){ + return true; + } + } + return false; + } + } diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/loader/JarResourceLoader.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/loader/JarResourceLoader.java index 48c4132..69d374b 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/loader/JarResourceLoader.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/loader/JarResourceLoader.java @@ -29,7 +29,7 @@ import java.util.jar.JarInputStream; * jar 资源加载者 * @author starBlues * @since 3.0.0 - * @version 3.1.1 + * @version 3.1.2 */ public class JarResourceLoader extends AbstractResourceLoader { @@ -75,6 +75,7 @@ public class JarResourceLoader extends AbstractResourceLoader { JarEntry jarEntry = null; while ((jarEntry = jarInputStream.getNextJarEntry()) != null) { if(excludeResource.exclude(jarEntry)){ + jarInputStream.closeEntry(); continue; } if(includeResource.include(jarEntry)){ @@ -84,8 +85,8 @@ public class JarResourceLoader extends AbstractResourceLoader { return getClassBytes(name, jarInputStream, false); }); resourceStorage.add(cacheResource); - jarInputStream.closeEntry(); } + jarInputStream.closeEntry(); } } finally { jarInputStream.close(); diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/storage/AbstractResourceStorage.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/storage/AbstractResourceStorage.java index 924633d..f915df5 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/storage/AbstractResourceStorage.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/storage/AbstractResourceStorage.java @@ -32,7 +32,7 @@ import java.util.*; * * @author starBlues * @since 3.0.0 - * @version 3.1.1 + * @version 3.1.2 */ public abstract class AbstractResourceStorage implements ResourceStorage { @@ -69,6 +69,7 @@ public abstract class AbstractResourceStorage implements ResourceStorage { IOUtils.closeQuietly(inputStream); } inputStreams.clear(); + hotUrls.clear(); baseUrls.clear(); } @@ -171,11 +172,9 @@ public abstract class AbstractResourceStorage implements ResourceStorage { addResource(resource); return resource; } catch (Exception e) { - e.printStackTrace(); return null; } } - return null; } @@ -211,6 +210,7 @@ public abstract class AbstractResourceStorage implements ResourceStorage { resource = null; return r; } + private boolean next() { if (resource != null) { return true; @@ -233,13 +233,20 @@ public abstract class AbstractResourceStorage implements ResourceStorage { return null; } Resource resource = new DefaultResource(name, baseUrl, existUrl); - try { - addResource(resource); - } catch (Exception e){ - // 忽略异常 - } + addResourceWrapper(resource); return resource; } } + private void addResourceWrapper(Resource resource){ + if(resource == null){ + return; + } + try { + addResource(resource); + } catch (Exception e){ + // 忽略异常 + } + } + } diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/storage/CacheFastResourceStorage.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/storage/CacheFastResourceStorage.java index 121ded3..b6b162d 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/storage/CacheFastResourceStorage.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/classloader/resource/storage/CacheFastResourceStorage.java @@ -33,15 +33,13 @@ import java.util.concurrent.TimeUnit; * * @author starBlues * @since 3.1.1 - * @version 3.1.1 + * @version 3.1.2 */ public class CacheFastResourceStorage extends AbstractResourceStorage { protected final MultiCache resourceStorage; private final ResourceStorage cacheResourceStorage; - private final List inputStreams = new ArrayList<>(); - private volatile boolean release = false; @SuppressWarnings("all") @@ -136,10 +134,8 @@ public class CacheFastResourceStorage extends AbstractResourceStorage { @Override public void close() throws Exception { resourceStorage.clear(ResourceUtils::release); - for (InputStream inputStream : inputStreams) { - IOUtils.closeQuietly(inputStream); - } - inputStreams.clear(); + IOUtils.closeQuietly(cacheResourceStorage); + super.close(); } diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/jar/Handler.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/jar/Handler.java index e8f61ed..517893d 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/jar/Handler.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/jar/Handler.java @@ -64,12 +64,6 @@ public class Handler extends URLStreamHandler { private static URL jarContextUrl; - private static SoftReference> rootFileCache; - - static { - rootFileCache = new SoftReference<>(null); - } - private final JarFile jarFile; private URLStreamHandler fallbackHandler; @@ -372,9 +366,9 @@ public class Handler extends URLStreamHandler { throw new IllegalStateException("Not a file URL"); } File file = new File(URI.create(name)); - JarFile jarFile = PluginResourceStorage.getRootJarFile(file); + JarFileWrapper jarFile = PluginResourceStorage.getRootJarFile(file); if (jarFile == null) { - jarFile = new JarFile(file); + jarFile = new JarFileWrapper(new JarFile(file)); PluginResourceStorage.addRootJarFile(file, jarFile); } return jarFile; @@ -383,20 +377,6 @@ public class Handler extends URLStreamHandler { } } - /** - * Add the given {@link JarFile} to the root file cache. - * @param sourceFile the source file to add - * @param jarFile the jar file. - */ - static void addToRootFileCache(File sourceFile, JarFile jarFile) { - Map cache = rootFileCache.get(); - if (cache == null) { - cache = new ConcurrentHashMap<>(); - rootFileCache = new SoftReference<>(cache); - } - cache.put(sourceFile, jarFile); - } - /** * If possible, capture a URL that is configured with the original jar handler so that * we can use it as a fallback context later. We can only do this if we know that we diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/jar/JarFileWrapper.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/jar/JarFileWrapper.java index 46d6d21..bc344a6 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/jar/JarFileWrapper.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/jar/JarFileWrapper.java @@ -40,7 +40,7 @@ import com.gitee.starblues.loader.utils.ObjectUtils; * * @author Phillip Webb */ -public class JarFileWrapper extends AbstractJarFile { +public class JarFileWrapper extends JarFile { private final String parentName; @@ -58,7 +58,7 @@ public class JarFileWrapper extends AbstractJarFile { } @Override - URL getUrl() throws MalformedURLException { + public URL getUrl() throws MalformedURLException { return this.parent.getUrl(); } @@ -88,7 +88,7 @@ public class JarFileWrapper extends AbstractJarFile { } @Override - public JarEntry getJarEntry(String name) { + public com.gitee.starblues.loader.jar.JarEntry getJarEntry(String name) { return this.parent.getJarEntry(name); } diff --git a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/utils/ResourceUtils.java b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/utils/ResourceUtils.java index 6af0671..440edc4 100644 --- a/spring-brick-loader/src/main/java/com/gitee/starblues/loader/utils/ResourceUtils.java +++ b/spring-brick-loader/src/main/java/com/gitee/starblues/loader/utils/ResourceUtils.java @@ -16,13 +16,11 @@ package com.gitee.starblues.loader.utils; + import java.io.File; import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.util.Objects; +import java.net.*; +import java.util.Collection; import java.util.function.Consumer; /** @@ -30,7 +28,7 @@ import java.util.function.Consumer; * * @author starBlues * @since 3.0.0 - * @version 3.0.0 + * @version 3.1.2 */ public class ResourceUtils { @@ -144,16 +142,36 @@ public class ResourceUtils { */ public static void release(final Object object, final Consumer consumer) { if (object instanceof Release) { - try { - ((Release)object).release(); - } catch (final Exception e) { - if (consumer != null) { - consumer.accept(e); + release((Release) object, consumer); + } + if(object instanceof Collection){ + Collection collection = (Collection) object; + for (Object o : collection) { + if(o instanceof Release){ + release((Release) o, consumer); } } } } + /** + * 释放资源 + * @param release release + * @param consumer consumer + */ + public static void release(final Release release, final Consumer consumer) { + if(release == null){ + return; + } + try { + release.release(); + } catch (final Exception e) { + if (consumer != null) { + consumer.accept(e); + } + } + } + /** * 获取存在的url * @param url url @@ -180,8 +198,9 @@ public class ResourceUtils { } catch (MalformedURLException e) { throw new IllegalArgumentException("非法:" + name); } + URLConnection uc = null; try { - URLConnection uc = url.openConnection(); + uc = url.openConnection(); if (uc instanceof HttpURLConnection) { HttpURLConnection hconn = (HttpURLConnection)uc; hconn.setRequestMethod("HEAD"); diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java b/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java index 66dcd01..00f63cd 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java @@ -50,7 +50,7 @@ import java.util.stream.Collectors; * 抽象的插件管理者 * @author starBlues * @since 3.0.0 - * @version 3.1.0 + * @version 3.1.2 */ public class DefaultPluginManager implements PluginManager{ @@ -190,6 +190,7 @@ public class DefaultPluginManager implements PluginManager{ String sourcePluginPath = pluginPath.toString(); try { // 解析插件 + PluginInfo pluginInfo = parse(pluginPath); // 检查是否存在当前插件 PluginInsideInfo plugin = getPlugin(pluginInfo.getPluginId()); @@ -352,7 +353,7 @@ public class DefaultPluginManager implements PluginManager{ } @Override - public synchronized PluginInfo getPluginInfo(String pluginId) { + public synchronized PluginInsideInfo getPluginInfo(String pluginId) { if(ObjectUtils.isEmpty(pluginId)){ return null; } @@ -360,23 +361,15 @@ public class DefaultPluginManager implements PluginManager{ if(wrapperInside == null){ wrapperInside = resolvedPlugins.get(pluginId); } - if(wrapperInside != null){ - return wrapperInside.toPluginInfo(); - } else { - return null; - } + return wrapperInside; } @Override - public synchronized List getPluginInfos() { - List pluginDescriptors = new ArrayList<>( + public synchronized List getPluginInfos() { + List pluginDescriptors = new ArrayList<>( resolvedPlugins.size() + startedPlugins.size()); - for (PluginInsideInfo wrapperInside : startedPlugins.values()) { - pluginDescriptors.add(wrapperInside.toPluginInfo()); - } - for (PluginInsideInfo wrapperInside : resolvedPlugins.values()) { - pluginDescriptors.add(wrapperInside.toPluginInfo()); - } + pluginDescriptors.addAll(startedPlugins.values()); + pluginDescriptors.addAll(resolvedPlugins.values()); return pluginDescriptors; } @@ -499,6 +492,7 @@ public class DefaultPluginManager implements PluginManager{ resultPath = targetFile.toPath(); } } else { + // 不在插件目录 File pluginFile = pluginPath.toFile(); pluginRootDir = new File(getDefaultPluginRoot()); File pluginRootDirFile = new File(getDefaultPluginRoot()); @@ -523,7 +517,6 @@ public class DefaultPluginManager implements PluginManager{ return resultPath; } - /** * 统一启动插件操作 * @param pluginInsideInfo PluginInsideInfo diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/PluginLauncherManager.java b/spring-brick/src/main/java/com/gitee/starblues/core/PluginLauncherManager.java index d48c543..4318ede 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/PluginLauncherManager.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/PluginLauncherManager.java @@ -48,7 +48,7 @@ import java.util.concurrent.ConcurrentHashMap; * 可引导启动的插件管理者 * @author starBlues * @since 3.0.0 - * @version 3.1.0 + * @version 3.1.2 */ public class PluginLauncherManager extends DefaultPluginManager{ @@ -129,9 +129,13 @@ public class PluginLauncherManager extends DefaultPluginManager{ } try { SpringPluginHook springPluginHook = registryPluginInfo.getSpringPluginHook(); + // 校验是否可停止 springPluginHook.stopVerify(); + // 关闭插件 springPluginHook.close(closeType); + // 移除插件相互调用缓存的信息 invokeSupperCache.remove(pluginId); + // 移除插件注册信息 registryInfo.remove(pluginId); super.stop(pluginInsideInfo, closeType); } catch (Exception e){ diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/PluginManager.java b/spring-brick/src/main/java/com/gitee/starblues/core/PluginManager.java index 5641ef1..7f453d1 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/PluginManager.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/PluginManager.java @@ -25,7 +25,7 @@ import java.util.List; * 插件管理者 * @author starBlues * @since 3.0.0 - * @version 3.0.0 + * @version 3.1.2 */ public interface PluginManager { @@ -125,12 +125,12 @@ public interface PluginManager { * @param pluginId 插件id * @return PluginDescriptor */ - PluginInfo getPluginInfo(String pluginId); + PluginInsideInfo getPluginInfo(String pluginId); /** * 得到全部的插件信息 * @return List PluginWrapper */ - List getPluginInfos(); + List getPluginInfos(); } diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/descriptor/ComposeDescriptorLoader.java b/spring-brick/src/main/java/com/gitee/starblues/core/descriptor/ComposeDescriptorLoader.java index f8aa241..6bcc236 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/descriptor/ComposeDescriptorLoader.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/descriptor/ComposeDescriptorLoader.java @@ -21,6 +21,7 @@ import com.gitee.starblues.core.descriptor.decrypt.EmptyPluginDescriptorDecrypt; import com.gitee.starblues.core.descriptor.decrypt.PluginDescriptorDecrypt; import com.gitee.starblues.core.exception.PluginException; import com.gitee.starblues.utils.SpringBeanUtils; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationContext; import java.nio.file.Path; @@ -33,6 +34,7 @@ import java.util.List; * @since 3.0.0 * @version 3.0.1 */ +@Slf4j public class ComposeDescriptorLoader implements PluginDescriptorLoader{ private final List pluginDescriptorLoaders = new ArrayList<>(); @@ -73,10 +75,14 @@ public class ComposeDescriptorLoader implements PluginDescriptorLoader{ @Override public InsidePluginDescriptor load(Path location) throws PluginException { for (PluginDescriptorLoader pluginDescriptorLoader : pluginDescriptorLoaders) { - InsidePluginDescriptor pluginDescriptor = pluginDescriptorLoader.load(location); - if(pluginDescriptor != null){ - pluginChecker.checkDescriptor(pluginDescriptor); - return pluginDescriptor; + try { + InsidePluginDescriptor pluginDescriptor = pluginDescriptorLoader.load(location); + if(pluginDescriptor != null){ + pluginChecker.checkDescriptor(pluginDescriptor); + return pluginDescriptor; + } + } catch (Exception e){ + log.debug("非法路径插件: {}", location); } } return null; diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/SpringPluginHookWrapper.java b/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/SpringPluginHookWrapper.java index 6b977ea..8c411f6 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/SpringPluginHookWrapper.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/SpringPluginHookWrapper.java @@ -20,6 +20,7 @@ import com.gitee.starblues.core.PluginCloseType; import com.gitee.starblues.core.PluginInsideInfo; import com.gitee.starblues.core.exception.PluginProhibitStopException; import com.gitee.starblues.core.launcher.plugin.involved.PluginLaunchInvolved; +import com.gitee.starblues.loader.PluginResourceStorage; import com.gitee.starblues.spring.ApplicationContext; import com.gitee.starblues.spring.SpringPluginHook; import com.gitee.starblues.spring.WebConfig; @@ -31,7 +32,7 @@ import lombok.extern.slf4j.Slf4j; * SpringPluginHook-Wrapper * @author starBlues * @since 3.0.0 - * @version 3.1.0 + * @version 3.1.2 */ @Slf4j public class SpringPluginHookWrapper implements SpringPluginHook { @@ -72,15 +73,21 @@ public class SpringPluginHookWrapper implements SpringPluginHook { @Override public void close(PluginCloseType closeType) throws Exception { + // 1. 关闭 application 等信息 try { - pluginLaunchInvolved.close(pluginInsideInfo, classLoader); + target.close(closeType); } catch (Exception e){ log.error("关闭插件异常: {}", e.getMessage(), e); } + // 2. 关闭 pluginLaunchInvolved try { - target.close(closeType); - } finally { - ResourceUtils.closeQuietly(classLoader); + pluginLaunchInvolved.close(pluginInsideInfo, classLoader); + } catch (Exception e){ + log.error("关闭插件异常: {}", e.getMessage(), e); } + // 3. 关闭classloader + ResourceUtils.closeQuietly(classLoader); + // 4. 移除插件jar等信息 + PluginResourceStorage.removePlugin(pluginInsideInfo.getPluginId()); } } diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/involved/DefaultPluginLaunchInvolved.java b/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/involved/DefaultPluginLaunchInvolved.java index 25184b1..9b97d6b 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/involved/DefaultPluginLaunchInvolved.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/involved/DefaultPluginLaunchInvolved.java @@ -19,6 +19,7 @@ package com.gitee.starblues.core.launcher.plugin.involved; import com.gitee.starblues.core.PluginInsideInfo; import com.gitee.starblues.core.descriptor.InsidePluginDescriptor; import com.gitee.starblues.core.PluginExtensionInfo; +import com.gitee.starblues.core.descriptor.PluginLibInfo; import com.gitee.starblues.loader.PluginResourceStorage; import com.gitee.starblues.spring.ApplicationContext; import com.gitee.starblues.spring.SpringPluginHook; @@ -30,12 +31,14 @@ import lombok.extern.slf4j.Slf4j; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; /** * 默认的插件启动介入者 * @author starBlues * @since 3.0.0 - * @version 3.1.0 + * @version 3.1.2 */ @Slf4j public class DefaultPluginLaunchInvolved implements PluginLaunchInvolved{ @@ -43,7 +46,12 @@ public class DefaultPluginLaunchInvolved implements PluginLaunchInvolved{ @Override public void before(PluginInsideInfo pluginInsideInfo, ClassLoader classLoader) throws Exception { InsidePluginDescriptor descriptor = pluginInsideInfo.getPluginDescriptor(); - PluginResourceStorage.addPlugin(descriptor.getPluginId(), descriptor.getPluginFileName()); + Set pluginLibInfo = descriptor.getPluginLibInfo(); + List libPath = null; + if(pluginLibInfo != null){ + libPath = pluginLibInfo.stream().map(PluginLibInfo::getPath).collect(Collectors.toList()); + } + PluginResourceStorage.addPlugin(descriptor.getPluginId(), descriptor.getPluginFileName(), libPath); } @Override @@ -57,7 +65,6 @@ public class DefaultPluginLaunchInvolved implements PluginLaunchInvolved{ public void close(PluginInsideInfo pluginInsideInfo, ClassLoader classLoader) throws Exception { InsidePluginDescriptor descriptor = pluginInsideInfo.getPluginDescriptor(); String pluginId = descriptor.getPluginId(); - PluginResourceStorage.removePlugin(pluginId); PluginStaticResourceResolver.remove(pluginId); } diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java b/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java index 77709d6..07b3208 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java @@ -16,10 +16,9 @@ package com.gitee.starblues.integration.operator; -import com.gitee.starblues.core.PluginInfo; -import com.gitee.starblues.core.PluginLauncherManager; -import com.gitee.starblues.core.PluginManager; -import com.gitee.starblues.core.RealizeProvider; +import com.gitee.starblues.core.*; +import com.gitee.starblues.core.descriptor.InsidePluginDescriptor; +import com.gitee.starblues.core.descriptor.PluginType; import com.gitee.starblues.core.exception.PluginDisabledException; import com.gitee.starblues.core.exception.PluginException; import com.gitee.starblues.integration.IntegrationConfiguration; @@ -50,12 +49,13 @@ import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; /** * 默认的插件操作者 * @author starBlues * @version 3.0.0 - * @since 3.0.4 + * @since 3.1.2 */ public class DefaultPluginOperator implements PluginOperator { protected final Logger log = LoggerFactory.getLogger(this.getClass()); @@ -219,7 +219,7 @@ public class DefaultPluginOperator implements PluginOperator { return backDirPath; } Objects.requireNonNull(backDirPath); - return backup(backDirPath, sign, false); + return operatePluginFile(backDirPath, sign, true, false); } @Override @@ -234,12 +234,18 @@ public class DefaultPluginOperator implements PluginOperator { @Override public List getPluginInfo() { - return pluginManager.getPluginInfos(); + return pluginManager.getPluginInfos().stream() + .map(PluginInsideInfo::toPluginInfo) + .collect(Collectors.toList()); } @Override public PluginInfo getPluginInfo(String pluginId) { - return pluginManager.getPluginInfo(pluginId); + PluginInsideInfo pluginInfo = pluginManager.getPluginInfo(pluginId); + if(pluginInfo != null){ + return pluginInfo.toPluginInfo(); + } + return null; } /** @@ -250,22 +256,16 @@ public class DefaultPluginOperator implements PluginOperator { * @return 如果备份插件, 则返回备份后的插件路径 */ protected Path uninstallBackup(String pluginId, boolean isDelete, boolean isBackup){ - PluginInfo pluginInfo = pluginManager.getPluginInfo(pluginId); - if(pluginInfo == null){ + PluginInsideInfo pluginInsideInfo = pluginManager.getPluginInfo(pluginId); + if(pluginInsideInfo == null){ throw new PluginException(pluginId, "没有发现"); } pluginManager.uninstall(pluginId); - if(!isDelete || configuration.isDev()){ + if(configuration.isDev()){ + log.trace("开发环境对插件文件不备份和删除"); return null; } - // 删除插件 - Path pluginPath = Paths.get(pluginInfo.getPluginPath()); - Path backupPath = null; - if(isBackup){ - // 将插件文件移到备份文件中 - backupPath = backup(pluginPath, "uninstall", true); - } - return backupPath; + return operatePluginFile(pluginInsideInfo, "uninstall", isBackup, isDelete); } protected PluginInfo uploadPlugin(String pluginFileName, InputStream inputStream, @@ -326,45 +326,84 @@ public class DefaultPluginOperator implements PluginOperator { /** * 备份 - * @param sourcePath 源文件的路径 + * @param pluginInsideInfo 插件信息 * @param sign 文件标志 - * @param deletedSourceFile 是否删除源文件 - * @return 返回备份的插件路径 + * @param back 是否备份插件文件 + * @param delete 是否删除插件文件 + * @return 如果为备份则返回备份后的文件,否则返回null */ - protected Path backup(Path sourcePath, String sign, boolean deletedSourceFile) { - try { - if(configuration.isDev()){ - // 如果是开发环境, 则不进行备份 - return null; - } - if(sourcePath == null){ - return null; - } - if(!Files.exists(sourcePath)){ - log.error("Path '{}' does not exist", sourcePath.toString()); - return null; + protected Path operatePluginFile(PluginInsideInfo pluginInsideInfo, String sign, boolean back, boolean delete) { + InsidePluginDescriptor pluginDescriptor = pluginInsideInfo.getPluginDescriptor(); + if(configuration.isDev()){ + // 如果是开发环境, 则不进行备份 + return null; + } + PluginType pluginType = pluginDescriptor.getType(); + if(ObjectUtils.equalsElement(pluginType, PluginType.ZIP, PluginType.JAR, PluginType.DIR)){ + return operatePluginFile(Paths.get(pluginInsideInfo.getPluginPath()), sign, back, delete); + } else if(ObjectUtils.equalsElement(pluginType, PluginType.JAR_OUTER, PluginType.ZIP_OUTER)){ + File pluginLibFile = new File(pluginDescriptor.getPluginLibDir()); + File pluginFile = new File(pluginDescriptor.getPluginPath()); + // 判断获取插件包和插件依赖是否在同一个目录,如果在返回父目录 + File parentFile = FilesUtils.sameParent(pluginLibFile, pluginFile); + if(FilesUtils.isChildFile(pluginManager.getPluginsRoots(), parentFile)){ + // 如果当前插件的父目录为当前插件的子目录 + // 为插件存放目录的子目录 + return operatePluginFile(parentFile.toPath(), sign, back, delete); + } else { + // 只备份插件jar包 + return operatePluginFile(pluginFile.toPath(), sign, back, delete); } - File sourceFile = sourcePath.toFile(); - touchBackupPath(); - String targetPathStr = configuration.backupPath() + File.separator; - if(!ObjectUtils.isEmpty(sign)){ - targetPathStr = targetPathStr + sign; + } else { + return operatePluginFile(Paths.get(pluginDescriptor.getPluginPath()), sign, back, delete); + } + } + + /** + * 备份路径 + * @param pluginPath 插件文件 + * @param sign 操作标志 + * @param back 是否备份插件文件 + * @param delete 是否删除插件文件 + * @return 如果为备份则返回备份后的文件,否则返回null + */ + private Path operatePluginFile(Path pluginPath, String sign, boolean back, boolean delete){ + if(!back && !delete){ + return null; + } + if(pluginPath == null){ + log.error("{}失败, 没有发现路径", sign); + return null; + } + if(!Files.exists(pluginPath)){ + log.error("{}}失败, 路径不存在: {}", sign, pluginPath); + return null; + } + File sourceFile = pluginPath.toFile(); + try { + Path targetBackPath = null; + if(back){ + touchBackupPath(); + String targetPathStr = configuration.backupPath() + File.separator; + if(!ObjectUtils.isEmpty(sign)){ + targetPathStr = targetPathStr + sign; + } + targetPathStr = targetPathStr + "_" + getNowTimeByFormat() + "_" +sourceFile.getName(); + targetBackPath = Paths.get(targetPathStr); + File targetBackFile = targetBackPath.toFile(); + copyFile(sourceFile, targetBackFile); + log.info("备份插件文件到: {}", targetBackFile.getAbsolutePath()); } - targetPathStr = targetPathStr + "_" + getNowTimeByFormat() + "_" +sourceFile.getName(); - Path targetPath = Paths.get(targetPathStr); - File targetFile = targetPath.toFile(); - copyFile(sourceFile, targetFile); - log.info("备份插件文件到: {}", targetFile.getAbsolutePath()); - if(deletedSourceFile){ + if(delete){ if(sourceFile.isFile()){ FileUtils.delete(sourceFile); } else { FileUtils.deleteDirectory(sourceFile); } } - return targetPath; + return targetBackPath; } catch (IOException e) { - log.error("Backup plugin jar '{}' failure. {}", sourcePath.toString(), e.getMessage(), e); + log.error("{}路径[{}]失败: {}", sign, pluginPath, e.getMessage(), e); return null; } } diff --git a/spring-brick/src/main/java/com/gitee/starblues/utils/LogUtils.java b/spring-brick/src/main/java/com/gitee/starblues/utils/LogUtils.java index ac9f547..9b90e8a 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/utils/LogUtils.java +++ b/spring-brick/src/main/java/com/gitee/starblues/utils/LogUtils.java @@ -24,7 +24,7 @@ import org.slf4j.Logger; * * @author starBlues * @since 3.0.0 - * @version 3.0.0 + * @version 3.1.2 */ public class LogUtils { @@ -34,4 +34,8 @@ public class LogUtils { logger.info("插件[{}]{}", MsgUtils.getPluginUnique(pluginDescriptor), msg); } + public static String getMsg(PluginDescriptor pluginDescriptor, String msg, Object... args){ + return "插件[ " + MsgUtils.getPluginUnique(pluginDescriptor) + " ]" + String.format(msg, args); + } + } diff --git a/update.md b/update.md index de7cb66..c4da9ac 100644 --- a/update.md +++ b/update.md @@ -1,4 +1,6 @@ 1. 【修复】修复主程序打成`jar-out`类型包时,无法加载主类的问题 2. 【修复】修复插件包打成`jar-out`时无法加载依赖的问题 3. 【修复】修复插件在运行状态无法加载类的问题 -4. 【修复】修复对同一个插件包重复安装时,源插件包被系统占用的问题 \ No newline at end of file +4. 【修复】修复对同一个插件包重复安装时,源插件包被系统占用的问题 +5. 【修复】修复`jar-outer`、`zip-outer`类型插件卸载时依赖文件被占用问题 +6. 【新增】新增`jar-outer`、`zip-outer`带依赖,且为压缩包的上传安装 【暂未完成】 \ No newline at end of file -- Gitee From 932b89b3d44a38df5e570b36ba43d9ee6480ce11 Mon Sep 17 00:00:00 2001 From: StarBlues Date: Sat, 3 Jun 2023 18:27:20 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E6=94=AF=E6=8C=81jar-outer=E3=80=81zip-out?= =?UTF-8?q?er=E7=B1=BB=E5=9E=8B=E5=B8=A6=E4=BE=9D=E8=B5=96=E4=B8=94?= =?UTF-8?q?=E4=B8=BA=E5=8E=8B=E7=BC=A9=E5=8C=85=E4=B8=8A=E4=BC=A0=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E7=9A=84=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- README_zh.md | 2 +- .../bootstrap/ConfigurePluginEnvironment.java | 2 +- .../starblues/core/DefaultPluginManager.java | 116 +++++++++-------- .../gitee/starblues/core/PluginManager.java | 12 +- .../AutoIntegrationConfiguration.java | 4 +- .../DefaultIntegrationConfiguration.java | 8 +- .../operator/DefaultPluginOperator.java | 29 +++-- .../starblues/utils/PluginFileUtils.java | 119 +++++++++++------- update.md | 2 +- 10 files changed, 185 insertions(+), 111 deletions(-) diff --git a/README.md b/README.md index 8293811..769d299 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,6 @@ The framework can be developed in the `spring-boot` project plugin, plugin can b - [spring-brick-example](https://gitee.com/starblues/springboot-plugin-framework-example) ### Contact -QQ: 859570617(**After you like the framework, you can enter the group. Please note the Gitee/GitHub nickname before entering the group**) +QQ: 859570617(QQ Group 1 is full), 536825438(QQ Group 2)(**After you like the framework, you can enter the group. Please note the Gitee/GitHub nickname before entering the group**) diff --git a/README_zh.md b/README_zh.md index fcd08f2..a4b0103 100644 --- a/README_zh.md +++ b/README_zh.md @@ -57,7 +57,7 @@ - [spring-brick 功能测试+案例](https://gitee.com/starblues/springboot-plugin-framework-example) ### 交流 | Contact -QQ交流群: 859570617 +QQ交流群: 859570617(群1, 已满), 536825438(群2) ### 支持 | Support 如果您觉得框架使用起来不错的, 或者想支持本框架继续维护, 开源不易, 您可以通过如下方式进行支持: diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigurePluginEnvironment.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigurePluginEnvironment.java index 3a05409..0f53317 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigurePluginEnvironment.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigurePluginEnvironment.java @@ -40,7 +40,7 @@ import java.util.Map; * * @author starBlues * @since 3.0.0 - * @version 3.1.1 + * @version 3.1.2 */ public class ConfigurePluginEnvironment { private final Logger logger = LoggerFactory.getLogger(ConfigurePluginEnvironment.class); diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java b/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java index 00f63cd..8c0a471 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java @@ -175,49 +175,77 @@ public class DefaultPluginManager implements PluginManager{ } @Override - public PluginInfo parse(Path pluginPath) throws PluginException { + public PluginInsideInfo parse(Path pluginPath) throws PluginException { + if(pluginPath == null){ + throw new PluginException("解析文件不能为 null"); + } PluginInsideInfo pluginInsideInfo = loadFromPath(pluginPath); if(pluginInsideInfo == null){ throw new PluginException("非法插件包: " + pluginPath); } pluginInsideInfo.setPluginState(PluginState.PARSED); - return pluginInsideInfo.toPluginInfo(); + return pluginInsideInfo; } @Override - public synchronized PluginInfo load(Path pluginPath, boolean unpackPlugin) throws PluginException { - Assert.isNotNull(pluginPath, "参数pluginPath不能为空"); - String sourcePluginPath = pluginPath.toString(); - try { + public PluginInsideInfo scanParse(Path pluginPath) throws PluginException { + if(pluginPath == null){ + throw new PluginException("解析文件不能为 null"); + } + List scanList = new ArrayList<>(1); + scanList.add(pluginPath.toString()); + List scanPluginPaths = provider.getPluginScanner().scan(scanList); + for (Path scanPluginPath : scanPluginPaths) { // 解析插件 + try { + PluginInsideInfo pluginInsideInfo = loadFromPath(scanPluginPath); + if(pluginInsideInfo != null){ + return pluginInsideInfo; + } + } catch (Exception e){ + // 忽略 + } + } + return null; + } - PluginInfo pluginInfo = parse(pluginPath); + @Override + public synchronized PluginInsideInfo load(Path pluginPath, boolean unpackPlugin) throws PluginException { + Assert.isNotNull(pluginPath, "参数pluginPath不能为空"); + Path sourcePluginPath = pluginPath; + File unpackPluginFile = null; + try { + if(unpackPlugin){ + unpackPluginFile = PluginFileUtils.decompressZip(pluginPath.toString(), configuration.uploadTempPath()); + pluginPath = unpackPluginFile.toPath(); + } + // 拷贝插件到root目录 + pluginPath = copyPluginToPluginRootDir(pluginPath); + PluginInsideInfo pluginInsideInfo = scanParse(pluginPath); + if(pluginInsideInfo == null){ + pluginListenerFactory.loadFailure(sourcePluginPath, new PluginException("Not found PluginInsideInfo")); + throw new PluginException("非法插件包: " + sourcePluginPath); + } // 检查是否存在当前插件 - PluginInsideInfo plugin = getPlugin(pluginInfo.getPluginId()); + PluginInsideInfo plugin = getPlugin(pluginInsideInfo.getPluginId()); if(plugin != null){ // 已经存在该插件 throw new PluginException("加载插件包[" + pluginPath + "]失败. 已经存在该插件: " + MsgUtils.getPluginUnique(plugin.getPluginDescriptor())); } - if(configuration.isProd()){ - // 如果为生产环境, 则拷贝插件 - pluginPath = copyPlugin(pluginPath, unpackPlugin); - } - // 加载插件 - PluginInsideInfo pluginInsideInfo = loadPlugin(pluginPath, true); - if(pluginInsideInfo != null){ - PluginInfo pluginInfoFace = pluginInsideInfo.toPluginInfo(); - pluginListenerFactory.loadSuccess(pluginInfoFace); - return pluginInfoFace; - } else { - pluginListenerFactory.loadFailure(pluginPath, new PluginException("Not found PluginInsideInfo")); - return null; - } + pluginInsideInfo = loadPlugin(Paths.get(pluginInsideInfo.getPluginPath()), false); + PluginInfo pluginInfoFace = pluginInsideInfo.toPluginInfo(); + pluginListenerFactory.loadSuccess(pluginInfoFace); + return pluginInsideInfo; } catch (Throwable e) { PluginException pluginException = PluginException.getPluginException(e, () -> { throw new PluginException("插件包加载失败: " + sourcePluginPath, e); }); - pluginListenerFactory.loadFailure(pluginPath, pluginException); + pluginListenerFactory.loadFailure(sourcePluginPath, pluginException); + if(unpackPluginFile != null){ + FileUtils.deleteQuietly(unpackPluginFile); + } + FileUtils.deleteQuietly(pluginPath.toFile()); throw pluginException; } } @@ -402,6 +430,12 @@ public class DefaultPluginManager implements PluginManager{ LogUtils.info(log, wrapperInside.getPluginDescriptor(), "卸载成功"); } + /** + * 加载插件信息 + * @param pluginPath 插件路径 + * @param resolvePath 是否直接解析路径 + * @return 插件内部细腻些 + */ protected PluginInsideInfo loadPlugin(Path pluginPath, boolean resolvePath) { if(resolvePath){ Path sourcePluginPath = pluginPath; @@ -455,19 +489,18 @@ public class DefaultPluginManager implements PluginManager{ /** * 拷贝插件文件到插件根目录 * @param pluginPath 源插件文件路径 - * @param unpackPlugin 是否解压插件包. 只有为压缩类型包才可解压 * @return 拷贝后的插件路径 * @throws IOException IO 异常 */ - protected Path copyPlugin(Path pluginPath, boolean unpackPlugin) throws IOException { + protected Path copyPluginToPluginRootDir(Path pluginPath) throws IOException { if(configuration.isDev()){ + // 开发环境不拷贝 return pluginPath; } File targetFile = pluginPath.toFile(); if(!targetFile.exists()) { throw new PluginException("不存在插件文件: " + pluginPath); } - String targetFileName = targetFile.getName(); // 先判断当前插件文件是否在插件目录中 File pluginRootDir = null; for (String dir : pluginRootDirs) { @@ -477,38 +510,22 @@ public class DefaultPluginManager implements PluginManager{ break; } } - String resolvePluginFileName = unpackPlugin ? PluginFileUtils.getFileName(targetFile) : targetFileName; + String fileName = targetFile.getName(); Path resultPath = null; if(pluginRootDir != null){ - // 在根目录中存在 - if(targetFile.isFile() && unpackPlugin){ - // 需要解压, 检查解压后的文件名称是否存在同名文件 - checkExistFile(pluginRootDir, resolvePluginFileName); - String unpackPluginPath = FilesUtils.joiningFilePath(pluginRootDir.getPath(), resolvePluginFileName); - PluginFileUtils.decompressZip(targetFile.getPath(), unpackPluginPath); - resultPath = Paths.get(unpackPluginPath); - PluginFileUtils.deleteFile(targetFile); - } else { - resultPath = targetFile.toPath(); - } + // 在根目录中存在, 检查是否存在同名文件 + checkExistFile(pluginRootDir, fileName); } else { // 不在插件目录 File pluginFile = pluginPath.toFile(); pluginRootDir = new File(getDefaultPluginRoot()); File pluginRootDirFile = new File(getDefaultPluginRoot()); // 检查是否存在同名文件 - checkExistFile(pluginRootDirFile, resolvePluginFileName); - targetFile = Paths.get(FilesUtils.joiningFilePath(pluginRootDir.getPath(), resolvePluginFileName)).toFile(); + checkExistFile(pluginRootDirFile, fileName); + targetFile = Paths.get(FilesUtils.joiningFilePath(pluginRootDir.getPath(), fileName)).toFile(); if(pluginFile.isFile()){ - if(unpackPlugin){ - // 需要解压 - String unpackPluginPath = FilesUtils.joiningFilePath(pluginRootDir.getPath(), resolvePluginFileName); - PluginFileUtils.decompressZip(pluginFile.getPath(), unpackPluginPath); - resultPath = Paths.get(unpackPluginPath); - } else { - FileUtils.copyFile(pluginFile, targetFile); - resultPath = targetFile.toPath(); - } + FileUtils.copyFile(pluginFile, targetFile); + resultPath = targetFile.toPath(); } else { FileUtils.copyDirectory(pluginFile, targetFile); resultPath = targetFile.toPath(); @@ -660,5 +677,4 @@ public class DefaultPluginManager implements PluginManager{ log.warn(warn.toString()); } - } diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/PluginManager.java b/spring-brick/src/main/java/com/gitee/starblues/core/PluginManager.java index 7f453d1..3f41aad 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/PluginManager.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/PluginManager.java @@ -61,7 +61,15 @@ public interface PluginManager { * @return 解析的插件信息 * @throws PluginException 插件异常 */ - PluginInfo parse(Path pluginPath) throws PluginException; + PluginInsideInfo parse(Path pluginPath) throws PluginException; + + /** + * 从某个目录扫描解析首个插件 + * @param pluginPath 插件路径 + * @return 解析的插件信息 + * @throws PluginException 插件异常 + */ + PluginInsideInfo scanParse(Path pluginPath) throws PluginException; /** * 根据具体插件路径来加载插件. @@ -70,7 +78,7 @@ public interface PluginManager { * @return 加载的插件信息 * @throws PluginException 插件异常 */ - PluginInfo load(Path pluginPath, boolean unpackPlugin) throws PluginException; + PluginInsideInfo load(Path pluginPath, boolean unpackPlugin) throws PluginException; /** * 卸载加载插件 diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/AutoIntegrationConfiguration.java b/spring-brick/src/main/java/com/gitee/starblues/integration/AutoIntegrationConfiguration.java index b0847e3..883887d 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/AutoIntegrationConfiguration.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/AutoIntegrationConfiguration.java @@ -34,7 +34,7 @@ import java.util.Set; * * @author starBlues * @since 3.0.0 - * @version 3.0.3 + * @version 3.1.2 */ @EqualsAndHashCode(callSuper = true) @Component @@ -73,7 +73,7 @@ public class AutoIntegrationConfiguration extends DefaultIntegrationConfiguratio /** * 上传的插件所存储的临时目录 */ - @Value("${uploadTempPath:temp}") + @Value("${uploadTempPath:}") private String uploadTempPath; /** diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/DefaultIntegrationConfiguration.java b/spring-brick/src/main/java/com/gitee/starblues/integration/DefaultIntegrationConfiguration.java index bd06974..59370c3 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/DefaultIntegrationConfiguration.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/DefaultIntegrationConfiguration.java @@ -20,6 +20,7 @@ import com.gitee.starblues.common.Constants; import com.gitee.starblues.integration.decrypt.DecryptConfiguration; import com.gitee.starblues.utils.Assert; +import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -30,13 +31,16 @@ import java.util.Set; * * @author starBlues * @since 3.0.0 - * @version 3.0.1 + * @version 3.1.2 */ public abstract class DefaultIntegrationConfiguration implements IntegrationConfiguration{ public static final String DEFAULT_PLUGIN_REST_PATH_PREFIX = "plugins"; public static final Boolean DEFAULT_ENABLE_PLUGIN_ID_REST_PATH_PREFIX = Boolean.TRUE; + private static final String DEFAULT_TEMP_FILE = + new File(System.getProperty("java.io.tmpdir"), "spring-brick-temp").getPath(); + @Override public Boolean enable() { return Boolean.TRUE; @@ -51,7 +55,7 @@ public abstract class DefaultIntegrationConfiguration implements IntegrationConf @Override public String uploadTempPath(){ - return "temp"; + return DEFAULT_TEMP_FILE; } @Override diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java b/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java index 07b3208..9bf851c 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java @@ -54,8 +54,8 @@ import java.util.stream.Collectors; /** * 默认的插件操作者 * @author starBlues - * @version 3.0.0 - * @since 3.1.2 + * @since 3.0.0 + * @version 3.1.2 */ public class DefaultPluginOperator implements PluginOperator { protected final Logger log = LoggerFactory.getLogger(this.getClass()); @@ -153,7 +153,7 @@ public class DefaultPluginOperator implements PluginOperator { @Override public PluginInfo parse(Path pluginPath) throws PluginException { - return pluginManager.parse(pluginPath); + return toPluginInfo(pluginManager.parse(pluginPath)); } @Override @@ -168,7 +168,7 @@ public class DefaultPluginOperator implements PluginOperator { @Override public PluginInfo load(Path pluginPath, boolean unpackPlugin) throws PluginException { - return pluginManager.load(pluginPath, unpackPlugin); + return toPluginInfo(pluginManager.load(pluginPath, unpackPlugin)); } @Override @@ -288,9 +288,13 @@ public class DefaultPluginOperator implements PluginOperator { } finally { IOUtils.closeQuietly(inputStream); } + File unpackPluginFile = tempFile; try { // 解析该插件包 - PluginInfo uploadPluginInfo = parse(tempFilePath); + if(isUnpackPluginFile){ + unpackPluginFile = PluginFileUtils.decompressZip(tempFile.toString(), configuration.uploadTempPath()); + } + PluginInfo uploadPluginInfo = pluginManager.scanParse(unpackPluginFile.toPath()); if(uploadPluginInfo == null){ Exception exception = new Exception(pluginFileName + " 文件校验失败"); verifyFailureDelete(tempFilePath, exception); @@ -306,12 +310,12 @@ public class DefaultPluginOperator implements PluginOperator { backupPlugin(oldPluginPath, "upload"); } // 然后进入更新模式 - pluginInfo = pluginManager.upgrade(tempFilePath, isUnpackPluginFile); + pluginInfo = pluginManager.upgrade(unpackPluginFile.toPath(), false); // 删除旧插件包 FileUtils.delete(oldPluginPath.toFile()); } else { // 不存在则进入安装插件模式 - pluginInfo = pluginManager.install(tempFilePath, isUnpackPluginFile); + pluginInfo = pluginManager.install(unpackPluginFile.toPath(), false); } return pluginInfo; } catch (Exception e){ @@ -319,8 +323,8 @@ public class DefaultPluginOperator implements PluginOperator { verifyFailureDelete(tempFilePath, e); throw e; } finally { - // 删除临时文件 - tempFile.deleteOnExit(); + // 删除解压文件 + FileUtils.deleteQuietly(unpackPluginFile); } } @@ -450,5 +454,12 @@ public class DefaultPluginOperator implements PluginOperator { FileUtils.forceMkdir(file); } + private PluginInfo toPluginInfo(PluginInsideInfo pluginInsideInfo){ + if(pluginInsideInfo == null){ + return null; + } + return pluginInsideInfo.toPluginInfo(); + } + } diff --git a/spring-brick/src/main/java/com/gitee/starblues/utils/PluginFileUtils.java b/spring-brick/src/main/java/com/gitee/starblues/utils/PluginFileUtils.java index d3ee784..acbd9a0 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/utils/PluginFileUtils.java +++ b/spring-brick/src/main/java/com/gitee/starblues/utils/PluginFileUtils.java @@ -45,7 +45,7 @@ import java.util.zip.ZipFile; * * @author starBlues * @since 3.0.0 - * @version 3.1.0 + * @version 3.1.2 */ public final class PluginFileUtils { @@ -124,76 +124,110 @@ public final class PluginFileUtils { /** * 得到文件名称 * @param file 原始文件 + * @param includeSuffix 是否包含后缀 * @return String */ - public static String getFileName(File file){ - String fileName = file.getName(); - if(!file.exists() | file.isDirectory()){ - return fileName; + public static String getFileName(File file, boolean includeSuffix){ + if(file == null){ + return null; } - return getFileName(fileName); + return getFileName(file.getName(), includeSuffix); } /** - * 得到文件名称 - * @param fileName 原始文件名称. 比如: file.txt + * 获取不包含文件后缀的文件名称 + * @param fileName 文件名称 * @return String */ public static String getFileName(String fileName){ + return getFileName(fileName, false); + } + + /** + * 得到文件名称 + * @param fileName 原始文件名称. 比如: file.txt , 则返回 file + * @param includeSuffix 是否包含后缀 + * @return String + */ + public static String getFileName(String fileName, boolean includeSuffix){ if(ObjectUtils.isEmpty(fileName)){ return fileName; } - if(fileName.lastIndexOf(FILE_POINT) > 0){ - return fileName.substring(0, fileName.lastIndexOf(FILE_POINT)); + if(includeSuffix){ + return fileName; + } + int i = fileName.lastIndexOf(FILE_POINT); + if(i > 0){ + return fileName.substring(0, i); } else { return fileName; } } - public static Manifest getManifest(InputStream inputStream) throws IOException { - Manifest manifest = new Manifest(); - Attributes attributes = manifest.getMainAttributes(); - List lines = IOUtils.readLines(inputStream, PackageStructure.CHARSET_NAME); - for (String line : lines) { - String[] split = line.split(":"); - if(split.length == 2){ - String key = split[0]; - String value = split[1]; - attributes.putValue(trim(key), trim(value)); + /** + * 创建随机文件 + * @param parentPath 父目录 + * @param isFile 是否为文件,不为文件就创建目录 + * @param fileSuffix 文件后缀 + * @return 创建的File + * @throws Exception 创建异常 + */ + public static File createRandomFile(String parentPath, boolean isFile, String fileSuffix) throws Exception{ + if(isFile){ + if(ObjectUtils.isEmpty(fileSuffix)){ + fileSuffix = ""; + } else { + if(!fileSuffix.startsWith(".")){ + fileSuffix = "." + fileSuffix; + } } + File file = new File(parentPath, String.valueOf(System.currentTimeMillis()) + fileSuffix); + if(file.createNewFile()){ + return file; + } else { + throw new IOException("Cannot create file '" + file + "'."); + } + } else { + File file = new File(parentPath, String.valueOf(System.currentTimeMillis())); + FileUtils.forceMkdir(file); + return file; } - return manifest; - } - - private static String trim(String value){ - if(ObjectUtils.isEmpty(value)){ - return value; - } - return value.trim(); } - public static void deleteFile(File file) throws IOException { - if(file == null || !file.exists()){ - return; - } - if(file.isDirectory()){ - FileUtils.deleteDirectory(file); - } else { - FileUtils.delete(file); - } + /** + * 判断是否能解压 + * @param zipPath zip路径 + * @return boolean + */ + public static boolean canDecompressZip(String zipPath){ + return ResourceUtils.isZip(zipPath) || ResourceUtils.isJar(zipPath); } - public static void decompressZip(String zipPath, String targetDir) throws IOException { + /** + * 解压zip 文件 + * @param zipPath zip 文件 + * @param targetDir 目标目录 + * @return 解压后的目录 + * @throws IOException 解压异常 + */ + public static File decompressZip(String zipPath, String targetDir) throws IOException { File zipFile = new File(zipPath); - if(!ResourceUtils.isZip(zipPath) && !ResourceUtils.isJar(zipPath)){ + if(!canDecompressZip(zipPath)){ throw new IOException("文件[" + zipFile.getName() + "]非压缩包, 不能解压"); } - File targetDirFile = new File(targetDir); + File targetDirFile = new File(targetDir, getFileName(zipFile, false)); if(!targetDirFile.exists()){ if(!targetDirFile.mkdirs()){ throw new IOException("创建目录异常: " + targetDir); } + targetDir = targetDirFile.getAbsolutePath(); + } else { + // 存在相同目录 + targetDirFile = new File(targetDir, getFileName(zipFile, false) + + "_" + System.currentTimeMillis()); + FileUtils.forceMkdir(targetDirFile); + targetDir = targetDirFile.getAbsolutePath(); } try (ZipFile zip = new ZipFile(zipFile, Charset.forName(PackageStructure.CHARSET_NAME))) { Enumeration zipEnumeration = zip.entries(); @@ -205,7 +239,8 @@ public final class PluginFileUtils { String currentTargetPath = FilesUtils.joiningFilePath(targetDir, currentZipPath); //判断路径是否存在,不存在则创建文件路径 if (zipEntry.isDirectory()) { - FileUtils.forceMkdir(new File(currentTargetPath)); + File file = new File(currentTargetPath); + FileUtils.forceMkdir(file); continue; } else { FilesUtils.createFile(currentTargetPath); @@ -221,9 +256,9 @@ public final class PluginFileUtils { } } } + return targetDirFile; } - private static void resolveDecompressPluginType(InputStream inputStream, OutputStream outputStream) throws IOException{ Manifest manifest = new Manifest(inputStream); Attributes mainAttributes = manifest.getMainAttributes(); diff --git a/update.md b/update.md index c4da9ac..3a97877 100644 --- a/update.md +++ b/update.md @@ -3,4 +3,4 @@ 3. 【修复】修复插件在运行状态无法加载类的问题 4. 【修复】修复对同一个插件包重复安装时,源插件包被系统占用的问题 5. 【修复】修复`jar-outer`、`zip-outer`类型插件卸载时依赖文件被占用问题 -6. 【新增】新增`jar-outer`、`zip-outer`带依赖,且为压缩包的上传安装 【暂未完成】 \ No newline at end of file +6. 【新增】支持`jar-outer`、`zip-outer`类型带依赖且为压缩包上传插件的方式 \ No newline at end of file -- Gitee