diff --git a/.DS_Store b/.DS_Store index f9d353f3..2d69961b 100755 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/components/.DS_Store b/components/.DS_Store new file mode 100644 index 00000000..612370d1 Binary files /dev/null and b/components/.DS_Store differ diff --git a/manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java b/manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java index 13cf7f48..9fabe171 100755 --- a/manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java +++ b/manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java @@ -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 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 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 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"); } + } diff --git a/manager/src/main/resources/application-dev.yml b/manager/src/main/resources/application-dev.yml index ebc395c7..33ee2342 100755 --- a/manager/src/main/resources/application-dev.yml +++ b/manager/src/main/resources/application-dev.yml @@ -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 diff --git a/manager/src/main/resources/application.yml b/manager/src/main/resources/application.yml index 1b6731d8..a69332eb 100755 --- a/manager/src/main/resources/application.yml +++ b/manager/src/main/resources/application.yml @@ -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 diff --git a/model/src/main/java/cc/iotkit/model/protocol/ProtocolComponent.java b/model/src/main/java/cc/iotkit/model/protocol/ProtocolComponent.java index e80098a1..40ee8bf7 100755 --- a/model/src/main/java/cc/iotkit/model/protocol/ProtocolComponent.java +++ b/model/src/main/java/cc/iotkit/model/protocol/ProtocolComponent.java @@ -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; diff --git a/protocol-gateway/component-server/pom.xml b/protocol-gateway/component-server/pom.xml index 3fc4ffbb..cc6164ce 100755 --- a/protocol-gateway/component-server/pom.xml +++ b/protocol-gateway/component-server/pom.xml @@ -47,6 +47,11 @@ slf4j-api + + commons-io + commons-io + + org.projectlombok lombok diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentClassLoader.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentClassLoader.java index 0f8cbc02..f025f5d3 100644 --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentClassLoader.java +++ b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentClassLoader.java @@ -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 findClass(String name) throws ClassNotFoundException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - return (Class) classLoader.loadClass("cc.iotkit.comp.mqtt.MqttComponent"); + return (Class) 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 componentClass = findClass(className); + return componentClass.newInstance(); + } catch (Throwable e) { + log.error("instance component from jar error", e); + return null; + } + } + } diff --git a/protocol-gateway/emqx-component/dependency-reduced-pom.xml b/protocol-gateway/emqx-component/dependency-reduced-pom.xml new file mode 100644 index 00000000..7a20b0f0 --- /dev/null +++ b/protocol-gateway/emqx-component/dependency-reduced-pom.xml @@ -0,0 +1,80 @@ + + + + protocol-gateway + cc.iotkit + 0.0.1-SNAPSHOT + + 4.0.0 + emqx-component + + + + maven-shade-plugin + 3.2.4 + + + package + + shade + + + + + + + io.vertx:vertx-core + io.vertx:vertx-web-proxy + io.vertx:vertx-mqtt + + + + + + maven-compiler-plugin + + 8 + 8 + + + + + + + io.vertx + vertx-core + 4.2.6 + provided + + + io.vertx + vertx-web-proxy + 4.2.6 + provided + + + io.vertx + vertx-mqtt + 4.2.6 + provided + + + cc.iotkit + model + 0.0.1-SNAPSHOT + compile + + + cc.iotkit + common + 0.0.1-SNAPSHOT + compile + + + cc.iotkit + component + 0.0.1-SNAPSHOT + compile + + + diff --git a/protocol-gateway/emqx-component/pom.xml b/protocol-gateway/emqx-component/pom.xml index 55ea7dbc..3e9788b0 100755 --- a/protocol-gateway/emqx-component/pom.xml +++ b/protocol-gateway/emqx-component/pom.xml @@ -45,4 +45,39 @@ + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + + + + + io.vertx:vertx-core + io.vertx:vertx-web-proxy + io.vertx:vertx-mqtt + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + \ No newline at end of file diff --git a/protocol-gateway/emqx-component/src/main/resources/component.spi b/protocol-gateway/emqx-component/src/main/resources/component.spi new file mode 100644 index 00000000..672ee448 --- /dev/null +++ b/protocol-gateway/emqx-component/src/main/resources/component.spi @@ -0,0 +1 @@ +cc.iotkit.comp.emqx.EmqxComponent \ No newline at end of file diff --git a/protocol-gateway/mqtt-component/src/main/resources/component.spi b/protocol-gateway/mqtt-component/src/main/resources/component.spi new file mode 100644 index 00000000..87d0d822 --- /dev/null +++ b/protocol-gateway/mqtt-component/src/main/resources/component.spi @@ -0,0 +1 @@ +cc.iotkit.comp.mqtt.MqttComponent \ No newline at end of file