This is an automated email from the ASF dual-hosted git repository.

liutianyou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git


The following commit(s) were added to refs/heads/master by this push:
     new 5d8727520 [improve] support plugins using other jar (#2553)
5d8727520 is described below

commit 5d872752067c6dcbbf61b3e5695371076f5508e1
Author: liutianyou <[email protected]>
AuthorDate: Mon Aug 19 12:36:51 2024 +0800

    [improve] support plugins using other jar (#2553)
    
    Co-authored-by: YuLuo <[email protected]>
    Co-authored-by: Logic <[email protected]>
---
 .../manager/service/impl/PluginServiceImpl.java    | 59 +++++++++++++++++++++-
 manager/src/main/resources/application.yml         | 11 ++--
 plugin/pom.xml                                     | 24 +++++++++
 plugin/src/main/resources/assembly/assembly.xml    | 41 +++++++++++++++
 4 files changed, 129 insertions(+), 6 deletions(-)

diff --git 
a/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/PluginServiceImpl.java
 
b/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/PluginServiceImpl.java
index 69b790479..162d4bc39 100644
--- 
a/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/PluginServiceImpl.java
+++ 
b/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/PluginServiceImpl.java
@@ -19,7 +19,10 @@ package org.apache.hertzbeat.manager.service.impl;
 
 import jakarta.persistence.criteria.Predicate;
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -96,6 +99,11 @@ public class PluginServiceImpl implements PluginService {
                 if (jarFile.exists()) {
                     FileUtils.delete(jarFile);
                 }
+                // removing jar files that are dependencies for the plugin
+                File otherLibDir = new 
File(getOtherLibDir(plugin.getJarFilePath()));
+                if (otherLibDir.exists()) {
+                    FileUtils.deleteDirectory(otherLibDir);
+                }
                 // delete metadata
                 metadataDao.deleteById(plugin.getId());
             } catch (IOException e) {
@@ -108,6 +116,16 @@ public class PluginServiceImpl implements PluginService {
         loadJarToClassLoader();
     }
 
+    /**
+     * get the directory where the JAR files dependent on the plugin are saved
+     *
+     * @param pluginJarPath jar file path
+     * @return lib dir
+     */
+    private String getOtherLibDir(String pluginJarPath) {
+        return pluginJarPath.substring(0, pluginJarPath.lastIndexOf("."));
+    }
+
     @Override
     public void updateStatus(PluginMetadata plugin) {
         Optional<PluginMetadata> pluginMetadata = 
metadataDao.findById(plugin.getId());
@@ -274,8 +292,9 @@ public class PluginServiceImpl implements PluginService {
             System.gc();
             List<PluginMetadata> plugins = 
metadataDao.findPluginMetadataByEnableStatusTrue();
             for (PluginMetadata metadata : plugins) {
-                URL url = new File(metadata.getJarFilePath()).toURI().toURL();
-                pluginClassLoaders.add(new URLClassLoader(new URL[]{url}, 
Plugin.class.getClassLoader()));
+                List<URL> urls = loadLibInPlugin(metadata.getJarFilePath());
+                urls.add(new File(metadata.getJarFilePath()).toURI().toURL());
+                pluginClassLoaders.add(new URLClassLoader(urls.toArray(new 
URL[0]), Plugin.class.getClassLoader()));
             }
         } catch (MalformedURLException e) {
             log.error("Failed to load plugin:{}", e.getMessage());
@@ -285,6 +304,42 @@ public class PluginServiceImpl implements PluginService {
         }
     }
 
+    /**
+     * loading other JAR files that are dependencies for the plugin
+     *
+     * @param pluginJarPath jar file path
+     * @return urls
+     */
+    @SneakyThrows
+    private List<URL> loadLibInPlugin(String pluginJarPath) {
+        File libDir = new File(getOtherLibDir(pluginJarPath));
+        FileUtils.forceMkdir(libDir);
+        List<URL> libUrls = new ArrayList<>();
+        try (JarFile jarFile = new JarFile(pluginJarPath)) {
+            Enumeration<JarEntry> entries = jarFile.entries();
+            while (entries.hasMoreElements()) {
+                JarEntry entry = entries.nextElement();
+                File file = new File(libDir, entry.getName());
+                if (!entry.isDirectory() && entry.getName().endsWith(".jar")) {
+                    if (!file.getParentFile().exists()) {
+                        FileUtils.createParentDirectories(file);
+                    }
+                    try (InputStream in = jarFile.getInputStream(entry);
+                        OutputStream out = new FileOutputStream(file)) {
+                        byte[] buffer = new byte[4096];
+                        int len;
+                        while ((len = in.read(buffer)) != -1) {
+                            out.write(buffer, 0, len);
+                        }
+                        libUrls.add(file.toURI().toURL());
+                        out.flush();
+                    }
+                }
+            }
+        }
+        return libUrls;
+    }
+
     @Override
     public <T> void pluginExecute(Class<T> clazz, Consumer<T> execute) {
         for (URLClassLoader pluginClassLoader : pluginClassLoaders) {
diff --git a/manager/src/main/resources/application.yml 
b/manager/src/main/resources/application.yml
index 619e52b1c..33ad559a2 100644
--- a/manager/src/main/resources/application.yml
+++ b/manager/src/main/resources/application.yml
@@ -33,7 +33,10 @@ spring:
     exclude: 
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, 
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
   freemarker:
     enabled: false
-
+  servlet:
+    multipart:
+      max-file-size: 100MB
+      max-request-size: 100MB
 
 management:
   health:
@@ -81,7 +84,7 @@ spring:
       eclipselink:
         logging:
           level: SEVERE
-          
+
   flyway:
     enabled: true
     clean-disabled: true
@@ -89,9 +92,9 @@ spring:
     baseline-version: 1
     locations:
       - classpath:db/migration/{vendor}
-    
+
   mail:
-    # Mail server address, eg: qq-mailbox is smtp.qq.com, qq-exmail is 
smtp.exmail.qq.com  
+    # Mail server address, eg: qq-mailbox is smtp.qq.com, qq-exmail is 
smtp.exmail.qq.com
     host: smtp.qq.com
     username: [email protected]
     # Attention this is not email account password, this requires an email 
authorization code
diff --git a/plugin/pom.xml b/plugin/pom.xml
index 461adca67..023225ceb 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -37,8 +37,32 @@
         <dependency>
             <groupId>org.apache.hertzbeat</groupId>
             <artifactId>hertzbeat-common</artifactId>
+            <scope>provided</scope>
         </dependency>
     </dependencies>
 
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>3.3.0</version>
+        <configuration>
+          <descriptors>
+            <descriptor>src/main/resources/assembly/assembly.xml</descriptor>
+          </descriptors>
+        </configuration>
+        <executions>
+          <execution>
+            <id>make-assembly</id>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
 
 </project>
diff --git a/plugin/src/main/resources/assembly/assembly.xml 
b/plugin/src/main/resources/assembly/assembly.xml
new file mode 100644
index 000000000..2b5008142
--- /dev/null
+++ b/plugin/src/main/resources/assembly/assembly.xml
@@ -0,0 +1,41 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0";
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 
https://maven.apache.org/xsd/assembly-2.1.0.xsd";>
+  <id>jar-with-lib</id>
+  <formats>
+    <format>jar</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>/lib</outputDirectory>
+      <unpack>false</unpack>
+      <scope>runtime</scope>
+      <excludes>
+        <exclude>${project.groupId}:${project.artifactId}</exclude>
+      </excludes>
+    </dependencySet>
+  </dependencySets>
+  <fileSets>
+    <fileSet>
+      <directory>${project.build.outputDirectory}</directory>
+      <outputDirectory>/</outputDirectory>
+    </fileSet>
+  </fileSets>
+</assembly>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to