组件管理、加载修改

V0.5.x
xiwa 2022-03-29 19:08:07 +08:00
parent 2d74d0fb91
commit b44c3d44c6
12 changed files with 200 additions and 25 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
components/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -13,7 +13,6 @@ import cc.iotkit.manager.utils.AuthUtil;
import cc.iotkit.model.Paging;
import cc.iotkit.model.UserInfo;
import cc.iotkit.model.protocol.ProtocolComponent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -25,7 +24,6 @@ import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
@ -33,6 +31,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Optional;
import java.util.UUID;
@Slf4j
@RestController
@ -42,8 +41,8 @@ public class ProtocolController {
@Value("${gateway.function-jar}")
private String functionJar;
@Value("${spring.servlet.multipart.upload-dir}")
private String uploadDir;
@Value("${component.dir}")
private String componentDir;
@Autowired
private ProtocolComponentRepository protocolComponentRepository;
@ -57,25 +56,25 @@ public class ProtocolController {
@Autowired
private ComponentManager componentManager;
private Path fileStorageLocation;
@SneakyThrows
@PostConstruct
public void init() {
this.fileStorageLocation = Paths.get(uploadDir).toAbsolutePath().normalize();
Files.createDirectories(this.fileStorageLocation);
private Path getFilePath(String comId, String type) {
return Paths.get(String.format("%s/%s/%s", componentDir, comId, type))
.toAbsolutePath().normalize();
}
@PostMapping("/uploadJar")
public void uploadJar(@RequestParam("file") MultipartFile file) {
public String uploadJar(@RequestParam("file") MultipartFile file) {
if (file == null) {
throw new BizException("file is null");
}
log.info("saving upload jar file:{}", file.getName());
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {
Path targetLocation = this.fileStorageLocation.resolve(fileName);
String id = UUID.randomUUID().toString();
Path jarFilePath = getFilePath(id, "jar");
Files.createDirectories(jarFilePath);
Path targetLocation = jarFilePath.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return id;
} catch (IOException ex) {
throw new BizException("upload jar error", ex);
}
@ -83,7 +82,16 @@ public class ProtocolController {
@PostMapping("/addComponent")
public void addComponent(ProtocolComponent component) {
Optional<ProtocolComponent> optComponent = protocolComponentRepository.findById(component.getId());
String id = component.getId();
if (!StringUtils.hasLength(id)) {
throw new BizException("component id is blank");
}
Path jarPath = getFilePath(id, "jar");
if (!jarPath.resolve(component.getJarFile()).toFile().exists()) {
throw new BizException("component jar file does not exist");
}
Optional<ProtocolComponent> optComponent = protocolComponentRepository.findById(id);
if (optComponent.isPresent()) {
throw new BizException("component already exists");
}
@ -93,7 +101,6 @@ public class ProtocolController {
throw new BizException("user does not exists");
}
component.setScript("new (function () {this.decode = function (msg) {return null; };})().decode(msg)");
component.setCreateAt(System.currentTimeMillis());
component.setUid(AuthUtil.getUserId());
protocolComponentRepository.save(component);
@ -104,6 +111,15 @@ public class ProtocolController {
@PostMapping("/saveComponent")
public void saveComponent(ProtocolComponent component) {
String id = component.getId();
if (!StringUtils.hasLength(id)) {
throw new BizException("component id is blank");
}
Path jarPath = getFilePath(id, "jar");
if (!jarPath.resolve(component.getJarFile()).toFile().exists()) {
throw new BizException("component jar file does not exist");
}
Optional<ProtocolComponent> optComponent = protocolComponentRepository.findById(component.getId());
if (!optComponent.isPresent()) {
throw new BizException("the protocol component does not exists");
@ -131,7 +147,7 @@ public class ProtocolController {
}
dataOwnerService.checkOwner(component);
ProtocolComponent oldComponent = optComponent.get();
oldComponent.setScript(component.getScript());
oldComponent.setScriptFile(component.getScriptFile());
try {
// gatewayService.saveFunction(oldGateway.getUuid(), oldGateway.getId(),
// "new (function (){" + oldGateway.getScript() + "})()", functionJar);
@ -145,6 +161,14 @@ public class ProtocolController {
public void deleteComponent(@PathVariable("id") String id) {
dataOwnerService.checkOwner(protocolComponentRepository, id);
try {
Path path = Paths.get(String.format("%s/%s", componentDir, id))
.toAbsolutePath().normalize();
File file = path.toFile();
if (file.isDirectory()) {
FileUtils.deleteDirectory(file);
} else {
FileUtils.delete(file);
}
protocolComponentRepository.deleteById(id);
} catch (Throwable e) {
throw new BizException("delete protocol component error", e);
@ -176,4 +200,5 @@ public class ProtocolController {
componentManager.stop("123");
componentManager.deRegister("123");
}
}

View File

@ -4,7 +4,6 @@ spring:
enabled: true
max-file-size: 10MB
max-request-size: 12MB
upload-dir: ./component_jar
data:
mongodb:
@ -70,5 +69,8 @@ app:
mqtt:
url: tcp://填写mqtt连接地址
component:
dir: ./components
gateway:
function-jar: 填写protocol-function打包的jar存放路径:/xx/xx.jar

View File

@ -4,7 +4,6 @@ spring:
enabled: true
max-file-size: 10MB
max-request-size: 12MB
upload-dir: ./component_jar
data:
mongodb:
@ -68,5 +67,8 @@ app:
mqtt:
url: tcp://填写mqtt连接地址
component:
dir: ./components
gateway:
function-jar: 填写protocol-function打包的jar存放路径:/xx/xx.jar

View File

@ -9,6 +9,9 @@ import org.springframework.data.mongodb.core.mapping.Document;
@Document
public class ProtocolComponent implements Owned {
public static final String STATE_STOPPED = "stopped";
public static final String STATE_RUNNING = "running";
@Id
private String id;
@ -25,7 +28,9 @@ public class ProtocolComponent implements Owned {
private String config;
private String script;
private String scriptFile;
private String state;
private Long createAt;

View File

@ -47,6 +47,11 @@
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>

View File

@ -1,24 +1,28 @@
package cc.iotkit.comps;
import cc.iotkit.comp.CompConfig;
import cc.iotkit.comp.IComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StreamUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
@Slf4j
public class ComponentClassLoader {
protected Class<IComponent> findClass(String name) throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
return (Class<IComponent>) classLoader.loadClass("cc.iotkit.comp.mqtt.MqttComponent");
return (Class<IComponent>) classLoader.loadClass(name);
}
public void addUrl(File jarPath) throws NoSuchMethodException, InvocationTargetException,
IllegalAccessException, MalformedURLException {
private String addUrl(File jarPath) throws NoSuchMethodException, InvocationTargetException,
IllegalAccessException, IOException {
URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
if (!method.isAccessible()) {
@ -26,5 +30,20 @@ public class ComponentClassLoader {
}
URL url = jarPath.toURI().toURL();
method.invoke(classLoader, url);
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("component.spi");
return StreamUtils.copyToString(is, Charset.forName("UTF-8"));
}
public IComponent getComponent(File jarPath) {
try {
String className = addUrl(jarPath);
Class<IComponent> componentClass = findClass(className);
return componentClass.newInstance();
} catch (Throwable e) {
log.error("instance component from jar error", e);
return null;
}
}
}

View File

@ -0,0 +1,80 @@
<?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/maven-v4_0_0.xsd">
<parent>
<artifactId>protocol-gateway</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>emqx-component</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactSet>
<includes>
<include>io.vertx:vertx-core</include>
<include>io.vertx:vertx-web-proxy</include>
<include>io.vertx:vertx-mqtt</include>
</includes>
</artifactSet>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>4.2.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-proxy</artifactId>
<version>4.2.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-mqtt</artifactId>
<version>4.2.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>model</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>component</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -45,4 +45,39 @@
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactSet>
<includes>
<include>io.vertx:vertx-core</include>
<include>io.vertx:vertx-web-proxy</include>
<include>io.vertx:vertx-mqtt</include>
</includes>
</artifactSet>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1 @@
cc.iotkit.comp.emqx.EmqxComponent

View File

@ -0,0 +1 @@
cc.iotkit.comp.mqtt.MqttComponent