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

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


The following commit(s) were added to refs/heads/udf by this push:
     new 840134c93 [feature]Hertzbeat custom plugin.
840134c93 is described below

commit 840134c93d03bf80ec592f44b0d266bc7e274935
Author: zqr10159 <[email protected]>
AuthorDate: Mon May 13 00:44:16 2024 +0800

    [feature]Hertzbeat custom plugin.
---
 .../org/apache/hertzbeat/common/util/UdfUtil.java  |  87 -----------
 manager/pom.xml                                    |   2 +-
 .../java/org/apache/hertzbeat/manager/Manager.java |   3 +
 .../manager/component/alerter/DispatcherAlarm.java |  48 ++-----
 .../hertzbeat/manager/config/PluginConfig.java     | 160 +++++++++++++++++++++
 plugin/pom.xml                                     |  44 ++++++
 .../java/org/apache/hertzbeat/plugin/Plugin.java   |   6 +-
 .../hertzbeat/plugin/impl/DemoPluginImpl1.java     |   9 +-
 pom.xml                                            |   4 +-
 9 files changed, 230 insertions(+), 133 deletions(-)

diff --git a/common/src/main/java/org/apache/hertzbeat/common/util/UdfUtil.java 
b/common/src/main/java/org/apache/hertzbeat/common/util/UdfUtil.java
deleted file mode 100644
index b32b289c5..000000000
--- a/common/src/main/java/org/apache/hertzbeat/common/util/UdfUtil.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *
- *  * 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.
- *
- */
-
-package org.apache.hertzbeat.common.util;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Arrays;
-import java.util.List;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.stream.Collectors;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * UdfUtil
- */
-@Slf4j
-public class UdfUtil {
-    public static URLClassLoader getClassLoader(String path) {
-        List<String> jars = getAllJars(path);
-
-        if (jars == null) {
-            return null;
-        }
-
-        URL[] urls = jars.stream().map(jar -> {
-            try {
-                return new File(jar).toURI().toURL();
-            } catch (MalformedURLException e) {
-                log.error("getClassLoader error", e);
-            }
-            return null;
-        }).toArray(URL[]::new);
-
-        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
-        try (URLClassLoader urlClassLoader = new URLClassLoader(urls, 
systemClassLoader)) {
-            return urlClassLoader;
-        } catch (Exception e) {
-            log.error("getClassLoader error", e);
-        }
-        return null;
-    }
-
-    private static List<String> getAllJars(String path) {
-        File file = new File(path);
-        File[] files = file.listFiles();
-        if (files == null) {
-            return null;
-        }
-        return Arrays.stream(files)
-                .filter(f -> f.getName().endsWith(".jar"))
-                .map(File::getAbsolutePath)
-                .collect(Collectors.toList());
-    }
-
-    public static List<String> getAllClassNamesFromJar(String jarFilePath) {
-        try (JarFile jarFile = new JarFile(jarFilePath)) {
-            return jarFile.stream()
-                    .filter(jarEntry -> jarEntry.getName().endsWith(".class"))
-                    .filter(jarEntry -> 
!jarEntry.getName().contains("org/apache/hertzbeat/udf/AfterAlertUdf"))
-                    .map(jarEntry -> jarEntry.getName().replace("/", 
".").replace(".class", ""))
-                    .collect(Collectors.toList());
-        } catch (Exception e) {
-            log.error("getAllClassNamesFromJar error", e);
-        }
-        return null;
-    }
-}
diff --git a/manager/pom.xml b/manager/pom.xml
index e39f10c69..d71203c7a 100644
--- a/manager/pom.xml
+++ b/manager/pom.xml
@@ -85,7 +85,7 @@
         <!-- udf -->
         <dependency>
             <groupId>org.apache.hertzbeat</groupId>
-            <artifactId>hertzbeat-udf</artifactId>
+            <artifactId>hertzbeat-plugin</artifactId>
         </dependency>
         <!-- spring -->
         <dependency>
diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/Manager.java 
b/manager/src/main/java/org/apache/hertzbeat/manager/Manager.java
index e9aac8c0c..2e69b6414 100644
--- a/manager/src/main/java/org/apache/hertzbeat/manager/Manager.java
+++ b/manager/src/main/java/org/apache/hertzbeat/manager/Manager.java
@@ -18,12 +18,14 @@
 package org.apache.hertzbeat.manager;
 
 import javax.annotation.PostConstruct;
+import org.apache.hertzbeat.manager.config.PluginConfig;
 import org.apache.hertzbeat.manager.nativex.HertzbeatRuntimeHintsRegistrar;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.domain.EntityScan;
 import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
 import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.ImportRuntimeHints;
 import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@@ -39,6 +41,7 @@ import 
org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 @ComponentScan(basePackages = {"org.apache.hertzbeat"})
 @ConfigurationPropertiesScan(basePackages = {"org.apache.hertzbeat"})
 @ImportRuntimeHints(HertzbeatRuntimeHintsRegistrar.class)
+@Import(PluginConfig.class)
 public class Manager {
     public static void main(String[] args) {
         SpringApplication.run(Manager.class, args);
diff --git 
a/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/DispatcherAlarm.java
 
b/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/DispatcherAlarm.java
index 768090b03..30160fadc 100644
--- 
a/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/DispatcherAlarm.java
+++ 
b/manager/src/main/java/org/apache/hertzbeat/manager/component/alerter/DispatcherAlarm.java
@@ -18,9 +18,6 @@
 package org.apache.hertzbeat.manager.component.alerter;
 
 import com.google.common.collect.Maps;
-
-import java.lang.reflect.Constructor;
-import java.net.URLClassLoader;
 import java.util.List;
 import java.util.Map;
 import lombok.extern.slf4j.Slf4j;
@@ -30,11 +27,11 @@ import 
org.apache.hertzbeat.common.entity.manager.NoticeReceiver;
 import org.apache.hertzbeat.common.entity.manager.NoticeRule;
 import org.apache.hertzbeat.common.entity.manager.NoticeTemplate;
 import org.apache.hertzbeat.common.queue.CommonDataQueue;
-import org.apache.hertzbeat.common.util.UdfUtil;
+import org.apache.hertzbeat.manager.config.PluginConfig;
 import org.apache.hertzbeat.manager.service.NoticeConfigService;
 import org.apache.hertzbeat.manager.support.exception.AlertNoticeException;
 import org.apache.hertzbeat.manager.support.exception.IgnoreException;
-import org.apache.hertzbeat.udf.AfterAlertUdf;
+import org.apache.hertzbeat.plugin.Plugin;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.stereotype.Component;
 
@@ -51,22 +48,25 @@ public class DispatcherAlarm implements InitializingBean {
     private final NoticeConfigService noticeConfigService;
     private final AlertStoreHandler alertStoreHandler;
     private final Map<Byte, AlertNotifyHandler> alertNotifyHandlerMap;
+    private final PluginConfig pluginConfig;
 
     public DispatcherAlarm(AlerterWorkerPool workerPool,
                            CommonDataQueue dataQueue,
                            NoticeConfigService noticeConfigService,
                            AlertStoreHandler alertStoreHandler,
-                           List<AlertNotifyHandler> alertNotifyHandlerList) {
+                           List<AlertNotifyHandler> alertNotifyHandlerList,
+                           PluginConfig pluginConfig) {
         this.workerPool = workerPool;
         this.dataQueue = dataQueue;
         this.noticeConfigService = noticeConfigService;
         this.alertStoreHandler = alertStoreHandler;
         alertNotifyHandlerMap = 
Maps.newHashMapWithExpectedSize(alertNotifyHandlerList.size());
+        this.pluginConfig = pluginConfig;
         alertNotifyHandlerList.forEach(r -> 
alertNotifyHandlerMap.put(r.type(), r));
     }
 
     @Override
-    public void afterPropertiesSet() throws Exception {
+    public void afterPropertiesSet() {
         // Start alarm distribution
         DispatchTask dispatchTask = new DispatchTask();
         for (int i = 0; i < DISPATCH_THREADS; i++) {
@@ -118,35 +118,11 @@ public class DispatcherAlarm implements InitializingBean {
                         alertStoreHandler.store(alert);
                         // Notice distribution
                         sendNotify(alert);
-                        //execute udf
-                        URLClassLoader classLoader = 
UdfUtil.getClassLoader("H:\\Java\\hertzbeat\\udf\\target\\");
-                        
Thread.currentThread().setContextClassLoader(classLoader);
-                        List<String> mainClassNameFromJar = 
UdfUtil.getAllClassNamesFromJar("H:\\Java\\hertzbeat\\udf\\target\\hertzbeat-udf-2.0-SNAPSHOT.jar");
-                        if (mainClassNameFromJar != null) {
-                            for (String name : mainClassNameFromJar) {
-                                if (name == null || name.trim().isEmpty()) {
-                                    log.error("class name is null or empty");
-                                    continue;
-                                }
-                                AfterAlertUdf afterAlertUdf = null;
-                                if (classLoader != null) {
-                                    try {
-                                        Class<?> clazz = 
classLoader.loadClass(name);
-                                        Constructor<?> constructor = 
clazz.getDeclaredConstructor();
-                                        afterAlertUdf = (AfterAlertUdf) 
constructor.newInstance();
-                                    } catch (ClassNotFoundException e) {
-                                        log.error("class not found : {}", 
e.getLocalizedMessage());
-                                    } catch (InstantiationException | 
IllegalAccessException | NoSuchMethodException e) {
-                                        log.error("class newInstance error : 
{}", e.getLocalizedMessage());
-                                    }
-                                }
-                                if (afterAlertUdf != null) {
-                                    try {
-                                        afterAlertUdf.execute(alert);
-                                    } catch (Exception e) {
-                                        log.error("execute udf error : {}", 
e.getLocalizedMessage());
-                                    }
-                                }
+                        // Execute the plugin
+                        List<Object> beans = pluginConfig.getBean();
+                        for (Object bean : beans) {
+                            if (bean instanceof Plugin) {
+                                ((Plugin) bean).execute(alert);
                             }
                         }
                     }
diff --git 
a/manager/src/main/java/org/apache/hertzbeat/manager/config/PluginConfig.java 
b/manager/src/main/java/org/apache/hertzbeat/manager/config/PluginConfig.java
new file mode 100644
index 000000000..fe9c6b9a1
--- /dev/null
+++ 
b/manager/src/main/java/org/apache/hertzbeat/manager/config/PluginConfig.java
@@ -0,0 +1,160 @@
+package org.apache.hertzbeat.manager.config;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanNameGenerator;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * Plugin configuration
+ */
+@Slf4j
+@Component
+public class PluginConfig implements ImportBeanDefinitionRegistrar, 
ApplicationContextAware {
+    @Autowired
+    private ApplicationContext applicationContext;
+    @Autowired
+    private DefaultListableBeanFactory defaultListableBeanFactory;
+
+    private static final String CLASS_SUFFIX = ".class";
+
+    private static final String BASE_PLUGIN_PATH = 
"org/apache/hertzbeat/plugin/Plugin";
+
+    private static final String BASE_PATH = System.getProperty("user.dir") + 
File.separator + "ext-lib";
+
+    private static final String PACKAGE = "org/hertzbeat/plugin";
+
+    private URLClassLoader getClassLoader() {
+        List<String> jars = getAllJars();
+        if (jars == null) {
+            return null;
+        }
+        List<URL> urlList = new ArrayList<>();
+        for (String jar : jars) {
+            try {
+                URL url = new File(jar).toURI().toURL();
+                urlList.add(url);
+            } catch (MalformedURLException e) {
+                log.error("Error converting jar to URL: {}", jar, e);
+            }
+        }
+        if (urlList.isEmpty()) {
+            return null;
+        }
+        URL[] urls = urlList.toArray(new URL[0]);
+        ClassLoader contextClassLoader = 
Thread.currentThread().getContextClassLoader();
+        return new URLClassLoader(urls, contextClassLoader);
+    }
+
+
+    private List<String> getAllJars() {
+        log.info("BASE_PATH:{}", PluginConfig.BASE_PATH);
+        File file = new File(PluginConfig.BASE_PATH);
+        File[] files = file.listFiles();
+        if (files == null) {
+            return null;
+        }
+        return Arrays.stream(files)
+                .filter(f -> f.getName().endsWith(".jar"))
+                .map(File::getAbsolutePath)
+                .collect(Collectors.toList());
+    }
+
+    private List<String> getAllClassNamesFromJar() throws IOException {
+        List<String> jars = getAllJars();
+        if (jars == null || jars.isEmpty()) {
+            return null;
+        }
+        List<String> classNames = new ArrayList<>();
+        for (String jar : jars) {
+            List<String> collect;
+            try (JarFile file = new JarFile(jar)) {
+                collect = file.stream()
+                        .filter(jarEntry -> 
jarEntry.getName().endsWith(CLASS_SUFFIX))
+                        .filter(jarEntry -> 
jarEntry.getName().startsWith(PACKAGE))
+                        .filter(jarEntry -> 
!jarEntry.getName().contains(BASE_PLUGIN_PATH))
+                        .map(jarEntry -> jarEntry.getName().replace("/", 
".").replace(".class", ""))
+                        .toList();
+            }
+            classNames.addAll(collect);
+        }
+        return classNames;
+    }
+
+    private void registerBean(Class<?> c, BeanDefinitionRegistry registry) {
+        String className = c.getName();
+        BeanDefinitionBuilder builder = 
BeanDefinitionBuilder.genericBeanDefinition(c);
+        BeanDefinition beanDefinition = builder.getBeanDefinition();
+        registry.registerBeanDefinition(className, beanDefinition);
+    }
+
+    @Override
+    public void registerBeanDefinitions(@NotNull AnnotationMetadata 
importingClassMetadata, @NotNull BeanDefinitionRegistry registry, @NotNull 
BeanNameGenerator importBeanNameGenerator) {
+        URLClassLoader classLoader = getClassLoader();
+        List<String> allClassNamesFromJar;
+        try {
+            allClassNamesFromJar = getAllClassNamesFromJar();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        if (allClassNamesFromJar != null) {
+            for (String name : allClassNamesFromJar) {
+                if (name == null || name.trim().isEmpty()) {
+                    log.error("class name is null or empty");
+                    continue;
+                }
+                if (classLoader != null) {
+                    Class<?> clazz = null;
+                    try {
+                        clazz = classLoader.loadClass(name);
+                    } catch (ClassNotFoundException e) {
+                        log.error("load class error:{}", 
e.getLocalizedMessage());
+                    }
+                    if (clazz != null) {
+                        registerBean(clazz, registry);
+                    }
+                }
+            }
+        }    }
+
+    public List<Object> getBean() throws IOException {
+        List<String> names = getAllClassNamesFromJar();
+        List<Object> beans = new ArrayList<>();
+        if (names != null) {
+            for (String name : names) {
+                Object bean = applicationContext.getBean(name);
+                beans.add(bean);
+            }
+        }
+        return beans;
+    }
+
+    @Override
+    public void setApplicationContext(@NotNull ApplicationContext 
applicationContext) throws BeansException {
+        this.applicationContext = applicationContext;
+        ConfigurableApplicationContext configurableApplicationContext = 
(ConfigurableApplicationContext) applicationContext;
+        this.defaultListableBeanFactory = (DefaultListableBeanFactory) 
configurableApplicationContext.getBeanFactory();
+    }
+}
diff --git a/plugin/pom.xml b/plugin/pom.xml
new file mode 100644
index 000000000..461adca67
--- /dev/null
+++ b/plugin/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <artifactId>hertzbeat</artifactId>
+        <groupId>org.apache.hertzbeat</groupId>
+        <version>2.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hertzbeat-plugin</artifactId>
+    <name>${project.artifactId}</name>
+    <properties>
+        <maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
+        <maven-assembly-plugin.version>3.3.0</maven-assembly-plugin.version>
+    </properties>
+
+    <dependencies>
+        <!-- common -->
+        <dependency>
+            <groupId>org.apache.hertzbeat</groupId>
+            <artifactId>hertzbeat-common</artifactId>
+        </dependency>
+    </dependencies>
+
+
+</project>
diff --git a/udf/src/main/java/org/apache/hertzbeat/udf/AfterAlertUdf.java 
b/plugin/src/main/java/org/apache/hertzbeat/plugin/Plugin.java
similarity index 91%
rename from udf/src/main/java/org/apache/hertzbeat/udf/AfterAlertUdf.java
rename to plugin/src/main/java/org/apache/hertzbeat/plugin/Plugin.java
index 4a99938be..8fcdf40d2 100644
--- a/udf/src/main/java/org/apache/hertzbeat/udf/AfterAlertUdf.java
+++ b/plugin/src/main/java/org/apache/hertzbeat/plugin/Plugin.java
@@ -17,13 +17,13 @@
  *
  */
 
-package org.apache.hertzbeat.udf;
+package org.apache.hertzbeat.plugin;
 
 import org.apache.hertzbeat.common.entity.alerter.Alert;
 
 /**
- * AfterAlertUdf
+ * Plugin
  */
-public interface AfterAlertUdf {
+public interface Plugin {
     void execute(Alert alert);
 }
diff --git 
a/udf/src/main/java/org/apache/hertzbeat/udf/DemoAfterAlertUdfImpl.java 
b/plugin/src/main/java/org/apache/hertzbeat/plugin/impl/DemoPluginImpl1.java
similarity index 81%
rename from 
udf/src/main/java/org/apache/hertzbeat/udf/DemoAfterAlertUdfImpl.java
rename to 
plugin/src/main/java/org/apache/hertzbeat/plugin/impl/DemoPluginImpl1.java
index 4852ca74c..f4a194c85 100644
--- a/udf/src/main/java/org/apache/hertzbeat/udf/DemoAfterAlertUdfImpl.java
+++ b/plugin/src/main/java/org/apache/hertzbeat/plugin/impl/DemoPluginImpl1.java
@@ -17,18 +17,19 @@
  *
  */
 
-package org.apache.hertzbeat.udf;
+package org.apache.hertzbeat.plugin.impl;
 
 import lombok.extern.slf4j.Slf4j;
 import org.apache.hertzbeat.common.entity.alerter.Alert;
+import org.apache.hertzbeat.plugin.Plugin;
 
 /**
- * DemoAfterAlertUdf
+ * DemoPlugin
  */
 @Slf4j
-public class DemoAfterAlertUdfImpl implements AfterAlertUdf{
+public class DemoPluginImpl1 implements Plugin {
     @Override
     public void execute(Alert alert) {
-        log.info("DemoAfterAlertUdfImpl execute alert: {}", alert);
+        log.info("DemoPluginImplsd;kjghsakdjghalskjdghjk execute alert: {}", 
alert);
     }
 }
diff --git a/pom.xml b/pom.xml
index a5b4ff317..dc6b61e68 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,7 +86,7 @@
         <module>warehouse</module>
         <module>remoting</module>
         <module>push</module>
-        <module>udf</module>
+        <module>plugin</module>
     </modules>
 
     <properties>
@@ -181,7 +181,7 @@
             <!-- udf -->
             <dependency>
                 <groupId>org.apache.hertzbeat</groupId>
-                <artifactId>hertzbeat-udf</artifactId>
+                <artifactId>hertzbeat-plugin</artifactId>
                 <version>${hertzbeat.version}</version>
             </dependency>
             <!-- spring -->


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

Reply via email to