فهرست منبع

feat:修复插件重启报错、增加iotdb支持

xiwa 1 سال پیش
والد
کامیت
4070f1cca3
92فایلهای تغییر یافته به همراه5199 افزوده شده و 65 حذف شده
  1. 2 2
      iot-dao/iot-data-model/pom.xml
  2. 2 2
      iot-dao/iot-data-service/pom.xml
  3. 2 2
      iot-dao/iot-data-serviceImpl-cache/pom.xml
  4. 2 2
      iot-dao/iot-data-serviceImpl-rdb/pom.xml
  5. 2 2
      iot-dao/iot-temporal-service/pom.xml
  6. 1 1
      iot-dao/iot-temporal-serviceImpl-es/pom.xml
  7. 57 0
      iot-dao/iot-temporal-serviceImpl-iotdb/pom.xml
  8. 38 0
      iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/config/IotDbConf.java
  9. 74 0
      iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/dao/IotDbTemplate.java
  10. 23 0
      iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/model/Record.java
  11. 46 0
      iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/DbStructureDataImpl.java
  12. 72 0
      iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/DevicePropertyDataImpl.java
  13. 32 0
      iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/RuleLogDataImpl.java
  14. 32 0
      iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/TaskLogDataImpl.java
  15. 44 0
      iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/ThingModelMessageDataImpl.java
  16. 28 0
      iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/VirtualDeviceLogDataImpl.java
  17. 2 2
      iot-dao/iot-temporal-serviceImpl-td/pom.xml
  18. 2 2
      iot-dao/iot-temporal-serviceImpl-ts/pom.xml
  19. 2 1
      iot-dao/pom.xml
  20. 1 1
      iot-module/iot-manager/pom.xml
  21. 24 0
      iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/PluginServiceImpl.java
  22. 1 1
      iot-module/iot-message-notify/pom.xml
  23. 1 1
      iot-module/iot-openapi/pom.xml
  24. 1 1
      iot-module/iot-plugin/iot-plugin-core/pom.xml
  25. 1 2
      iot-module/iot-plugin/iot-plugin-core/src/main/java/cc/iotkit/plugin/core/LocalPluginScript.java
  26. 1 1
      iot-module/iot-plugin/iot-plugin-main/pom.xml
  27. 4 18
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/PluginMainImpl.java
  28. 44 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/Chan.java
  29. 46 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/DataDecoder.java
  30. 42 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/DataEncoder.java
  31. 45 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/DataPackage.java
  32. 45 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/DataReader.java
  33. 77 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/PluginScriptEngine.java
  34. 48 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/PluginScriptServer.java
  35. 83 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/ScriptClientVerticle.java
  36. 30 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/ScriptServerConfig.java
  37. 142 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/ScriptVerticle.java
  38. 94 0
      iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/VertxTcpClient.java
  39. 2 1
      iot-module/iot-plugin/pom.xml
  40. 101 0
      iot-module/iot-plugin/spring-brick-maven-packager/pom.xml
  41. 108 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractDependencyFilterMojo.java
  42. 93 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractPackagerMojo.java
  43. 380 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/BasicRepackager.java
  44. 85 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/Constant.java
  45. 38 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/Dependency.java
  46. 73 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/DependencyPlugin.java
  47. 38 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/LoadMainResourcePattern.java
  48. 35 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/LoadToMain.java
  49. 92 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/PluginInfo.java
  50. 133 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/RepackageMojo.java
  51. 39 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/Repackager.java
  52. 41 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/Dependency.java
  53. 44 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevConfig.java
  54. 102 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevRepackager.java
  55. 33 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/AesConfig.java
  56. 43 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/AesEncryptPlugin.java
  57. 41 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/EncryptConfig.java
  58. 40 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/EncryptPlugin.java
  59. 50 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/EncryptPluginFactory.java
  60. 36 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/RsaConfig.java
  61. 57 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/RsaEncryptPlugin.java
  62. 75 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/DependencyFilter.java
  63. 35 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/Exclude.java
  64. 51 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/ExcludeFilter.java
  65. 38 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/FilterableDependency.java
  66. 27 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/Include.java
  67. 46 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/IncludeFilter.java
  68. 138 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/JarNestPackager.java
  69. 146 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/JarOuterPackager.java
  70. 68 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/MainConfig.java
  71. 136 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/MainRepackager.java
  72. 156 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/DirProdRepackager.java
  73. 77 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/JarNestedProdRepackager.java
  74. 56 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/JarOuterProdRepackager.java
  75. 59 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ProdConfig.java
  76. 95 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ProdRepackager.java
  77. 128 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ZipOuterProdRepackager.java
  78. 197 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ZipProdRepackager.java
  79. 100 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/CommonUtils.java
  80. 58 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageJar.java
  81. 249 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageZip.java
  82. 168 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/resources/META-INF/maven/com.gitee.starblues.springboot-plugin-maven-packager/plugin-help.xml
  83. 168 0
      iot-module/iot-plugin/spring-brick-maven-packager/src/main/resources/META-INF/maven/plugin.xml
  84. 1 1
      iot-module/iot-rule-engine/pom.xml
  85. 1 1
      iot-module/iot-screen/pom.xml
  86. 1 1
      iot-module/iot-system/pom.xml
  87. 1 1
      iot-module/pom.xml
  88. 1 1
      iot-starter/pom.xml
  89. 22 14
      iot-starter/src/main/resources/application.yml
  90. 1 1
      iot-test-tool/iot-virtual-device/pom.xml
  91. 1 1
      iot-test-tool/pom.xml
  92. 2 2
      pom.xml

+ 2 - 2
iot-dao/iot-data-model/pom.xml

@@ -5,9 +5,9 @@
     <parent>
         <artifactId>iot-dao</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
-    <version>0.5.0-SNAPSHOT</version>
+    <version>0.5.1-SNAPSHOT</version>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>iot-data-model</artifactId>

+ 2 - 2
iot-dao/iot-data-service/pom.xml

@@ -5,10 +5,10 @@
     <parent>
         <artifactId>iot-dao</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <version>0.5.0-SNAPSHOT</version>
+    <version>0.5.1-SNAPSHOT</version>
     <artifactId>iot-data-service</artifactId>
 
     <dependencies>

+ 2 - 2
iot-dao/iot-data-serviceImpl-cache/pom.xml

@@ -5,10 +5,10 @@
     <parent>
         <artifactId>iot-dao</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <version>0.5.0-SNAPSHOT</version>
+    <version>0.5.1-SNAPSHOT</version>
     <artifactId>iot-data-serviceImpl-cache</artifactId>
 
     <dependencies>

+ 2 - 2
iot-dao/iot-data-serviceImpl-rdb/pom.xml

@@ -5,9 +5,9 @@
     <parent>
         <artifactId>iot-dao</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
-    <version>0.5.0-SNAPSHOT</version>
+    <version>0.5.1-SNAPSHOT</version>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>iot-data-serviceImpl-rdb</artifactId>
     <description>

+ 2 - 2
iot-dao/iot-temporal-service/pom.xml

@@ -5,10 +5,10 @@
     <parent>
         <artifactId>iot-dao</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <version>0.5.0-SNAPSHOT</version>
+    <version>0.5.1-SNAPSHOT</version>
     <artifactId>iot-temporal-service</artifactId>
 
     <dependencies>

+ 1 - 1
iot-dao/iot-temporal-serviceImpl-es/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-dao</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 57 - 0
iot-dao/iot-temporal-serviceImpl-iotdb/pom.xml

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>iot-dao</artifactId>
+        <groupId>cc.iotkit</groupId>
+        <version>0.5.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>iot-temporal-serviceImpl-iotdb</artifactId>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>cc.iotkit</groupId>
+            <artifactId>iot-temporal-service</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cc.iotkit</groupId>
+            <artifactId>iot-data-serviceImpl-cache</artifactId>
+        </dependency>
+
+        <!--====================第三方库===================-->
+
+        <dependency>
+            <groupId>org.apache.iotdb</groupId>
+            <artifactId>iotdb-session</artifactId>
+            <version>1.2.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.github.linpeilie</groupId>
+            <artifactId>mapstruct-plus-spring-boot-starter</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 38 - 0
iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/config/IotDbConf.java

@@ -0,0 +1,38 @@
+package cc.iotkit.temporal.iotdb.config;
+
+
+import org.apache.iotdb.session.pool.SessionPool;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * iotdb数据库配置
+ *
+ * @author sjg
+ */
+@Configuration
+public class IotDbConf {
+
+    @Value("${spring.iotdb-datasource.host}")
+    private String host;
+
+    @Value("${spring.iotdb-datasource.port}")
+    private int port;
+
+    @Value("${spring.iotdb-datasource.username}")
+    private String username;
+
+    @Value("${spring.iotdb-datasource.password}")
+    private String password;
+
+    @Bean
+    public SessionPool getSession() {
+        return new SessionPool.Builder()
+                .host(host)
+                .port(port)
+                .user(username)
+                .password(password)
+                .build();
+    }
+}

+ 74 - 0
iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/dao/IotDbTemplate.java

@@ -0,0 +1,74 @@
+package cc.iotkit.temporal.iotdb.dao;
+
+import lombok.Data;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.iotdb.isession.pool.SessionDataSetWrapper;
+import org.apache.iotdb.session.pool.SessionPool;
+import org.apache.iotdb.tsfile.read.common.Field;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author sjg
+ */
+@Slf4j
+@Component
+@Data
+public class IotDbTemplate {
+
+    @Autowired
+    private SessionPool sessionPool;
+
+    private static String group = "root.iotkit";
+
+    private String getPath(String productKey, String deviceId) {
+        return group + "." + productKey + "." + deviceId;
+    }
+
+    /**
+     * 对齐插入时序序列
+     * @param productKey 产品key
+     * @param deviceId  设备id
+     * @param time  数据时间
+     * @param data  数据键值对
+     */
+    @SneakyThrows
+    public void insert(String productKey, String deviceId, long time, Map<String, Object> data) {
+        String path = getPath(productKey, deviceId);
+        List<String> measurements = new ArrayList<>();
+        // 需要服务器做类型判断
+        List<String> values = new ArrayList<>();
+        for (String key : data.keySet()) {
+            measurements.add(key);
+            values.add(String.valueOf(data.get(key)));
+        }
+        //对齐插入,使用PREVIOUS填充查询
+        sessionPool.insertAlignedRecord(path, time, measurements, values);
+    }
+
+    @SneakyThrows
+    public List<Map<String,Object>> query(String productKey, String deviceId,long startTime,long endTime) {
+        List<Map<String,Object>> list = new ArrayList<>();
+        SessionDataSetWrapper dataSetWrapper = sessionPool.executeRawDataQuery(
+                List.of(getPath(productKey,deviceId)),startTime,endTime,5000);
+        while (dataSetWrapper.hasNext()) {
+            RowRecord record = dataSetWrapper.next();
+            Map<String, Object> data = new HashMap<>(record.getFields().size() + 1);
+            long time = record.getTimestamp();
+            data.put("time", time);
+            for (Field field : record.getFields()) {
+                field.getObjectValue(field.getDataType());
+            }
+            list.add(data);
+        }
+        return list;
+    }
+
+}

+ 23 - 0
iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/model/Record.java

@@ -0,0 +1,23 @@
+package cc.iotkit.temporal.iotdb.model;
+
+
+/**
+ * @author sjg
+ */
+public interface Record {
+
+    /**
+     * 设备Id
+     *
+     * @return string
+     */
+    String getDeviceId();
+
+    /**
+     * 时间
+     *
+     * @return long
+     */
+    Long getTime();
+
+}

+ 46 - 0
iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/DbStructureDataImpl.java

@@ -0,0 +1,46 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.temporal.iotdb.service;
+
+import cc.iotkit.common.enums.ErrCode;
+import cc.iotkit.common.exception.BizException;
+import cc.iotkit.model.product.ThingModel;
+import cc.iotkit.temporal.IDbStructureData;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+
+@Slf4j
+@Service
+public class DbStructureDataImpl implements IDbStructureData {
+
+    @SneakyThrows
+    @Override
+    public void defineThingModel(ThingModel thingModel) {
+        //无须处理,自动创建
+    }
+
+    @Override
+    public void updateThingModel(ThingModel thingModel) {
+        throw new BizException(ErrCode.UNSUPPORTED_OPERATION_EXCEPTION);
+    }
+
+    /**
+     * 初始化其它数据结构
+     */
+    @Override
+    @PostConstruct
+    public void initDbStructure() {
+
+    }
+
+}

+ 72 - 0
iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/DevicePropertyDataImpl.java

@@ -0,0 +1,72 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.temporal.iotdb.service;
+
+import cc.iotkit.data.manager.IDeviceInfoData;
+import cc.iotkit.model.device.DeviceInfo;
+import cc.iotkit.model.device.message.DeviceProperty;
+import cc.iotkit.model.device.message.DevicePropertyCache;
+import cc.iotkit.temporal.IDevicePropertyData;
+import cc.iotkit.temporal.iotdb.dao.IotDbTemplate;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Service
+public class DevicePropertyDataImpl implements IDevicePropertyData {
+
+    @Autowired
+    @Qualifier("deviceInfoDataCache")
+    private IDeviceInfoData deviceInfoData;
+
+    @Autowired
+    private IotDbTemplate dbTemplate;
+
+    @Override
+    public List<DeviceProperty> findDevicePropertyHistory(String deviceId, String name, long start, long end, int size) {
+        DeviceInfo device = deviceInfoData.findByDeviceId(deviceId);
+        if (device == null) {
+            return new ArrayList<>();
+        }
+        List<DeviceProperty> list=new ArrayList<>();
+        List<Map<String, Object>> records = dbTemplate.query(device.getProductKey(), deviceId, start, end);
+        int i=0;
+        for (Map<String, Object> record : records) {
+            Object val = record.get(name);
+            list.add(new DeviceProperty(String.valueOf(++i),deviceId,name,val, (Long) record.get("time")));
+        }
+
+        return list;
+    }
+
+    @Override
+    public void addProperties(String deviceId, Map<String, DevicePropertyCache> properties, long time) {
+        DeviceInfo device = deviceInfoData.findByDeviceId(deviceId);
+        if (device == null) {
+            return;
+        }
+        //获取设备旧属性
+        Map<String, DevicePropertyCache> oldProperties = deviceInfoData.getProperties(deviceId);
+        //用新属性覆盖
+        oldProperties.putAll(properties);
+        Map<String, Object> data = new HashMap<>(oldProperties.size());
+        oldProperties.forEach((k, v) -> data.put(k, v.getValue()));
+        //添加对齐序列
+        dbTemplate.insert(device.getProductKey(), deviceId, System.currentTimeMillis(), data);
+    }
+
+}

+ 32 - 0
iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/RuleLogDataImpl.java

@@ -0,0 +1,32 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.temporal.iotdb.service;
+
+import cc.iotkit.common.api.Paging;
+import cc.iotkit.model.rule.RuleLog;
+import cc.iotkit.temporal.IRuleLogData;
+import org.springframework.stereotype.Service;
+
+@Service
+public class RuleLogDataImpl implements IRuleLogData {
+
+    @Override
+    public void deleteByRuleId(String ruleId) {
+    }
+
+    @Override
+    public Paging<RuleLog> findByRuleId(String ruleId, int page, int size) {
+        return new Paging<>();
+    }
+
+    @Override
+    public void add(RuleLog log) {
+    }
+}

+ 32 - 0
iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/TaskLogDataImpl.java

@@ -0,0 +1,32 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.temporal.iotdb.service;
+
+import cc.iotkit.common.api.Paging;
+import cc.iotkit.model.rule.TaskLog;
+import cc.iotkit.temporal.ITaskLogData;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TaskLogDataImpl implements ITaskLogData {
+
+    @Override
+    public void deleteByTaskId(String taskId) {
+    }
+
+    @Override
+    public Paging<TaskLog> findByTaskId(String taskId, int page, int size) {
+        return new Paging<>();
+    }
+
+    @Override
+    public void add(TaskLog log) {
+    }
+}

+ 44 - 0
iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/ThingModelMessageDataImpl.java

@@ -0,0 +1,44 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.temporal.iotdb.service;
+
+import cc.iotkit.common.api.Paging;
+import cc.iotkit.common.thing.ThingModelMessage;
+import cc.iotkit.model.stats.TimeData;
+import cc.iotkit.temporal.IThingModelMessageData;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class ThingModelMessageDataImpl implements IThingModelMessageData {
+
+    @Override
+    public Paging<ThingModelMessage> findByTypeAndIdentifier(String deviceId, String type,
+                                                             String identifier,
+                                                             int page, int size) {
+        return new Paging<>();
+    }
+
+    @Override
+    public List<TimeData> getDeviceMessageStatsWithUid(String uid, long start, long end) {
+        return new ArrayList<>();
+    }
+
+    @Override
+    public void add(ThingModelMessage msg) {
+    }
+
+    @Override
+    public long count() {
+        return 0L;
+    }
+}

+ 28 - 0
iot-dao/iot-temporal-serviceImpl-iotdb/src/main/java/cc/iotkit/temporal/iotdb/service/VirtualDeviceLogDataImpl.java

@@ -0,0 +1,28 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.temporal.iotdb.service;
+
+import cc.iotkit.common.api.Paging;
+import cc.iotkit.model.device.VirtualDeviceLog;
+import cc.iotkit.temporal.IVirtualDeviceLogData;
+import org.springframework.stereotype.Service;
+
+@Service
+public class VirtualDeviceLogDataImpl implements IVirtualDeviceLogData {
+
+    @Override
+    public Paging<VirtualDeviceLog> findByVirtualDeviceId(String virtualDeviceId, int page, int size) {
+       return new Paging<>();
+    }
+
+    @Override
+    public void add(VirtualDeviceLog log) {
+    }
+}

+ 2 - 2
iot-dao/iot-temporal-serviceImpl-td/pom.xml

@@ -5,10 +5,10 @@
     <parent>
         <artifactId>iot-dao</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <version>0.5.0-SNAPSHOT</version>
+    <version>0.5.1-SNAPSHOT</version>
     <artifactId>iot-temporal-serviceImpl-td</artifactId>
 
     <description>

+ 2 - 2
iot-dao/iot-temporal-serviceImpl-ts/pom.xml

@@ -6,9 +6,9 @@
     <parent>
         <artifactId>iot-dao</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
-    <version>0.5.0-SNAPSHOT</version>
+    <version>0.5.1-SNAPSHOT</version>
     <artifactId>iot-temporal-serviceImpl-ts</artifactId>
 
     <description>

+ 2 - 1
iot-dao/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iotkit-parent</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>pom</packaging>
@@ -23,6 +23,7 @@
         <module>iot-temporal-service</module>
         <module>iot-temporal-serviceImpl-td</module>
         <module>iot-temporal-serviceImpl-es</module>
+        <module>iot-temporal-serviceImpl-iotdb</module>
     </modules>
 
     <artifactId>iot-dao</artifactId>

+ 1 - 1
iot-module/iot-manager/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-module</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 24 - 0
iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/PluginServiceImpl.java

@@ -15,14 +15,18 @@ import cc.iotkit.model.plugin.PluginInfo;
 import cn.hutool.core.io.IoUtil;
 import com.gitee.starblues.core.PluginState;
 import com.gitee.starblues.core.descriptor.PluginDescriptor;
+import com.gitee.starblues.integration.AutoIntegrationConfiguration;
 import com.gitee.starblues.integration.operator.PluginOperator;
 import com.gitee.starblues.integration.operator.upload.UploadParam;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.File;
 import java.nio.charset.Charset;
+import java.util.List;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
@@ -33,6 +37,9 @@ import java.util.jar.JarFile;
 @Service
 public class PluginServiceImpl implements IPluginService {
 
+    @Autowired
+    private AutoIntegrationConfiguration autoIntegrationConfiguration;
+
     @Autowired
     private IPluginInfoData pluginInfoData;
 
@@ -58,6 +65,17 @@ public class PluginServiceImpl implements IPluginService {
                     pluginOperator.uninstall(pluginId, true, false);
                     //兼容相同版本包,先删除,再上传
                     FileUtils.del(pluginInfo.getPluginDescriptor().getPluginPath());
+                } else {
+                    //删除对应插件的所有包
+                    for (String pluginPath : autoIntegrationConfiguration.getPluginPath()) {
+                        List<String> fileNames = FileUtils.listFileNames(new File(pluginPath).getAbsolutePath());
+                        for (String fileName : fileNames) {
+                            if (!fileName.startsWith(pluginId)) {
+                                continue;
+                            }
+                            FileUtils.del(new File(pluginPath + "/" + fileName));
+                        }
+                    }
                 }
             }
 
@@ -175,10 +193,16 @@ public class PluginServiceImpl implements IPluginService {
                 //停止插件
                 pluginOperator.stop(pluginId);
             }
+        } else {
+            //已经停止,未获取到插件
+            if (PluginInfo.STATE_RUNNING.equals(state)) {
+                throw new BizException(ErrCode.PLUGIN_INSTALL_FAILED, "插件启动失败");
+            }
         }
 
         old.setState(state);
         pluginInfoData.save(old);
+
     }
 
 }

+ 1 - 1
iot-module/iot-message-notify/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-module</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
iot-module/iot-openapi/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-module</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
iot-module/iot-plugin/iot-plugin-core/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-plugin</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 2
iot-module/iot-plugin/iot-plugin-core/src/main/java/cc/iotkit/plugin/core/LocalPluginScript.java

@@ -35,8 +35,7 @@ public class LocalPluginScript implements IPluginScript {
             return null;
         }
 
-        scriptEngine = ScriptEngineFactory.getScriptEngine("js");
-        scriptEngine.setScript(script);
+        scriptEngine = ScriptEngineFactory.getJsEngine(script);
         return scriptEngine;
     }
 

+ 1 - 1
iot-module/iot-plugin/iot-plugin-main/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-plugin</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 4 - 18
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/PluginMainImpl.java

@@ -7,7 +7,6 @@ import cc.iotkit.common.thing.DeviceService;
 import cc.iotkit.common.thing.ThingModelMessage;
 import cc.iotkit.common.thing.ThingService;
 import cc.iotkit.common.utils.JsonUtils;
-import cc.iotkit.common.utils.StringUtils;
 import cc.iotkit.data.manager.IDeviceInfoData;
 import cc.iotkit.data.manager.IPluginInfoData;
 import cc.iotkit.data.manager.IProductData;
@@ -21,8 +20,8 @@ import cc.iotkit.plugin.core.thing.actions.ActionResult;
 import cc.iotkit.plugin.core.thing.actions.down.PropertyGet;
 import cc.iotkit.plugin.core.thing.actions.down.PropertySet;
 import cc.iotkit.plugin.core.thing.actions.down.ServiceInvoke;
+import cc.iotkit.plugin.main.script.PluginScriptServer;
 import cc.iotkit.script.IScriptEngine;
-import cc.iotkit.script.ScriptEngineFactory;
 import com.gitee.starblues.integration.user.PluginUser;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -67,29 +66,16 @@ public class PluginMainImpl implements IPluginMain, DeviceService {
     @Autowired
     private MqProducer<ThingModelMessage> producer;
 
-    public IScriptEngine initScriptEngine(String pluginId) {
-        PluginInfo pluginInfo = pluginInfoData.findByPluginId(pluginId);
-        if (pluginInfo == null) {
-            return null;
-        }
-        String script = pluginInfo.getScript();
-        if (StringUtils.isBlank(script)) {
-            return null;
-        }
-
-        IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
-        scriptEngine.setScript(script);
-        return scriptEngine;
-    }
+    @Autowired
+    private PluginScriptServer pluginScriptServer;
 
     @Override
     public IScriptEngine getScriptEngine(String pluginId) {
-        return initScriptEngine(pluginId);
+        return pluginScriptServer.getScriptEngine(pluginId);
     }
 
     @Override
     public void reloadScript(String pluginId) {
-        initScriptEngine(pluginId);
     }
 
     @Override

+ 44 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/Chan.java

@@ -0,0 +1,44 @@
+package cc.iotkit.plugin.main.script;
+
+import cc.iotkit.common.utils.JsonUtils;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.concurrent.locks.LockSupport;
+
+@Slf4j
+public class Chan<T> {
+
+    private static final long THREAD_WAIT_TIME = 1000_000L * 10_000;
+
+    private volatile T data;
+
+    private volatile Thread t;
+
+    private Chan() {
+
+    }
+
+    public static Chan getInstance() {
+        return ChanSingleton.INSTANCE;
+    }
+
+    public T get(Object blocker) {
+        this.t = Thread.currentThread();
+        LockSupport.parkNanos(blocker, THREAD_WAIT_TIME);
+        this.t = null;
+        return data;
+    }
+
+    public void put(T data) {
+        this.data = data;
+        if (t == null) {
+            return;
+        }
+        log.debug("put message data:{}", JsonUtils.toJsonString(data));
+        LockSupport.unpark(t);
+    }
+
+    private static class ChanSingleton {
+        private static final Chan<?> INSTANCE = new Chan<>();
+    }
+}

+ 46 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/DataDecoder.java

@@ -0,0 +1,46 @@
+package cc.iotkit.plugin.main.script;
+
+import io.vertx.core.buffer.Buffer;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 数据解码
+ *
+ * @author sjg
+ */
+@Slf4j
+public class DataDecoder {
+
+    public static DataPackage decode(Buffer buffer) {
+        DataPackage data = new DataPackage();
+        ReadField rf = new ReadField(0, buffer);
+
+        data.setMid(rf.read());
+        data.setPluginId(rf.read());
+        data.setMethod(rf.read());
+        data.setArgs(rf.read());
+        data.setResult(rf.read());
+        return data;
+    }
+
+
+    @Data
+    @AllArgsConstructor
+    private static class ReadField {
+
+        private int idx = 0;
+
+        private Buffer buffer;
+
+        private String read() {
+            int len = buffer.getInt(idx);
+            idx += 4;
+            String s = new String(buffer.getBytes(idx, idx + len));
+            idx += len;
+            return s;
+        }
+
+    }
+}

+ 42 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/DataEncoder.java

@@ -0,0 +1,42 @@
+package cc.iotkit.plugin.main.script;
+
+import io.vertx.core.buffer.Buffer;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 数据编码
+ *
+ * @author sjg
+ */
+@Slf4j
+public class DataEncoder {
+
+    public static Buffer encode(DataPackage data) {
+
+        Buffer body = Buffer.buffer();
+
+        append(data.getMid(), body);
+
+        append(data.getPluginId(), body);
+
+        append(data.getMethod(), body);
+
+        append(data.getArgs(), body);
+
+        append(data.getResult(), body);
+
+        Buffer buffer = Buffer.buffer();
+
+        byte[] bytes = body.getBytes();
+        buffer.appendInt(bytes.length);
+        buffer.appendBytes(bytes);
+
+        return buffer;
+    }
+
+    private static void append(String s, Buffer buffer) {
+        byte[] bytes = s == null ? new byte[]{} : s.getBytes();
+        buffer.appendInt(bytes.length);
+        buffer.appendBytes(bytes);
+    }
+}

+ 45 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/DataPackage.java

@@ -0,0 +1,45 @@
+package cc.iotkit.plugin.main.script;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+/**
+ * 数据包
+ *
+ * @author sjg
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class DataPackage {
+
+    /**
+     * 消息id
+     */
+    private String mid;
+
+    /**
+     * 插件id
+     */
+    private String pluginId;
+
+    /**
+     * 调用方法
+     */
+    private String method;
+
+    /**
+     * 方法参数
+     */
+    private String args;
+
+    /**
+     * 执行结果
+     */
+    private String result;
+
+}

+ 45 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/DataReader.java

@@ -0,0 +1,45 @@
+package cc.iotkit.plugin.main.script;
+
+
+import io.vertx.core.Handler;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.core.parsetools.RecordParser;
+
+import java.util.function.Consumer;
+
+/**
+ * 数据包读取器
+ *
+ * @author sjg
+ */
+public class DataReader {
+
+    public static RecordParser getParser(Consumer<Buffer> receiveHandler) {
+        RecordParser parser = RecordParser.newFixed(4);
+        // 设置处理器
+        parser.setOutput(new Handler<>() {
+            // 表示当前数据长度
+            int size = -1;
+
+            @Override
+            public void handle(Buffer buffer) {
+                //-1表示当前还没有长度信息,需要从收到的数据中取出长度
+                if (-1 == size) {
+                    //取出长度
+                    size = buffer.getInt(0);
+                    //动态修改长度
+                    parser.fixedSizeMode(size);
+                } else {
+                    //如果size != -1, 说明已经接受到长度信息了,接下来的数据就是protobuf可识别的字节数组
+                    byte[] buf = buffer.getBytes();
+                    receiveHandler.accept(Buffer.buffer(buf));
+                    //处理完后要将长度改回
+                    parser.fixedSizeMode(4);
+                    //重置size变量
+                    size = -1;
+                }
+            }
+        });
+        return parser;
+    }
+}

+ 77 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/PluginScriptEngine.java

@@ -0,0 +1,77 @@
+package cc.iotkit.plugin.main.script;
+
+import cc.iotkit.common.utils.JsonUtils;
+import cc.iotkit.script.IScriptEngine;
+import cc.iotkit.script.JavaScriptEngine;
+import cn.hutool.core.util.IdUtil;
+import com.fasterxml.jackson.core.type.TypeReference;
+import io.vertx.core.Future;
+import io.vertx.core.Vertx;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 用于插件的脚本引擎,为了规避graalvm js加载问题,不直接调用使用tcp通讯交互
+ *
+ * @author sjg
+ */
+@Slf4j
+@Data
+public class PluginScriptEngine implements IScriptEngine {
+
+    private String pluginId;
+
+    private ScriptClientVerticle scriptClientVerticle = new ScriptClientVerticle();
+
+    public PluginScriptEngine(String pluginId) {
+        this.pluginId = pluginId;
+        Vertx vertx = Vertx.vertx();
+        Future<String> future = vertx.deployVerticle(scriptClientVerticle);
+        future.onSuccess((s -> {
+            log.info("tcp client started success");
+        }));
+        future.onFailure((e) -> {
+            log.error("tcp client startup failed", e);
+        });
+    }
+
+    @Override
+    public void setScript(String s) {
+
+    }
+
+    @Override
+    public void putScriptEnv(String s, Object o) {
+
+    }
+
+    @Override
+    public void invokeMethod(String s, Object... args) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <T> T invokeMethod(TypeReference<T> type, String method, Object... args) {
+        List<String> argJson = new ArrayList<>();
+        for (Object arg : args) {
+            argJson.add(JsonUtils.toJsonString(arg));
+        }
+
+        String json = scriptClientVerticle.send(DataPackage.builder()
+                .pluginId(pluginId)
+                .mid(IdUtil.getSnowflakeNextIdStr())
+                .method(method)
+                .args(JsonUtils.toJsonString(argJson))
+                .build());
+        return json == null ? null : JsonUtils.parseObject(json, type);
+    }
+
+    @Override
+    public String invokeMethod(String s, String s1) {
+        throw new UnsupportedOperationException();
+    }
+
+}

+ 48 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/PluginScriptServer.java

@@ -0,0 +1,48 @@
+package cc.iotkit.plugin.main.script;
+
+import cc.iotkit.data.manager.IPluginInfoData;
+import cc.iotkit.script.IScriptEngine;
+import io.vertx.core.Future;
+import io.vertx.core.Vertx;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 用于插件的脚本引擎,为了规避graalvm js加载问题,不直接调用使用tcp通讯交互
+ *
+ * @author sjg
+ */
+@Slf4j
+@Service
+public class PluginScriptServer {
+    @Autowired
+    private IPluginInfoData pluginInfoData;
+
+    @Autowired
+    private ScriptVerticle scriptVerticle;
+
+    private static final Map<String, IScriptEngine> PLUGIN_SCRIPT_ENGINES = new HashMap<>();
+
+    @PostConstruct
+    public void init() {
+        Vertx vertx = Vertx.vertx();
+        Future<String> future = vertx.deployVerticle(scriptVerticle);
+        future.onSuccess((s -> {
+            log.info("plugin script server started success");
+        }));
+        future.onFailure(Throwable::printStackTrace);
+    }
+
+    public IScriptEngine getScriptEngine(String pluginId) {
+        if (!PLUGIN_SCRIPT_ENGINES.containsKey(pluginId)) {
+            PLUGIN_SCRIPT_ENGINES.put(pluginId,new PluginScriptEngine(pluginId));
+        }
+        return PLUGIN_SCRIPT_ENGINES.get(pluginId);
+    }
+
+}

+ 83 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/ScriptClientVerticle.java

@@ -0,0 +1,83 @@
+package cc.iotkit.plugin.main.script;
+
+import cn.hutool.core.util.HexUtil;
+import io.vertx.core.AbstractVerticle;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.core.net.NetClient;
+import io.vertx.core.net.NetClientOptions;
+import io.vertx.core.net.NetSocket;
+import io.vertx.core.parsetools.RecordParser;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author sjg
+ */
+@Slf4j
+public class ScriptClientVerticle extends AbstractVerticle {
+
+    private NetClient netClient;
+
+    private NetSocket socket;
+
+    private AtomicInteger atMid = new AtomicInteger(0);
+
+    @Override
+    public void start() {
+        initClient();
+    }
+
+    @Override
+    public void stop() {
+        if (null != netClient) {
+            netClient.close();
+        }
+    }
+
+    private void initClient() {
+        NetClientOptions options = new NetClientOptions();
+        options.setReconnectAttempts(Integer.MAX_VALUE);
+        options.setReconnectInterval(20000L);
+        netClient = vertx.createNetClient(options);
+        RecordParser parser = DataReader.getParser(this::handle);
+
+        netClient.connect(new ScriptServerConfig().getPort(), "127.0.0.1", result -> {
+            if (result.succeeded()) {
+                log.debug("connect tcp success");
+                socket = result.result();
+                socket.handler(parser);
+            } else {
+                log.error("connect tcp error", result.cause());
+            }
+        });
+    }
+
+    private short getMid() {
+        atMid.compareAndSet(254, 0);
+        return (short) atMid.getAndIncrement();
+    }
+
+    public String send(DataPackage data) {
+        Buffer buffer = DataEncoder.encode(data);
+        log.info("send data:{}", HexUtil.encodeHexStr(buffer.getBytes()));
+        socket.write(buffer);
+        Chan<DataPackage> chan = Chan.getInstance();
+        DataPackage receiver = chan.get(data.getMid());
+        if (receiver == null) {
+            return null;
+        }
+        if (receiver.getMid().equals(data.getMid())) {
+            return receiver.getResult();
+        }
+        return null;
+    }
+
+    public void handle(Buffer buffer) {
+        log.info("receive server data:{}", buffer.toString());
+        DataPackage data = DataDecoder.decode(buffer);
+        Chan<DataPackage> chan = Chan.getInstance();
+        chan.put(data);
+    }
+
+}

+ 30 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/ScriptServerConfig.java

@@ -0,0 +1,30 @@
+package cc.iotkit.plugin.main.script;
+
+import cn.hutool.core.util.RandomUtil;
+import io.vertx.core.net.SocketAddress;
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @author sjg
+ */
+public class ScriptServerConfig {
+    private static int _port;
+
+    static {
+        _port = RandomUtil.randomInt(11024, 12024);
+    }
+
+    @Getter
+    private String host = "localhost";
+
+    @Getter
+    private int port = _port;
+
+    public SocketAddress createSocketAddress() {
+        if (StringUtils.isEmpty(host)) {
+            host = "localhost";
+        }
+        return SocketAddress.inetSocketAddress(port, host);
+    }
+}

+ 142 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/ScriptVerticle.java

@@ -0,0 +1,142 @@
+package cc.iotkit.plugin.main.script;
+
+import cc.iotkit.common.utils.StringUtils;
+import cc.iotkit.data.manager.IPluginInfoData;
+import cc.iotkit.model.plugin.PluginInfo;
+import cc.iotkit.script.IScriptEngine;
+import cc.iotkit.script.ScriptEngineFactory;
+import cn.hutool.core.util.IdUtil;
+import io.vertx.core.AbstractVerticle;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.core.net.NetServer;
+import io.vertx.core.net.NetServerOptions;
+import io.vertx.core.net.NetSocket;
+import io.vertx.core.parsetools.RecordParser;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Slf4j
+@Component
+public class ScriptVerticle extends AbstractVerticle {
+
+    private final Map<String, VertxTcpClient> clientMap = new ConcurrentHashMap<>();
+
+    private static final Map<String, IScriptEngine> PLUGIN_SCRIPT_ENGINES = new HashMap<>();
+
+    @Setter
+    private long keepAliveTimeout = Duration.ofSeconds(30).toMillis();
+
+    @Autowired
+    private IPluginInfoData pluginInfoData;
+
+    public IScriptEngine initScriptEngine(String pluginId) {
+        PluginInfo pluginInfo = pluginInfoData.findByPluginId(pluginId);
+        if (pluginInfo == null) {
+            return null;
+        }
+        String script = pluginInfo.getScript();
+        if (StringUtils.isBlank(script)) {
+            return null;
+        }
+
+        IScriptEngine jsEngine = ScriptEngineFactory.getJsEngine(script);
+        PLUGIN_SCRIPT_ENGINES.put(pluginId, ScriptEngineFactory.getJsEngine(script));
+        return jsEngine;
+    }
+
+    public IScriptEngine getScriptEngine(String pluginId) {
+        if (!PLUGIN_SCRIPT_ENGINES.containsKey(pluginId)) {
+            return initScriptEngine(pluginId);
+        }
+        return PLUGIN_SCRIPT_ENGINES.get(pluginId);
+    }
+
+    @Override
+    public void start() {
+        initTcpServer();
+        log.info("init tcp server failed");
+    }
+
+    @Override
+    public void stop() {
+        log.info("tcp server stopped");
+    }
+
+    /**
+     * 初始TCP服务
+     */
+    private void initTcpServer() {
+        ScriptServerConfig config = new ScriptServerConfig();
+        NetServer netServer = vertx.createNetServer(
+                new NetServerOptions().setHost("127.0.0.1")
+                        .setPort(config.getPort()));
+        netServer.connectHandler(this::acceptTcpConnection);
+        netServer.listen(config.createSocketAddress(), result -> {
+            if (result.succeeded()) {
+                log.info("tcp server startup on {}", result.result().actualPort());
+            } else {
+                result.cause().printStackTrace();
+            }
+        });
+    }
+
+    /**
+     * TCP连接处理逻辑
+     *
+     * @param socket socket
+     */
+    protected void acceptTcpConnection(NetSocket socket) {
+        // 客户端连接处理
+        String clientId = IdUtil.simpleUUID() + "_" + socket.remoteAddress();
+        VertxTcpClient client = new VertxTcpClient(clientId);
+        client.setKeepAliveTimeoutMs(keepAliveTimeout);
+        try {
+            // TCP异常和关闭处理
+            socket.exceptionHandler(Throwable::printStackTrace).closeHandler(nil -> {
+                log.debug("tcp server client [{}] closed", socket.remoteAddress());
+                client.shutdown();
+            });
+            // 这个地方是在TCP服务初始化的时候设置的 parserSupplier
+            client.setKeepAliveTimeoutMs(keepAliveTimeout);
+            client.setSocket(socket);
+            RecordParser parser = DataReader.getParser(buffer -> {
+                try {
+                    DataPackage data = DataDecoder.decode(buffer);
+                    String pluginId = data.getPluginId();
+                    clientMap.put(pluginId, client);
+                    IScriptEngine scriptEngine = getScriptEngine(pluginId);
+                    if(scriptEngine==null){
+                        data.setResult("");
+                    }else {
+                        //调用执行脚本方法返回结果
+                        String result = scriptEngine.invokeMethod(data.getMethod(), data.getArgs());
+                        data.setResult(result);
+                    }
+                    sendMsg(pluginId, DataEncoder.encode(data));
+                } catch (Exception e) {
+                    log.error("decode error", e);
+                }
+            });
+            client.setParser(parser);
+            log.debug("accept tcp client [{}] connection", socket.remoteAddress());
+        } catch (Exception e) {
+            log.error("acceptTcpConnection error", e);
+            client.shutdown();
+        }
+    }
+
+    public void sendMsg(String pluginId, Buffer msg) {
+        VertxTcpClient tcpClient = clientMap.get(pluginId);
+        if (tcpClient != null) {
+            tcpClient.sendMessage(msg);
+        }
+    }
+
+}

+ 94 - 0
iot-module/iot-plugin/iot-plugin-main/src/main/java/cc/iotkit/plugin/main/script/VertxTcpClient.java

@@ -0,0 +1,94 @@
+package cc.iotkit.plugin.main.script;
+
+import io.vertx.core.buffer.Buffer;
+import io.vertx.core.net.NetSocket;
+import io.vertx.core.parsetools.RecordParser;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Hex;
+
+import java.time.Duration;
+
+/**
+ * @author sjg
+ */
+@Slf4j
+public class VertxTcpClient {
+    @Getter
+    private String id;
+    public NetSocket socket;
+    @Setter
+    private long keepAliveTimeoutMs = Duration.ofSeconds(30).toMillis();
+    private volatile long lastKeepAliveTime = System.currentTimeMillis();
+
+    @Setter
+    private RecordParser parser;
+
+    public VertxTcpClient(String id) {
+        this.id = id;
+    }
+
+    public void keepAlive() {
+        lastKeepAliveTime = System.currentTimeMillis();
+    }
+
+    public boolean isOnline() {
+        return System.currentTimeMillis() - lastKeepAliveTime < keepAliveTimeoutMs;
+    }
+
+    public void setSocket(NetSocket socket) {
+        synchronized (this) {
+            if (this.socket != null && this.socket != socket) {
+                this.socket.close();
+            }
+
+            this.socket = socket
+                    .closeHandler(v -> shutdown())
+                    .handler(buffer -> {
+                        if (log.isDebugEnabled()) {
+                            log.debug("handle tcp client[{}] payload:[{}]",
+                                    socket.remoteAddress(),
+                                    Hex.encodeHexString(buffer.getBytes()));
+                        }
+                        keepAlive();
+                        parser.handle(buffer);
+                        if (this.socket != socket) {
+                            log.warn("tcp client [{}] memory leak ", socket.remoteAddress());
+                            socket.close();
+                        }
+                    });
+        }
+    }
+
+    public void shutdown() {
+        log.debug("tcp client [{}] disconnect", getId());
+        synchronized (this) {
+            if (null != socket) {
+                execute(socket::close);
+                this.socket = null;
+            }
+        }
+    }
+
+    public void sendMessage(Buffer buffer) {
+        log.info("wirte data:{}", buffer.toString());
+        socket.write(buffer, r -> {
+            keepAlive();
+            if (r.succeeded()) {
+                log.info("client msg send success");
+            } else {
+                log.error("client msg send failed", r.cause());
+            }
+        });
+    }
+
+    private void execute(Runnable runnable) {
+        try {
+            runnable.run();
+        } catch (Exception e) {
+            log.warn("close tcp client error", e);
+        }
+    }
+
+}

+ 2 - 1
iot-module/iot-plugin/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-module</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -15,6 +15,7 @@
     <modules>
         <module>iot-plugin-core</module>
         <module>iot-plugin-main</module>
+        <module>spring-brick-maven-packager</module>
     </modules>
 
 </project>

+ 101 - 0
iot-module/iot-plugin/spring-brick-maven-packager/pom.xml

@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>iot-plugin</artifactId>
+        <groupId>cc.iotkit</groupId>
+        <version>0.5.1-SNAPSHOT</version>
+    </parent>
+
+    <groupId>com.gitee.starblues</groupId>
+    <version>3.1.3</version>
+    <artifactId>spring-brick-maven-packager</artifactId>
+    <packaging>jar</packaging>
+
+    <description>用于打包主程序/插件模块</description>
+
+    <properties>
+        <java.version>8</java.version>
+        <maven.version>3.0.0</maven.version>
+        <maven.compiler.source>${java.version}</maven.compiler.source>
+        <maven.compiler.target>${java.version}</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
+
+        <maven-plugin-api.version>3.8.4</maven-plugin-api.version>
+        <maven-plugin-annotations.version>3.6.2</maven-plugin-annotations.version>
+        <maven-common-artifact-filters.version>3.2.0</maven-common-artifact-filters.version>
+        <commons-compress.version>1.21</commons-compress.version>
+        <commons-io.version>2.11.0</commons-io.version>
+        <lombok.version>1.18.20</lombok.version>
+        <junit.version>3.8.1</junit.version>
+
+        <maven-plugin-plugin.version>3.6.0</maven-plugin-plugin.version>
+    </properties>
+
+    <dependencies>
+        <!-- common -->
+        <dependency>
+            <groupId>com.gitee.starblues</groupId>
+            <artifactId>spring-brick-common</artifactId>
+            <version>${spring-brick.version}</version>
+        </dependency>
+        <!-- maven api -->
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-plugin-api</artifactId>
+            <version>${maven-plugin-api.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.maven.plugin-tools</groupId>
+            <artifactId>maven-plugin-annotations</artifactId>
+            <version>${maven-plugin-annotations.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.maven.shared</groupId>
+            <artifactId>maven-common-artifact-filters</artifactId>
+            <version>${maven-common-artifact-filters.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <version>${commons-compress.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons-io.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${junit.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-plugin-plugin</artifactId>
+                <version>${maven-plugin-plugin.version}</version>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 108 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractDependencyFilterMojo.java

@@ -0,0 +1,108 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import com.gitee.starblues.plugin.pack.filter.Exclude;
+import com.gitee.starblues.plugin.pack.filter.ExcludeFilter;
+import com.gitee.starblues.plugin.pack.filter.Include;
+import com.gitee.starblues.plugin.pack.filter.IncludeFilter;
+import com.gitee.starblues.plugin.pack.utils.CommonUtils;
+import com.gitee.starblues.utils.ObjectUtils;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
+import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
+import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 抽象可过滤依赖的 mojo
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public abstract class AbstractDependencyFilterMojo extends AbstractMojo {
+
+
+    @Parameter(property = "spring-brick-packager.includes")
+    private List<Include> includes;
+
+    @Parameter(property = "spring-brick-packager.excludes")
+    private List<Exclude> excludes;
+
+
+    protected final Set<Artifact> filterDependencies(Set<Artifact> dependencies, FilterArtifacts filters)
+            throws MojoExecutionException {
+        try {
+            Set<Artifact> filtered = new LinkedHashSet<>(dependencies);
+            filtered.retainAll(filters.filter(dependencies));
+            return filtered;
+        }
+        catch (ArtifactFilterException ex) {
+            throw new MojoExecutionException(ex.getMessage(), ex);
+        }
+    }
+
+    protected final FilterArtifacts getFilters(ArtifactsFilter... additionalFilters) {
+        FilterArtifacts filters = new FilterArtifacts();
+        for (ArtifactsFilter additionalFilter : additionalFilters) {
+            filters.addFilter(additionalFilter);
+        }
+        if (!ObjectUtils.isEmpty(includes)) {
+            filters.addFilter(new IncludeFilter(this.includes));
+        }
+        if(ObjectUtils.isEmpty(excludes)){
+            excludes = new ArrayList<>();
+        }
+        // 添加主框架排除
+        addPluginFrameworkExclude();
+        // 添加spring web 环境排除
+        addSpringWebEnvExclude();
+        filters.addFilter(new ExcludeFilter(this.excludes));
+        return filters;
+    }
+
+    private void addPluginFrameworkExclude(){
+        excludes.add(CommonUtils.getPluginFrameworkExclude());
+    }
+
+    private void addSpringWebEnvExclude(){
+        excludes.add(Exclude.get("org.springframework.boot", "spring-boot-starter-web"));
+        excludes.add(Exclude.get("org.springframework.boot", "spring-boot-starter-tomcat"));
+        excludes.add(Exclude.get("org.springframework.boot", "spring-boot-starter-json"));
+        excludes.add(Exclude.get("org.springframework", "spring-webmvc"));
+        excludes.add(Exclude.get("org.springframework", "spring-web"));
+
+        // jackson
+        excludes.add(Exclude.get("com.fasterxml.jackson.core", "jackson-core"));
+        excludes.add(Exclude.get("com.fasterxml.jackson.core", "jackson-databind"));
+        excludes.add(Exclude.get("com.fasterxml.jackson.core", "jackson-annotations"));
+        excludes.add(Exclude.get("com.fasterxml.jackson.module", "jackson-module-parameter-names"));
+    }
+
+}

+ 93 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractPackagerMojo.java

@@ -0,0 +1,93 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+
+import java.io.File;
+import java.util.Set;
+
+/**
+ * 抽象的重新打包 mojo
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.1.1
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo{
+
+    @Parameter(defaultValue = "${project}", readonly = true, required = true)
+    private MavenProject project;
+
+    @Parameter(defaultValue = "${project.build.directory}", required = true)
+    private File outputDirectory;
+
+    @Parameter(property = "spring-brick-packager.mode", defaultValue = "dev", required = true)
+    private String mode;
+
+    @Parameter(property = "spring-brick-packager.skip", defaultValue = "false")
+    private boolean skip;
+
+    @Parameter
+    private String classifier;
+
+    @Parameter(property = "spring-brick-packager.pluginInfo")
+    private PluginInfo pluginInfo;
+
+    @Parameter(property = "spring-brick-packager.loadMainResourcePattern", required = false)
+    private LoadMainResourcePattern loadMainResourcePattern;
+
+    @Parameter(property = "spring-brick-packager.includeSystemScope", defaultValue = "true", required = false)
+    private Boolean includeSystemScope;
+
+    @Override
+    public final void execute() throws MojoExecutionException, MojoFailureException {
+        if(Constant.isPom(this.getProject().getPackaging())){
+            getLog().debug("repackage goal could not be applied to pom project.");
+            return;
+        }
+        if (this.skip) {
+            getLog().debug("skipping plugin package.");
+            return;
+        }
+        pack();
+    }
+
+    /**
+     * 打包
+     * @throws MojoExecutionException MojoExecutionException
+     * @throws MojoFailureException MojoFailureException
+     */
+    protected abstract void pack() throws MojoExecutionException, MojoFailureException;
+
+    public final Set<Artifact> getFilterDependencies() throws MojoExecutionException {
+        Set<Artifact> artifacts = project.getArtifacts();
+        return filterDependencies(artifacts, getFilters());
+    }
+
+    public final Set<Artifact> getSourceDependencies() throws MojoExecutionException {
+        return project.getArtifacts();
+    }
+}

+ 380 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/BasicRepackager.java

@@ -0,0 +1,380 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import com.gitee.starblues.common.*;
+import com.gitee.starblues.plugin.pack.utils.CommonUtils;
+import com.gitee.starblues.utils.FilesUtils;
+import com.gitee.starblues.utils.ObjectUtils;
+import lombok.Getter;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.*;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import static com.gitee.starblues.common.PackageStructure.*;
+import static com.gitee.starblues.common.PluginDescriptorKey.*;
+
+/**
+ * 基础打包
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.1.1
+ */
+public class BasicRepackager implements Repackager{
+
+    @Getter
+    private String rootDir;
+    private String relativeManifestPath;
+    private String relativePluginMetaPath;
+    private String relativeResourcesDefinePath;
+
+    protected File resourcesDefineFile;
+
+    protected final RepackageMojo repackageMojo;
+    protected JarFile sourceJarFile;
+
+    public BasicRepackager(RepackageMojo repackageMojo) {
+        this.repackageMojo = repackageMojo;
+    }
+
+    @Override
+    public void repackage() throws MojoExecutionException, MojoFailureException {
+        sourceJarFile = CommonUtils.getSourceJarFile(repackageMojo.getProject());
+        checkPluginInfo();
+        rootDir = createRootDir();
+        relativeManifestPath = getRelativeManifestPath();
+        relativePluginMetaPath = getRelativePluginMetaPath();
+        relativeResourcesDefinePath = getRelativeResourcesDefinePath();
+        try {
+            Manifest manifest = getManifest();
+            writeManifest(manifest);
+        } catch (Exception e) {
+            repackageMojo.getLog().error(e.getMessage(), e);
+            throw new MojoFailureException(e);
+        } finally {
+            IOUtils.closeQuietly(sourceJarFile);
+        }
+    }
+
+    private void checkPluginInfo() throws MojoExecutionException {
+        PluginInfo pluginInfo = repackageMojo.getPluginInfo();
+        if(pluginInfo == null){
+            throw new MojoExecutionException("configuration.pluginInfo config cannot be empty");
+        }
+        if(ObjectUtils.isEmpty(pluginInfo.getId())){
+            throw new MojoExecutionException("configuration.pluginInfo.id config cannot be empty");
+        } else {
+            String id = pluginInfo.getId();
+            String illegal = PackageStructure.getIllegal(id);
+            if(illegal != null){
+                throw new MojoExecutionException("configuration.pluginInfo.id config can't contain: " + illegal);
+            }
+        }
+        if(ObjectUtils.isEmpty(pluginInfo.getBootstrapClass())){
+            throw new MojoExecutionException("configuration.pluginInfo.bootstrapClass config cannot be empty");
+        }
+        if(ObjectUtils.isEmpty(pluginInfo.getVersion())){
+            throw new MojoExecutionException("configuration.pluginInfo.version config cannot be empty");
+        } else {
+            String version = pluginInfo.getVersion();
+            String illegal = PackageStructure.getIllegal(version);
+            if(illegal != null){
+                throw new MojoExecutionException("configuration.pluginInfo.version config can't contain: " + illegal);
+            }
+        }
+    }
+
+    protected String getRelativeManifestPath(){
+        return MANIFEST;
+    }
+
+    protected String getRelativeResourcesDefinePath(){
+        return RESOURCES_DEFINE_NAME;
+    }
+
+    protected String getRelativePluginMetaPath(){
+        return PLUGIN_META_NAME;
+    }
+
+    protected String createRootDir() throws MojoFailureException {
+        String rootDirPath = getBasicRootDir();
+        File rootDir = new File(rootDirPath);
+        CommonUtils.deleteFile(rootDir);
+        if(rootDir.mkdir()){
+            return rootDirPath;
+        }
+        throw new MojoFailureException("Failed to create the plugin root directory. " + rootDirPath);
+    }
+
+    protected String getBasicRootDir(){
+        File outputDirectory = repackageMojo.getOutputDirectory();
+        return FilesUtils.joiningFilePath(outputDirectory.getPath(), PackageStructure.META_INF_NAME);
+    }
+
+    protected void writeManifest(Manifest manifest) throws Exception {
+        String manifestPath = FilesUtils.joiningFilePath(rootDir, resolvePath(this.relativeManifestPath));
+        File file = new File(manifestPath);
+        FileOutputStream outputStream = null;
+        try {
+            FileUtils.forceMkdirParent(file);
+            if(file.createNewFile()){
+                outputStream = new FileOutputStream(file, false);
+                manifest.write(outputStream);
+            }
+        } finally {
+            if(outputStream != null){
+                try {
+                    outputStream.close();
+                } catch (IOException e) {
+                    repackageMojo.getLog().error(e.getMessage(), e);
+                }
+            }
+        }
+    }
+
+    protected Manifest getManifest() throws Exception{
+        Manifest manifest = null;
+        if(sourceJarFile != null){
+            manifest = sourceJarFile.getManifest();
+        } else {
+            manifest = new Manifest();
+        }
+        Attributes attributes = manifest.getMainAttributes();
+        attributes.putValue(ManifestKey.MANIFEST_VERSION, ManifestKey.MANIFEST_VERSION_1_0);
+        attributes.putValue(ManifestKey.BUILD_TIME, CommonUtils.getDateTime());
+        attributes.putValue(ManifestKey.PLUGIN_META_PATH, getPluginMetaInfoPath());
+        attributes.putValue(ManifestKey.PLUGIN_PACKAGE_TYPE, PackageType.PLUGIN_PACKAGE_TYPE_DEV);
+        // 增加jar包title和version属性
+        MavenProject mavenProject = this.repackageMojo.getProject();
+        attributes.putValue(ManifestKey.IMPLEMENTATION_TITLE, mavenProject.getArtifactId());
+        attributes.putValue(ManifestKey.IMPLEMENTATION_VERSION, mavenProject.getVersion());
+        return manifest;
+    }
+
+    /**
+     * 得到插件信息存储文件路径
+     * @return 插件信息存储文件路径
+     * @throws Exception Exception
+     */
+    protected String getPluginMetaInfoPath() throws Exception {
+        Properties pluginMetaInfo = createPluginMetaInfo();
+        return writePluginMetaInfo(pluginMetaInfo);
+    }
+
+    /**
+     * 创建插件信息
+     * @return Properties
+     * @throws Exception Exception
+     */
+    protected Properties createPluginMetaInfo() throws Exception {
+        Properties properties = new Properties();
+        PluginInfo pluginInfo = repackageMojo.getPluginInfo();
+        properties.put(PLUGIN_ID, pluginInfo.getId());
+        properties.put(PLUGIN_BOOTSTRAP_CLASS, pluginInfo.getBootstrapClass());
+        properties.put(PLUGIN_VERSION, pluginInfo.getVersion());
+        properties.put(PLUGIN_PATH, getPluginPath());
+
+        String resourcesDefineFilePath = writeResourcesDefineFile(getResourcesDefineContent());
+        if(!ObjectUtils.isEmpty(resourcesDefineFilePath)){
+            properties.put(PLUGIN_RESOURCES_CONFIG, resourcesDefineFilePath);
+        }
+        String configFileName = pluginInfo.getConfigFileName();
+        if(!ObjectUtils.isEmpty(configFileName)){
+            properties.put(PLUGIN_CONFIG_FILE_NAME, configFileName);
+        }
+        String configFileLocation = pluginInfo.getConfigFileLocation();
+        if(!ObjectUtils.isEmpty(configFileLocation)){
+            properties.put(PLUGIN_CONFIG_FILE_LOCATION, configFileLocation);
+        }
+        String args = pluginInfo.getArgs();
+        if(!ObjectUtils.isEmpty(args)){
+            properties.put(PLUGIN_ARGS, args);
+        }
+        String provider = pluginInfo.getProvider();
+        if(!ObjectUtils.isEmpty(provider)){
+            properties.put(PLUGIN_PROVIDER, provider);
+        }
+        String requires = pluginInfo.getRequires();
+        if(!ObjectUtils.isEmpty(requires)){
+            properties.put(PLUGIN_REQUIRES, requires);
+        }
+        String dependencyPlugins = getDependencyPlugin(pluginInfo);
+        if(!ObjectUtils.isEmpty(dependencyPlugins)){
+            properties.put(PLUGIN_DEPENDENCIES, dependencyPlugins);
+        }
+        String description = pluginInfo.getDescription();
+        if(!ObjectUtils.isEmpty(description)){
+            properties.put(PLUGIN_DESCRIPTION, description);
+        }
+        String license = pluginInfo.getLicense();
+        if(!ObjectUtils.isEmpty(license)){
+            properties.put(PLUGIN_LICENSE, license);
+        }
+        return properties;
+    }
+
+    protected String getDependencyPlugin(PluginInfo pluginInfo){
+        List<DependencyPlugin> dependencyPlugins = pluginInfo.getDependencyPlugins();
+        return AbstractDependencyPlugin.toStr(dependencyPlugins);
+    }
+
+    /**
+     * 写入插件信息
+     * @param properties properties
+     * @return String
+     * @throws IOException IOException
+     */
+    protected String writePluginMetaInfo(Properties properties) throws Exception {
+        File pluginMetaFile = createPluginMetaFile();
+        try (OutputStreamWriter writer = new OutputStreamWriter(
+                Files.newOutputStream(pluginMetaFile.toPath()), StandardCharsets.UTF_8)){
+            properties.store(writer, Constant.PLUGIN_METE_COMMENTS);
+            return pluginMetaFile.getPath();
+        }
+    }
+
+    /**
+     * 创建插件信息存储文件
+     * @return File
+     * @throws IOException 创建文件异常
+     */
+    protected File createPluginMetaFile() throws IOException {
+        String path = FilesUtils.joiningFilePath(rootDir, resolvePath(relativePluginMetaPath));
+        return FilesUtils.createFile(path);
+    }
+
+    /**
+     * 获取插件路径
+     * @return 插件路径
+     */
+    protected String getPluginPath(){
+        return repackageMojo.getProject().getBuild().getOutputDirectory();
+    }
+
+    protected String writeResourcesDefineFile(String resourcesDefineContent) throws Exception{
+        resourcesDefineFile = createResourcesDefineFile();
+        FileUtils.write(resourcesDefineFile, resourcesDefineContent, CHARSET_NAME, true);
+        return resourcesDefineFile.getPath();
+    }
+
+    protected File createResourcesDefineFile() throws IOException {
+        String path = FilesUtils.joiningFilePath(rootDir, resolvePath(relativeResourcesDefinePath));
+        return FilesUtils.createFile(path);
+    }
+
+    protected String getResourcesDefineContent() throws Exception {
+        String dependenciesIndex = getDependenciesIndex();
+        String loadMainResources = getLoadMainResources();
+        boolean indexIsEmpty = ObjectUtils.isEmpty(dependenciesIndex);
+        boolean resourceIsEmpty = ObjectUtils.isEmpty(loadMainResources);
+
+        if(!indexIsEmpty && !resourceIsEmpty){
+            return dependenciesIndex + "\n" + loadMainResources;
+        } else if(!indexIsEmpty){
+            return dependenciesIndex;
+        } else if(!resourceIsEmpty){
+            return loadMainResources;
+        } else {
+            return "";
+        }
+    }
+
+    protected String getDependenciesIndex() throws Exception {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append(RESOURCES_DEFINE_DEPENDENCIES).append("\n");
+        Set<String> libIndex = getDependenciesIndexSet();
+        for (String index : libIndex) {
+            stringBuilder.append(index).append("\n");
+        }
+        return stringBuilder.toString();
+    }
+
+    protected String getLoadMainResources(){
+        LoadMainResourcePattern loadMainResourcePattern = repackageMojo.getLoadMainResourcePattern();
+        if(loadMainResourcePattern == null){
+            return null;
+        }
+        String[] includes = loadMainResourcePattern.getIncludes();
+        String[] excludes = loadMainResourcePattern.getExcludes();
+        StringBuilder stringBuilder = new StringBuilder();
+        addLoadMainResources(stringBuilder, RESOURCES_DEFINE_LOAD_MAIN_INCLUDES, includes);
+        addLoadMainResources(stringBuilder, RESOURCES_DEFINE_LOAD_MAIN_EXCLUDES, excludes);
+        return stringBuilder.toString();
+    }
+
+    protected Set<String> getDependenciesIndexSet() throws Exception {
+        Set<Artifact> dependencies = repackageMojo.getFilterDependencies();
+        Set<String> libPaths = new LinkedHashSet<>(dependencies.size());
+        for (Artifact artifact : dependencies) {
+            if(filterArtifact(artifact)){
+                continue;
+            }
+            libPaths.add(getLibIndex(artifact));
+        }
+        return libPaths;
+    }
+
+    protected String getLibIndex(Artifact artifact){
+        return artifact.getFile().getPath() + repackageMojo.resolveLoadToMain(artifact);
+    }
+
+    private void addLoadMainResources(StringBuilder stringBuilder, String header, String[] patterns){
+        if(ObjectUtils.isEmpty(patterns)){
+           return;
+        }
+        Set<String> patternSet = new LinkedHashSet<>(Arrays.asList(patterns));
+        stringBuilder.append(header).append("\n");
+        for (String patternStr : patternSet) {
+            if(ObjectUtils.isEmpty(patternStr)){
+                continue;
+            }
+            stringBuilder.append(resolvePattern(patternStr)).append("\n");
+        }
+    }
+
+    protected String resolvePattern(String patternStr){
+        return patternStr.replace(".", "/");
+    }
+
+    /**
+     * 过滤Artifact
+     * @param artifact Artifact
+     * @return 返回true表示被过滤掉
+     */
+    protected boolean filterArtifact(Artifact artifact){
+        return Constant.filterMainTypeArtifact(artifact) ||
+                Constant.filterArtifact(artifact, repackageMojo.getIncludeSystemScope());
+    }
+
+
+
+}

+ 85 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/Constant.java

@@ -0,0 +1,85 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import org.apache.maven.artifact.Artifact;
+
+/**
+ * 静态类
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class Constant {
+
+    public static final String PACKAGING_POM = "pom";
+    public static final String SCOPE_PROVIDED = "provided";
+    public static final String SCOPE_COMPILE = "compile";
+    public static final String SCOPE_SYSTEM = "system";
+    public static final String SCOPE_TEST = "test";
+
+    public static final String MAVEN_POM_TYPE = "pom";
+
+    public static final String MAVEN_MAIN_TYPE = "main";
+
+    public static final String MODE_MAIN = "main";
+    public static final String MODE_DEV = "dev";
+    public static final String MODE_PROD = "prod";
+
+    public static final String PLUGIN_METE_COMMENTS = "plugin meta configuration";
+
+    /**
+     * 开发模式方法名称
+     */
+    public static final String DEVELOPMENT_MODE_METHOD_NAME = "developmentMode";
+
+
+    public static boolean isPom(String packageType){
+        return PACKAGING_POM.equalsIgnoreCase(packageType);
+    }
+
+    public static boolean filterArtifact(Artifact artifact, Boolean includeSystemScope){
+        boolean scopeFilter = Constant.scopeFilter(artifact.getScope());
+        if(scopeFilter){
+            return true;
+        }
+        if(Constant.isSystemScope(artifact.getScope())){
+            return includeSystemScope == null || !includeSystemScope;
+        }
+        return Constant.filterPomTypeArtifact(artifact);
+    }
+
+    public static boolean filterMainTypeArtifact(Artifact artifact){
+        // 配置了为main的依赖, 则对其过滤
+        return MAVEN_MAIN_TYPE.equalsIgnoreCase(artifact.getType());
+    }
+
+    public static boolean filterPomTypeArtifact(Artifact artifact){
+        return MAVEN_POM_TYPE.equalsIgnoreCase(artifact.getType());
+    }
+
+    public static boolean scopeFilter(String scope){
+        return SCOPE_PROVIDED.equalsIgnoreCase(scope)
+                || SCOPE_TEST.equalsIgnoreCase(scope);
+    }
+
+    public static boolean isSystemScope(String scope){
+        return SCOPE_SYSTEM.equalsIgnoreCase(scope);
+    }
+
+}

+ 38 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/Dependency.java

@@ -0,0 +1,38 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import lombok.Data;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * 依赖Bean
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+@Data
+public class Dependency {
+
+    @Parameter(required = true)
+    private String groupId;
+
+    @Parameter(required = true)
+    private String artifactId;
+
+}

+ 73 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/DependencyPlugin.java

@@ -0,0 +1,73 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import com.gitee.starblues.common.AbstractDependencyPlugin;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * 依赖的插件
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class DependencyPlugin extends AbstractDependencyPlugin {
+
+    @Parameter(required = true)
+    private String id;
+
+    @Parameter(required = true)
+    private String version;
+
+    @Parameter(required = false, defaultValue = "true")
+    private Boolean optional = false;
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public String getVersion() {
+        return version;
+    }
+
+    @Override
+    public Boolean getOptional() {
+        if(optional == null){
+            return false;
+        }
+        return optional;
+    }
+
+    @Override
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    @Override
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    @Override
+    public void setOptional(Boolean optional) {
+        this.optional = optional;
+    }
+
+}

+ 38 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/LoadMainResourcePattern.java

@@ -0,0 +1,38 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import lombok.Data;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * 从主程序加载资源配置
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+@Data
+public class LoadMainResourcePattern {
+
+    @Parameter(name = "includes")
+    private String[] includes;
+
+    @Parameter(name = "excludes")
+    private String[] excludes;
+
+}

+ 35 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/LoadToMain.java

@@ -0,0 +1,35 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 定义依赖加载到主程序中
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+@Data
+public class LoadToMain {
+
+    private List<Dependency> dependencies;
+
+}

+ 92 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/PluginInfo.java

@@ -0,0 +1,92 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import lombok.Data;
+import org.apache.maven.plugins.annotations.Parameter;
+
+import java.util.List;
+
+/**
+ * 插件信息
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+@Data
+public class PluginInfo {
+
+    /**
+     * 插件id
+     */
+    @Parameter(required = true)
+    private String id;
+
+    /**
+     * 插件引导启动类
+     */
+    @Parameter(required = true)
+    private String bootstrapClass;
+
+    /**
+     * 插件版本
+     */
+    @Parameter(required = true)
+    private String version;
+
+    /**
+     * 插件配置文件名称。
+     */
+    private String configFileName;
+
+    /**
+     * 插件配置文件所在目录。如果不填写, 默认从 target/classes 下读取
+     */
+    private String configFileLocation;
+
+    /**
+     * 插件启动入口参数配置
+     */
+    private String args;
+
+    /**
+     * 插件描述
+     */
+    private String description;
+
+    /**
+     * 插件提供者
+     */
+    private String provider;
+
+    /**
+     * 需要安装的主程序版本
+     */
+    private String requires;
+
+    /**
+     * 插件 license
+     */
+    private String license;
+
+    /**
+     * 依赖的插件
+     */
+    private List<DependencyPlugin> dependencyPlugins;
+
+}

+ 133 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/RepackageMojo.java

@@ -0,0 +1,133 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import com.gitee.starblues.common.Constants;
+import com.gitee.starblues.plugin.pack.dev.DevConfig;
+import com.gitee.starblues.plugin.pack.dev.DevRepackager;
+import com.gitee.starblues.plugin.pack.encrypt.*;
+import com.gitee.starblues.plugin.pack.main.MainConfig;
+import com.gitee.starblues.plugin.pack.main.MainRepackager;
+import com.gitee.starblues.plugin.pack.prod.ProdConfig;
+import com.gitee.starblues.plugin.pack.prod.ProdRepackager;
+import com.gitee.starblues.plugin.pack.utils.CommonUtils;
+import com.gitee.starblues.utils.ObjectUtils;
+import lombok.Getter;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 重新打包 mojo
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.1.1
+ */
+@Mojo(name = "repackage", defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true, threadSafe = true,
+        requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
+        requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME)
+@Getter
+public class RepackageMojo extends AbstractPackagerMojo {
+
+
+    @Parameter(property = "spring-brick-packager.devConfig")
+    private DevConfig devConfig;
+
+    @Parameter(property = "spring-brick-packager.prodConfig")
+    private ProdConfig prodConfig;
+
+    @Parameter(property = "spring-brick-packager.mainConfig")
+    private MainConfig mainConfig;
+
+    @Parameter(property = "spring-brick-packager.mainLoad")
+    private LoadToMain loadToMain;
+
+    @Parameter(property = "spring-brick-packager.encryptConfig")
+    private EncryptConfig encryptConfig;
+
+    private final Set<String> loadToMainSet = new LinkedHashSet<>();
+
+    @Override
+    protected void pack() throws MojoExecutionException, MojoFailureException {
+        initLoadToMainSet();
+        String mode = getMode();
+        try {
+            encrypt();
+        } catch (Exception e) {
+            throw new MojoExecutionException("encrypt failed: " + e.getMessage());
+        }
+        if(Constant.MODE_PROD.equalsIgnoreCase(mode)){
+            new ProdRepackager(this).repackage();
+        } else if(Constant.MODE_DEV.equalsIgnoreCase(mode)){
+            new DevRepackager(this).repackage();
+        } else if(Constant.MODE_MAIN.equalsIgnoreCase(mode)){
+            new MainRepackager(this).repackage();
+        } else {
+            throw new MojoExecutionException(mode  +" model not supported, mode support : "
+                    + Constant.MODE_DEV + "/" + Constant.MODE_PROD);
+        }
+    }
+
+    public String resolveLoadToMain(Artifact artifact){
+        if(artifact == null){
+            return "";
+        }
+        if(loadToMainSet.contains(artifact.getGroupId() + artifact.getArtifactId())){
+            return Constants.LOAD_TO_MAIN_SIGN;
+        }
+        return "";
+    }
+
+    private void initLoadToMainSet(){
+        if(loadToMain == null){
+            return;
+        }
+        List<Dependency> dependencies = loadToMain.getDependencies();
+        if(ObjectUtils.isEmpty(dependencies)){
+            return;
+        }
+        for (Dependency dependency : dependencies) {
+            loadToMainSet.add(dependency.getGroupId() + dependency.getArtifactId());
+        }
+    }
+
+    /**
+     * 加密
+     * @throws Exception 加密异常
+     */
+    private void encrypt() throws Exception {
+        if(encryptConfig == null){
+            return;
+        }
+        EncryptPlugin encryptPlugin = new EncryptPluginFactory();
+        PluginInfo pluginInfo = encryptPlugin.encrypt(encryptConfig, getPluginInfo());
+        if(pluginInfo != null){
+            setPluginInfo(pluginInfo);
+        }
+    }
+
+}

+ 39 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/Repackager.java

@@ -0,0 +1,39 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+/**
+ * 重新打包接口
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public interface Repackager {
+
+    /**
+     * 重新打包
+     * @throws MojoExecutionException MojoExecutionException
+     * @throws MojoFailureException MojoFailureException
+     */
+    void repackage() throws MojoExecutionException, MojoFailureException;
+
+
+}

+ 41 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/Dependency.java

@@ -0,0 +1,41 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.dev;
+
+import lombok.Data;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * 开发环境下配置本地依赖的Bean
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+@Data
+public class Dependency {
+
+    @Parameter(required = true)
+    private String groupId;
+
+    @Parameter(required = true)
+    private String artifactId;
+
+    @Parameter(required = true)
+    private String classesPath;
+
+}

+ 44 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevConfig.java

@@ -0,0 +1,44 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.dev;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 开发模式配置
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+@Data
+public class DevConfig {
+
+    /**
+     * 当前项目依赖其他模块的定义。
+     * 主要定义依赖模块target->classes的目录, 方便开发调试
+     */
+    private List<Dependency> moduleDependencies;
+
+    /**
+     * 本地jar依赖文件定义
+     */
+    private List<String> localJars;
+
+}

+ 102 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevRepackager.java

@@ -0,0 +1,102 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.dev;
+
+import com.gitee.starblues.plugin.pack.BasicRepackager;
+import com.gitee.starblues.plugin.pack.Constant;
+import com.gitee.starblues.plugin.pack.RepackageMojo;
+import com.gitee.starblues.plugin.pack.utils.CommonUtils;
+import com.gitee.starblues.utils.FilesUtils;
+import com.gitee.starblues.utils.ObjectUtils;
+import lombok.Getter;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+
+import java.util.*;
+
+/**
+ * 开发环境打包
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class DevRepackager extends BasicRepackager {
+
+    @Getter
+    private Map<String, Dependency> moduleDependencies = Collections.emptyMap();
+
+    public DevRepackager(RepackageMojo repackageMojo) {
+        super(repackageMojo);
+    }
+
+    @Override
+    protected Set<String> getDependenciesIndexSet() throws Exception {
+        DevConfig devConfig = repackageMojo.getDevConfig();
+        if(devConfig == null){
+            return super.getDependenciesIndexSet();
+        }
+        moduleDependencies = getModuleDependencies(devConfig);
+        Set<String> dependenciesIndexSet = super.getDependenciesIndexSet();
+        for (Dependency dependency : moduleDependencies.values()) {
+            dependenciesIndexSet.add(dependency.getClassesPath());
+        }
+        List<String> localJars = devConfig.getLocalJars();
+        if(!ObjectUtils.isEmpty(localJars)){
+            dependenciesIndexSet.addAll(localJars);
+        }
+        return dependenciesIndexSet;
+    }
+
+    @Override
+    protected boolean filterArtifact(Artifact artifact) {
+        if(super.filterArtifact(artifact)){
+            return true;
+        }
+        String moduleDependencyKey = getModuleDependencyKey(artifact.getGroupId(), artifact.getArtifactId());
+        Dependency dependency = moduleDependencies.get(moduleDependencyKey);
+        return dependency != null && !ObjectUtils.isEmpty(dependency.getClassesPath());
+    }
+
+    protected Map<String, Dependency> getModuleDependencies(DevConfig devConfig) {
+        if(devConfig == null){
+            return Collections.emptyMap();
+        }
+        List<Dependency> moduleDependencies = devConfig.getModuleDependencies();
+        if(ObjectUtils.isEmpty(moduleDependencies)){
+            return Collections.emptyMap();
+        }
+        Map<String, Dependency> moduleDependenciesMap = new HashMap<>();
+        for (Dependency dependency : moduleDependencies) {
+            String moduleDependencyKey = getModuleDependencyKey(dependency.getGroupId(),
+                    dependency.getArtifactId());
+            if(moduleDependencyKey == null){
+                continue;
+            }
+            moduleDependenciesMap.put(moduleDependencyKey, dependency);
+        }
+        return moduleDependenciesMap;
+    }
+
+    protected String getModuleDependencyKey(String groupId, String artifactId){
+        if(ObjectUtils.isEmpty(groupId) || ObjectUtils.isEmpty(artifactId)){
+            return null;
+        }
+        return groupId + artifactId;
+    }
+
+}

+ 33 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/AesConfig.java

@@ -0,0 +1,33 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.encrypt;
+
+import lombok.Data;
+
+/**
+ * aes 加密配置
+ *
+ * @author starBlues
+ * @since 3.0.1
+ * @version 3.0.1
+ */
+@Data
+public class AesConfig {
+
+    private String secretKey;
+
+}

+ 43 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/AesEncryptPlugin.java

@@ -0,0 +1,43 @@
+package com.gitee.starblues.plugin.pack.encrypt;
+
+import com.gitee.starblues.common.cipher.AbstractPluginCipher;
+import com.gitee.starblues.common.cipher.AesPluginCipher;
+import com.gitee.starblues.plugin.pack.PluginInfo;
+import com.gitee.starblues.utils.ObjectUtils;
+import org.apache.maven.plugin.MojoExecutionException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * rsa 加密者
+ *
+ * @author starBlues
+ * @since 3.0.1
+ * @version 3.0.1
+ */
+public class AesEncryptPlugin implements EncryptPlugin{
+
+
+    @Override
+    public PluginInfo encrypt(EncryptConfig encryptConfig, PluginInfo pluginInfo) throws Exception{
+        AesConfig aesConfig = encryptConfig.getAes();
+        if(aesConfig == null){
+            return null;
+        }
+
+        String secretKey = aesConfig.getSecretKey();
+        if(ObjectUtils.isEmpty(secretKey)){
+            throw new MojoExecutionException("encryptConfig.aes.secretKey can't be empty");
+        }
+        AbstractPluginCipher pluginCipher = new AesPluginCipher();
+        Map<String, Object> params = new HashMap<>();
+        params.put(AesPluginCipher.SECRET_KEY, secretKey);
+        pluginCipher.initParams(params);
+
+        String bootstrapClass = pluginInfo.getBootstrapClass();
+        String encrypt = pluginCipher.encrypt(bootstrapClass);
+        pluginInfo.setBootstrapClass(encrypt);
+        return pluginInfo;
+    }
+}

+ 41 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/EncryptConfig.java

@@ -0,0 +1,41 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.encrypt;
+
+import lombok.Data;
+
+/**
+ * 加密配置
+ *
+ * @author starBlues
+ * @since 3.0.1
+ * @version 3.0.1
+ */
+@Data
+public class EncryptConfig {
+
+    /**
+     * rsa 配置
+     */
+    private RsaConfig rsa;
+
+    /**
+     * aes 配置
+     */
+    private AesConfig aes;
+
+}

+ 40 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/EncryptPlugin.java

@@ -0,0 +1,40 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.encrypt;
+
+import com.gitee.starblues.plugin.pack.PluginInfo;
+
+/**
+ * 加密插件
+ *
+ * @author starBlues
+ * @since 3.0.1
+ * @version 3.0.1
+ */
+public interface EncryptPlugin {
+
+
+    /**
+     * 加密
+     * @param pluginInfo 当前插件信息
+     * @param encryptConfig 加密配置
+     * @return 加密后得字符
+     * @throws Exception 加密异常
+     */
+    PluginInfo encrypt(EncryptConfig encryptConfig, PluginInfo pluginInfo) throws Exception;
+
+}

+ 50 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/EncryptPluginFactory.java

@@ -0,0 +1,50 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.encrypt;
+
+import com.gitee.starblues.plugin.pack.PluginInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 加密插件工厂
+ *
+ * @author starBlues
+ * @since 3.0.1
+ * @version 3.0.1
+ */
+public class EncryptPluginFactory implements EncryptPlugin {
+
+    private final List<EncryptPlugin> encryptPlugins = new ArrayList<>();
+
+    public EncryptPluginFactory(){
+        encryptPlugins.add(new AesEncryptPlugin());
+        encryptPlugins.add(new RsaEncryptPlugin());
+    }
+
+    @Override
+    public PluginInfo encrypt(EncryptConfig encryptConfig, PluginInfo pluginInfo) throws Exception{
+        for (EncryptPlugin encryptPlugin : encryptPlugins) {
+            PluginInfo encrypt = encryptPlugin.encrypt(encryptConfig, pluginInfo);
+            if(encrypt != null){
+                return encrypt;
+            }
+        }
+        return pluginInfo;
+    }
+}

+ 36 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/RsaConfig.java

@@ -0,0 +1,36 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.encrypt;
+
+import lombok.Data;
+
+/**
+ * rsa 加密配置
+ *
+ * @author starBlues
+ * @since 3.0.1
+ * @version 3.0.1
+ */
+@Data
+public class RsaConfig {
+
+    /**
+     * rsa 公钥
+     */
+    private String publicKey;
+
+}

+ 57 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/encrypt/RsaEncryptPlugin.java

@@ -0,0 +1,57 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.encrypt;
+
+import com.gitee.starblues.common.cipher.AbstractPluginCipher;
+import com.gitee.starblues.common.cipher.RsaPluginCipher;
+import com.gitee.starblues.plugin.pack.PluginInfo;
+import com.gitee.starblues.utils.ObjectUtils;
+import org.apache.maven.plugin.MojoExecutionException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * rsa 算法插件加密
+ *
+ * @author starBlues
+ * @since 3.0.1
+ * @version 3.0.1
+ */
+public class RsaEncryptPlugin implements EncryptPlugin{
+
+    @Override
+    public PluginInfo encrypt(EncryptConfig encryptConfig, PluginInfo pluginInfo) throws Exception {
+        RsaConfig rsaConfig = encryptConfig.getRsa();
+        if(rsaConfig == null){
+            return null;
+        }
+
+        String publicKey = rsaConfig.getPublicKey();
+        if(ObjectUtils.isEmpty(publicKey)){
+            throw new MojoExecutionException("encryptConfig.rsa.publicKey can't be empty");
+        }
+        AbstractPluginCipher pluginCipher = new RsaPluginCipher();
+        Map<String, Object> params = new HashMap<>();
+        params.put(RsaPluginCipher.PUBLIC_KEY, publicKey);
+        pluginCipher.initParams(params);
+
+        String bootstrapClass = pluginInfo.getBootstrapClass();
+        pluginInfo.setBootstrapClass(pluginCipher.encrypt(bootstrapClass));
+        return pluginInfo;
+    }
+}

+ 75 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/DependencyFilter.java

@@ -0,0 +1,75 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.filter;
+
+import com.gitee.starblues.utils.ObjectUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.shared.artifact.filter.collection.AbstractArtifactsFilter;
+import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
+
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 依赖过滤
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public abstract class DependencyFilter extends AbstractArtifactsFilter {
+
+    private final List<? extends FilterableDependency> filters;
+
+    public DependencyFilter(List<? extends FilterableDependency> dependencies) {
+        this.filters = dependencies;
+    }
+
+    @Override
+    public Set<Artifact> filter(Set<Artifact> artifacts) throws ArtifactFilterException {
+        if(ObjectUtils.isEmpty(artifacts)){
+            return artifacts;
+        }
+        Set<Artifact> result = new LinkedHashSet<>();
+        for (Artifact artifact : artifacts) {
+            if (!filter(artifact)) {
+                result.add(artifact);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 子类过滤结果
+     * @param artifact artifact
+     * @return boolean
+     */
+    protected abstract boolean filter(Artifact artifact);
+
+    protected final boolean equals(Artifact artifact, FilterableDependency dependency) {
+        if (!dependency.getGroupId().equals(artifact.getGroupId())) {
+            return false;
+        }
+        return dependency.getArtifactId().equals(artifact.getArtifactId());
+    }
+
+    protected final List<? extends FilterableDependency> getFilters() {
+        return this.filters;
+    }
+
+}

+ 35 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/Exclude.java

@@ -0,0 +1,35 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.filter;
+
+/**
+ * 排除的依赖定义
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class Exclude extends FilterableDependency{
+
+    public static Exclude get(String groupId, String artifactId){
+        Exclude exclude = new Exclude();
+        exclude.setGroupId(groupId);
+        exclude.setArtifactId(artifactId);
+        return exclude;
+    }
+
+}

+ 51 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/ExcludeFilter.java

@@ -0,0 +1,51 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.filter;
+
+import org.apache.maven.artifact.Artifact;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 排除过滤
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class ExcludeFilter extends DependencyFilter {
+
+    public ExcludeFilter(Exclude... excludes) {
+        this(Arrays.asList(excludes));
+    }
+
+    public ExcludeFilter(List<Exclude> excludes) {
+        super(excludes);
+    }
+
+    @Override
+    protected boolean filter(Artifact artifact) {
+        for (FilterableDependency dependency : getFilters()) {
+            if (equals(artifact, dependency)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

+ 38 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/FilterableDependency.java

@@ -0,0 +1,38 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.filter;
+
+import lombok.Data;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * 可过滤依赖bean
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+@Data
+public abstract class FilterableDependency {
+
+    @Parameter(required = true)
+    private String groupId;
+
+    @Parameter(required = true)
+    private String artifactId;
+
+}

+ 27 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/Include.java

@@ -0,0 +1,27 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.filter;
+
+/**
+ * 包含的依赖定义
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class Include extends FilterableDependency{
+}

+ 46 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/filter/IncludeFilter.java

@@ -0,0 +1,46 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.filter;
+
+import org.apache.maven.artifact.Artifact;
+
+import java.util.List;
+
+/**
+ * 包含过滤器
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class IncludeFilter extends DependencyFilter {
+
+    public IncludeFilter(List<Include> includes) {
+        super(includes);
+    }
+
+    @Override
+    protected boolean filter(Artifact artifact) {
+        for (FilterableDependency dependency : getFilters()) {
+            if (equals(artifact, dependency)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+}

+ 138 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/JarNestPackager.java

@@ -0,0 +1,138 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.main;
+
+import com.gitee.starblues.common.PackageType;
+import com.gitee.starblues.plugin.pack.Constant;
+import com.gitee.starblues.plugin.pack.RepackageMojo;
+import com.gitee.starblues.plugin.pack.Repackager;
+import com.gitee.starblues.plugin.pack.utils.CommonUtils;
+import com.gitee.starblues.plugin.pack.utils.PackageJar;
+import org.apache.commons.io.IOUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import static com.gitee.starblues.common.PackageStructure.*;
+import static com.gitee.starblues.common.ManifestKey.*;
+
+/**
+ * 嵌套jar打包
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.1.1
+ */
+public class JarNestPackager implements Repackager {
+
+    protected final MainConfig mainConfig;
+    protected final RepackageMojo repackageMojo;
+
+    protected PackageJar packageJar;
+
+    private JarFile sourceJarFile;
+
+    public JarNestPackager(MainRepackager mainRepackager) {
+        this.mainConfig = mainRepackager.getMainConfig();
+        this.repackageMojo = mainRepackager.getRepackageMojo();
+    }
+
+    @Override
+    public void repackage() throws MojoExecutionException, MojoFailureException {
+        try {
+            sourceJarFile = CommonUtils.getSourceJarFile(repackageMojo.getProject());
+            packageJar = new PackageJar(mainConfig.getOutputDirectory(), mainConfig.getFileName());
+            writeClasses();
+            writeDependencies();
+            writeManifest();
+        } catch (Exception e) {
+            repackageMojo.getLog().error(e.getMessage(), e);
+            throw new MojoFailureException(e);
+        } finally {
+            IOUtils.closeQuietly(packageJar);
+            IOUtils.closeQuietly(sourceJarFile);
+        }
+    }
+
+    protected void writeManifest() throws Exception {
+        Manifest manifest = getManifest();
+        packageJar.putDirEntry(META_INF_NAME + SEPARATOR);
+        packageJar.write(PROD_MANIFEST_PATH, manifest::write);
+    }
+
+    protected Manifest getManifest() throws Exception{
+        Manifest manifest = null;
+        if(sourceJarFile != null){
+            manifest = sourceJarFile.getManifest();
+        } else {
+            manifest = new Manifest();
+        }
+        Attributes attributes = manifest.getMainAttributes();
+        attributes.putValue(MANIFEST_VERSION, MANIFEST_VERSION_1_0);
+        attributes.putValue(BUILD_TIME, CommonUtils.getDateTime());
+        attributes.putValue(START_CLASS, mainConfig.getMainClass());
+        attributes.putValue(MAIN_CLASS, MAIN_CLASS_VALUE);
+        attributes.putValue(MAIN_PACKAGE_TYPE, PackageType.MAIN_PACKAGE_TYPE_JAR);
+        attributes.putValue(DEVELOPMENT_MODE, mainConfig.getDevelopmentMode());
+
+        // 增加jar包title和version属性
+        MavenProject mavenProject = this.repackageMojo.getProject();
+        attributes.putValue(IMPLEMENTATION_TITLE, mavenProject.getArtifactId());
+        attributes.putValue(IMPLEMENTATION_VERSION, mavenProject.getVersion());
+        return manifest;
+    }
+
+    protected void writeClasses() throws Exception {
+        String buildDir = repackageMojo.getProject().getBuild().getOutputDirectory();
+        packageJar.copyDirToPackage(new File(buildDir), null);
+    }
+
+    protected void writeDependencies() throws Exception {
+        Set<Artifact> dependencies = repackageMojo.getSourceDependencies();
+        String libDirEntryName = createLibEntry();
+        for (Artifact artifact : dependencies) {
+            if(filterArtifact(artifact)){
+                continue;
+            }
+            if(CommonUtils.isPluginFrameworkLoader(artifact)){
+                // 本框架loader依赖
+                packageJar.copyZipToPackage(artifact.getFile());
+            } else {
+                packageJar.writeDependency(artifact.getFile(), libDirEntryName);
+            }
+        }
+    }
+
+    protected boolean filterArtifact(Artifact artifact) {
+        return Constant.filterArtifact(artifact, repackageMojo.getIncludeSystemScope());
+    }
+
+    protected String createLibEntry() throws Exception {
+        String libDirEntryName = PROD_LIB_PATH;
+        packageJar.putDirEntry(libDirEntryName);
+        return libDirEntryName;
+    }
+
+}

+ 146 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/JarOuterPackager.java

@@ -0,0 +1,146 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.main;
+
+import com.gitee.starblues.common.PackageStructure;
+import com.gitee.starblues.common.PackageType;
+import com.gitee.starblues.plugin.pack.utils.CommonUtils;
+import com.gitee.starblues.utils.FilesUtils;
+import com.gitee.starblues.utils.ObjectUtils;
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import static com.gitee.starblues.common.ManifestKey.*;
+
+/**
+ * jar 外置包
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.2
+ */
+public class JarOuterPackager extends JarNestPackager {
+
+    private static final String LIB_INDEXES_SPLIT = " ";
+
+    private final Set<String> dependencyIndexNames = new LinkedHashSet<>();
+
+    public JarOuterPackager(MainRepackager mainRepackager) {
+        super(mainRepackager);
+    }
+
+    @Override
+    public void repackage() throws MojoExecutionException, MojoFailureException {
+        // 生成依赖文件夹
+        String rootDir = createRootDir();
+        mainConfig.setOutputDirectory(rootDir);
+        super.repackage();
+    }
+
+    @Override
+    protected void writeClasses() throws Exception {
+        String buildDir = repackageMojo.getProject().getBuild().getOutputDirectory();
+        packageJar.copyDirToPackage(new File(buildDir), null);
+    }
+
+    private String createRootDir() throws MojoFailureException{
+        String outputDirectory = mainConfig.getOutputDirectory();
+        String fileName = mainConfig.getFileName();
+        String rootDirPath = FilesUtils.joiningFilePath(outputDirectory, fileName);
+        File rootFile = new File(rootDirPath);
+        CommonUtils.deleteFile(rootFile);
+        if(rootFile.mkdirs()){
+            return rootDirPath;
+        } else {
+            throw new MojoFailureException("Create dir failure : " + rootDirPath);
+        }
+    }
+
+    @Override
+    protected Manifest getManifest() throws Exception {
+        Manifest manifest = new Manifest();
+        Attributes attributes = manifest.getMainAttributes();
+        attributes.putValue(MANIFEST_VERSION, MANIFEST_VERSION_1_0);
+        attributes.putValue(START_CLASS, mainConfig.getMainClass());
+        attributes.putValue(MAIN_CLASS, MAIN_CLASS_VALUE);
+        attributes.putValue(MAIN_PACKAGE_TYPE, PackageType.MAIN_PACKAGE_TYPE_JAR_OUTER);
+        attributes.putValue(MAIN_LIB_DIR, getLibPath());
+        attributes.putValue(DEVELOPMENT_MODE, mainConfig.getDevelopmentMode());
+
+        // 增加jar包title和version属性
+        MavenProject mavenProject = this.repackageMojo.getProject();
+        attributes.putValue(IMPLEMENTATION_TITLE, mavenProject.getArtifactId());
+        attributes.putValue(IMPLEMENTATION_VERSION, mavenProject.getVersion());
+        return manifest;
+    }
+
+
+    private String getLibIndexes() throws Exception {
+        if(dependencyIndexNames.isEmpty()){
+            return "";
+        }
+        StringBuilder libName = new StringBuilder();
+        for (String dependencyIndexName : dependencyIndexNames) {
+            libName.append(dependencyIndexName).append(LIB_INDEXES_SPLIT);
+        }
+        return libName.toString();
+    }
+
+    @Override
+    protected void writeDependencies() throws Exception {
+        Set<Artifact> dependencies = repackageMojo.getSourceDependencies();
+        for (Artifact artifact : dependencies) {
+            if(filterArtifact(artifact)){
+                continue;
+            }
+            if(CommonUtils.isPluginFrameworkLoader(artifact)){
+                // 本框架loader依赖
+                packageJar.copyZipToPackage(artifact.getFile());
+            } else {
+                File artifactFile = artifact.getFile();
+                String libPath = getLibPath();
+                if(FilesUtils.isRelativePath(libPath)){
+                    libPath = FilesUtils.resolveRelativePath(mainConfig.getOutputDirectory(), getLibPath());
+                } else {
+                    libPath = FilesUtils.joiningFilePath(mainConfig.getOutputDirectory(), libPath);
+                }
+                String targetFilePath = FilesUtils.joiningFilePath(libPath, artifactFile.getName());
+                FileUtils.copyFile(artifactFile, new File(targetFilePath));
+                dependencyIndexNames.add(artifactFile.getName());
+            }
+        }
+    }
+
+    private String getLibPath(){
+        String libDir = PackageStructure.LIB_NAME;
+        if(!ObjectUtils.isEmpty(mainConfig.getLibDir())){
+            libDir = mainConfig.getLibDir();
+        }
+        return libDir;
+    }
+
+}

+ 68 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/MainConfig.java

@@ -0,0 +1,68 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.main;
+
+import lombok.Data;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * 主程序打包配置
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+@Data
+public class MainConfig {
+
+    /**
+     * 主启动类
+     */
+    @Parameter(required = true)
+    private String mainClass;
+
+    /**
+     * 打包类型。默认:jar
+     * {@link com.gitee.starblues.common.PackageType#MAIN_PACKAGE_TYPE_JAR}
+     * {@link com.gitee.starblues.common.PackageType#MAIN_PACKAGE_TYPE_JAR_OUTER}
+     */
+    private String packageType;
+
+    /**
+     * 文件名称。默认 artifactId-version-repackage
+     */
+    private String fileName;
+
+    /**
+     * 依赖包所在目录
+     */
+    private String libDir;
+
+    /**
+     * 输出文件目录。默认target
+     */
+    private String outputDirectory;
+
+    /**
+     * 开发模式:
+     * isolation: 隔离模式[默认]
+     * coexist: 共享模式
+     * simple: 简单模式
+     */
+    private String developmentMode;
+
+}

+ 136 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/MainRepackager.java

@@ -0,0 +1,136 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.main;
+
+import com.gitee.starblues.common.PackageType;
+import com.gitee.starblues.plugin.pack.Constant;
+import com.gitee.starblues.plugin.pack.RepackageMojo;
+import com.gitee.starblues.plugin.pack.Repackager;
+import com.gitee.starblues.plugin.pack.utils.CommonUtils;
+import com.gitee.starblues.utils.ObjectUtils;
+import com.gitee.starblues.utils.ReflectionUtils;
+import lombok.Getter;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Set;
+
+/**
+ * 主程序打包
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.1.1
+ */
+@Getter
+public class MainRepackager implements Repackager {
+
+    private final RepackageMojo repackageMojo;
+    private final MainConfig mainConfig;
+
+    public MainRepackager(RepackageMojo repackageMojo) {
+        this.repackageMojo = repackageMojo;
+        this.mainConfig = repackageMojo.getMainConfig();
+    }
+
+    @Override
+    public void repackage() throws MojoExecutionException, MojoFailureException {
+        checkConfig();
+        setDevelopmentMode();
+        String packageType = mainConfig.getPackageType();
+        Repackager repackager = null;
+        if(PackageType.MAIN_PACKAGE_TYPE_JAR.equalsIgnoreCase(packageType)){
+            repackager = new JarNestPackager(this);
+        } else if(PackageType.MAIN_PACKAGE_TYPE_JAR_OUTER.equalsIgnoreCase(packageType)){
+            repackager = new JarOuterPackager(this);
+        } else {
+            throw new MojoFailureException("Not found packageType : " + packageType);
+        }
+        repackager.repackage();
+    }
+
+    private void checkConfig() throws MojoFailureException {
+        if(mainConfig == null){
+            throw new MojoFailureException("configuration.mainConfig config cannot be empty");
+        }
+        if(ObjectUtils.isEmpty(mainConfig.getMainClass())) {
+            throw new MojoFailureException("configuration.mainConfig.mainClass config cannot be empty");
+        }
+        String fileName = mainConfig.getFileName();
+        if(ObjectUtils.isEmpty(fileName)) {
+            MavenProject project = repackageMojo.getProject();
+            mainConfig.setFileName(project.getArtifactId() + "-" + project.getVersion() + "-repackage");
+        }
+        String packageType = mainConfig.getPackageType();
+        if(ObjectUtils.isEmpty(packageType)) {
+            mainConfig.setPackageType(PackageType.MAIN_PACKAGE_TYPE_JAR);
+        }
+        String outputDirectory = mainConfig.getOutputDirectory();
+        if(ObjectUtils.isEmpty(outputDirectory)){
+            mainConfig.setOutputDirectory(repackageMojo.getOutputDirectory().getPath());
+        }
+    }
+
+    private void setDevelopmentMode() throws MojoFailureException{
+        String developmentMode = mainConfig.getDevelopmentMode();
+        if(!ObjectUtils.isEmpty(developmentMode)){
+            return;
+        }
+        try {
+            File file =  new File(repackageMojo.getProject().getBuild().getOutputDirectory());
+            Set<Artifact> artifacts = repackageMojo.getProject().getArtifacts();
+
+            URL[] urls = new URL[artifacts.size() + 1];
+            int i = 0;
+            for (Artifact artifact : artifacts) {
+                urls[i] = artifact.getFile().toURI().toURL();
+                i++;
+            }
+            urls[i] = file.toURI().toURL();
+            URLClassLoader urlClassLoader = new URLClassLoader(urls, null);
+
+            String mainClass = repackageMojo.getMainConfig().getMainClass();
+            if(ObjectUtils.isEmpty(mainClass)){
+                throw new Exception("mainConfig.mainClass config can't be empty");
+            }
+            Class<?> aClass = urlClassLoader.loadClass(mainClass);
+            Method method = ReflectionUtils.findMethod(aClass, Constant.DEVELOPMENT_MODE_METHOD_NAME);
+            String methodKey =  aClass.getName() + "#" + Constant.DEVELOPMENT_MODE_METHOD_NAME + "()";
+            if(method == null){
+                throw new Exception("Not found method : " + methodKey);
+            }
+            method.setAccessible(true);
+            Object o = aClass.getConstructor().newInstance();
+            Object result = method.invoke(o);
+            if(ObjectUtils.isEmpty(result)){
+                throw new Exception(methodKey + " return value can't be empty");
+            }
+            getMainConfig().setDevelopmentMode(String.valueOf(result));
+        } catch (Exception e) {
+            throw new MojoFailureException("Set developmentMode failure:" + e.getMessage());
+        }
+    }
+
+
+}

+ 156 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/DirProdRepackager.java

@@ -0,0 +1,156 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.prod;
+
+import com.gitee.starblues.common.*;
+import com.gitee.starblues.plugin.pack.RepackageMojo;
+import com.gitee.starblues.plugin.pack.dev.DevRepackager;
+import com.gitee.starblues.plugin.pack.utils.CommonUtils;
+import com.gitee.starblues.utils.FilesUtils;
+import com.gitee.starblues.utils.ObjectUtils;
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import static com.gitee.starblues.common.PackageStructure.*;
+
+/**
+ * 文件夹包生成
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.1.1
+ */
+public class DirProdRepackager extends DevRepackager {
+
+    protected final ProdConfig prodConfig;
+
+
+    public DirProdRepackager(RepackageMojo repackageMojo, ProdConfig prodConfig) {
+        super(repackageMojo);
+        this.prodConfig = prodConfig;
+    }
+
+    @Override
+    public void repackage() throws MojoExecutionException, MojoFailureException {
+        super.repackage();
+        try {
+            resolveClasses();
+            logSuccess();
+        } catch (Exception e) {
+            repackageMojo.getLog().error(e.getMessage(), e);
+            throw new MojoFailureException(e);
+        }
+    }
+
+    protected void logSuccess(){
+        repackageMojo.getLog().info("Success package prod dir file : " + getRootDir());
+    }
+
+    @Override
+    protected String createRootDir() throws MojoFailureException {
+        String fileName = prodConfig.getFileName();
+        String dirPath = FilesUtils.joiningFilePath(prodConfig.getOutputDirectory(), fileName);
+        File dirFile = new File(dirPath);
+        CommonUtils.deleteFile(dirFile);
+        if(!dirFile.mkdirs()){
+            throw new MojoFailureException("Create package dir failure: " + dirFile.getPath());
+        }
+        return dirFile.getPath();
+    }
+
+    @Override
+    protected String getRelativeManifestPath() {
+        return FilesUtils.joiningFilePath(META_INF_NAME, MANIFEST);
+    }
+
+    @Override
+    protected String getRelativePluginMetaPath() {
+        return FilesUtils.joiningFilePath(META_INF_NAME, PLUGIN_META_NAME);
+    }
+
+    @Override
+    protected String getRelativeResourcesDefinePath() {
+        return FilesUtils.joiningFilePath(META_INF_NAME, RESOURCES_DEFINE_NAME);
+    }
+
+    @Override
+    protected Manifest getManifest() throws Exception {
+        Manifest manifest = super.getManifest();
+        Attributes attributes = manifest.getMainAttributes();
+        attributes.putValue(ManifestKey.PLUGIN_META_PATH, PROD_PLUGIN_META_PATH);
+        attributes.putValue(ManifestKey.PLUGIN_PACKAGE_TYPE, PackageType.PLUGIN_PACKAGE_TYPE_DIR);
+        return manifest;
+    }
+
+    @Override
+    protected Properties createPluginMetaInfo() throws Exception {
+        Properties properties = super.createPluginMetaInfo();
+        properties.put(PluginDescriptorKey.PLUGIN_PATH, CLASSES_NAME);
+        properties.put(PluginDescriptorKey.PLUGIN_RESOURCES_CONFIG, PROD_RESOURCES_DEFINE_PATH);
+        String libDir = prodConfig.getLibDir();
+        if(ObjectUtils.isEmpty(libDir)){
+           libDir = Constants.RELATIVE_SIGN + PackageStructure.PROD_LIB_PATH;
+        }
+        properties.put(PluginDescriptorKey.PLUGIN_LIB_DIR, libDir);
+        return properties;
+    }
+
+    protected void resolveClasses() throws Exception {
+        String buildDir = repackageMojo.getProject().getBuild().getOutputDirectory();
+        String path = FilesUtils.joiningFilePath(getRootDir(), CLASSES_NAME);
+        File file = new File(path);
+        FileUtils.forceMkdir(file);
+        FileUtils.copyDirectory(new File(buildDir), file);
+    }
+
+    @Override
+    protected Set<String> getDependenciesIndexSet() throws Exception {
+        Set<Artifact> dependencies = repackageMojo.getFilterDependencies();
+        String libDir = createLibDir();
+        Set<String> dependencyIndexNames = new LinkedHashSet<>(dependencies.size());
+        for (Artifact artifact : dependencies) {
+            if(filterArtifact(artifact)){
+                continue;
+            }
+            File artifactFile = artifact.getFile();
+            FileUtils.copyFile(artifactFile, new File(FilesUtils.joiningFilePath(libDir, artifactFile.getName())));
+            dependencyIndexNames.add(artifactFile.getName() + repackageMojo.resolveLoadToMain(artifact));
+        }
+        return dependencyIndexNames;
+    }
+
+    protected String createLibDir() throws IOException {
+        String dir = FilesUtils.joiningFilePath(getRootDir(), PackageStructure.LIB_NAME);
+        File file = new File(dir);
+        if(file.mkdir()){
+            return dir;
+        }
+        throw new IOException("Create " + PackageStructure.LIB_NAME + " dir failure");
+    }
+
+}

+ 77 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/JarNestedProdRepackager.java

@@ -0,0 +1,77 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.prod;
+
+import com.gitee.starblues.common.ManifestKey;
+import com.gitee.starblues.common.PackageType;
+import com.gitee.starblues.common.PluginDescriptorKey;
+import com.gitee.starblues.plugin.pack.RepackageMojo;
+import com.gitee.starblues.plugin.pack.utils.PackageJar;
+import com.gitee.starblues.plugin.pack.utils.PackageZip;
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.archivers.jar.JarArchiveEntry;
+import org.apache.commons.compress.archivers.jar.JarArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import java.io.*;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import static com.gitee.starblues.common.PackageStructure.PROD_CLASSES_PATH;
+import static com.gitee.starblues.common.PackageStructure.PROD_RESOURCES_DEFINE_PATH;
+
+/**
+ * jar包生成
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.1.1
+ */
+public class JarNestedProdRepackager extends ZipProdRepackager {
+
+
+    public JarNestedProdRepackager(RepackageMojo repackageMojo, ProdConfig prodConfig) {
+        super(repackageMojo, prodConfig);
+    }
+
+    @Override
+    public void repackage() throws MojoExecutionException, MojoFailureException {
+        super.repackage();
+    }
+
+    protected void logSuccess(){
+        repackageMojo.getLog().info("Success package prod jar file : "
+                + packageZip.getFile().getPath());
+    }
+
+    @Override
+    protected PackageZip getPackageZip() throws Exception {
+        return new PackageJar(prodConfig.getOutputDirectory(), prodConfig.getFileName());
+    }
+
+    @Override
+    protected Manifest getManifest() throws Exception {
+        Manifest manifest = super.getManifest();
+        manifest.getMainAttributes().putValue(
+                ManifestKey.PLUGIN_PACKAGE_TYPE, PackageType.PLUGIN_PACKAGE_TYPE_JAR);
+        return manifest;
+    }
+
+
+}

+ 56 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/JarOuterProdRepackager.java

@@ -0,0 +1,56 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.prod;
+
+import com.gitee.starblues.common.ManifestKey;
+import com.gitee.starblues.common.PackageType;
+import com.gitee.starblues.common.PluginDescriptorKey;
+import com.gitee.starblues.plugin.pack.RepackageMojo;
+import com.gitee.starblues.plugin.pack.utils.PackageJar;
+import com.gitee.starblues.plugin.pack.utils.PackageZip;
+
+import java.util.jar.Manifest;
+
+/**
+ * jar-outer包生成
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class JarOuterProdRepackager extends ZipOuterProdRepackager {
+
+
+    public JarOuterProdRepackager(RepackageMojo repackageMojo, ProdConfig prodConfig) {
+        super(repackageMojo, prodConfig);
+    }
+
+    @Override
+    protected PackageZip getPackageZip(String rootDir) throws Exception {
+        return new PackageJar(rootDir, super.prodConfig.getFileName());
+    }
+
+    @Override
+    protected Manifest getManifest() throws Exception {
+        Manifest manifest = super.getManifest();
+        manifest.getMainAttributes().putValue(ManifestKey.PLUGIN_PACKAGE_TYPE,
+                PackageType.PLUGIN_PACKAGE_TYPE_JAR_OUTER);
+        return manifest;
+    }
+
+
+}

+ 59 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ProdConfig.java

@@ -0,0 +1,59 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.prod;
+
+
+import lombok.Data;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * 生产环境打包配置
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.2
+ */
+@Data
+public class ProdConfig {
+
+    /**
+     * 打包类型。默认jar包
+     * {@link com.gitee.starblues.common.PackageType#PLUGIN_PACKAGE_TYPE_JAR}
+     * {@link com.gitee.starblues.common.PackageType#PLUGIN_PACKAGE_TYPE_JAR_OUTER}
+     * {@link com.gitee.starblues.common.PackageType#PLUGIN_PACKAGE_TYPE_ZIP}
+     * {@link com.gitee.starblues.common.PackageType#PLUGIN_PACKAGE_TYPE_ZIP_OUTER}
+     * {@link com.gitee.starblues.common.PackageType#PLUGIN_PACKAGE_TYPE_DIR}
+     */
+    @Parameter(required = true, defaultValue = "jar")
+    private String packageType = "jar";
+
+    /**
+     * 文件名称。默认 pluginId-version-repackage
+     */
+    private String fileName;
+
+    /**
+     * 输出文件目录。默认target
+     */
+    private String outputDirectory;
+
+    /**
+     * jar-outer、zip-outer、dir 类型可指定依赖包目录
+     */
+    private String libDir;
+
+}

+ 95 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ProdRepackager.java

@@ -0,0 +1,95 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.prod;
+
+import com.gitee.starblues.common.PackageType;
+import com.gitee.starblues.plugin.pack.PluginInfo;
+import com.gitee.starblues.plugin.pack.RepackageMojo;
+import com.gitee.starblues.plugin.pack.Repackager;
+import com.gitee.starblues.plugin.pack.dev.DevRepackager;
+import com.gitee.starblues.utils.ObjectUtils;
+import lombok.Getter;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+
+/**
+ * 生产环境打包
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class ProdRepackager implements Repackager {
+
+    @Getter
+    private ProdConfig prodConfig;
+
+    private final RepackageMojo repackageMojo;
+    private final Repackager repackager;
+
+    public ProdRepackager(RepackageMojo repackageMojo) {
+        this.repackageMojo = repackageMojo;
+        this.repackager = new DevRepackager(repackageMojo);
+    }
+
+    @Override
+    public void repackage() throws MojoExecutionException, MojoFailureException {
+        repackager.repackage();
+        this.prodConfig = getProdConfig(repackageMojo);
+        String packageType = prodConfig.getPackageType();
+        Repackager repackager = null;
+
+        if(PackageType.PLUGIN_PACKAGE_TYPE_ZIP.equalsIgnoreCase(packageType)){
+            repackager = new ZipProdRepackager(repackageMojo, prodConfig);
+        }  else if(PackageType.PLUGIN_PACKAGE_TYPE_JAR.equalsIgnoreCase(packageType)){
+            repackager = new JarNestedProdRepackager(repackageMojo, prodConfig);
+        } else if(PackageType.PLUGIN_PACKAGE_TYPE_ZIP_OUTER.equalsIgnoreCase(packageType)){
+            repackager = new ZipOuterProdRepackager(repackageMojo, prodConfig);
+        } else if(PackageType.PLUGIN_PACKAGE_TYPE_JAR_OUTER.equalsIgnoreCase(packageType)){
+            repackager = new JarOuterProdRepackager(repackageMojo, prodConfig);
+        } else if(PackageType.PLUGIN_PACKAGE_TYPE_DIR.equalsIgnoreCase(packageType)){
+            repackager = new DirProdRepackager(repackageMojo, prodConfig);
+        }  else {
+            throw new MojoFailureException("Not found packageType : " + packageType);
+        }
+        repackager.repackage();
+    }
+
+    protected ProdConfig getProdConfig(RepackageMojo repackageMojo){
+        ProdConfig prodConfig = repackageMojo.getProdConfig();
+        if(prodConfig == null){
+            prodConfig = new ProdConfig();
+        }
+        if(ObjectUtils.isEmpty(prodConfig.getPackageType())){
+            prodConfig.setPackageType(PackageType.PLUGIN_PACKAGE_TYPE_JAR);
+        }
+        String fileName = prodConfig.getFileName();
+        if(ObjectUtils.isEmpty(fileName)) {
+            PluginInfo pluginInfo = repackageMojo.getPluginInfo();
+            prodConfig.setFileName(pluginInfo.getId() + "-" + pluginInfo.getVersion() + "-repackage");
+        }
+        String outputDirectory = prodConfig.getOutputDirectory();
+        if(ObjectUtils.isEmpty(outputDirectory)){
+            prodConfig.setOutputDirectory(repackageMojo.getOutputDirectory().getPath());
+        }
+        return prodConfig;
+    }
+
+
+
+}

+ 128 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ZipOuterProdRepackager.java

@@ -0,0 +1,128 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.prod;
+
+import com.gitee.starblues.common.ManifestKey;
+import com.gitee.starblues.common.PackageType;
+import com.gitee.starblues.common.PluginDescriptorKey;
+import com.gitee.starblues.plugin.pack.Constant;
+import com.gitee.starblues.plugin.pack.RepackageMojo;
+import com.gitee.starblues.plugin.pack.utils.PackageJar;
+import com.gitee.starblues.plugin.pack.utils.PackageZip;
+import com.gitee.starblues.utils.FilesUtils;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import java.io.File;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import static com.gitee.starblues.common.PackageStructure.*;
+
+/**
+ * zip-outer 包生成
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class ZipOuterProdRepackager extends DirProdRepackager {
+
+    protected PackageZip packageZip;
+
+    public ZipOuterProdRepackager(RepackageMojo repackageMojo, ProdConfig prodConfig) {
+        super(repackageMojo, prodConfig);
+    }
+
+    @Override
+    public void repackage() throws MojoExecutionException, MojoFailureException {
+        try {
+            super.repackage();
+        } catch (Exception e){
+            throw new MojoFailureException(e);
+        } finally {
+            if(packageZip != null){
+                IOUtils.closeQuietly(packageZip);
+            }
+        }
+    }
+
+    @Override
+    protected String createRootDir() throws MojoFailureException {
+        String rootDir = super.createRootDir();
+        try {
+            packageZip = getPackageZip(rootDir);
+            return rootDir;
+        } catch (Exception e) {
+            throw new MojoFailureException(e);
+        }
+    }
+
+    protected PackageZip getPackageZip(String rootDir) throws Exception {
+        return new PackageZip(rootDir, super.prodConfig.getFileName());
+    }
+
+    @Override
+    protected void resolveClasses() throws Exception {
+        String buildDir = repackageMojo.getProject().getBuild().getOutputDirectory();
+        packageZip.copyDirToPackage(new File(buildDir), "");
+    }
+
+    @Override
+    protected Manifest getManifest() throws Exception {
+        Manifest manifest = super.getManifest();
+        Attributes attributes = manifest.getMainAttributes();
+        attributes.putValue(ManifestKey.PLUGIN_META_PATH, PROD_PLUGIN_META_PATH);
+        attributes.putValue(ManifestKey.PLUGIN_PACKAGE_TYPE, PackageType.PLUGIN_PACKAGE_TYPE_ZIP_OUTER);
+        return manifest;
+    }
+
+    @Override
+    protected Properties createPluginMetaInfo() throws Exception {
+        Properties properties = super.createPluginMetaInfo();
+        properties.put(PluginDescriptorKey.PLUGIN_PATH, packageZip.getFileName());
+        return properties;
+    }
+    @Override
+    protected void writeManifest(Manifest manifest) throws Exception {
+        packageZip.writeManifest(manifest);
+    }
+
+    @Override
+    protected String writePluginMetaInfo(Properties properties) throws Exception {
+        packageZip.write(PROD_PLUGIN_META_PATH, outputStream->{
+            properties.store(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8),
+                    Constant.PLUGIN_METE_COMMENTS);
+        });
+        return PROD_PLUGIN_META_PATH;
+    }
+
+
+    @Override
+    protected String writeResourcesDefineFile(String resourcesDefineContent) throws Exception {
+        packageZip.write(PROD_RESOURCES_DEFINE_PATH, resourcesDefineContent);
+        return PROD_RESOURCES_DEFINE_PATH;
+    }
+}

+ 197 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ZipProdRepackager.java

@@ -0,0 +1,197 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.prod;
+
+import com.gitee.starblues.common.ManifestKey;
+import com.gitee.starblues.common.PackageStructure;
+import com.gitee.starblues.common.PackageType;
+import com.gitee.starblues.common.PluginDescriptorKey;
+import com.gitee.starblues.plugin.pack.Constant;
+import com.gitee.starblues.plugin.pack.RepackageMojo;
+import com.gitee.starblues.plugin.pack.dev.Dependency;
+import com.gitee.starblues.plugin.pack.dev.DevConfig;
+import com.gitee.starblues.plugin.pack.dev.DevRepackager;
+import com.gitee.starblues.plugin.pack.utils.CommonUtils;
+import com.gitee.starblues.plugin.pack.utils.PackageZip;
+import com.gitee.starblues.utils.FilesUtils;
+import com.gitee.starblues.utils.ObjectUtils;
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import static com.gitee.starblues.common.PackageStructure.*;
+
+/**
+ * zip 打包
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class ZipProdRepackager extends DevRepackager {
+
+
+    protected final ProdConfig prodConfig;
+
+    protected PackageZip packageZip;
+
+    public ZipProdRepackager(RepackageMojo repackageMojo, ProdConfig prodConfig) {
+        super(repackageMojo);
+        this.prodConfig = prodConfig;
+    }
+
+    @Override
+    public void repackage() throws MojoExecutionException, MojoFailureException {
+        try {
+            packageZip = getPackageZip();
+            super.repackage();
+            resolveClasses();
+            resolveResourcesDefine();
+            String rootDir = getRootDir();
+            try {
+                FileUtils.deleteDirectory(new File(rootDir));
+            } catch (IOException e) {
+                // 忽略
+            }
+            logSuccess();
+        } catch (Exception e){
+            repackageMojo.getLog().error(e.getMessage(), e);
+            throw new MojoFailureException(e);
+        } finally {
+            if(packageZip != null){
+                IOUtils.closeQuietly(packageZip);
+            }
+        }
+    }
+
+    protected void logSuccess(){
+        repackageMojo.getLog().info("Success package prod zip file : "
+                + packageZip.getFile().getPath());
+    }
+
+    protected PackageZip getPackageZip() throws Exception {
+        return new PackageZip(prodConfig.getOutputDirectory(), prodConfig.getFileName());
+    }
+
+    @Override
+    protected String getBasicRootDir(){
+        File outputDirectory = repackageMojo.getOutputDirectory();
+        return FilesUtils.joiningFilePath(outputDirectory.getPath(), UUID.randomUUID().toString());
+    }
+
+    @Override
+    protected Map<String, Dependency> getModuleDependencies(DevConfig devConfig) {
+        // 将项目中模块依赖置为空
+        return Collections.emptyMap();
+    }
+
+    @Override
+    protected String getPluginPath() {
+        return CLASSES_NAME + SEPARATOR;
+    }
+
+    @Override
+    protected boolean filterArtifact(Artifact artifact) {
+        return Constant.scopeFilter(artifact.getScope());
+    }
+
+    protected void resolveClasses() throws Exception {
+        String buildDir = repackageMojo.getProject().getBuild().getOutputDirectory();
+        packageZip.copyDirToPackage(new File(buildDir), null);
+    }
+
+    @Override
+    protected Manifest getManifest() throws Exception {
+        Manifest manifest = super.getManifest();
+        Attributes attributes = manifest.getMainAttributes();
+        attributes.putValue(ManifestKey.PLUGIN_META_PATH, PROD_PLUGIN_META_PATH);
+        attributes.putValue(ManifestKey.PLUGIN_PACKAGE_TYPE, PackageType.PLUGIN_PACKAGE_TYPE_ZIP);
+        return manifest;
+    }
+
+    @Override
+    protected Properties createPluginMetaInfo() throws Exception {
+        Properties properties = super.createPluginMetaInfo();
+        properties.put(PluginDescriptorKey.PLUGIN_RESOURCES_CONFIG, PROD_RESOURCES_DEFINE_PATH);
+        properties.put(PluginDescriptorKey.PLUGIN_LIB_DIR, PROD_LIB_PATH);
+        return properties;
+    }
+
+    @Override
+    protected void writeManifest(Manifest manifest) throws Exception {
+        packageZip.writeManifest(manifest);
+    }
+
+    @Override
+    protected String writePluginMetaInfo(Properties properties) throws Exception {
+        packageZip.write(PROD_PLUGIN_META_PATH, outputStream->{
+            properties.store(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8),
+                    Constant.PLUGIN_METE_COMMENTS);
+        });
+        return PROD_PLUGIN_META_PATH;
+    }
+
+    protected void resolveResourcesDefine() throws Exception{
+        Set<String> dependencyIndexNames = resolveDependencies();
+        StringBuilder content = new StringBuilder();
+        content.append(RESOURCES_DEFINE_DEPENDENCIES).append("\n");
+        for (String dependencyIndexName : dependencyIndexNames) {
+            content.append(dependencyIndexName).append("\n");
+        }
+        String loadMainResources = super.getLoadMainResources();
+        if(!ObjectUtils.isEmpty(loadMainResources)){
+            content.append(loadMainResources).append("\n");
+        }
+        final byte[] bytes = content.toString().getBytes(StandardCharsets.UTF_8);
+        try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes)){
+            packageZip.putInputStreamEntry(PROD_RESOURCES_DEFINE_PATH, byteArrayInputStream);
+        }
+    }
+
+    protected Set<String> resolveDependencies() throws Exception {
+        Set<Artifact> dependencies = repackageMojo.getFilterDependencies();
+        String libDirEntryName = createLibEntry();
+        Set<String> dependencyIndexNames = new LinkedHashSet<>(dependencies.size());
+        for (Artifact artifact : dependencies) {
+            if(filterArtifact(artifact)){
+                continue;
+            }
+            File artifactFile = artifact.getFile();
+            packageZip.writeDependency(artifactFile, libDirEntryName);
+            // fix 解决依赖前缀携带, lib 配置的前缀
+            dependencyIndexNames.add(artifactFile.getName());
+        }
+        return dependencyIndexNames;
+    }
+
+    protected String createLibEntry() throws Exception {
+        String libDirEntryName = PROD_LIB_PATH;
+        packageZip.putDirEntry(libDirEntryName);
+        return libDirEntryName;
+    }
+
+}

+ 100 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/CommonUtils.java

@@ -0,0 +1,100 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.utils;
+
+import com.gitee.starblues.plugin.pack.filter.Exclude;
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Objects;
+import java.util.jar.JarFile;
+
+/**
+ * Object 工具类
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.1
+ */
+public class CommonUtils {
+
+    public final static String PLUGIN_FRAMEWORK_GROUP_ID = "com.gitee.starblues";
+    public final static String PLUGIN_FRAMEWORK_ARTIFACT_ID = "spring-brick";
+
+    public final static String PLUGIN_FRAMEWORK_LOADER_ARTIFACT_ID = "spring-brick-loader";
+
+    public static final String PATTERN = "yyyy-MM-dd HH:mm:ss";
+    public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(PATTERN);
+
+    private CommonUtils(){}
+
+    public static Exclude getPluginFrameworkExclude(){
+        return Exclude.get(PLUGIN_FRAMEWORK_GROUP_ID, PLUGIN_FRAMEWORK_ARTIFACT_ID);
+    }
+
+    public static boolean isPluginFramework(Artifact artifact){
+        return Objects.equals(artifact.getGroupId(), PLUGIN_FRAMEWORK_GROUP_ID)
+                && Objects.equals(artifact.getArtifactId(), PLUGIN_FRAMEWORK_ARTIFACT_ID);
+    }
+
+    public static boolean isPluginFrameworkLoader(Artifact artifact){
+        return Objects.equals(artifact.getGroupId(), PLUGIN_FRAMEWORK_GROUP_ID)
+                && Objects.equals(artifact.getArtifactId(), PLUGIN_FRAMEWORK_LOADER_ARTIFACT_ID);
+    }
+
+    public static JarFile getSourceJarFile(MavenProject mavenProject) {
+        File file = mavenProject.getArtifact().getFile();
+        try {
+            return new JarFile(file);
+        } catch (Exception e){
+            return null;
+        }
+    }
+
+    public static String getDateTime() {
+        return DATE_TIME_FORMATTER.format(LocalDateTime.now());
+    }
+
+    public static void deleteFile(File rootFile) throws MojoFailureException {
+        try {
+            if(rootFile == null){
+                return;
+            }
+            if(!rootFile.exists()){
+                return;
+            }
+            if(rootFile.isFile()){
+                FileUtils.delete(rootFile);
+            } else {
+                FileUtils.deleteDirectory(rootFile);
+            }
+        } catch (Exception e){
+            e.printStackTrace();
+            throw new MojoFailureException("Delete file '" + rootFile.getPath() + "' failure. " + e.getMessage());
+        }
+    }
+
+}

+ 58 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageJar.java

@@ -0,0 +1,58 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.utils;
+
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.archivers.jar.JarArchiveEntry;
+import org.apache.commons.compress.archivers.jar.JarArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.nio.file.Files;
+
+/**
+ * jar 打包工具
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class PackageJar extends PackageZip{
+    public PackageJar(File file) throws Exception {
+        super(file);
+    }
+
+    public PackageJar(String outputDirectory, String packageName) throws Exception {
+        super(outputDirectory, packageName);
+    }
+
+    @Override
+    protected String getPackageFileSuffix() {
+        return "jar";
+    }
+
+    @Override
+    protected ArchiveOutputStream getOutputStream(File packFile) throws Exception {
+        return new JarArchiveOutputStream(Files.newOutputStream(packFile.toPath()));
+    }
+
+    @Override
+    protected ZipArchiveEntry getArchiveEntry(String name) {
+        return new JarArchiveEntry(name);
+    }
+}

+ 249 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageZip.java

@@ -0,0 +1,249 @@
+/**
+ * Copyright [2019-Present] [starBlues]
+ *
+ * Licensed 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 com.gitee.starblues.plugin.pack.utils;
+
+import com.gitee.starblues.common.PackageStructure;
+import com.gitee.starblues.utils.FilesUtils;
+import com.gitee.starblues.utils.ObjectUtils;
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.UnixStat;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.util.Enumeration;
+import java.util.jar.Manifest;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+
+import static com.gitee.starblues.common.PackageStructure.*;
+
+/**
+ * zip 打包工具
+ *
+ * @author starBlues
+ * @since 3.0.0
+ * @version 3.0.0
+ */
+public class PackageZip implements Closeable{
+
+
+    private static final int UNIX_FILE_MODE = UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM;
+
+    private static final int UNIX_DIR_MODE = UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM;
+
+    private final File file;
+    private final ArchiveOutputStream outputStream;
+
+
+    public PackageZip(File file) throws Exception {
+        this.file = file;
+        this.outputStream = getOutputStream(file);
+    }
+
+    public PackageZip(String outputDirectory, String packageName) throws Exception{
+        String rootPath = FilesUtils.joiningFilePath(outputDirectory, packageName);
+        this.file = getPackageFile(rootPath);
+        this.outputStream = getOutputStream(file);
+    }
+
+    public File getFile(){
+        return file;
+    }
+
+    public String getFileName(){
+        return file.getName();
+    }
+
+    protected File getPackageFile(String rootPath) throws Exception {
+        String fileSuffix = getPackageFileSuffix();
+        File file = new File(rootPath + "." + fileSuffix);
+        CommonUtils.deleteFile(file);
+        if(file.createNewFile()){
+            return file;
+        }
+        throw new IOException("Create file '" + file.getPath() + "' failure.");
+    }
+
+    protected String getPackageFileSuffix(){
+        return "zip";
+    }
+
+    protected ArchiveOutputStream getOutputStream(File packFile) throws Exception {
+        return new ZipArchiveOutputStream(Files.newOutputStream(packFile.toPath()));
+    }
+
+    public void copyDirToPackage(File rootDir, String packageDir) throws Exception {
+        if(packageDir == null){
+            packageDir = rootDir.getName();
+        }
+        if (rootDir.isDirectory()) {
+            File[] childFiles = rootDir.listFiles();
+            if(ObjectUtils.isEmpty(packageDir)){
+                packageDir = "";
+            } else {
+                packageDir = packageDir + "/";
+                putDirEntry(packageDir);
+            }
+            if(childFiles == null){
+                return;
+            }
+            for (File childFile : childFiles) {
+                copyDirToPackage(childFile, packageDir + childFile.getName());
+            }
+        } else {
+            putFileEntry(rootDir, packageDir);
+        }
+    }
+
+    public void copyZipToPackage(File sourceZipFile) throws Exception {
+        if(sourceZipFile == null || !sourceZipFile.exists()){
+            return;
+        }
+        try (ZipFile zipFile = new ZipFile(sourceZipFile)){
+            Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
+            while (entries.hasMoreElements()){
+                ZipArchiveEntry zipArchiveEntry = entries.nextElement();
+                String name = zipArchiveEntry.getName();
+                if(name.contains(PackageStructure.META_INF_NAME)){
+                    // 不拷贝 mate-inf
+                    continue;
+                }
+                if(zipArchiveEntry.isDirectory()){
+                    putDirEntry(name);
+                } else {
+                    try (InputStream inputStream = zipFile.getInputStream(zipArchiveEntry)){
+                        putInputStreamEntry(name, inputStream);
+                    }
+                }
+            }
+        }
+    }
+
+    public String writeDependency(File dependencyFile, String libDirEntryName) throws Exception {
+        String indexName = libDirEntryName + dependencyFile.getName();
+        ZipArchiveEntry entry = getArchiveEntry(indexName);
+        entry.setTime(System.currentTimeMillis());
+        entry.setUnixMode(indexName.endsWith("/") ? UNIX_DIR_MODE : UNIX_FILE_MODE);
+        entry.getGeneralPurposeBit().useUTF8ForNames(true);
+        try(FileInputStream inputStream = new FileInputStream(dependencyFile)){
+            new CrcAndSize(inputStream).setupStoredEntry(entry);
+        }
+        try (FileInputStream inputStream = new FileInputStream(dependencyFile)){
+            outputStream.putArchiveEntry(entry);
+            IOUtils.copy(inputStream, outputStream);
+            outputStream.closeArchiveEntry();
+        }
+        return indexName;
+    }
+
+    public void putFileEntry(File destFile, String rootDir) throws Exception {
+        if(!destFile.exists()){
+            throw new FileNotFoundException("Not found file : " + destFile.getPath());
+        }
+        outputStream.putArchiveEntry(getArchiveEntry(rootDir));
+        FileUtils.copyFile(destFile, outputStream);
+        outputStream.closeArchiveEntry();
+    }
+
+    public void putInputStreamEntry(String name, InputStream inputStream) throws Exception {
+        outputStream.putArchiveEntry(getArchiveEntry(name));
+        IOUtils.copy(inputStream, outputStream);
+        outputStream.closeArchiveEntry();
+    }
+
+    public void write(String name, String content) throws Exception {
+        outputStream.putArchiveEntry(getArchiveEntry(name));
+        IOUtils.write(content, outputStream, CHARSET_NAME);
+        outputStream.closeArchiveEntry();
+    }
+
+    public void write(String name, Writer writer) throws Exception {
+        outputStream.putArchiveEntry(getArchiveEntry(name));
+        writer.write(outputStream);
+        outputStream.closeArchiveEntry();
+    }
+
+    public void write(String name, File file) throws Exception {
+        outputStream.putArchiveEntry(getArchiveEntry(name));
+        try (FileInputStream fileInputStream = new FileInputStream(file)){
+            IOUtils.copy(fileInputStream, outputStream);
+            outputStream.closeArchiveEntry();
+        }
+    }
+
+    public void writeManifest(Manifest manifest) throws Exception {
+        putDirEntry(META_INF_NAME + SEPARATOR);
+        write(PROD_MANIFEST_PATH, manifest::write);
+    }
+
+    public void putDirEntry(String dir) throws IOException {
+        outputStream.putArchiveEntry(getArchiveEntry(dir));
+        outputStream.closeArchiveEntry();
+    }
+
+    protected ZipArchiveEntry getArchiveEntry(String name){
+        return new ZipArchiveEntry(name);
+    }
+
+
+    @Override
+    public void close() throws IOException {
+        outputStream.finish();
+        outputStream.close();
+    }
+
+    private static class CrcAndSize {
+
+        private static final int BUFFER_SIZE = 32 * 1024;
+
+        private final CRC32 crc = new CRC32();
+
+        private long size;
+
+        CrcAndSize(InputStream inputStream) throws IOException {
+            load(inputStream);
+        }
+
+        private void load(InputStream inputStream) throws IOException {
+            byte[] buffer = new byte[BUFFER_SIZE];
+            int bytesRead;
+            while ((bytesRead = inputStream.read(buffer)) != -1) {
+                this.crc.update(buffer, 0, bytesRead);
+                this.size += bytesRead;
+            }
+        }
+
+        void setupStoredEntry(ZipArchiveEntry entry) {
+            entry.setSize(this.size);
+            entry.setCompressedSize(this.size);
+            entry.setCrc(this.crc.getValue());
+            entry.setMethod(ZipEntry.STORED);
+        }
+
+    }
+
+    @FunctionalInterface
+    public interface Writer{
+        void write(ArchiveOutputStream outputStream) throws Exception;
+    }
+
+}

+ 168 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/resources/META-INF/maven/com.gitee.starblues.springboot-plugin-maven-packager/plugin-help.xml

@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin>
+    <name>Spring Boot Plugin Maven Packager</name>
+    <groupId>com.gitee.starblues</groupId>
+    <artifactId>spring-brick-maven-packager</artifactId>
+    <version>3.1.3</version>
+    <goalPrefix>spring-brick-packager</goalPrefix>
+    <isolatedRealm>false</isolatedRealm>
+    <inheritedByDefault>true</inheritedByDefault>
+    <mojos>
+        <mojo>
+            <goal>repackage</goal>
+            <description>重新打包</description>
+            <requiresDependencyResolution>compile+runtime</requiresDependencyResolution>
+            <requiresDirectInvocation>false</requiresDirectInvocation>
+            <requiresProject>true</requiresProject>
+            <requiresReports>false</requiresReports>
+            <aggregator>false</aggregator>
+            <requiresOnline>false</requiresOnline>
+            <inheritedByDefault>true</inheritedByDefault>
+            <phase>package</phase>
+            <implementation>com.gitee.starblues.plugin.pack.RepackageMojo</implementation>
+            <language>java</language>
+            <instantiationStrategy>per-lookup</instantiationStrategy>
+            <executionStrategy>once-per-session</executionStrategy>
+            <since>3.0.0</since>
+            <requiresDependencyCollection>compile+runtime</requiresDependencyCollection>
+            <threadSafe>true</threadSafe>
+            <parameters>
+                <parameter>
+                    <name>project</name>
+                    <type>org.apache.maven.project.MavenProject</type>
+                    <since>3.0.0</since>
+                    <required>true</required>
+                    <editable>false</editable>
+                    <description>当前项目</description>
+                </parameter>
+                <parameter>
+                    <name>outputDirectory</name>
+                    <type>java.io.File</type>
+                    <since>3.0.0</since>
+                    <required>true</required>
+                    <editable>true</editable>
+                    <description>打包输出目录地址</description>
+                </parameter>
+                <parameter>
+                    <name>includes</name>
+                    <type>java.util.List</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>包含依赖定义</description>
+                </parameter>
+                <parameter>
+                    <name>excludes</name>
+                    <type>java.util.List</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>排除依赖定义</description>
+                </parameter>
+                <parameter>
+                    <name>skip</name>
+                    <type>boolean</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>跳过执行</description>
+                </parameter>
+                <parameter>
+                    <name>mode</name>
+                    <type>string</type>
+                    <since>3.0.0</since>
+                    <required>true</required>
+                    <editable>true</editable>
+                    <description>打包模式: dev/prod ,默认为dev</description>
+                </parameter>
+                <parameter>
+                    <name>pluginInfo</name>
+                    <type>com.gitee.starblues.plugin.pack.PluginInfo</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>插件信息</description>
+                </parameter>
+                <parameter>
+                    <name>loadMainResourcePattern</name>
+                    <type>com.gitee.starblues.plugin.pack.LoadMainResourcePattern</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>从主程序加载资源的定义</description>
+                </parameter>
+                <parameter>
+                    <name>devConfig</name>
+                    <type>com.gitee.starblues.plugin.pack.dev.DevConfig</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>dev打包模式配置</description>
+                </parameter>
+                <parameter>
+                    <name>prodConfig</name>
+                    <type>com.gitee.starblues.plugin.pack.prod.ProdConfig</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>prod打包模式配置</description>
+                </parameter>
+                <parameter>
+                    <name>mainConfig</name>
+                    <type>com.gitee.starblues.plugin.pack.main.MainConfig</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>main打包模式配置</description>
+                </parameter>
+                <parameter>
+                    <name>loadToMain</name>
+                    <type>com.gitee.starblues.plugin.pack.LoadToMain</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>加载到主程序的依赖</description>
+                </parameter>
+                <parameter>
+                    <name>encryptConfig</name>
+                    <type>com.gitee.starblues.plugin.pack.encrypt.EncryptConfig</type>
+                    <since>3.0.1</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>加密配置</description>
+                </parameter>
+                <parameter>
+                    <name>includeSystemScope</name>
+                    <type>boolean</type>
+                    <since>3.0.2</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>是否包含scope类型为system的依赖</description>
+                </parameter>
+            </parameters>
+            <configuration>
+                <project implementation="org.apache.maven.project.MavenProject" default-value="${project}"/>
+                <outputDirectory implementation="java.io.File" default-value="${project.build.directory}"/>
+                <skip implementation="boolean" default-value="false"/>
+                <mode implementation="string" default-value="dev"/>
+                <pluginInfo implementation="com.gitee.starblues.plugin.pack.PluginInfo" />
+                <loadMainResourcePattern implementation="com.gitee.starblues.plugin.pack.LoadMainResourcePattern" />
+                <includes implementation="java.util.List">${springboot-plugin.includes}</includes>
+                <excludes implementation="java.util.List">${springboot-plugin.excludes}</excludes>
+                <devConfig implementation="com.gitee.starblues.plugin.pack.dev.DevConfig" />
+                <prodConfig implementation="com.gitee.starblues.plugin.pack.prod.ProdConfig" />
+                <mainConfig implementation="com.gitee.starblues.plugin.pack.main.MainConfig" />
+                <loadToMain implementation="com.gitee.starblues.plugin.pack.LoadToMain" />
+                <includeSystemScope implementation="boolean" default-value="true" />
+            </configuration>
+            <requirements>
+                <requirement>
+                    <role>org.apache.maven.project.MavenProjectHelper</role>
+                    <field-name>projectHelper</field-name>
+                </requirement>
+            </requirements>
+        </mojo>
+    </mojos>
+    <dependencies/>
+</plugin>

+ 168 - 0
iot-module/iot-plugin/spring-brick-maven-packager/src/main/resources/META-INF/maven/plugin.xml

@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin>
+    <name>Spring Boot Plugin Maven Packager</name>
+    <groupId>com.gitee.starblues</groupId>
+    <artifactId>spring-brick-maven-packager</artifactId>
+    <version>3.1.3</version>
+    <goalPrefix>spring-brick-packager</goalPrefix>
+    <isolatedRealm>false</isolatedRealm>
+    <inheritedByDefault>true</inheritedByDefault>
+    <mojos>
+        <mojo>
+            <goal>repackage</goal>
+            <description>重新打包</description>
+            <requiresDependencyResolution>compile+runtime</requiresDependencyResolution>
+            <requiresDirectInvocation>false</requiresDirectInvocation>
+            <requiresProject>true</requiresProject>
+            <requiresReports>false</requiresReports>
+            <aggregator>false</aggregator>
+            <requiresOnline>false</requiresOnline>
+            <inheritedByDefault>true</inheritedByDefault>
+            <phase>package</phase>
+            <implementation>com.gitee.starblues.plugin.pack.RepackageMojo</implementation>
+            <language>java</language>
+            <instantiationStrategy>per-lookup</instantiationStrategy>
+            <executionStrategy>once-per-session</executionStrategy>
+            <since>3.0.0</since>
+            <requiresDependencyCollection>compile+runtime</requiresDependencyCollection>
+            <threadSafe>true</threadSafe>
+            <parameters>
+                <parameter>
+                    <name>project</name>
+                    <type>org.apache.maven.project.MavenProject</type>
+                    <since>3.0.0</since>
+                    <required>true</required>
+                    <editable>false</editable>
+                    <description>当前项目</description>
+                </parameter>
+                <parameter>
+                    <name>outputDirectory</name>
+                    <type>java.io.File</type>
+                    <since>3.0.0</since>
+                    <required>true</required>
+                    <editable>true</editable>
+                    <description>打包输出目录地址</description>
+                </parameter>
+                <parameter>
+                    <name>includes</name>
+                    <type>java.util.List</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>包含依赖定义</description>
+                </parameter>
+                <parameter>
+                    <name>excludes</name>
+                    <type>java.util.List</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>排除依赖定义</description>
+                </parameter>
+                <parameter>
+                    <name>skip</name>
+                    <type>boolean</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>跳过执行</description>
+                </parameter>
+                <parameter>
+                    <name>mode</name>
+                    <type>string</type>
+                    <since>3.0.0</since>
+                    <required>true</required>
+                    <editable>true</editable>
+                    <description>打包模式: dev/prod ,默认为dev</description>
+                </parameter>
+                <parameter>
+                    <name>pluginInfo</name>
+                    <type>com.gitee.starblues.plugin.pack.PluginInfo</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>插件信息</description>
+                </parameter>
+                <parameter>
+                    <name>loadMainResourcePattern</name>
+                    <type>com.gitee.starblues.plugin.pack.LoadMainResourcePattern</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>从主程序加载资源的定义</description>
+                </parameter>
+                <parameter>
+                    <name>devConfig</name>
+                    <type>com.gitee.starblues.plugin.pack.dev.DevConfig</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>dev打包模式配置</description>
+                </parameter>
+                <parameter>
+                    <name>prodConfig</name>
+                    <type>com.gitee.starblues.plugin.pack.prod.ProdConfig</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>prod打包模式配置</description>
+                </parameter>
+                <parameter>
+                    <name>mainConfig</name>
+                    <type>com.gitee.starblues.plugin.pack.main.MainConfig</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>main打包模式配置</description>
+                </parameter>
+                <parameter>
+                    <name>loadToMain</name>
+                    <type>com.gitee.starblues.plugin.pack.LoadToMain</type>
+                    <since>3.0.0</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>加载到主程序的依赖</description>
+                </parameter>
+                <parameter>
+                    <name>encryptConfig</name>
+                    <type>com.gitee.starblues.plugin.pack.encrypt.EncryptConfig</type>
+                    <since>3.0.1</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>加密配置</description>
+                </parameter>
+                <parameter>
+                    <name>includeSystemScope</name>
+                    <type>boolean</type>
+                    <since>3.0.2</since>
+                    <required>false</required>
+                    <editable>true</editable>
+                    <description>是否包含scope类型为system的依赖</description>
+                </parameter>
+            </parameters>
+            <configuration>
+                <project implementation="org.apache.maven.project.MavenProject" default-value="${project}"/>
+                <outputDirectory implementation="java.io.File" default-value="${project.build.directory}"/>
+                <skip implementation="boolean" default-value="false"/>
+                <mode implementation="string" default-value="dev"/>
+                <pluginInfo implementation="com.gitee.starblues.plugin.pack.PluginInfo" />
+                <loadMainResourcePattern implementation="com.gitee.starblues.plugin.pack.LoadMainResourcePattern" />
+                <includes implementation="java.util.List">${springboot-plugin.includes}</includes>
+                <excludes implementation="java.util.List">${springboot-plugin.excludes}</excludes>
+                <devConfig implementation="com.gitee.starblues.plugin.pack.dev.DevConfig" />
+                <prodConfig implementation="com.gitee.starblues.plugin.pack.prod.ProdConfig" />
+                <mainConfig implementation="com.gitee.starblues.plugin.pack.main.MainConfig" />
+                <loadToMain implementation="com.gitee.starblues.plugin.pack.LoadToMain" />
+                <includeSystemScope implementation="boolean" default-value="true" />
+            </configuration>
+            <requirements>
+                <requirement>
+                    <role>org.apache.maven.project.MavenProjectHelper</role>
+                    <field-name>projectHelper</field-name>
+                </requirement>
+            </requirements>
+        </mojo>
+    </mojos>
+    <dependencies/>
+</plugin>

+ 1 - 1
iot-module/iot-rule-engine/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-module</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
iot-module/iot-screen/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-module</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
iot-module/iot-system/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-module</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
iot-module/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iotkit-parent</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
iot-starter/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iotkit-parent</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 22 - 14
iot-starter/src/main/resources/application.yml

@@ -93,22 +93,31 @@ spring:
   # ============mysql配置结束============>>
 
   #<<================es时序数据配置开始===============
-  elasticsearch:
-    rest:
-      #使用内置es的配置
-      #uris: http://elasticsearch:9200
-      uris: http://127.0.0.1:9200
-      username:
-      password:
-      connection-timeout: 10s
+#  elasticsearch:
+#    rest:
+#      #使用内置es的配置
+#      #uris: http://elasticsearch:9200
+#      uris: http://127.0.0.1:9200
+#      username:
+#      password:
+#      connection-timeout: 10s
   #================es时序数据配置结束===============>>
 
   #<<===========tdengine时序数据库配置开始============
-  #  td-datasource:
-  #    url: jdbc:TAOS-RS://127.0.0.1:6041/iotkit?timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8
-  #    username: root
-  #    password: taosdata
-  #    driverClassName: com.taosdata.jdbc.rs.RestfulDriver
+#  td-datasource:
+#    url: jdbc:TAOS-RS://127.0.0.1:6041/iotkit?timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8
+#    username: root
+#    password: taosdata
+#    driverClassName: com.taosdata.jdbc.rs.RestfulDriver
+  #===========tdengine时序数据库配置开始============>>
+
+
+  #<<===========iotdb时序数据库配置开始============
+  iotdb-datasource:
+    host: 127.0.0.1
+    port: 6667
+    username: root
+    password: root
   #===========tdengine时序数据库配置开始============>>
 
   redis:
@@ -195,6 +204,5 @@ weixin:
 plugin:
   runMode: prod
   mainPackage: cc.iotkit
-  # 如果配置是 windows 下路径, mac、linux 自行修改
   pluginPath:
     - ./data/plugins

+ 1 - 1
iot-test-tool/iot-virtual-device/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iot-test-tool</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
iot-test-tool/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>iotkit-parent</artifactId>
         <groupId>cc.iotkit</groupId>
-        <version>0.5.0-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>pom</packaging>

+ 2 - 2
pom.xml

@@ -12,7 +12,7 @@
 
     <groupId>cc.iotkit</groupId>
     <artifactId>iotkit-parent</artifactId>
-    <version>0.5.0-SNAPSHOT</version>
+    <version>0.5.1-SNAPSHOT</version>
     <name>${project.artifactId}</name>
     <description>奇特物联是一个开源的物联网基础开发平台,提供了物联网及相关业务开发的常见基础功能,
         能帮助你快速搭建自己的物联网相关业务平台。
@@ -29,7 +29,7 @@
 
     <properties>
         <java.version>11</java.version>
-        <iot-iita-core.version>1.0.0</iot-iita-core.version>
+        <iot-iita-core.version>1.0.1</iot-iita-core.version>
         <spring-boot.version>2.7.11</spring-boot.version>
         <vertx.version>4.2.2</vertx.version>
         <satoken.version>1.34.0</satoken.version>